Laravel反序列化学习
前言
最近在刷buuoj发现了Laravel框架的题目,web菜鸡开始按照网上的方法开始学习挖掘pop链
0x 01 [CISCN2019 总决赛 Day1 Web4]Laravel1
- 第一种pop链
- 题目打开给了提示,需要审计Laravel源码,找反序列化链
- 源代码拖入phpstrom,先全局搜索__destruct函数,找到这个类
进入TagAwareAdapter.php
跟进魔术方法
跟进commit->跟进invalidateTags
在该类下ctrl+f搜一下$this->pool进行查看
可以看到$this->pool是可控的,但是需要实现AdapterInterface接口,那么如果我们找到某个类,它既实现了AdapterInterface这个接口,同时又有saveDeferred方法(或者没有而有__call方法),而且满足一定条件能文件读取或命令执行即可。
全局搜索saveDeferred方法,然后首先跟据有无AdapterInterface接口进行排除
发现在PhpArrayAdapter.php
跟进initialize方法,来到PhpArrayTrait类下
存在文件包含点,至此分析结束
- 构造poc,首先在PhpArrayAdapter类下的saveDeferred方法的入口参数item是实现了CacheItemInterface的,也就是item应该为实现了该接口的类的实例
在头文件的定义出发现使用use Symfony\Component\Cache\CacheItem;
构造如下
1 | namespace Symfony\Component\Cache{ |
令include下的文件为/flag
1 | namespace Symfony\Component\Cache\Adapter{ |
回到触发点,其中item为deferred这个数组的值,并且这里的item需要实现CacheItemInterface接口,也就是item为CacheItem类的实例,而pool就是phparrayadapter的实例
得到:
1 | class TagAwareAdapter{ |
组合在一起得
1 |
|
- 第二种pop链:
进入ProxyAdapter.php中,跟进doSave方法
pop链图如下
poc如下:
1 | <?php |
tips:
选中一个类文件,右键,选择diagrams->show diagrams,可以查看查看类的继承关系
参考资料:
0x 02 [护网杯 2018]easy_laravel
题目环境说明:buuoj 上的复现,和原版的题目不是完全一样。原题使用的是 nginx + mysql的配置 而 buuoj 上的是 apache + sqlite配置环境
- 前置知识
composer
这是在 PHP5.3 以上的一个依赖管理工具。感觉和 docker 很像,docker-compose 根据 docker-compose.yml
中配置的服务和镜像,生成虚拟机。PHP 中的 composer 则是根据 composer.json
加载配置的 php package
配置更新源,Composer 镜像站
1 | composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ |
升级
1 | composer self-update 或者 composer update --lock |
诊断命令
1 | composer diagnose |
清除缓存
1 | composer clear |
根据 composer.json
安装 php package
1 | composer install |
Laravel中间件(Middleware)
在Laravel中起着过滤进入应用的HTTP请求对象(Request)和完善离开应用的HTTP响应对象(Reponse)的作用, 而且可以通过应用多个中间件来层层过滤请求、逐步完善相应。
- 解题过程
- 打开后网页源码提示github上有源码。但是做题的时候源码已经没了,所以从题目环境中拖下来审计
首先查看数据库文件,database/factories/ModelFactory.php中记录User的信息,发现用户名和email已知,密码是随机生成且进过经过 bcrypt
处理的,注入出来是没办法解开
路由信息在routes/web.php中,对应的Controller在app/Http/Controllers/下对应的PHP文件。Upload和Flag只有admin用户可以访问。
- 不难发现在
App\Http\Controllers
中的NoteController
存在注入
由于数据库是sqlite,所以不能使用#,根据数据表可以有五个字段,进行联合注入,查看回显位
1 | admin' union select 1,2,3,4,5-- |
得到回显位是第二位,由于admin用户的密码进过bcrypt
处理的,注入出来是没办法解开,根据存在的password_resets尝试注入出admin用户重置的token
先发送重置邮件,生成token插入数据库中
然后进行SQL注入查询。payload如下:
1 | admin'union select 1,token,3,4,5 from password_resets where email='admin@qvq.im'; |
然后访问 http://url/password/reset/token 即可重置密码
然后改密码即可登入管理员,但是flag下面是no flag
题目提示是blade过期的问题,根据资料发现Blade 是 laravel 提供的一个简单强大的模板引擎。它不像其他流行的 PHP 模板引擎那样限制你在视图中使用原生的 PHP 代码,事实上它就是把 Blade 视图编译成原生的 PHP 代码并缓存起来。缓存会在 Blade 视图改变时而改变,这意味着 Blade 并没有给你的应用添加编译的负担。
那下一目标就是把缓存的文件删除掉。
blade 缓存位置是 storage/framework/views
apache 的默认目录是 /var/www/html/
在一起就是 /var/www/html/storage/framework/views
结合上面的 sha1 就是 /var/www/html/storage/framework/views/73eb5933be1eb2293500f4a74b45284fd453f0bb.php
- 接来下是寻找pop链删除文件,这里发现
composer.json
中提供了大量组件,我们安装一下,然后全局搜索unlink()
在vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php
中发现如下代码:
然后在 UploadController 中的 check() 函数中发现调用了 file_exists() 函数,并且两个参数都可控,可以触发phar反序列化
上传后的文件路径也可以得知
构造exp:
1 |
|
将生成的文件上传后,点击check抓包,添加path参数phar:///var/www/html/storage/app/public/1.gif
提交以后模板文件就会被删除,我们访问/flag就会出现刷新以后的页面,即flag了
另外我在先知上看到有一个pop链可以rce,https://xz.aliyun.com/t/2901,有时间补一下,先占个坑
参考资料:
https://www.cnblogs.com/peri0d/p/12512343.html
https://tiaonmmn.github.io/2019/09/04/BUUOJ%E5%88%B7%E9%A2%98-Web-easy-laravel/#more
0x 03 [CISCN2019 总决赛 Day2 Web2]Laravel File Manager
参考:https://blog.szfszf.top/article/39/#getshell-or-blade 以后慢慢填坑QAQ