NepCTF 2025
Web
EasyGooGooVVVY
Groovy 表达式注入
"".class.forName("java.lang.Runtime").getRuntime().exec("env").textFlag 就在环境变量中。
RevengeGooGooVVVY
"".class.forName("java.lang.Runtime").getRuntime().exec("env").textFlag 就在环境变量中。
JavaSeri
工具一把梭(x)
https://github.com/SummerSec/ShiroAttack2

Safe_bank
这道题在比赛中没做出来,只通过 从源码看JsonPickle反序列化利用与绕WAF 试出了些黑名单还有源代码,赛后根据 LamentXU 师傅 的 WP 复现了下,通过 list.clear() 删掉黑名单这方法确实妙哇。
通过 关于我们 发现技术细节。
随机注册并登录,通过对 Cookies 进行 base64 解码发现内容如下。
通过修改 user 为 admin 尝试。

得到路径 /vault ,通过管理员账号 Cookie 访问发现是假的 flag。

在文章 从源码看JsonPickle反序列化利用与绕WAF 中存在一些利用链还有手工测试,初步通过回显判断发现部分黑名单内容如下。
注意:部分利用链存在 JSON 格式问题,可以通过 https://www.json.cn/ 来校验。
通过其中一个 Payload 如下成功读取目录内容。
通过另外一个 Payload 如下成功发现 /flag 为空,说明 flag 在 /readflag 中,但 re 在黑名单中。
通过 Payload 如下能够获取源代码,代码整理就交给 AI 了。
之后,在 LamentXU 师傅 这了解到可以把黑名单给全扬了。
在 list 对象中,存在 clear() 方法,能够把整个列表内容都删了,详细如下。
构造 Payload 如下。
此时就已经成功把黑名单全删了,通过 Payload 如下即可得到 flag。
FakeXSS
赛后根据 LamentXU 师傅 的 WP 复现。
将下载的客户端改为 zip 并解压可以发现 $PLUGINSDIR\app-64.7z\LICENSE.electron.txt ,可推测客户端采用的是 Electron 框架,通过 WinAsar 解包后得到 main.js 如下。
通过 Web 中注册账号,登录账号,存在个人资料修改页面,通过 BP 抓包发现上传头像时泄露了腾讯云 COS 的 KEY。
通过 Web 页面中的 JavaScript 代码可知存储桶 Bucket 和 Region。
这里就直接用师傅搓的脚本吧,通过 pip install -U cos-python-sdk-v5 -i https://mirrors.aliyun.com/pypi/simple/ 安装 Python SDK。
可以发现存在两个文件。
在登录页面接口中,存在一个 <iframe> 标签,并允许直接将用户的输入原封不动进行输出,可以结合设置登录页面背景接口来发起攻击。由于 Bot 并不会携带秘密(也就是 Cookie),因此需要通过 document.cookie 为 Bot 写入一个账号 admin 的 Cookie 进去,然后利用 window.electronAPI.curl (前提是 Bot 使用提供的 Electron 客户端访问)拿出 flag 内容并通过保存个人简介接口将 flag 写入到账号 admin 的简介中。
fetch()方法是不携带 Cookie 的,所以最好不在 headers 里面些 Cookie。
具体 JavaScript 代码如下。
Payload 如下。
上传后的结果如下。
设置登录背景图请求响应包如下。(若出现失败则可以多尝试几次,因为 https://ctf.mudongmudong.com/x 其实是无法访问的,也不知道为什么会判断为真)
访问 /api/bot ,请求响应包如下。
访问 /api/user ,得到 flag。(如果没有的话尝试多触发几次 /api/bot)
我难道不是 SQL 注入天才吗
Hint: 后端数据库是
clickhouse,黑名单字符串如下preg_match('/select.*from|\(|or|and|union|except/is',$id)。
本题通过 NepCTF QQ 群的师傅们所发的 Exp 进行复现。
通过传入 1 、2 、3 等等可以输出 id 为相应值的结果。

通过 BP 传入 id 发现输出了所有用户数据。

通过 BP 传入 name 发现输出了报错。

通过 AI 可以发现得到这是典型 ClickHouse 错误信息,并且可以得到服务端中的注入点语句如下。
通过 INTERSECT 和 LIKE 子句实现盲注,INTERSECT 子句实现计算两个查询的交集,但需要两个查询语句的列数量、类型和顺序一致,返回结果仅包括两个查询中重复的记录。
来解释下 Exp 中的 Payload。
拼下后的 SQL 语句如下。
在 ClickHouse 中,可以将 FROM 放在 SELECT 子句之前,因此可以通过这种方式绕过黑名单中的 select.*from 。另外,JOIN 和 ARRAY JOIN 子句也可以用于扩展 FROM 子句功能。
INTERSECT 子句的前一半内容如下,返回的内容是所有用户的 ID、Name、Email 和 Age 。
后一半的内容转换成熟悉的样子如下所示。
该依据同样跟前一半一样,获取了用户的 ID、Name、Email 和 Age,虽然 FROM 是系统中所有数据库的信息,但是 JOIN 子句访问了用户表 users ,将 ON 条件当作 IF 判断来用,若 ON 条件为真则同样输出所有用户的 ID、Name、Email 和 Age 。
此时,与 INTERSECT 子句的前一半内容取交集输出结果。因此,可以通过 ON 条件盲注出所想要的数据。具体原理就是上面这样,感谢群里师傅发的 Exp !
由于 Exp 缺少了对于内存超限(如下图所示)时候的重试,以及在爆破 Flag 的时候依旧采用 BFS 导致爆破效率较低,故使用 AI 进行了一些优化~


优化后 Exp 如下,请自行根据所爆破的字段修改 FLAG_MODE 的值。
通过运行 python test2.py "NepCTF{" 稍许片刻(可能是片刻)即可得到 flag ,若出现多次内存超限,可尝试歇几分钟再来猛攻。

Misc
NepBotEvent
根据题目描述可知为 Linux 系统环境,需结合 Linux input_event 格式解密,用 AI 糊一个脚本。
https://github.com/albert-gee/linux-keylogger
Flag 就是 NepCTF{NepCTF-20250725-114514}
SpeedMino
游戏每次得分整数增加时都会对存储在 youwillget 数组中的密文调用一次 calcData();当调用次数达到 2600 次时,这个数组就变成了真正的 flag。但在开始游戏时还会先用 55 个空格(从剪贴板读取后补足)对 RC 4 进行一次初始化,所以总的调用顺序是:先对 55 个空格调用一次 calcData(),然后对 youwillget 调用 2600 次。
客服小美
流量为 CS 流量,通过流量包可知 IP 和端口 192.168.27.132:12580
通过 Volatility 查看版本可知为 Win10x64_19041 。
通过查询进程发现可疑进程 s?2025t??G??? ,PID 为 6492。
导出可疑进程内存数据。
https://github.com/DidierStevens/DidierStevensSuite/blob/master/cs-parse-traffic.py
通过 cs-parse-traffic.py 尝试提取加密数据流量。
https://github.com/DidierStevens/DidierStevensSuite/blob/master/cs-extract-key.py
通过 cs-extract-key.py 尝试提取密钥。
尝试通过提取的密钥进行解密。
可知用户名为 JohnDoe ,并且获得的 secret 为 5c1eb2c4-0b85-491f-8d50-4e965b9d8a43 。
拼接得到 Flag NepCTF{JohnDoe_192.168.27.132:12580_5c1eb2c4-0b85-491f-8d50-4e965b9d8a43} 。
Crypto
Nepsign
题目在 SM3 上实现了一个单次签名,但服务器允许对任意消息进行多次请求签名。通过找出链中每一步所需的链元,最终拼出对目标消息的签名。
ICS
薯饼的 PLC
打开附件发现全是 TCP ,通过 TCP Payload 发现存在 S7COMM 流量,查看端口发现 PLC 端口为 11102 ,主机端口为 49810 。
通过编辑-首选项-Protocols-TPKT 中的 TPKT TCP port (s) 中加上 11102 和 49810 。
通过 s7comm 筛选可以发现存在请求包中的 DB number 有 1002 和 1003 。
通过 s7comm.param.item.db == 1002 筛选可以发现存在请求包中所请求的地址均为连续。
通过脚本提取 DB number 为 1002 的请求包的响应包,从响应包中获取 Data 数据。由于通过跟踪 TCP 流发现均在一个 TCP 流中,并且 DB number 为请求包中倒数第五第六个字节,Data 为响应包中倒数第二个字节,因此直接将原始数据丢进去还原出数据。( hex_blob 有所省略)
将 ASCII 表示的结果去掉零和一外其他字符转换成字符串即可得到 Flag。
Last updated