type
status
date
slug
summary
tags
category
icon
password
感觉排序不是很友好..因为难度不是相对递增的
建议顺序
- web254-258、web260、web262-web266、web259、web261、web275-276
- 然后 web277-278 是 Python 反序列化,不过比较简单
- 最后是 web267-web274 都是框架的反序列化漏洞,分析起来会麻烦些,web267-270 是 Yii 的 CVE 和 绕过,web271-273 是 Laravel 5.7 和 5.8 的反序列化,web274是 thinkphp5.1 的反序列化
框架的反序列化有空会(咕咕预订…)额外写文章复现,23333
web254 PHP类简单认识
poc
web255 简单逻辑
nginx/1.16.1 PHP/7.3.11
分析:
即要满足
- 类成员
isVip
为true
- 传入的
username
和 类成员username
相等
- 传入的
password
和 类成员password
相等
username 和 password 已知,反序列化修改
isVip
即可poc
web256 简单逻辑
nginx/1.16.1 PHP/7.3.11
分析:
即要满足
- 类成员
isVip
为 true
- 传入的
username
和 类成员username
相等
- 传入的
password
和 类成员password
相等
- 类的 username 和 password 不等(原来是相等的)
因为通过反序列化修改原有数据即可
poc
web257 简单POP链
nginx/1.16.1 PHP/7.3.11
分析:
触发 backDoor 即可
poc
web258 正则
PHP/5.6.40 正则绕过
分析:
绕过正则
/[oc]:\d+:/i
, 其实就是 C:数字
或 O:数字
不连续,这里只需让 O:11
不连续即可,比如 O:+11
poc
图中
%2b
为 +
的 url编码web259 SSRF + CRLF + SoapClient
PHP/7.3.11 SSRF CRLF SoapClient
index.php
flag.php (大概如下
分析:
不就 XFF伪造?
估计给的代码是不完整的,还真实 IP 判断,估计大概是这样的
搜了一波,奇怪的知识增加了,除了XFF,本题还用到 SSRF(SoapClient)+CRLF组合拳,毕竟我们的 index.php 还有用到呢
需要利用 SSRF 访问 flag.php 并构造 XFF 和 POST 数据,SSRF漏洞在哪呢?
SoapClient类
__call
魔术方法__call() 魔术方法:当调用一个类不存在的方法时候会触发这个魔术方法当调用 SoapClient 类的 __call() 魔术方法的时候,会发送一个 POST 请求,请求的参数由着 SoapClient 类的一些参数决定。
因此,当我们运行
index.php
的 $vip->getFlag();
方法时,会因 SoapClient
不存在 getFlag
方法而调用 __call()
魔术方法,进而发送一个 POST 请求poc
这里注意下,包含特殊字符转义的,比如
\r\n
要用双引号 "
单引号保持原来的语义的。warning 没关系
web260 简单正则
PHP/5.6.40
poc
(原) web261 SSRF Redis
PHP/7.3.11
index.php
分析:
- 题目提示:打 Redis,默认端口为 6379
原来的 web261,不知为啥换成了下面这个。
原本的解题思路大概是在 web259 的基础上,构造 POST包去打 redis
web261 PHP特性
nginx/1.18.0 PHP/7.4.16
分析
__wakeup()
unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
因这里写着
username
和 password
必须为非空,否则会退出,所以可以考虑要绕过这里参考 CVE-2016-7124
- 影响范围
PHP5 < 5.6.25
PHP7 < 7.0.10
- 漏洞原理
当反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过 __wakeup 函数的执行。
但是题目是 PHP 7.4.2 明显不满足要求,
然后guguru了一下比较显眼的
__unserialize
魔术方法,因为没见过https://www.php.net/manual/en/language.oop5.magic.php#object.unserialize
发现有趣的东西,官方文档是这样介绍的
就当同时存在
__wakeup
和 __unserialize
魔术方法时,只会调用 __unserialize
魔术方法。仔细观察析构方法,是个弱比较
$this->code==0x36d
然后
0x36d
的十进制是 877
,写个小实验也就是说弱比较
$code
变量前面是 877
就好了,不管后面加了啥字符串,就可以让 $code == 0x36d
成立了。构造 POC
会生成
877.php
然后 cat /flag_is_here
即可题外
因为 PHP 底层是用 C语言写的,原本想着用
\0
作为字符串截断,这样不会拼接 $passwod
字段,然后发现,如果第一个参数有 \0
, file_put_contents
会报错。然后
__invoke
和 __sleep
在这里的用处不太清楚。。web262 字符逃逸
PHP/5.6.40 字符逃逸
index.php
看注释发现 message.php
第一种做法
poc
第二种做法
因有一个正则替换,注意是序列化后再替换,且替换每次内容长度增加1,假如输入
t=fuck"
我们输入的
"
刚刚好可以发前面闭合,也就是说,我们每输入一个 fuck
,我们可控的内容就多出 1
个字符。我们目的构造
$token="admin"
序列化长这样即
s:5:"token";s:5:"admin";
加上闭合
长度为
27
也就是我们需要输入
27 个 fuck
poc
web263 session伪造
PHP/7.3.11 session伪造
通过
/www.zip
扫描到源码,这里目录扫描全是 200,建议使用可以看到返回包大小的扫描器,或者有 404 页面识别的扫描器,比如 dirmap日常吐槽 fortify,咋啥也扫不出来 (x
seay 发现 file_put_contents 输入可控
利用前提:
利用点是
session.serialize_handler
与 php.ini 的配置不同引起的反序列化,至于为什么不同,如果相同的也就没必要加上这句设置了(ini_set('session.serialize_handler', 'php');
),毕竟是默认配置对吧目标:
file_put_contents
可控点在inc/inc.php
在User
类,可以通过反序列化触发__destruct
思路:
- 首先访问两次首页,抓包可以看到
Cookie
limit
参数,构造 exp ,使得我们的反序列化数据写入 session 文件(通过$_SESSION['limit']=base64_decode($_COOKIE['limit']);
写入,这是PHP session 机制,可参考 此链接)
- 因
inc/inc.php
存在ini_set('session.serialize_handler', 'php');
和session_start();
,只要访问即会获取之前写入的session
数据,然后check.php
包含inc/inc.php
,即会触发User类
的__destruct方法
,从而把恶意数据通过file_put_contents
写入名为log-$this.username
,内容为$this.password
的文件。
poc
这里加
'|'
是因为 session.serialize_handler
使用 php引擎
,session 关联数组的 key
和 value
是通过 '|'
区分的, value
是需要被反序列化的部分。然后默认不是用 php 引擎,所以…. 所以写入是正常字符串,在 inc/inc.php
这读取语义又不一样了。随便请求一下 check.php
image.png
注意是
log-tari.php
!web264 字符逃逸
PHP/5.6.40 字符逃逸
看注释发现 message.php
看注释发现 message.php
一开始没看出和 web262 有啥区别,仔细看了一下发现,反序列化时使用了 session 而不是直接通过 Cookie 接收
做法和 web262中第二种做法一样,虽然不是通过 Cookie 接收,也别忘了了 Cookie 的 msg 字段附加个值,不然不满足
先请求
index.php
(这里 poc 不明白怎么构造看一下 web262 第二种做法)因为 PHP 的
session
是通过 Cookie 里的 PHPSESSID
获取的(不清除参考 web263 session 伪造),所以要记录下来,然后在 message.php
里带上。然后请求一下
message.php
, 别忘了 Cookie
部分web265 变量引用
PHP/5.6.40 变量引用
token 会变,让 password 成为 token 的引用就好了
poc
web266 类和方法不区分大小写
PHP/7.3.11 PHP特性 类和方法不区分大小写
拦截点:序列化数据不能包括 ctfshow,
PHP特性:函数名和类名不区分大小写,变量名区分,例如
poc
web267 Yii 框架 CVE
PHP/7.3.11 框架审计 CVE-2020-15148 Yii登录前
弱密码 admin/admin 登录
about 页面有个
<!--?view-source -->
提示可以通过
index.php?r=site%2Fabout&view-source
查看提示这是 Yii 的路由规则,传送门 ,咋知道的 Yii?通过 burp 抓包记录看到很多 yii.js php 搜了下 (
框架反序列化漏洞,网上应该可以搜到,一个不错的复现和挖掘文章,传送门
有空会(咕咕预订…)额外写文章复现 (
poc
web268 Yii 框架 CVE 补丁绕过 1
PHP/7.3.11 框架审计 CVE-2020-15148 Yii登录前 补丁绕过
思路类似 web267,估计是打过补丁版本
有空会(咕咕预订…)额外写文章复现 (
poc1
web269 Yii 框架 CVE 补丁绕过 2
PHP/7.3.11 框架审计 CVE-2020-15148 Yii登录前 补丁绕过
思路类似 web267,估计是打过补丁版本
有空会(咕咕预订…)额外写文章复现 (
poc2
web270 Yii 框架 CVE 补丁绕过 3
PHP/7.3.11 框架审计 CVE-2020-15148 Yii登录前 补丁绕过
思路类似 web267,估计是打过补丁版本
有空会(咕咕预订…)额外写文章复现 (
poc3
web271 Laravel 5.7 框架 CVE
PHP/7.1.26 框架审计 CVE-2019-9081 Laravel5.7登录前
poc
因代码里是通过 POST 的
data
接收,所以这里是用 data
POST 过去web272 Laravel 5.8 框架 CVE
PHP/7.1.26 框架审计 Laravel5.8登录前
有空会(咕咕预订…)额外写文章复现 (
poc
其实还有挺多链的
https://www.anquanke.com/post/id/189718
web273 和web273一样
PHP/7.1.32 框架审计 Laravel5.8登录前
emm,说实话除了PHP版本细微差别,还不知道有啥区别,竟然 poc 一毛一样
有空会(咕咕预订…)额外写文章复现 (
web274 thinkphp5.1
nginx/1.16.1 PHP/7.3.11 框架审计 thinkphp5.1登录前
thinkphp 5.1反序列化漏洞
参考文章:https://xz.aliyun.com/t/6619
数据接收方式
有空会(咕咕预订…)额外写文章复现 (
poc
web275 命令执行拼接
nginx/1.16.1 PHP/7.3.11
分析:
看似花里胡哨,其实
__destruct
里的 system
可直接拼接,也就是设法让 $this->evilfile
置为 true
,然后拼接命令即可。题外:第一眼看去这一读一写,长的这么想被我条件竞争的样子 (
web276 phar反序列化 条件竞争
nginx/1.16.1 PHP/7.3.11 phar反序列化 条件竞争
分析:
emm,在上题基础上新增了个判断
$this->admin
然后想着,构造一下序列化不就行了嘛,然后发现没有反序列化函数。。看了下发现可以通过
file_put_contents
写 phar文件,然后题目中 file_put_contents
第一个参数可控,那么我们可以使用 phar://
协议,通过 $content
传入 phar 数据,这样在 PHP 通过 phar://
协议解析数据时,会将 meta-data
部分进行反序列化。不过题目会删除文件,所以需要在删除文件前执行文件进行以上操作,因此要用到条件竞争,即生成了 phar 文件,在极短时间内文件是存在的,因为执行到
unlink
函数前还有一个 copy
文件操作,磁盘 io 是需要一定时间的。只要我们不断在写入 phar 文件,那么这个文件就可以断断续续访问到~poc
phar构造如下,会在当前目录生成
evil.phar
文件条件竞争,py3脚本
base64解码一下即可
题外
除了 file_put_contents 外,会把 phar 反序列化的函数还有:
受影响的函数列表 | ㅤ | ㅤ | ㅤ |
filename | filectime (获取文件的inode更改时间) | file_exists | file_get_contents |
file_put_contents | file | filegroup (获取文件的组名) | fopen |
fileinode (获取文件inode) | filemtime (获取文件的修改时间) | fileowner | fileperms (获取文件权限) |
is_dir | is_executable | is_file | is_link (判断文件名是否为符号链接) |
is_readable | is_writable | is_writeable | parse_ini_file (解析配置文件) |
copy | unlink | stat (获取文件相关信息) | readfile (输入文件内容) |
表格参考自:https://v0w.top/2020/03/12/phar-unsearise/
web277 python 反序列化
Werkzeug/1.0.1 Python/3.7.9 pickle 反序列化
Python反序列化,之前有过一些研究,晚点把Python反序列化基础链接更新上来~
尝试了很多,发现是无回显的,需要反弹shell
poc
先在服务器上监听
运行脚本
回到服务器上
cat
一下即可web278 python 反序列化 简单绕过
Werkzeug/1.0.1 Python/3.7.9 pickle 反序列化
和 web277 差不多,只不过过滤了 system,换个函数即可
poc
一些参考的题解