BlueCMS v1.6 sp1 /admin/login.php SQL注入漏洞分析

BlueCMS v1.6 sp1 /admin/login.php SQL注入漏洞分析

  • BlueCMS v1.6 sp1 /admin/login.php SQL注入漏洞分析
    • 略读代码:
    • 转换思路:
    • 尝试宽字节注入:
    • 理解宽字节:
    • 编写pocsuite插件:
      • requests不进行urldecode:
      • 验证:
    • 总结:
    • 参考:


略读代码:

开头包含了文件

require_once(dirname(__FILE__) . '/include/common.inc.php');

该文件中,全局数据转义

 if(!get_magic_quotes_gpc())//如果没有开启
 {
    $_POST = deep_addslashes($_POST);
    $_GET = deep_addslashes($_GET);
    $_COOKIES = deep_addslashes($_COOKIES);
    $_REQUEST = deep_addslashes($_REQUEST);
 } //加上斜杠转义

输入了双引号,会被转义掉,那么此处就没办法简单地引入引号去控制Sql语句了。


转换思路:

这个时候发现自己没有思路了,只会单引号双引号。。。渣-c-

参考一下:【Code Review】bluecms v1.6 Sql Injection 分析

可以发现对数据的注入,进行了加斜杠转义的操作。那么接下来找注入思路主要有以下3点:

  • 整数型注入
  • 整套cms默认gb2312编码,容易造成宽字节注入
  • http头并不在转义的范围内,所以类似存入ip,reffer的位置也能发生注入

尝试宽字节注入:

  • 抓包修改admin_name=%df%27+or+1%3D1%23
  • 明文就是%df' or 1=1#
  • 单引号被转义后变成%df\' or 1=1#
  • 宽字节注入是利用mysql的一个特性,因为gbk是多字节编码,他认为两个字节代表一个汉字,所以%df和后面的\也就是%5c变成了一个汉字“運”,而单引号逃逸了出来,就可以成功闭合sql语句了
  • 再加上后面的or 1=1 #就构造成了永真语句,可以成功免密登录管理员后台了

理解宽字节:

参考:浅析白盒审计中的字符编码及SQL注入

  • 本质是如何绕过addslashes函数:
  • addslashes函数产生的效果就是,让变成\’,让引号变得不再是“单引号”
  • 一般绕过方式就是,想办法处理\’前面的\

    • 想办法给\前面再加一个\(或单数个即可),变成\\’,这样\被转义了,逃出了限制
    • 想办法把\弄没有。
  • mysql怎么判断一个字符是不是汉字?

    • 根据gbk编码,第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以
  • gb2312和gbk的区别?

    • gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\0x5c,是不在低位范围中的。
    • 0x5c根本不是gb2312中的编码,所以自然也是不会被吃掉的。

修复方案1:

  • 先调用mysql_set_charset函数设置连接所使用的字符集为gbk
  • 再调用mysql_real_escape_string来过滤用户输入。

  • 这个方式是可行的,但有部分老的cms,在多处使用addslashes来过滤字符串,我们不可能去一个一个把addslashes都修改成mysql_real_escape_string。

所以有修复方案2:

  • 将character_set_client设置为binary(二进制)。
  • 只需在所有sql语句前指定一下连接的形式是二进制:
    mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn);
  • 所有数据以二进制的形式传递,就能有效避免宽字符注入。

编写pocsuite插件:

requests不进行urldecode:

参考:如何在requests post时不做urlencode
There are many times that you want to send data that is not form-encoded. If you pass in a string instead of a dict , that data will be posted directly.
所以,只要直接传一个string作为payload数据,requests就不会做任何转换,直接发出去。

并且加上headers = {"Content-Type": "application/x-www-form-urlencoded"}

验证:

poc链接


总结:

  • 阅读源码的时候,先看看全局过滤
  • gb2312、gbk编码的话,考虑宽字节注入
  • 宽字节注入的原理是 gbk是多字节编码,他认为两个字节代表一个汉字,所以可以用%df和后面的\也就是%5c变成了一个汉字“運”,而单引号逃逸了出来

参考:

  • 【Code Review】bluecms v1.6 Sql Injection 分析
  • 浅析白盒审计中的字符编码及SQL注入

你可能感兴趣的:(代码审计,security)