unictf 的wp中译中,包含名词解释和代码批注,全手打无粘贴(链接和回显除外)
intrasight
https://www.ctfplus.cn/problem-detail/2019277782340603904/description
打开界面判断是ssrf,预览80端口请求成功,预览https://111222.free.beeceptor.com也请求成功,说明可以出网
出网可以主动访问公网ip和域名,可以直接nc反弹shell到自己的公网vps(云服务器),远程下载利用脚本(靶机支持wget,cuel,certutil等下载命令),dnslog外带信息
不出网只能访问本地和内网,只能本地提权,读取和写入本地文件,内网横向移动(有跳板,很像ssrf)。本地编译exp,内网端口扫描
但是看题目应该是本地读取文件,不需要用到外网,还看到了允许ws协议,提示有internal-services: [public_web, admin_panel, w*_*e*1*r]
然后,然后就不会做了,看wp
还能用到ssti
openapi.json也叫swagger.json,是遵循OpenAPI规范的JSON格式文件
所以可以直接访问http://127.0.0.1:8001/openapi.json
返回
1 | { |
依次访问
/status
1 | { |
/api/debug/config
1 | { |
/redirect_ws
1 | { |
原来w*_*e*1*r是ws_render的意思
ws特性
一次握手,建立长连接,可以篡改
Sec-WebSocket-Key,Sec-WebSocket-version的握手参数
还有fuzz的不仅是端口,还有路径,只访问端口还是会返回404
访问 ws://127.0.0.1:9000/ws?token=125f8fa0bf994f4abf4c208e1c94be75
1 | { |
看了wp说这才是ssrf的真正利用点
要post请求
1 | POST /fetch?url=ws://127.0.0.1:9000/ws?token=f8c9668761ae4716839b60c98b898323 HTTP/1.1 |
返回
1 | HTTP/1.1 200 OK |
到这一步复现失败了,刷新redirect_us发现token值一直在刷新…
然后一直到不了wp展示的结果:
1 | { |
为什么啊为什么
继续往下
在template处传payload即可
1 | payload = "{{ self.__init__.__globals__.__builtins__.__import__('os').popen('cat /flag').read() }}" |
GlyphWeaver
看前端源码是jinja2,怀疑是ssti,结果{{7*7}}被拦截,好不容易用全角花括号绕过,结果回显原文·,怀疑不是ssti,寄,看wp
1 | Online namecard generator for bilingual teams. Supports typography cleanup (CJK-friendly). |
CJK-friendly暗示服务端会针对中日韩文字和符号的使用习惯做兼容处理
NFKC:兼容合成型规范化
不用记复杂编码,只记和 SSTI 相关的符号 / 数字 / 字母转换即可,这是题目提示里重点强调的:
| 输入的兼容字符(全角 / 特殊) | NFKC 转换后的标准字符(半角) | 对应的 Unicode 编码变化 |
|---|---|---|
| 全角大括号 { } | 半角大括号 { } | U+FF5B→U+007B;U+FF5D→U+007D |
| 全角小括号 ( ) | 半角小括号 ( ) | U+FF08→U+0028;U+FF09→U+0029 |
| 全角方括号 [ ] | 半角方括号 [ ] | U+FF3B→U+005B;U+FF3D→U+005D |
| 全角等号 = | 半角等号 = | U+FF1D→U+003D |
| 全角数字 0-9 | 半角数字 0-9 | U+FF10→U+0030 等 |
| 全角字母 a-z/A-Z | 半角字母 a-z/A-Z | U+FF41→U+0061 等 |
| 全角符号 !@#$%^&* | 半角符号!@#$%^&* | 对应半角编码 |
全角占两个字位符(一个中文宽度),半角占一个字位符
1 | {{7*7}} |
结果回显原文,说明预览只有一次渲染,需要寻找二次触发点
渲染:模板引擎 解析 模板内容,把模板语法{{}}执行后,生成最终普通字符串
预览:传
template: "{{config}}"→ 服务端用模板引擎渲染这个内容 → 把渲染结果(比如 config 的内容)展示给你
结果是二次触发点在Export Console
心碎了,关键就是全角符号和二次渲染,当时到底卡到哪里了没做出来
1 | {{cycler.__init__.__globals__.__builtins__.open('/flag').read()}} |
SecureDoc
这是唯一做出来的题目,因为它是cve,可以直接套
CVE-2025-66516
开题是文本文档提取工具界面,仅接受pdf格式,可以从pdf中提取文本内容,支持解析pdf表单,交互式元素,以及基于xfa的动态表单,可以获取文档的元数据信息
xfa:adobe推出的一种可以输入验证,下拉菜单,按钮等复杂交互元素,与后端系统对接,实现数据的实施提交与加载
由于 XFA 依赖 Adobe 专属技术,很多通用 PDF 阅读器不支持直接解析,需要专业工具(如 SecureDoc Parser)来处理。
xxe漏洞
1 | <!-- 1. XML文档声明:告诉解析器这是XML文件,编码UTF-8 --> |
mio’s waf
极难题目看不进去,明天填坑
ez Upload & ez Upload Revenge
开题是文件上传,禁用了?$&;|<我自己测试还禁止了<?php,所以用GIFA绕过,传是传成功了,但是解析原图,所以传个.htaccess,回显Forbidden keywords detected!禁用关键词,到这里我就做不出来了,看wp
碎了,我以为文件名htaccess被禁了,结果是文件里的内容被禁了,早知道应该多测试一下
突然想起isctf的mv超绝参数注入
我要传的htaccess内容是
1 | AddType application/x-httpd-php .jpg |
测试了一下是把php过滤了,大小写绕过也不行
受wp启发去搜.htaccess的bypass了,试了
1 | Options +ExecCGI |
然后传1.xx
1 | #! /bin/bash |
回显原文
https://www.anquanke.com/post/id/205098
反正把这篇博客的内容都试了一遍,都不行,为什么啊为什么
问了ai是文件执行命令权限没开(???)
所以直接让htaccess重写
1 | RewriteEngine On |
然后新建任意文件,回显的X-Test-Expe自带flag
一鸣唱吧
以为是写马题,没想到是路径爆破
上传一个文件会得到它的保存目录:uploads/UNiCTF202604.txt
再次上传,会发现规律
会保留上传的后缀名,并且只有后两位数字改变。那么可以遍历一下uploads下是否存在其他的文件。
看到两个好用的工具
seq(Linux 系统自带的序列生成工具);
1 | seq -w 0 99 > num.txt |
ffuf 执行文件名字典爆破;
运行wp命令不通,新的命令
1 | ffuf -u http://80-3d190993-53d1-4f13-8682-26d9271cb571.challenge.ctfplus.cn/uploads/UNiCTF2026W1W2W1W2 -w /tmp/num.txt:W1 -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-extensions-lowercase.txt:W2 |
关键参数解释:
| 参数 | 含义 |
|---|---|
-u |
指定要爆破的 URL 模板(W1/W2是变量,会被字典内容替换) |
-w |
加载字典文件,格式:字典路径:变量名(支持多字典组合爆破) |
num.txt:W1 |
把num.txt的内容赋值给变量W1(数字) |
raft-medium...:W2 |
把后缀字典赋值给变量W2(后缀) |
不如bp
扫出来有一个 UNiCTF202667.db,和 UNiCTF202638.php
关于php,是phpinfo。
在registered php streams看到开启了ssh2服务
ssh2是 PHP 的一个扩展,专门用于和 SSH 服务器交互,核心函数包括:
| 核心函数 | 功能 |
|---|---|
ssh2_connect() |
连接远程 SSH 服务器 |
ssh2_auth_password() |
用账号密码验证 SSH 登录 |
ssh2_exec() |
在 SSH 服务器上执行系统命令 |
ssh2_scp_send()/ssh2_scp_recv() |
上传 / 下载文件(SCP 协议) |
ssh2_shell() |
获取 SSH 交互式 shell |
ssh2模块启用,说明服务器大概率开启了 SSH 服务(端口 22)
关于db,是sqlite
1 admin 7fef6171469e80d32c0559f88b377245 1
2 ctfer 58d506617a1e20a9d87ab5a3debcb151 0
3 11 6512bd43d9caa6e02c990b0a82652dca 0
用账密登录,登不进去,被哈希加密了
7fef6171469e80d32c0559f88b377245 是一个 32 位的十六进制哈希值,MD5 哈希的特征就是 32 位十六进制字符串)
密码是admin888
登录后点击曲库发现多了一个功能
1 | 管理员内部预览 (Dev Mode) |
(是的就是不粘图片,以为至今没搞懂图片路径格式)
直接读取file:///flag会返回错误。那么试着读取源码。
1 | file:///var/www/html/download.php |
经验加一
1 |
|
PHP 的fopen()函数不只是能打开本地文件 / HTTP 链接,还支持自定义流封装协议(比如file://、http://、php://);而ssh2扩展为 SSH 功能新增了ssh2.exec://等协议,让你可以像 “打开文件” 一样,通过fopen()执行远程 SSH 命令
语法
ssh2.exec://user:pass@ip/cmd
| 协议片段 | 通俗解释 | 必选 / 可选 | 示例 |
|---|---|---|---|
ssh2.exec:// |
协议头,告诉 PHP:这是 ssh2 扩展的 “执行命令” 协议 | 必选 | - |
user |
远程 SSH 服务器的登录用户名(比如 root、ubuntu) | 必选 | root |
pass |
远程 SSH 服务器的登录密码 | 必选 | 123456 |
@ |
分隔符,分隔 “账号密码” 和 “IP 地址” | 必选 | - |
ip |
远程 SSH 服务器的 IP 地址(或域名),可加端口(默认 22) | 必选 | 127.0.0.1(本机)、192.168.1.100:2222(非默认端口) |
/ |
分隔符,分隔 “IP 地址” 和 “要执行的命令” | 必选 | - |
cmd |
要在远程 SSH 服务器上执行的系统命令 | 必选 | cat /flag、whoami、ls /tmp |
尝试写入文件。
1 | /download.php?preview=true&format=ssh2.exec://ctfer:duhgrl@127.0.0.1:22/id > /var/www/html/1.txt; |
1 | id > /var/www/html/1.txt; |
id:Linux 系统命令,用于查看当前用户身份(UID/GID/ 所属组);> /var/www/html/1.txt:将id命令的输出重定向到网站根目录下的1.txt文件;;:命令分隔符,可追加更多命令(如;cat /etc/passwd)。
然后,最后一部分没复现出来,直接复制wp的回显加载不出来
???
CloudDiag
开题看到页面底部文字提示
1 | CloudDiag runs in a cloud environment with instance roles for diagnostics. |
暗示AWS,ssrf
云环境元数据:云服务商为虚拟机提供的内置服务,实例可用通过特定的本地网址访问自身的配置信息
IMDSv1:http直接访问
http://169.254.169.254/latest/meta-data/即可获取实例ID,IAM角色,安全组等信息IMDSv2:加入了会话验证机制,需要先请求一个临时令牌,再用令牌访问元数据,提升了安全性。
然后我用admin弱口令,一开始就偏了
元数据(比如 AWS 的169.254.169.254)地址是系统及资源,只有root账户的操作历史,配置文件才会记录这些信息,而admin是应用级用户,根本接触不到系统级的元数据配置
弱口令root,root123
其实进入网页我根本不清楚该网页的应用场景和生活用途,笑死我了连题都没读懂,英语+代码被薄纱乐
CloudDiag可能是企业云运维诊断平台,用于
云实例故障排查(如 AWS EC2 实例)
云环境安全巡检(企业的安全团队会定期创建 “legacy metadata check” 这类任务,扫描云实例是否仍在使用不安全的旧版元数据接口,及时修复漏洞,避免黑客通过该接口窃取云凭证。)
多租户云资源监控(在多租户的云管理平台中,管理员(如界面中的 root 用户)可以通过该平台统一查看所有业务部门的诊断任务,确保各租户的云资源运行合规,避免单个租户的风险影响整个云环境。)
diagnostic task :诊断任务,提交一条用于排查云问题的指令,比如ping
Legacy metadata check :对“遗留元数据接口”的检查任务,root执行该任务是为了检查旧版元数据接口,防止黑客通过该接口窃取凭证
所以应该重点关注这里,进行信息搜集
Cloud Exporer: 云资源浏览器,用于查看和管理云资源
S3 存储桶(S3 Bucket)是亚马逊云服务(AWS)推出的 对象存储服务 的核心载体
点开legacy metedata check
http://metadata:1338/latest/meta-data/iam/security-credentials/获取实例的 IAM 角色凭证(临时访问密钥,aws默认一小时,仅允许读取特定s3存储桶,只能被绑定该角色的实例使用,其他设备无法复用)。
config preview:配置预览,展示从 Config URL 获取到的前 2KB 数据。这里显示的 clouddiag-instance-role 是当前云实例绑定的 IAM 角色名称,通过这个角色可以访问特定的云资源(如 S3 存储桶)。
已知这个就可以在security-credentials/后面加这个名称继续深入访问
parsed Config:解析后的配置,系统会尝试对获取到的元数据进行结构化解析。
这里显示 (parse failed) 说明返回的内容格式不符合预期,可能是数据不完整或格式错误。
Execution Log :重点看到这个运行日志里面有[INFO] Report uploaded to object storage表示诊断报告已上传到云对象存储(如 S3),暗示后续可以尝试访问该存储位置获取报告。
然后我们在已有url后面加入角色名称new task继续查询
回显Parsed Config
1 | { |
获取密钥后在云资源浏览器里面查询发现三个桶
1 |
|
填入secrets桶
回显
1 |
|
然后又看不懂不知道怎么填了,问ai!
Prefix(可选)
这是文件路径的前缀。因为目标文件路径是 flags/runtime/flag-067a118342f5439ab95d04bd31a9ecec.txt,你可以在这里填写 flags/runtime/ 来缩小查询范围。
Object Key(可选)
这是文件的完整路径(或文件名),用来精确指定要获取的文件。
直接填写完整路径:flags/runtime/flag-067a118342f5439ab95d04bd31a9ecec.txt
得到flag
gogogos
这题我搜到cve了,但是当时没复现出来,爆炸
cve-2025-8110
Gogs 允许用户通过 API 修改仓库文件,但未正确校验文件类型,导致符号链接(symlink)可被篡改;
符号链接指向 Git 仓库的核心配置文件.git/config,修改符号链接等价于直接修改.git/config;
Git 的fsmonitor配置项是 “文件系统监视器”,会在 Git 执行add/commit等操作时调用指定命令,注入恶意命令后,Gogs 内部执行 Git 操作时就会触发命令执行(RCE)。
1 | import requests |
为什么注释都是英文啊,读懂wp难上加难
目前uniwp全部看完,复现失败2个,看不进去两个
如有错误,多多指教