关于 hunt-aspnet
hunt-aspnet 是用于授权测试 ASP.NET 应用及相关服务的安全技能。它整理了框架指纹识别,并涵盖 ViewState 解析问题、诊断端点暴露、WCF 服务以及 Telerik 或 SharePoint 攻击面的检查。
主要功能
- 01ASP.NET 技术栈与版本识别
- 02ViewState 配置与解析差异测试
- 03trace.axd 与 elmah.axd 暴露检查
- 04WCF 服务与元数据枚举
- 05Telerik 和 SharePoint 攻击面检查
适用场景
- 01审查 WebForms 页面中的 ViewState 风险
- 02检查匿名错误日志或跟踪信息泄露
- 03盘点遗留 WCF 服务及其元数据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-aspnet安装后在 Claude Code 中输入/hunt-aspnet确认已加载。
详细介绍
高价值目标
ASP.NET 反序列化漏洞一旦导致 RCE,通常能获得最高额的漏洞赏金。即使漏洞已修补,披露级别的发现(仅签名的 ViewState、双解析器差异、请求验证器异常)也能稳定获得低至中等奖励。
价值最高的目标:
- SharePoint 场(任何版本——2013/2016/2019/SE)——仅签名的 ViewState + 宽松的 ToolPane.aspx + 匿名 FormDigest,构成 CVE-2025-53770 ToolShell 的前置条件链
- Telerik UI for ASP.NET AJAX——当密钥泄露时,
Telerik.Web.UI.WebResource.axd是有记录的 RCE 接收端(CVE-2017-11317、CVE-2017-11357、CVE-2019-18935) - 传统 ASP.NET Webforms 企业应用——仍使用 .NET Framework 4.x 的银行门户、经销商门户、人力资源系统
- WCF 服务(
*.svc?WSDL)——常被遗忘的管理端点,其身份验证通常比主应用宽松 - Sitecore CMS——ViewState + Sitecore 专属反序列化链(CVE-2021-42237)
- DotNetNuke (DNN)——历史上的 ViewState RCE 利用链
- Umbraco CMS——ViewState + 自定义反序列化接收端
**最有价值的资产类型:**可从互联网访问的 ASP.NET Webforms 应用 > WCF 管理服务 > 集成 Telerik 的网站 > 使用 VSF 的传统 ASP.NET MVC(极少见)
攻击面信号
表明使用 ASP.NET 的响应标头:
X-AspNet-Version: 4.0.30319 (classic — disclosure on its own)
X-Powered-By: ASP.NET
X-AspNetMvc-Version: 5.2
Server: Microsoft-IIS/10.0
Set-Cookie: ASP.NET_SessionId=...
Set-Cookie: .ASPXAUTH=... (Forms auth cookie)
Set-Cookie: .ASPXFORMSAUTH=...
Set-Cookie: ASP.NET_SessionId=...; SameSite=None (suggests cross-origin embedding)
正文信号(表单 HTML 中):
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="..." />
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="..." />
<input type="hidden" name="__VIEWSTATEENCRYPTED" id="__VIEWSTATEENCRYPTED" value="" />
↑ EMPTY = signed-only, not encrypted = exploitable if key leaks
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="..." />
<input type="hidden" name="__REQUESTDIGEST" id="__REQUESTDIGEST" value="0x...,...">
↑ SharePoint CSRF token; if anon-issued, see hunt-sharepoint
待探测的 URL 模式:
/trace.axd (per-app trace viewer; sometimes anon-accessible)
/elmah.axd (ELMAH error log viewer)
/elmah.axd/?id=... (ELMAH RCE / stack-trace leak)
/*.svc (WCF services)
/*.svc?wsdl (WCF WSDL)
/*.svc/mex (Metadata Exchange)
/*.asmx (legacy SOAP)
/*.asmx?WSDL (legacy SOAP description)
/*.asmx?disco (legacy discovery)
/Telerik.Web.UI.WebResource.axd (Telerik AJAX components)
/ChartImg.axd (DataVisualization controls; historic deserialization)
/ScriptResource.axd (script resource handler; sometimes leaks paths)
/WebResource.axd (web resource handler)
/_vti_bin/* (SharePoint Web Service Forwarder)
/api/ (Web API 2.x is ASP.NET on classic framework)
/signin (often FedAuth / WS-Federation)
技术栈信号:
Server: Microsoft-IIS/10.0(或/8.5、/7.5)——已确认使用 Windows + IISX-AspNet-Version标头——传统 .NET Framework (4.x);.NET Core/5+ 不会发出此标头- 包含
ASP.NET_SessionId、.ASPXAUTH、FedAuth的 Cookie——Forms 或声明身份验证 - 表单正文中的
__VIEWSTATE——Webforms(不是 MVC、不是 Razor Pages、不是 Blazor) MicrosoftSharePointTeamServices标头(有时会被 ELB 移除,但会泄露在start.aspx正文中)——SharePoint
分步漏洞挖掘方法
-
**识别框架版本。**触发任意 500 错误(过期的 ViewState POST 是可靠的方法),并在错误正文中查找
Version Information: Microsoft .NET Framework Version:X.X.XXXXX; ASP.NET Version:X.X.XXXX.X。此横幅会披露运行时和 ASP.NET 版本特定的补丁级别。.NET 4.0.30319 + ASP.NET 4.8.x 是最常见的现代组合。 -
**定位每个包含
__VIEWSTATE的表单。**爬取目标并搜索name="__VIEWSTATE"。如果可以绕过 MAC / 加密,每个表单都是反序列化攻击的潜在接收端。 -
**检查
__VIEWSTATEENCRYPTED的值。**空值(value="")表示 ViewState 仅通过<machineKey>签名,但未加密。恢复验证密钥即可实现任意反序列化。非空值(value="something")表示 ViewState 同时经过签名和加密;伪造需要两种密钥。 -
测试 ViewState 解析器错误差异(双解析器反模式)。发送 7 种以上的 ViewState 形态并对响应分类:
- 无意义数据(
AAAA)→"Validation of viewstate MAC failed" - 当前页面的真实前缀 →
"Validation of viewstate MAC failed" - 翻转位后的真实 ViewState →
"Validation of viewstate MAC failed" - 超大数据(
A * 100000)→"Validation of viewstate MAC failed" - XML 形态(
<xss/>)→ "The state information is invalid for this page and might be corrupted" ← 不同的解析器路径 - LosFormatter 风格前缀(
/wEPDwUKMTcxNzgyOTQwMmRkkz9p4lzA...)→ "The state information is invalid for this page and might be corrupted"
这种差异证明存在两个不同的反序列化入口,其中一个会在某些负载形态下于 MAC 检查之前进行分派。从历史上看,这使 MAC-before-parse 绕过利用成为可能。
- 无意义数据(
-
查找负载均衡导致的跨节点 ViewState MAC 失败。 如果 POST 请求返回 500,并显示
"Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey...",说明服务器场中有多个 WFE,但未同步 machineKey,或未启用会话亲和性。从运维角度看,这会影响正常用户;从安全角度看,这证实了服务器场的拓扑结构。 -
探测
trace.axd和elmah.axd。 如果其中任一端点可匿名访问并返回 200,即为严重发现(trace 会泄露每个请求及其标头和表单数据;ELMAH 会泄露每个服务器错误,包括堆栈跟踪)。 -
枚举 WCF 服务(
.svc)。 对每个服务,获取?wsdl和?mex(元数据交换)。MEX 端点有时会返回包含管理操作的完整服务契约。 -
测试请求验证器绕过。 ASP.NET 的请求验证器默认会阻止查询字符串中的
<。仍可能奏效的绕过类型:- HTML 实体编码的载荷(
<script>——但这些不会执行) - 在 JSON / XML POST 请求体中编码(不同的内容类型 ≠ 相同的验证器)
- 位于路径段中(而非查询字符串)——验证器的作用范围取决于框架版本
- 位于 Cookie / Referer 标头中(因情况而异)
- 若通过 WebDAV PUT 访问,则位于
<%@ ... %>ASP 指令中(罕见)
- HTML 实体编码的载荷(
-
检查
customErrors模式。 如果 500 错误暴露了完整堆栈跟踪、框架版本、文件路径和内部方法名,则说明已设置customErrors mode="Off"。生产环境应设为RemoteOnly。 -
查找 Telerik 组件。
Telerik.Web.UI.WebResource.axd?type=rau是历史上的上传到 RCE 攻击链(CVE-2017-11317)。dialogParametersHolder参数攻击链(CVE-2019-18935)需要加密密钥,但除此之外可实现 RCE。 -
SharePoint 专属反序列化路径——参见
hunt-sharepoint技能,了解 ToolPane.aspx + 匿名 FormDigest + 未加密 ViewState 攻击链。 -
通过反射枚举 SafeControl。 SharePoint 的
Picker.aspx?PickerDialogType=<TypeName>(以及 DNN 等效端点)接受类名,并会针对“类型存在但未列入白名单”和“类型不存在”返回不同的错误消息。输入Microsoft.SharePoint.*.WebControls.*类型的字典,以枚举 SafeControl 列表——这对排查 CVE-2019-0604 系列漏洞很有用。
载荷与检测模式
堆栈跟踪指纹(通过过期的 ViewState POST 触发):
curl -sk -X POST "https://target.example/page.aspx" \
--data "__VIEWSTATE=AAAA&__VIEWSTATEGENERATOR=AAAA"
# Inspect body for:
# - "Validation of viewstate MAC failed" → confirms signed ViewState
# - "The state information is invalid for this page" → confirms ALTERNATE parser path
# - "Version Information: Microsoft .NET Framework Version:X.X.XXXXX" → exact patch level
# - "Microsoft.SharePoint.Client.ServerStub..." → SharePoint farm
ViewState 解析器错误差异探测(Python):
import requests, re, json
S = requests.Session(); S.verify = False
# Get fresh form
r = S.get("https://target.example/path/page.aspx")
real_vs = re.search(r'__VIEWSTATE" id="__VIEWSTATE" value="([^"]+)', r.text).group(1)
real_vsg = re.search(r'__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="([^"]+)', r.text).group(1)
# Test 7 payload shapes
for label, vs in [
("trivial", "AAAA"),
("real", real_vs),
("flipped-bit", real_vs[:50] + "X" + real_vs[51:]),
("oversize", "A" * 100000),
("base64", "VGVzdE1hcmtlcjY3OFhZWg=="),
("xml-shaped", "<xss/>"),
("losformatter", "/wEPDwUKMTcxNzgyOTQwMmRkkz9p4lzA" + "A"*50),
]:
r = S.post("https://target.example/path/page.aspx",
data={"__VIEWSTATE": vs, "__VIEWSTATEGENERATOR": real_vsg})
title = re.search(r'<title>([^<]+)</title>', r.text)
title = title.group(1)[:100] if title else "—"
print(f" [{label:14s}] {r.status_code} {title}")
匿名检查 trace.axd:
curl -sk -o /dev/null -w "%{http_code}\n" "https://target.example/trace.axd"
# 200 = full trace dump exposed → Critical
# 403 = mod set to localhost-only → check via X-Forwarded-For: 127.0.0.1
WCF 服务枚举:
# Find all .svc files
curl -sk "https://target.example/" -o body.html
grep -oE '/[a-zA-Z0-9/_-]+\.svc' body.html | sort -u
# For each found:
curl -sk "https://target.example/Service.svc?wsdl" | xmllint --format - | head -60
请求验证器绕过类型:
# Default: <script>alert(1)</script> in ?q= → "Potentially dangerous Request.QueryString value detected"
# Bypasses that sometimes work:
?q=%3cscript%3e (URL-encoded — depends on validator config)
?q=<svg/onload=alert(1)> (depends on validator version)
?q=<%00script> (NUL-byte; older validators)
?q=javascript:alert(1) (no < at all — passes validator)
Cookie: foo=<script> (cookie body not validated by default)
Referer: http://x.com/<script> (referer not validated in classic ASP.NET)
Telerik 漏洞利用门槛(CVE-2019-18935——需要加密密钥):
# Fingerprint Telerik
curl -sk "https://target.example/Telerik.Web.UI.WebResource.axd?type=rau" -X POST
# If response is RadAsyncUploadHandler-style → Telerik present; try keys
# Public exploits require leaked machineKey AND telerikEncryptionKey
常见根本原因
-
在没有敏感 ViewState 数据的页面上,
viewStateEncryption="Auto"默认仅使用签名。 许多 SharePoint 页面都采用这种配置。当__VIEWSTATEENCRYPTED为空时,ViewState 仅使用签名——仅恢复validationKey就足以伪造数据。 -
Web 场中的
<machineKey>使用 AutoGenerate。 每台 WFE 首次启动时都会生成不同的密钥;一台 WFE 签发的 ViewState 在另一台上无法通过 MAC 验证。运维层面会产生 500 错误;安全层面则会泄露拓扑信息(错误消息会指出集群)。 -
开发阶段遗留了
<customErrors mode="Off">。 完整的方法名、文件路径和版本标识等堆栈跟踪信息会暴露给匿名互联网用户。 -
生产环境中仍启用了
trace.axd/elmah.axd。<system.web><trace enabled="true">块中的设置常常会被遗忘。 -
遗忘了 WCF
.svc管理端点。 这些端点原本用于内部管理工具,主应用对外开放后却从未禁用。 -
双解析器反模式:
ObjectStateFormatter(旧版)与LosFormatter(新版)相对于 MAC 验证的反序列化顺序不同。 某些载荷会在 MAC 检查之前触发旧版解析器。 -
请求验证器只适用于 URL 编码的请求正文和查询字符串。 默认情况下,标头、Cookie、XML/JSON 请求正文和 multipart 字段都不会经过验证。开发者以为验证器适用于所有内容,但事实并非如此。
-
将
<machineKey>提交到了源代码仓库。 配置文件提交到 GitHub 时经常会泄露验证密钥/解密密钥。结合使用hunt-misc进行源码侦察,可查找 Telerik / SharePoint / DNN 密钥。 -
认为 web.config 中的
SafeControls条目可以控制反序列化。 SharePoint 的<SafeControl>列表决定了 Picker.aspx 可以实例化哪些类。如果继承检查是唯一的限制,则可能存在绕过方式(CVE-2019-0604 系列)。
绕过技术
| 防御措施 | 绕过方式 |
|---|---|
__VIEWSTATEENCRYPTED 非空(已加密) | 从任何源代码泄露 / 配置泄露 / VS 伪造原语中恢复解密密钥和验证密钥;没有密钥就无法触发反序列化 |
请求验证器会拦截查询字符串中的 < | 将载荷移至 Cookie / Referer / JSON 请求正文 / multipart 文件名中——在经典 ASP.NET 中,验证器不会检查这些上下文 |
强制启用 EnableViewStateMac="true" | 从 web.config 泄露或 <machineKey> AutoGenerate 指纹识别中恢复 validationKey(ysoserial.net 的 --minify --islegacy 模式可以生成能够通过某些 MAC 验证缺口的 ViewState) |
trace.axd 仅限 localhost 访问 | 如果 trace 模式为 localOnly,且验证使用的是 Request.UserHostAddress,则设置 X-Forwarded-For: 127.0.0.1(有些应用会改用 Forwarded-For) |
WCF .svc 匿名访问时返回 401 | 先尝试 ?wsdl 和 ?mex;即使服务操作需要身份验证,有时仍可匿名枚举元数据 |
| Telerik 上传功能已修补 | 检查 Telerik 版本:2017Q1 之前的版本(build 2017.1.118 或更早版本)都存在原始 RAU RCE。检查 2017Q3 - 2019Q3 是否存在 CVE-2019-18935 |
强制执行 SafeControl 白名单 | 在已修补的 SP 中,继承限制(instanceof PickerDialog)就是限制本身——要绕过就必须找到带有反序列化接收点的 SafeControl 子类;可通过 Picker.aspx 枚举 |
customErrors mode="On"(不显示堆栈跟踪) | 触发其他错误路径:使用无效的 Content-Length,或格式错误的 ViewState,以在 customErrors 处理程序下层触发解析器级异常 |
Gate 0 验证
撰写报告前,请确认:
-
攻击者目前能利用披露的信息做什么?
trace.axd返回 200,且包含完整请求转储 → 严重(暴露 PII / 会话 Cookie / Authorization 标头)elmah.axd返回 200,且包含错误日志 → 高危(堆栈跟踪 + 内部路径 + 有时包含凭据)__VIEWSTATEENCRYPTED为空,且通过单独发现恢复了 machineKey → 可串联至 RCE 的严重漏洞__VIEWSTATEENCRYPTED为空,但未恢复密钥 → 低危至中危(存在该原语,但本身不可利用)- 500 错误中出现堆栈跟踪 → 低危,除非其中包含凭据 / 连接字符串
-
你是否已复现从头到尾可造成攻击者实际影响的完整利用链,还是只确认了原语?
- 参阅
triage-validation的 Pre-Severity Gate。“已确认原语”并不意味着严重,除非利用链最终造成实际影响。
- 参阅
-
分诊人员能否在不到 10 分钟内根据你的报告复现?
- 每个步骤都应提供可直接复制粘贴的 curl / Python 命令。
- 对于 RCE 利用链:附上公开的漏洞利用工具链接(ysoserial.net、viewgen、telerik-revda)以及具体的 gadget 链。
实际影响示例
场景 A — EoL SharePoint 2013 上仅签名的 ViewState + 过于宽松的 ToolPane
匿名访问 https://target-portal.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit 会返回 200。表单中包含 __VIEWSTATE(仅签名 — __VIEWSTATEENCRYPTED=""),并且 _api/contextinfo 会向匿名用户签发 __REQUESTDIGEST。再加上 SP2013 已停止支持(永远不会再发布补丁),这就是 CVE-2025-53770 “ToolShell” 的典型前置条件链,且漏洞所在代码路径永久不会得到修补。报告的严重性:严重。双解析器测试(方法论第 4 节)确认,XML 结构的有效负载会在 MAC 验证之前到达旧版 ObjectStateFormatter——这进一步证明,即使未完全恢复 machineKey,该利用链仍可触达(不过,完整 RCE 需要同时满足两项条件)。
场景 B — 传统银行门户暴露 Telerik RadAsyncUploadHandler
/Telerik.Web.UI.WebResource.axd?type=rau 会返回 Telerik 上传处理程序。从 JS bundle 元数据中可见 Telerik 版本为 2016.3.1027。适用 CVE-2017-11317——该版本的公有 Telerik DLL 中内置了密钥。上传 → 将 aspx 写入 /app_data/ → 发起请求 → RCE。报告的严重性:严重。
场景 C — 企业 HR 门户同时暴露 trace.axd 和 elmah.axd
trace.axd 返回 200,并提供最近 50 条请求,其中 API 请求包含 Authorization: Bearer eyJ... 标头。elmah.axd 返回 200,并提供完整错误日志,其中一个异常包含数据库连接字符串。报告的严重性:严重(匿名互联网用户可获取明文凭据)。
相关技能与链路
hunt-rce— ViewState 反序列化是 ASP.NET RCE 的主要攻击路径;仅签名的 ViewState + 泄露的 machineKey = 每次都能实现 RCE。链路原语:检测到 ASP.NET ViewState 双解析器 MAC 绕过反模式(已签名但未加密,<%@ Page enableViewStateMac="true" viewStateEncryptionMode="Never" %>)+ 找回 machineKey(从 web.config 泄露、elmah.axd、源码泄露或 GitHub 获取)→hunt-rceysoserial.netTypeConfuseDelegategadget → 以w3wp.exe工作进程身份执行任意命令。hunt-sharepoint— SharePoint 场继承了所有 ASP.NET 反模式,同时还有自身的攻击面。链路原语:ASP.NET 指纹显示为 SharePoint(可见 X-SharePoint 标头 +/_layouts/可访问)→ 转向hunt-sharepoint,先检查 SharePoint 专属 RCE 路径(ToolShell、SafeControl 反射),再尝试通用 ViewState 攻击。hunt-ntlm-info— 匿名公开 NTLM/Negotiate 的 IIS 站点会泄露 AD 拓扑。链路原语:IIS 后的 ASP.NET 应用包含WWW-Authenticate: NTLM→hunt-ntlm-info捕获 Type-2 挑战 → 获取内部林名称 → 通过m365-entra-attack发现功能交叉查询 Entra 租户。hunt-file-upload— Telerik RadAsyncUpload、Kentico、Umbraco 和 DotNetNuke 都曾出现过上传处理程序 RCE。链路原语:识别出 ASP.NET CMS 指纹 → 使用hunt-file-upload针对 CMS 上传处理程序的绕过矩阵 → 将.aspx写入 Web 可访问路径 → 发出请求 → 以应用程序池身份实现 RCE。triage-validation— 只有在trace.axd/elmah.axd泄露实时凭据/令牌时,信息泄露才属于严重问题;纯堆栈跟踪通常为低危。链路原语:提交前,将每项报告的发现都通过triage-validation的 7 问门槛进行审核——在撰写报告(redteam-report-template)前,区分“详细错误”(信息性)与“错误日志中的实时承载令牌”(严重)。