PHP多字节编码漏洞小结

2023-12-07 0 509

如果小结中有理解错误的地方,麻烦大家提出。漏洞本质: php 使用 php_escape_shell_cmd这个函数来转义命令行字符串时是作为单字节处理的而当操作系统设置了GBK、EUC-KR、SJIS等宽字节字符集时候,将 …如果小结中有理解错误的地方,麻烦大家提出。漏洞本质:php 使用 php_escape_shell_cmd这个函数来转义命令行字符串时是作为单字节处理的而当操作系统设置了GBK、EUC-KR、SJIS等宽字节字符集时候,将这些命令行字符串传递给MySQL处理时是作为多字节处理的先看个简单的例子

复制代码代码如下:<?php header(\’Content-type: text/html; charset=gbk\’); //连接MySQL $conn = mysql_connect(\”localhost\”, \”root\”, \”\”); //选择数据库 mysql_select_db(\”test\”, $conn); //设置字符集编码 mysql_query(\”SET CHARACTER SET \’gbk\’\”, $conn); //创建DEMO表如果不存在 mysql_query(\”CREATE TABLE IF NOT EXISTS `demo` ( `uid` int(10) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL, `password` varchar(32) NOT NULL, PRIMARY KEY (`uid`) ) ENGINE=MyISAM DEFAULT CHARSET=gbk AUTO_INCREMENT=1;\”, $conn); //插入个测试数据 mysql_query(\”REPLACE INTO `demo` VALUES(\’\’,\’admin\’,\’admin888\’) \”,$conn); //获取用户输入 $username = isset($_REQUEST[\’username\’]) ? $_REQUEST[\’username\’] : \’\’; //执行查询并且DEBUG $sql = \”SELECT * FROM demo WHERE username = \'{$username}\’ LIMIT 1\”; echo \”sql: \”.$sql.\”\”; $res = mysql_query($sql, $conn); $row = mysql_fetch_array($res); echo \”result: <br/>\”; var_dump($row); ?>

当GPC=OFF时:username未经任何过滤,这是个典型的字符型SQL注入测试地址:http://localhost/gbk.php?username=\’ or 1%23http://localhost/gbk.php?username=\’ or 0%23当然很多情况下GPC=OFF时候都会使用一些函数来过滤用户的输入

复制代码代码如下:// 对用户传入的变量进行转义操作 if (!get_magic_quotes_gpc()) { $username = addslashes($username); }

看上去貌似没问题了,但是由于多字节编码问题,同样还是可以注入的测试地址:http://localhost/gbk.php?username=%df%27使用mysql_real_escape_string函数对用户输入进行转义存在同样的问题目前的很多开源的系统都是通过设置客户端的字符集为二进制来防止多字节编码问题的。//使用上面这句来替换DEMO中的 mysql_query("SET CHARACTER SET \’gbk\’", $conn);mysql_query("SET character_set_connection=gbk, character_set_results=gbk, character_set_client=binary", $conn);再次测试:http://localhost/gbk.php?username=%df%27OK,这样一来,多字节编码问题就不存在了吗?不见得当使用mb_convert_encoding、iconv对字符集进行错误的转换时候,漏洞再次的出现了(GPC=ON时问题同样存在)例如:$username = iconv(\’gbk\’,\’utf-8\’,$username);或$username = mb_convert_encoding($username,\’utf-8\’,\’gbk\’);来看下T00ls上看到的ECSHOP 2.6.x/2.7.x GBK版本的漏洞吧漏洞文件在api/checkorder.php line 28

复制代码代码如下:$sql = \”SELECT COUNT(*) \”. \” FROM \” . $ecs->table(\’admin_user\’) . \” WHERE user_name = \’\” . trim($_REQUEST[\’username\’]). \”\’ AND password = \’\” . md5(trim($_REQUEST[\’password\’])) . \”\’\”;

我们来看下$_REQUEST[\’username\’] 的获取过程

复制代码代码如下:$_REQUEST[\’username\’] = json_str_iconv($_REQUEST[\’username\’]); json_str_iconv()这个函数在includes/lib_base.php中定义,其功能是将非UTF-8编码的字符串进行转换,然后return ecs_iconv(\’utf-8\’, EC_CHARSET, $str); ecs_inonv这个函数也在 includes/lib_base.php中定义,看下函数吧: function ecs_iconv($source_lang, $target_lang, $source_string = \’\’) { static $chs = NULL; /* 如果字符串为空或者字符串不需要转换,直接返回 */ if ($source_lang == $target_lang || $source_string == \’\’ || preg_match(\”/[\\x80-\\xFF]+/\”, $source_string) == 0) { return $source_string; } if ($chs === NULL) { require_once(ROOT_PATH . \’includes/cls_iconv.php\’); $chs = new Chinese(ROOT_PATH); } return $chs->Convert($source_lang, $target_lang, $source_string); }

先是引入了includes/cls_iconv.php这个文件,然后实例化了Chinese这个类,在调用类的Convert的方法见line 127$string = $this->_convert_iconv_mbstring($this->SourceText, $this->config[\’target_lang\’], $this->config[\’source_lang\’]);又调用了另外一个函数_conver_iconv_mbstring见line 278//这里错误的吧字符集从gbk转为了utf8,所以漏洞产生了$return_string = @mb_convert_encoding($string, $target_lang, $source_lang);

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 脚本攻防 PHP多字节编码漏洞小结 https://www.u-9.cn/security/gongfang/124733.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务