环境搭建
直接用composer安装
D:\tools\xampp\htdocs\thinkphp>php composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
D:\tools\xampp\htdocs\thinkphp>php composer create-project topthink/think think6
下下来是最新的6.0.5版本,在comoposer.json改成有漏洞的版本然后update
D:\tools\xampp\htdocs\thinkphp\think6>php ../composer update
打开session
修改一下控制器
漏洞利用
其实就是session名没有校验,直接拼接到文件名中导致的跨目录写文件
漏洞分析
配vscode+xdebug调试环境整了好久,最后用了这个配置才行(本地调试)
在index.php的最后下断点
调用中间件的end函数
SessionInit中间件调用session的save函数
但是session其实没有save函数,触发__call魔术方法,调用驱动的save函数
一直追溯到Store类
Store->save中调用了write,sessionId通过getId获取,data是类属性
跟进write看看是怎么做的,调用了getFilename,然后writeFile写文件
很明显就是这里实现了路径穿越,还帮忙建目录了
很直接的调用了file_put_contents
然后再来看看路径(sessionId)和数据(data)是怎么传进来的,首先setId方法会对$this->id赋值,注意sessionId需要长度为32,不然会被md5处理
这次从index.php的开头下断点,进入到runWithRequest,这里调用中间件的pipeline,类似servlet的filter一样,链式调用每个中间件的handle函数
SessionInit的handle函数中,从cookie里取出了我们的PHPSESSID值,调用了上面的Store类中的setId方法
然后data就是在控制器中调用session("demo",$_GET['c']);
的时候,进入Store类的set方法,即$this->data[$name] = $value;
Arr::set的第一个参数,传的是实参