news 2026/5/1 9:46:55

[CISCN2019 总决赛 Day1 Web4]Laravel1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[CISCN2019 总决赛 Day1 Web4]Laravel1

1.打开是一个反序列化的入口

<?php //backup in source.tar.gz namespace App\Http\Controllers; class IndexController extends Controller { public function index(\Illuminate\Http\Request $request){ $payload=$request->input("payload"); if(empty($payload)){ highlight_file(__FILE__); }else{ @unserialize($payload); } } }

首先是使用namespace导入一个命名空间,后面是他的路径 App\Http\Controllers

定义一个名为IndexController的类,它是继承Controller类的

定义一个公共的index方法,里面是Laravel路由默认调用的动作,参数\Illuminate\Http\Request $request ,使用完整命名空间\Illuminate\Http\Request,明确指定 类型。$request是Laravel封装的HTTP请求对象,用于获取用户传入的数据,如POST/GET参数,触发了会获取请求中名为payload的参数值支持POST、GET、JSON body等多种方式传参,然后赋值给$payload,然后if判断$payload是否为空,如果为空就高亮显示当前文件,否的话对他进行反序列化的操作,还提示了源码的位置source.tar.gz,下载下来分析源码

2.分析源码

他这是个Laravel框架的源码

头一次审框架的反序列化,有点看不懂,就按照wp的步骤来做一些这题

第一步:

首先先找function __destruct()方法,因为在unserialize的时候会触发他,也是链子的启动部分

phpstorm中英文状态 ctrl+shift+f搜索 一下function __destruct()

在TagAwareAdapter.php中发现了一个可以调用方法的地方,追进看看

agAwareAdapter.php文件部分代码

public function commit() { return $this->invalidateTags([]); } public function __destruct() { $this->commit(); }

首先destruct方法触发了会调用本类的commit方法,上面是commit方法,触发了会返回本类的invalidateTags方法,参数为一个数组 ,向上找,找invalidateTags方法

