Hack The Box: Cypher Machine Walkthrough β Medium Difficultyy
Introduction to Cypher:

In this write-up, we will explore the βCypherβ machine from Hack The Box, categorised as a Medium difficulty challenge. This walkthrough will cover the reconnaissance, exploitation, and privilege escalation steps required to capture the flag.
Objective:
The goal of this walkthrough is to complete the βCypherβ machine from Hack The Box by achieving the following objectives:
User Flag: Exploit a vulnerable Neo4j database by injecting a Cypher query to extract a password hash, authenticate via SSH, and retrieve the user flag.
Root Flag: Leverage a misconfigured bbot binary with sudo privileges to execute a command that sets the SUID bit on /bin/bash, granting root access to capture the root flag.
Enumerating the Cypher Machine
Establishing Connectivity
I connected to the Hack The Box environment via OpenVPN using my credentials, running all commands from a Kali Linux virtual machine. The target IP address for the Cypher machine was 10.10.11.57
Reconnaissance:
Nmap Scan:
Begin with a network scan to identify open ports and running services on the target machine.
nmap -sC -sV -oA initial 10.10.11.57Nmap Output:
ββ[dark@parrot]β[~/Documents/htb/cypher]
ββββΌ $nmap -sC -sV -oA initial 10.10.11.57
# Nmap 7.94SVN scan initiated Sun Jul 20 11:35:15 2025 as: nmap -sC -sV -oA initial 10.10.11.57
Nmap scan report for 10.10.11.57
Host is up (0.26s latency).
Not shown: 998 closed tcp ports (conn-refused)
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 at Sun Jul 20 11:50:37 2025 -- 1 IP address (1 host up) scanned in 921.53 seconds
ββ[dark@parrot]β[~/Documents/htb/cypher]
ββββΌ $
Analysis:
- 22/tcp (SSH): OpenSSH 8.2p1 running, indicating potential remote access with valid credentials.
- 80/tcp (HTTP): Apache web server, likely hosting a web application for further enumeration.
Web Enumeration:
I performed directory enumeration on the web server using Gobuster
gobuster dir -u http://cypher.htb -w /opt/common.txtGobuster Output:

Analysis:
- The web interface revealed a βTry out free demoβ button redirecting to /login/.
- The /api/docs directory was inaccessible or empty.
- A .jar file was found in /testing/, which seemed unusual and warranted further investigation.

The website interface looks something as shown above

Inspecting the login page at /login/ revealed a form.

In this example, the application builds a database query by directly inserting the username and password the user enters into the query string. Because the system does not properly check or clean these inputs, an attacker can insert special characters or code that changes the queryβs intended behaviour. This lack of input validation creates a Cypher injection vulnerability.
Hereβs a simplified version of the vulnerable code:
def verify_creds(username, password):
cypher = f"""
MATCH (u:USER) -[:SECRET]-> (h:SHA1)
WHERE u.name = '{username}' AND u.password = '{password}'
RETURN h.value AS hash
"""
results = run_cypher(cypher)
return resultsHere, the username and password Values are inserted directly into the Cypher query string without any validation or escaping. This allows an attacker to inject malicious Cypher code by crafting special input, leading to a Cypher injection vulnerability.

No content found in the /api/docs directory.

A JAR file was located in the /testing/ directory, which appeared suspicious or out of place.
Static Analysis of JAR File Using JADX-GUI on Cypher machine

Examine the JAR file by opening it with jadx-gui.

The Code Walkthrough (Simplified)
The Function Setup
@Procedure(name = "custom.getUrlStatusCode", mode = Mode.READ)<br>public Stream<StringOutput> getUrlStatusCode(@Name("url") String url)<span style="background-color: initial; font-family: inherit; font-size: inherit; text-align: initial;">This creates a special function that anyone can call from the database. Itβs like putting up a sign that says βRing this bell and Iβll check any website for you!β The problem is, no security guard is checking who is ringing the bell or what theyβre really asking for.
The Weak Security Check
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://")) {
url = "https://" + url;
}The so-called βsecurityβ in place is like a bouncer who only checks if youβre wearing shoes before letting you into a club. As long as you have shoes on, youβre allowed inβnever mind the fact that youβre holding a crowbar and carrying a bag labeled βSTOLEN GOODS.β
The Dangerous Command
String[] command = {"/bin/sh", "-c", "curl -s -o /dev/null --connect-timeout 1 -w %{http_code} " + url};The real issue arises when the system takes the user-provided URL and passes it straight to the computer as-is, saying, βExecute this exactly as the user entered it.β Thereβs no validation or filtering, which makes it easy for attackers to sneak in malicious commands.
Exploitation
Web Application Exploration:

