查找sessionid 代码_代码审计之TP6任意文件操作漏洞

7e82b07f8e7a47f682ff08fe869d504e.png

沙漏安全团队

欢迎真正热爱技术的你!

本文首发于先知社区➡https://xz.aliyun.com/t/8409


前言: 审计代码能力太弱了,每次一看到审计代码的题目就不知道要如何进行,恰好做Web题的时候发现了一个有关ThinkPHP6.0漏洞的题目,趁这个机会也练习一下。 

0x00:漏洞介绍

2020年1月10日,ThinkPHP团队发布一个补丁更新,修复了一处由不安全的SessionId导致的任意文件操作漏洞。该漏洞允许攻击者在目标环境启用session的条件下创建任意文件以及删除任意文件,在特定情况下还可以getshell。

具体受影响版本为ThinkPHP6.0.0-6.0.1

0x01:环境准备

Windows:Apache + Thinkphp(6.0.0) + php7.2.10

先安装composer工具,我这里使用的是phpstudy,在php目录找到一个php7版本的即可,安装好之后

composer create-project topthink/think tp 6.0.0#tp是文件夹命名#6.0.0是版本号

进入安装目录,执行命令

php think run#会开启一个临时的开发环境的服务器,默认运行在localhost:8000

0x02:漏洞分析

根据官方Github上提供的c5b559c736aa39979e7dd1c4b3efd381.png修改的文件是

src/think/session/Store.php

先来看一下,添加ctype_alnum这个函数有什么作用62db980cbd49a060c9e8581996986b62.png

这个函数是用来检测输入的$text中所有的字符全部是字母和(或者)数字,返回 TRUE 否则返回FALSE

通过官方的修复可以推出来漏洞的成因,主要原因应该是出现在Session中,那下面就来分析一下Session的相关代码

/vendor/topthink/framework/src/think/session/Store.php#TP6存储Session文件的目录

漏洞介绍中说到该漏洞允许攻击者在目标环境启用session的条件下可以删除任意文件创建任意文件,那就先定位一下关键词delete,既然是任意文件删除,那么参数就一定是用户可控的。

4e482694609519dcdf9b0f1df6b7a644.pngdelete关键字的一共有三处,可以推测在函数265行的位置很可能是该漏洞的形成位置,因为涉及到了SessionId。而且漏洞介绍中也说了可以任意创建文件,在delete关键字上面就有一个write函数且包含有SessionId

7b45e90672a58bea5618855a6560bcc8.png跟踪一下这个write函数,在全局搜索函数中找到了write()delete()函数的详细定义

vendor/topthink/framework/src/think/session/driver/File.php

83ebda7080713113842da25d53904f51.png814c1ba99c515c01c4c7efca94176b04.png发现有一个writeFile函数,再跟进一下看看9be7b4e688962f6a990cd771d1ba6e84.png发现了函数file_put_contents(),这里进行了写入文件操作,根据所含的参数进行反向分析一下,看能否找到可控点:

file_put_contents函数中的两个参数来源于writeFile($path, $content)函数中23617feabdd5fef5f49eae2be7e5c5f0.pngwriteFile这个函数中的参数又是从write()函数的两个参数$sessID、$sessData中获取到的c1f0b1d0dbe5889832bfa378e30e7400.png全局搜索一下参数write函数5964bad194d84dadb2f317d20175bd5d.png发现很开可疑的$sessionID$data,进去仔细查看一下,这里就可看出来了,这两个参数来源是来自Save()函数调用write()函数3168b239a634efcc0db10f07f375922f.png而且$sessionID是从getId()函数得到了,可以直接搜这个函数,也可以进行猜测,既然有getId函数,就一定有setId()f02daae719b8723cef0e74a4ce84ccdb.png兜兜转转又回到了官方修补的地方,再继续审计

$this->id = is_string($id) && strlen($id) === 32 && ctype_alnum($id) ? $id : md5(microtime(true) . session_create_id());

当传入的参数$id满足32位的时候,便会将该值设置为$this->id。查找一下setId被调用的地方

vendor/topthink/framework/src/think/middleware/SessionInit.php

