Laravel 相关几道题目复现

Laravel 相关几道题目复现

这几天在学习各个php框架,在粗略看了laravel文档之后,找了几道laravel的题做做,以此更深的了解这个框架。

2018护网杯easy_laravel

因为有源码,可以发现laravel 版本 5.3.*

查看router和controller,使用了内置auth功能实现登录注册重置等功能,/flag路由要求admin登录

在AdminMiddleware中间件实现邮箱为admin@qvq.im的用户即为admin

注入

源码审计,赤裸裸的注入,也没过滤啥的。NoteController中username可以注入。

在/database/migrations 可以看到创建时表结构,/database/factories 看到admin用户插入时密码bcrypt加密过的。


laravel内置重置密码在Illuminate\Auth\Passwords中实现,重置密码需要填写邮箱,并向邮箱发送一个重置链接。

重置链接中的token存到数据库中

laravel在5.4以后都是将token加密存储的,而之前是明文存储,所以我们就可以注入出token重置admin密码。
如下,当然你之前得访问/password/reset先重置admin密码数据库中才有token。

拿到token,访问/password/reset/[token]就可以重置admin密码了。

phar反序列化

登陆了admin之后发现访问/flag出现no_flag字样,审计出题人写得上传Controller。

检查文件后缀和图片头

另外还有个check方法,使用file_exists检查上传的文件是否存在,输入filename完全可控,明显可以进行phar反序列化操作了。

Getshell Or Blade

已经有了反序列化点,现在可以构造POP链Getshell。而这道题出题者本意是想用户通过反序列化找到pop链删除过期的blade模板,从而getshell。

Blade

删除的POP链很容易找到,在namespace Symfony\Component\Process\Pipes 中WindowsPipes类有个removeFIles

__destruct直接调用它

所以payload很简单,(其中编译过的模板都存放在/storage/framework/views/中,名字为原模板绝对路径的sha1值)

也有师傅利用Swift_ByteStream_TemporaryFileByteStream类 也是很简洁的思路

GetShell

Illuminate\Broadcasting PendingBroadcast类的__destruct入手,其中event和events都是完全可控的。

然后全局搜索fire函数,没有找到合适的函数。全局搜索__callFaker中找到Generator类的__call

它会调用format函数,其中format会调用call_user_func_array,且第一个参数,由下面的getFormatter返回,简单审计发现两个参数都可控。这样POP链就构造好了。

 

CISCN 2019 决赛 Laravel1

给了源码,直接就是反序列化找POP链。

有意思的是,作者注释掉了以往两个POP链的初始点,旨在希望用户新找一个POP链(虽然,大部分人都是从日志或者session里看到payload的)。


这个是利用Symfony组件中的gaget,laravel5.7都是默认安装方法自带。

首先找__destruct ,位于Symfony\Component\Cache\Adapter

依次向下进入invalidateTags函数。

经过一番简单的操作进入saveDeferred函数,本类的该函数没有啥危害,搜索找到ProxyAdapter类的saveDeferred函数

跟进,可以看到下面有个动态函数调用,$this->setInnerItem可控,函数的输入$item即为上面类的输入也可控,system函数正好可以有两个参数。

其中的 $item 本来输入是CacheItemInterface的对象,但是在里面强制转换成了array,也就有了类似"\0*\0expiry"的键值,其实就是该类的protected属性。

那么这么一顺,POP链差不多就出来了,细节看payload就可以了。

CISCN 2019 决赛 Laravel File Manager

还是有代码的审计,welcome界面显示Only localhost can access it!,其实和这没啥关系。

app中自己实现的GetPairController可以向用户返回椭圆曲线加密的公钥并吧私钥存入session。

题目名叫Laravel File Manager,关键点还是在于filemanger组件,在FileManger.php中,download操作有问题,首先它没有使用laravel自带的文件系统Storage进行操作文件,而且在过滤filename时也没有用,最后还是直接用了$path

对比一下原项目咋写的

当然现在还不能简单的读flag,题作者还写了一个参数加密中间件位于app/Http/Middleware/Encryption/EncryptionBody.php

代码大致是根据ECDH密钥协商算法和客户端得到共同key,用AES对POST所有响应和请求数据进行加密和解密。所以我们随便带上一个X-Client-Key发送一个POST数据获得X-Server-Key,再本地生成公私钥对与服务器端公钥生成协商好的AES的key。
最后向/file-manager/download POST加密后的{"disk": "public", "path":"../../../../../../../../flag.txt"} 就行

一开始以为作者自己写得Controller有啥用,原来并没有啥用,按照代码原理协商密钥就行了。
这里还有个小点,encrypt和decrypt居然不是互逆的Orz。本地按照encrypt的算法正常加密,decrypt是解不开的。decrypt最后的检查加密数据是否被篡改检查的是hash_hmac('sha256', 解密后原始数据, $key, true),而encrypt加密返回的$hmac确是hash_hmac('sha256', 加密过的数据, $key, true);

这两个肯定是不同的,所以写payload的时候要注意一下。

One thought on “Laravel 相关几道题目复现

发表评论

电子邮件地址不会被公开。 必填项已用*标注