Lesson learned?
Have you learned your lesson? - by Tib3rius
Last updated
Have you learned your lesson? - by Tib3rius
Last updated
Thanks Tib3rius for the room and the quick exchange on discord. I definitely take the topic with me and have learned something, even if I am so far only active in CTFs.
The following post by 0xb0b is licensed under
Even though the room description states that there is only a login page, no hidden files, and no rabbit holes, we hit up Nmap and scanned our target machine. We have two open ports: an HTTP server running on port 80 and an SSH server running on port 22.
While visiting the website, we use Gobuster to check for interesting directories on the web server, but do not find anything of interest.
Visiting the site gives us a login form, asking for a username and password. Common attacks on login forms are SQL injection and brute-force attacks. To get the flag, we have to bypass the login using either of these attacks.
First of all, we check the login page with default credentials admin:admin
and retrieve the error message Invalid username and password
. This might come in handy later.
Next, we check for possible SQL injection, but most of the payloads did not respond with any errors.
After several attempts and missing error messages, we just tried the following.
Desperately trying to bypass the login via admin' OR '1'='1
simply, we get a warning message.
It is teaching us why it wouldn't bypass the login and the consequences of our injection. The injected statement made it into a DELETE statement, which removes our flag. To get the flag, we have to restart the machine and avoid using the OR injection next time.
Another example of ' OR '1'='1
bad practice is that all rows of a table are returned, and those can be very large.
Even SQLmap does not use OR 1=1
unless the risk level is set to 3. Having the error message in mind and the message to treat this box as if it were a real target and not a CTF, we continue with a different approach.
Revisiting our login with default credentials admin:admin
we look at the error message.
With the error message Invalid username and password
, we are able to enumerate possible stored usernames. This violates against the OWASP Authentication Guidelines
Incorrectly implemented error messages in the case of authentication functionality can be used for the purposes of user ID and password enumeration. An application should respond (both HTTP and HTML) in a generic manner.
Some of the SQL statements provided by Tib3rius are less harmful and good examples of SQL injection, and we'll follow his example.
So the idea is, to retrieve a valid username, to be able to inject a valid ' AND '1'='1
statement to bypass the login.
We intercept the login request via Burp Suite to get the necessary information to craft our command for Hydra to brute-force a possible user. We see that it is a POST request, requiring the variables username
and password
.
With the following command, we fire up Hydra and are able to retrieve some usernames using the xato-net-10-million-usernames.txt
from SecLists:
To confirm the results, we try to log in with one of the usernames and get another error message about an invalid password - Nice. We enumerated the user kelly
.
Now, we want to craft our statement.
With the original statement in mind, which probably looks something like this
SELECT * FROM users WHERE username = 'user_var' AND password = 'pass_var’
We craft the payload kelly' AND '1'='1'-- -
resulting in
SELECT * FROM users WHERE username = 'kelly' AND '1'='1' -- - AND password = ''
By providing the payload, we are greeted with the flag and an explanation about the risks of using the OR 1 = 1
injection.
Upon trying some payloads provided by HackTricks to check the login form for SQL injection and checking for the number of columns using union-based SQL injection to enumerate the table further, the flag was also retrieved and the login bypassed.
The query admin' UNION SELECT null-- -
does bypass the login as well.
After a quick chat with Tib3rius I got the following explanation:
The username check solely verifies the presence of a single row resulting from the query. With the remaining portion of the query commented out, the password check is absent as well. Since UNION makes no sense in a DELETE statement, it got skipped too.
If you want good examples for SQL injection, use these. Auth Bypass: admin'; -- - SELECT * FROM users WHERE username = 'admin'; -- -' AND password = 'password' Boolean: ' AND '1'='1 / ' AND '1'='2 SELECT * FROM articles WHERE author = 'admin' AND '1'='1'
— Tib3rius (@0xTib3rius)