Analyse the login pageβs packet by intercepting it, which returns an invalid credentials response.

Review the error that occurred after entering a Cypher injection into the username field.
Cypher Injection on Cypher Machine
Cypher injection happens when an application doesnβt properly check what you type into a login form or search box before sending it to the database. Think of it like filling out a form at a bank: instead of just writing your name, you also add a note telling the bank to open the vault. If the bank employee doesnβt read carefully and just follows the instructions, you could get access to things you shouldnβt.
In the same way, attackers can type special commands into a websiteβs input fields. If the website passes those commands straight to the database without checking, attackers can trick it into revealing private data or even taking control of the system.
Cypher Injection Verification and Exploitation Steps

This query tries to find a user node labeled USER with the name βtestβ OR 1=1//β and then follows the SECRET relationship to get the related SHA1 node. It returns the value property from that SHA1 node as hash. The extra single quote after βtestβ likely causes a syntax error, which may be why the injection triggers an error.

Analyze the next step by modifying the payload to avoid syntax errors and bypass filters.

Analyze the network traffic by executing tcpdump.

Start by testing with the ping command to check for command execution.

We received an immediate response, confirming that the command was successfully executed.

Set up a Python HTTP server to test for outbound connections from the target system.

Attempt to fetch a file that doesnβt exist on the target system to observe the error behaviour.

The attempt was successful, confirming that the system executed the command and reached out as expected.

Start a listener on your machine to catch any incoming reverse connections from the target system.

Call the shell.sh file from your machine, and observe that the request hangs, indicating that the payload was likely executed and the reverse shell is in progress.

The shell.sh file was successfully transferred, confirming that the target system was able to fetch and process the file.

We have successfully gained access as the neo4j user on the target system.

Check the neo4j userβs home directory for any configuration files, databases, or credentials that could aid further exploitation.

The neo4j directory does not contain any files of interest.

A password was found in the .bash_history file.

Start the Neo4j service by using the cypher-shell command.

We successfully retrieved the hashes.

Access attempt as graphasm failed.

However, access is graphasm succeeded through the SSH or pwncat-cs service.

We successfully obtained the user flag.
Escalate to Root Privileges Access
Privilege Escalation:

The sudo -l command reveals the presence of the bbot binary with elevated privileges.


Executing sudo /usr/local/bin/bbot -cy /root/root.txt -d --dry-run returns the root flag.

The bbot_present.yaml file contains important configuration details. It specifies the target as ecorp.htb and sets the output directory to /home/graphasm/bbot_scans. Under the configuration section, the Neo4j module is configured with the username neo4j and the password cU4btyib.20xtCMCXkBmerhK.

The dark.yml file specifies the module_dirs configuration with a directory path set to ["/home/graphasm"]. This indicates where the system will look for custom modules to load.
In the dark.py script, which imports BaseModule from bbot.modules.base, there is a class named dark that runs the command chmod +s /bin/bash through os.system(). This command changes the permissions of /bin/bash to set the setuid bit, allowing anyone to execute the shell with root privileges, posing a serious security risk.

First, check if /bin/bash has the SUID bit set. Look for an s in the userβs execute position (e.g., -rwsr-xr-x); this indicates itβs a SUID binary. If you donβt see it, the setuid bit isnβt set.


Execute the command to run bbot with the specified configuration and module
This runs the dark module using the settings from /home/graphasm/dark.yml, forcing execution with the --force flag.

Another way to gain root access is by executing the reverse shell with root privileges.

We have successfully received a reverse shell connection back to our machine.
The post Hack The Box: Cypher Machine Walkthrough β Medium Difficultyy appeared first on Threatninja.net.