### 简要描述: 人生第一发代码审计 ### 详细说明: 首先给厂商说句抱歉,测试demo的时候把demo搞挂了 漏洞文件:control/ajax/balance.php 看代码 ``` $arrSellerInfo = db_factory::get_one(sprintf('select * from %s a left join %s b on a.uid = b.uid where a.uid =%s',TABLEPRE.'witkey_space',TABLEPRE.'witkey_shop',intval($id))); if($arrSellerInfo['shop_backstyle']){ $arrBackgroudStyle = unserialize($arrSellerInfo['shop_backstyle']); } if($_R['a']==1){ $arr['shop_background']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); }elseif($_R['a']==2){ $arr['banner']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); } if (isset($formhash)&&kekezu::submitcheck($formhash)) { $shopObjT = keke_table_class::get_instance ( 'witkey_shop' ); $banner and $arrFields['banner'] = $banner; $background and $arrFields['shop_background'] = $background;...
### 简要描述: 人生第一发代码审计 ### 详细说明: 首先给厂商说句抱歉,测试demo的时候把demo搞挂了 漏洞文件:control/ajax/balance.php 看代码 ``` $arrSellerInfo = db_factory::get_one(sprintf('select * from %s a left join %s b on a.uid = b.uid where a.uid =%s',TABLEPRE.'witkey_space',TABLEPRE.'witkey_shop',intval($id))); if($arrSellerInfo['shop_backstyle']){ $arrBackgroudStyle = unserialize($arrSellerInfo['shop_backstyle']); } if($_R['a']==1){ $arr['shop_background']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); }elseif($_R['a']==2){ $arr['banner']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); } if (isset($formhash)&&kekezu::submitcheck($formhash)) { $shopObjT = keke_table_class::get_instance ( 'witkey_shop' ); $banner and $arrFields['banner'] = $banner; $background and $arrFields['shop_background'] = $background; $repeat and $arrBackgroudStyle['repeat']= $repeat; $position and $arrBackgroudStyle['position']= $position; is_array($arrBackgroudStyle) and $arrFields['shop_backstyle'] = serialize($arrBackgroudStyle); $shopObjT->save($arrFields,array('uid'=>intval($id))); kekezu::show_msg('已保存','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); } ``` 变量 $arr 是可控的 而且没做任何过滤传入 updatetable()函数 跟进updatetable()函数 ``` public function updatetable($tablename, $setsqlarr, $wheresqlarr) { return $this->_mydb->update ( $tablename, $setsqlarr, $wheresqlarr ); ``` 可见没做处理,跟进update() ``` public function update($tablename, $setsqlarr, $wheresqlarr) { $setsql = ''; $fields = array (); foreach ( $setsqlarr as $k => $v ) { $fileds [] = $this->special_filed ( $k ) . '=' . $this->mysqlEscapeString ( $v ); } $setsql = implode ( ',', $fileds ); $where = ""; if (empty ( $wheresqlarr )) { $where = 1; } elseif (is_array ( $wheresqlarr )) { $temp = array (); foreach ( $wheresqlarr as $k => $v ) { $temp [] = $this->special_filed ( $k ) . '=' . $this->escape_string ( $v ); } $where = implode ( ' and ', $temp ); } else { $where = $wheresqlarr; } return $affectrows = $this->execute ( 'UPDATE ' . $tablename . ' SET ' . $setsql . ' WHERE ' . $where ); } ``` 这里就可以看出我们从url传过来的arr要是数组才行,才能控字段。 先看效果 [<img src="https://images.seebug.org/upload/201505/13132550eb1c0bb3e4cfe35f80beadc4af42525f.png" alt="QQ图片20150513132015.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13132550eb1c0bb3e4cfe35f80beadc4af42525f.png) [<img src="https://images.seebug.org/upload/201505/13132604f3000199064ef294207eeb2f46df06af.png" alt="QQ图片20150513132059.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13132604f3000199064ef294207eeb2f46df06af.png) 可见真的进入了update语句,但是是否 显得鸡肋呢,因为只能更新shop表下的字段而已,也就是改改别人的店铺名啊之类的,要是能逃逸单引号多,这时候就开始fuzz一下发现,如果交一个单引号会经过两次转义,一次是系统全局的,另一次是update()函数里的escape_string()函数,测试一下 [<img src="https://images.seebug.org/upload/201505/13133253eb363ce403805bd44081638b27f2f14a.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133253eb363ce403805bd44081638b27f2f14a.png) [<img src="https://images.seebug.org/upload/201505/1313330929d61d890dee013b9c9a03091222e2dc.png" alt="4.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/1313330929d61d890dee013b9c9a03091222e2dc.png) 可见一个单引号会变成一个3个反斜杠加一个单引号。这时候我fuzz了一下 发现如果提交%bf'哈哈 [<img src="https://images.seebug.org/upload/201505/13133639875ca86c93c9fe580e2a2094fd5e6f0f.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133639875ca86c93c9fe580e2a2094fd5e6f0f.png) [<img src="https://images.seebug.org/upload/201505/13133650d7e50453f1066a902eedbb18cb4678a1.png" alt="6.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133650d7e50453f1066a902eedbb18cb4678a1.png) 哈哈 单引号成功逃逸出来。 这个时候就可以盲注了哈哈 至于你问我为什么 我也还不大清楚,我再还要分析看看,注:我的环境是apache+mysql5.5.4+php5.3。本来是要测dome的但是由于手抖没闭合好官网已经挂了 实在抱歉 poc http://127.0.0.1:81/www/kppw/index.php?do=ajax&view=banner&id=1&a=1&arr[shop_name]=123%bf' where uid=1 and sleep(5)%23 [<img src="https://images.seebug.org/upload/201505/131340151e3bfe25d191c088d988fcdd0e615550.png" alt="7.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/131340151e3bfe25d191c088d988fcdd0e615550.png) 成功盲注。 ### 漏洞证明: 首先给厂商说句抱歉,测试demo的时候把demo搞挂了 漏洞文件:control/ajax/balance.php 看代码 ``` $arrSellerInfo = db_factory::get_one(sprintf('select * from %s a left join %s b on a.uid = b.uid where a.uid =%s',TABLEPRE.'witkey_space',TABLEPRE.'witkey_shop',intval($id))); if($arrSellerInfo['shop_backstyle']){ $arrBackgroudStyle = unserialize($arrSellerInfo['shop_backstyle']); } if($_R['a']==1){ $arr['shop_background']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); }elseif($_R['a']==2){ $arr['banner']=""; db_factory::updatetable(TABLEPRE."witkey_shop", $arr, "uid=".$_R['id']); kekezu::show_msg('已清除','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); } if (isset($formhash)&&kekezu::submitcheck($formhash)) { $shopObjT = keke_table_class::get_instance ( 'witkey_shop' ); $banner and $arrFields['banner'] = $banner; $background and $arrFields['shop_background'] = $background; $repeat and $arrBackgroudStyle['repeat']= $repeat; $position and $arrBackgroudStyle['position']= $position; is_array($arrBackgroudStyle) and $arrFields['shop_backstyle'] = serialize($arrBackgroudStyle); $shopObjT->save($arrFields,array('uid'=>intval($id))); kekezu::show_msg('已保存','index.php?do=seller&id='.intval($id),NULL,NULL,'ok'); } ``` 变量 $arr 是可控的 而且没做任何过滤传入 updatetable()函数 跟进updatetable()函数 ``` public function updatetable($tablename, $setsqlarr, $wheresqlarr) { return $this->_mydb->update ( $tablename, $setsqlarr, $wheresqlarr ); ``` 可见没做处理,跟进update() ``` public function update($tablename, $setsqlarr, $wheresqlarr) { $setsql = ''; $fields = array (); foreach ( $setsqlarr as $k => $v ) { $fileds [] = $this->special_filed ( $k ) . '=' . $this->mysqlEscapeString ( $v ); } $setsql = implode ( ',', $fileds ); $where = ""; if (empty ( $wheresqlarr )) { $where = 1; } elseif (is_array ( $wheresqlarr )) { $temp = array (); foreach ( $wheresqlarr as $k => $v ) { $temp [] = $this->special_filed ( $k ) . '=' . $this->escape_string ( $v ); } $where = implode ( ' and ', $temp ); } else { $where = $wheresqlarr; } return $affectrows = $this->execute ( 'UPDATE ' . $tablename . ' SET ' . $setsql . ' WHERE ' . $where ); } ``` 这里就可以看出我们从url传过来的arr要是数组才行,才能控字段。 先看效果 [<img src="https://images.seebug.org/upload/201505/13132550eb1c0bb3e4cfe35f80beadc4af42525f.png" alt="QQ图片20150513132015.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13132550eb1c0bb3e4cfe35f80beadc4af42525f.png) [<img src="https://images.seebug.org/upload/201505/13132604f3000199064ef294207eeb2f46df06af.png" alt="QQ图片20150513132059.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13132604f3000199064ef294207eeb2f46df06af.png) 可见真的进入了update语句,但是是否 显得鸡肋呢,因为只能更新shop表下的字段而已,也就是改改别人的店铺名啊之类的,要是能逃逸单引号多,这时候就开始fuzz一下发现,如果交一个单引号会经过两次转义,一次是系统全局的,另一次是update()函数里的escape_string()函数,测试一下 [<img src="https://images.seebug.org/upload/201505/13133253eb363ce403805bd44081638b27f2f14a.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133253eb363ce403805bd44081638b27f2f14a.png) [<img src="https://images.seebug.org/upload/201505/1313330929d61d890dee013b9c9a03091222e2dc.png" alt="4.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/1313330929d61d890dee013b9c9a03091222e2dc.png) 可见一个单引号会变成一个3个反斜杠加一个单引号。这时候我fuzz了一下 发现如果提交%bf'哈哈 [<img src="https://images.seebug.org/upload/201505/13133639875ca86c93c9fe580e2a2094fd5e6f0f.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133639875ca86c93c9fe580e2a2094fd5e6f0f.png) [<img src="https://images.seebug.org/upload/201505/13133650d7e50453f1066a902eedbb18cb4678a1.png" alt="6.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/13133650d7e50453f1066a902eedbb18cb4678a1.png) 哈哈 单引号成功逃逸出来。 这个时候就可以盲注了哈哈 至于你问我为什么 我也还不大清楚,我再还要分析看看,注:我的环境是apache+mysql5.5.4+php5.3。本来是要测dome的但是由于手抖没闭合好官网已经挂了 实在抱歉 poc http://127.0.0.1:81/www/kppw/index.php?do=ajax&view=banner&id=1&a=1&arr[shop_name]=123%bf' where uid=1 and sleep(5)%23 [<img src="https://images.seebug.org/upload/201505/131340151e3bfe25d191c088d988fcdd0e615550.png" alt="7.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/131340151e3bfe25d191c088d988fcdd0e615550.png) 成功盲注。