public function invalidateTags(array $tags) { $ok = true; $tagsByKey = []; $invalidatedTags = []; foreach ($tags as $tag) { CacheItem::validateKey($tag); $invalidatedTags[$tag] = 0; } if ($this->deferred) { $items = $this->deferred; foreach ($items as $key => $item) { if (!$this->pool->saveDeferred($item)) { unset($this->deferred[$key]); $ok = false; } }

首先将$ok设置为true,然后设置$tagsByKey为空数组,还有一个$invalidatedTags为空数组,然后循环遍历将$tags的值 遍历到$tag中,然后调用CacheItem类中的validateKey方法,里面的参数为$tag,然后下面是一个$invalidatedTags参数,他的索引值为$tag,赋值为0

if语句这个是关键代码,他首先判断本类的deferred属性是否存在,如果存在,就将他的值赋值给$items,然后使用循环遍历,给$items转换成键值对的形式,又是一个if语句,如果$this->pool对象没有saveDeferred方法,就unset销毁本类的 deferred属性,然后将$ok设置为false

第二步:

看到invalidateTags方法中的这个$this->pool->saveDeferred($item),可以$this->pool可以修改然后就能任意调用类调用saveDeferred方法

但是在他的construct方法中又要求了他带是AdapterInterface接口的

class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface

全局搜索一下saveDeferred方法,需要是AdapterInterface接口的

在PhpArrayAdapter.php文件中 找到一个saveDeferred方法,追进 看看

public function saveDeferred(CacheItemInterface $item) { if (null === $this->values) { $this->initialize(); } return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); }

一个公共的saveDeferred方法,里面参数为CacheItemInterface $item, CacheItemInterface是一个接口,然后$item是个参数,只允许这个接口的对象来填入,就相当于$item是个坑位,而这个坑位指定了只能由符合CacheItemInterface要求的对象来填入,触发了是一个if语句,需要让本类的values属性强等于为空,那么就会调用本类的initialize方法,又是一环,接下来寻找initialize方法,但是这个方法本类中没有定义,而因为trait这个关键词修饰的类中trait PhpArrayTrait

trait这个关键词是php为了解决单继承的问题而特意建立的,在java这种面向对象的语言中,继承都是单继承的,一个类只能继承一个父类,从下面这副流程图中可以看到PhpArrayAdapter这个类的继承关系

既然这里没有肯定到他的父类中寻找,到父类中搜索initialize方法

PhpArrayTrait.php

private function initialize() { if (!file_exists($this->file)) { $this->keys = $this->values = []; return; } $values = (include $this->file) ?: [[], []]; if (2 !== \count($values) || !isset($values[0], $values[1])) { $this->keys = $this->values = []; } else { list($this->keys, $this->values) = $values; } }

他是一个私有属性,触发了有一个if语句 ,判断本类的file属性是否存在这个文件,如果不存在,就将空数组赋值给本类的values属性,在赋值给本类的keys属性,然后返回为空,if语句外是一个三元运算符的简写,如果include包含$this->file文件不成功,就返回[[],[]],这里也是最后的结尾,可以进行一个文件包含

捋一下思路

首先是搜索 destruct方法,因为unserialize会触发他,

此时是在这个命名空间namespace Symfony\Component\Cache\Adapter的TagAwareAdapter.php文件下

然后destruct方法触发 会调用本类的commit方法,到了commit方法,会返回调用本类的invalidateTags()方法,然后到了本类的invalidateTags()方法中 ,首先判断本类的deferred属性不能为空,并且是个数组,因为后面会循环遍历成键值对形式,接下来就是控制$this->pool的值,来让他调用对应类中的saveDeferred方法了

此时还是在namespace Symfony\Component\Cache\Adapter命名空间中

接下来就找saveDeferred方法到PhpArrayAdapter.php文件中了,调用了saveDeferred方法触发了会有一个if语句 ,判断本类values属性是否为空,不为空,就调用本类的initialize方法,因为他本类中没有调用,而是根据trait这个关键词修饰的类中的trait PhpArrayTrait,在他的父类PhpArrayTrait中寻找 ,找到了发现他可以对本类的file属性进行一个文件包含就此到达终点,因为看wp了所以知道flag在/flag文件中,所以file的值就为/flag了

3.开始构造

那么跟着上面的思路来进行构造payload

调用链:

TagAwareAdapter :: destruct --> TagAwareAdapter :: commit --> TagAwareAdapter :: invalidateTags --> PhpArrayAdapter::saveDeferred --> PhpArrayTrait::initialize (include文件包含成功)

关键点就是$this->poo成为PhpArrayAdapter对象,然后会触发saveDeferred方法,然后转到PhpArrayTrait.php,的initialize方法的include成功执行

分析下exp的中的命名空间意思,首先第一个命名空间Symfony\Component\Cache,涉及的是CacheItem类,为了填充deferred数组,骗过类型检查, Symfony\Component\Cache\Adapter 涉及的TagAwareAdapter和PhpArrayAdapter类,他俩的命名空间要对应上

然后生成的GET传参上去,得到flag

4.知识点

这题其实链子不是特别难,跟着wp也挺好捋清楚的,主要就是命名空间的问题,好绕

PHP命名空间(namespace)是一种机制,用于将代码封装在一个逻辑单元中,从而避免不同代码段之间的命名冲突。简单来说,命名空间就像一个"容器",它可以包含类、函数和常量等元素。通过使用命名空间,我们可以为这些元素提供一个唯一的标识符,即使他们的名字相同也不会冲突

命名空间其实就像我们平时使用的绝对路径一样,只不过是在类名前面加了一个斜杠\,这就叫完全限定名称,不管你当前身处哪个命名空间,只要从\开始写,php就会从最顶层开始找

基本语法

在php中,使用namespace关键字来定义命名空间。命名空间可以嵌套,形成多级结构。

use也可以说是引用吧,就是每次如果不使用use,没使用一个类就要写他的完全限定名称,代码会变的非常 冗长,使用了之后就直接可以进行简写了

还有就是编译代码的时候起作用,告诉PHP编译器,只要看到Profile这个词就把他当成

useApp\Modules\User\Member\Profile,还可以使用as来对他进行一个改名字

implements是接口的关键词,就算是一个规范,接口定义了一组方法名,但没有具体内容。当一个类implements实现了这个接口,他就必需完成接口里所要求的所有任务

简介一下,抽空好好学习一下这个

参考链接:

https://blog.csdn.net/zhaoxilengfeng/article/details/144274431

https://www.runoob.com/php/php-namespace.html

wp:

https://blog.csdn.net/cjdgg/article/details/114873555

https://xz.aliyun.com/news/5429#toc-3

https://cn-sec.com/archives/942151.html

https://syunaht.com/p/3199619840.html

https://mixbp.github.io/2025/05/29/CISCN2019%E6%80%BB%E5%86%B3%E8%B5%9BDay1Web4-Laravel1/

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 11:23:17

照片修改工具Paint Net

链接&#xff1a;https://pan.quark.cn/s/2496f46de488Paint.NET是一个照片修改工具&#xff0c;它由华盛顿州立大学的学生开发和维护并由微软公司提供项目指导&#xff0c;早期定 位于MS Paint的免费替代软件&#xff0c;现在逐渐发展为一个功能强大且易用的的图像和照片处理软…

作者头像 李华
网站建设 2026/5/1 5:26:42

Ubuntu 24.04 安装企业微信(Deepin-Wine)避坑指南

Deepin-Wine 环境下的企业微信由于其兼容性较好&#xff0c;一直是 Linux 用户办公的首选方案。但在最新的 Ubuntu 24.04 系统上&#xff0c;由于安全机制更新和依赖库版本差异&#xff0c;直接安装往往会报错。本文总结了一套完整的避坑安装流程。 一、 初始化仓库环境 首先…

作者头像 李华
网站建设 2026/4/26 23:44:44

[C语言]整理经常需要查到的三张表-ASCII码表,运算符优先级表,数据类型所占用大小表与记忆方法

文章目录ASCII码列表记忆方法运算符的优先级表记忆方法数据类型所占用大小表记忆方法ASCII码列表 十进制十六进制字符/控制说明重点00x00NUL\0 字符串结束符*70x07BEL\a 响铃80x08BS\b 退格90x09HT\t 制表100x0ALF\n 换行130x0DCR\r 回车320x20(space)空格*33–470x21–0x2F!&…

作者头像 李华
网站建设 2026/5/1 6:56:06

Altium Designer电路图一文说清:工程结构与组织

Altium Designer电路图工程结构实战指南&#xff1a;从零搭建可协作的模块化设计体系 你有没有遇到过这样的场景&#xff1f; 一张密密麻麻、布满走线的原理图&#xff0c;放大十倍都找不到某个信号的源头&#xff1b;团队成员同时修改同一个文件&#xff0c;结果版本对不上&a…

作者头像 李华
网站建设 2026/5/1 6:57:01

LC.98 | 验证二叉搜索树 | 树 | 中序遍历单调性

输入&#xff1a; 二叉树根节点 root。 要求&#xff1a; 判断该树是否为有效二叉搜索树&#xff08;BST&#xff09;。 任意节点&#xff1a;左子树所有值 严格小于 它&#xff0c;右子树所有值 严格大于 它。左右子树本身也必须是 BST。 输出&#xff1a; true / false。思路…

作者头像 李华
网站建设 2026/5/1 5:46:56

Java计算机毕设之基于springboot的篮球管理系统的设计与实现基于springboot的篮球场地管理系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华