e68f2b7e2c0fd532b4abff40a9fd8d9a.png简单分析一下,变量cookieName的值来源于getName函数688e3fbf4af1fa08ad43045e7fecfccb.png找一下属性name7784f059bab650fa002f3febff954e45.png所以cookieName的值为PHPSESSID,而$sessionIdcookie中名为PHPSESSID的值,因此是攻击者可控的,从而导致写入的文件名可控。

既然写入文件名可控,那么写入的内容是否可控那?在默认环境下,session的内容vendor/topthink/framework/src/think/session/Store.php:261的变量$data传入565b37f59a362ead13dd599288bac078.png找一下$data,发现默认为空值,默认环境是不开启session的1d1ecfa160e9d40399eb6e889feed0e5.png写入的内容就是创建session使用的内容。但是session的创建是由实际的后端业务逻辑来决定的,而默认环境下并没有创建session。因此,默认环境下无法做到任意文件写入。

参考了Is4b3lla3师傅的方法,尝试复现复现

app\controller\index.php中修改下代码,如下:

<?php namespace app\controller;use think\facade\Session;use app\BaseController;class Index extends BaseController{    public function index()    {        Session::set('name','thinkphp');        return 'lemon';        return '

:)

ThinkPHP V613载初心不改 - 你值得信赖的PHP框架

'; } public function hello($name = 'ThinkPHP6') { return 'hello,' . $name; }}

除此之外,还需要开启一下session,删除/app/middleware.php最后一行的注释即可26b3f992d38e4ee56f24007257a72d44.png

0x04:本地复现

修改好文件之后,进行抓包

注意:要删除官方修补添加的ctype_alnum函数,否则会实验不成功

e8e28ff8203d0f23bd501e57e122c9a7.png只需要构造PHPSESSID的值即可,值为string且长度为329b2f059273b3ffdc70f0eba1cca6cae5.png

\runtime\session查看一下生成的session文件887eb7f420fec65e1b71304c321d0dd6.png查看一下内容

a:1:{s:4:"name";s:8:"thinkphp";}

session的内容经过了序列化操作,只要将session的内容反序列化即可getshell,但前提是后端需要有类似的Session::Set('name',$_POST['i'])代码才可以利用。

0x05:总结:

•在环境开启Session的条件下,此漏洞经过构造可进行任意文件删除•在环境开启Session且Session中的数据可控的情况下,可以通过此操作达到构造webshell的目的

0x06:[GYCTF2020]EasyThinking

2e051799fa438d20b1ec67b860b9de91.png用御剑扫发现有源码文件,下载下来发现是Thinkphp6.04a9c7d2ad8c96aea9cfc4375c74989af.png题目提示是漏洞搜索,那就很容易联想到TP6任意文件操作漏洞,先观察一下Store.php文件

vendor/topthink/framework/src/think/session/Store.php

1efa0477a0b75cad6b7985aa0836ef13.png没有加上ctype_alnum函数,所以应该是存在这个漏洞的。

在注册时就会将session文件写入到\runtime\session中,所以从注册开始就进行修改,只要满足32位就可以6d9f8e695453fdd3fd69195952c7fc32.png写好之后,发现有搜索功能,可以传入key值,感觉应该是搜索的内容直接被写入了SESSION,就先传入一句话木马试试352114c2549595cbcd5c7f2648024738.png发现上传木马成功3f9a7d4d1fb4ede34f42898c09a97ceb.png使用蚁剑进行连接68866b74fb6995346dcec123fda9d100.png一看这种格式的就是需要绕过disable_functions,传一个phpinfo看看aa22178f696d0b7e022e8a16f062f238.png974e03ec4968f5bb06bee7c072e1cf21.png先尝试下bypass_disablefunc_via_LD_PRELOAD方法,上传下文件9f1ef145e0e206e33dd01252ac88e9e5.png这种方法不行就换另外一种常见的,恰好是这题是php7的,可以使用下bypass PHP7.0-7.3 disable_function这个exp,上传进去访问后便可获取到flag2c78efa09fbb805b2eb2b45c8c598615.png


参考博客: https://blog.csdn.net/zhangchensong168/article/details/104106869   https://paper.seebug.org/1114/   http://www.pdsdt.lovepdsdt.com/index.php/2020/05/15/thinkphp6-getshell/
20fb374e94b5d3f96f5dc7dc568cec63.png       

沙漏安全团队

奋发努力

拼搏向上

本期编辑:bosoun_ho

▇ 扫码关注我们哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值