Blind SQL Injection  

Identifying the Vulnerability

Note: You can start the VM found in the question at the end of the next section for the module's practice web apps.

Scenario

We have been contracted by Aunt Maria's Donuts to conduct a vulnerability assessment of their business website. We were not given any user credentials, as they wish for the test to simulate an external attacker as closely as possible.

After taking a quick tour of the home page, we move to the registration page to see if creating a user will gain us any additional access.

After entering a username we notice the text The username 'moody' is available pop up underneath the field. This suggests that the database might've been queried to check if the username entered already exists or not, so this is worth checking out.

Investigating the 'Username Availability' Check

Taking a look at the source code of signup.php, we can see that usernameInput calls checkUsername() on the onfocusout event, which occurs when the user shifts focus away from the username field.

A bit further down in the source code we can see a reference to static/js/signup.js.

Taking a closer look at this script, we can see the definition of the checkUsername() function.

function checkUsername() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var json = JSON.parse(xhr.responseText);
            var username = document.getElementById("usernameInput").value;
            username = username.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
            var usernameHelp = document.getElementById("usernameHelp");
            
            if (json['status'] === 'available') {
                usernameHelp.innerHTML = "<span style='color:green'>The username '" + username + "' is <b>available</b></span>";
            } else {
                usernameHelp.innerHTML = "<span style='color:red'>The username '" + username + "' is <b>taken</b>, please use a different one</span>";
            }
        }
    };
    xhr.open("GET", "/api/check-username.php?u=" + document.getElementById("usernameInput").value, true);
    xhr.send();
}

What it does is:

  1. Sends a GET request to /api/check-username.php?u=<username>
  2. Updates the usernameHelp element to inform the user if the given username is available or taken, depending on the response from /api/check-username.php.

Using BurpSuite we can try a few various usernames out. For example admin and maria both return status: taken. More interesting, however, is that when we supply a single quote as the username the server returns an Error 500: Internal Server Error.

image

Confirming the SQL Injection Vulnerability

This suggests the presence of an SQL injection vulnerability. The query that is evaluated on the back-end most likely looks something like this:

SELECT Username FROM Users WHERE Username = '<u>'

By this logic, injecting ' or '1'='1 should make the query return something and in turn make the server think this 'username' is already taken. We can confirm this theory by sending the following request in Burp:

image

In this case, we have found a boolean-based SQL injection. We can inject whatever we want, but the server will only respond with status:taken or status:available meaning we will have to rely on using "Yes/No" questions to infer the data we want to extract from the database.

Previous

+10 Streak pts

Next
My Workstation

OFFLINE

/ 1 spawns left