热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

让encodeURIComponent过的尖括号躲过ASP.NET的误拦截

问题所处环境:IIS7.5,ASP.NET4.0,应用程序池(ApplicationPool)运行于集成模式(Integrated)。今天一位园友向我们反馈用网摘收藏博客文章LINQ那些事(

问题所处环境:IIS 7.5, ASP.NET 4.0, 应用程序池(Application Pool)运行于集成模式(Integrated)。

今天一位园友向我们反馈用网摘收藏博客文章LINQ那些事(9)-解析Table.Attach引发的异常和解决方法时出错(注意:文章标题中有尖括号)。

我们查了一下,具体的错误信息是:

A potentially dangerous Request.QueryString value was detected from the client (t="...9)-解析Table.Attach引发的异常和解决方法...").

错误信息分析:为了防止XSS跨站脚本攻击,IIS的默认安全设置不允许查询字符串中包含尖括号,而这次网摘收藏操作却违反了这个规定,于是引发了这个错误。

对于这个问题,你也许会说这么简单的问题也好意思写篇博客,肯定是通过url参数传递标题时没有编码。如果真是这样,也会写篇博客,但不是技术分享,而是检讨书。

刚开始看到这个错误时,的确闪过这样的念头 —— 难道真的忘了编码?。。。不会的,记得编了。打开代码一看,松了一口气,检讨书不用写了,但技术分享必须的,当然前提是解决了问题。

上网摘中用到的js代码:

var url = 'http://home.cnblogs.com/wz/create?t=' + encodeURIComponent(document.title);

看!刚刚的!encodeURIComponent,经过无数次实践证明过的有效的Javascript Url Encode方式。

可是,现在竟然出问题了。。。

首先怀疑是不是页面标题中没有对标题内容进行HTML编码。检查确认,编码了:

<title>LINQ那些事(9)-解析Table<T>.Attach引发的异常和解决方法 - 海南K.K - 博客园title>

接着,看一下document.title的值:

LINQ那些事(9)-解析Table<T>.Attach引发的异常和解决方法  - 海南K.K - 博客园

竟然自动进行HTML解码了!这还是第一次发现!解码也没关系啊,encodeURIComponent对尖括号也会编码。

继续前进,看一下encodeURIComponent(document.title)的值:

LINQ%E9%82%A3%E4%BA%9B%E4%BA%8B(9)-%E8%A7%A3%E6%9E%90Table%3CT%3E.Attach%E5%BC%95%E5%8F%91%E7%9A%84%E5%BC%82%E5%B8%B8%E5%92%8C%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%20-%20%E6%B5%B7%E5%8D%97K.K%20-%20%E5%8D%9A%E5%AE%A2%E5%9B%AD

<被编码为%3C,>被编码为%3E,正常啊。明明是编了码的尖括号,IIS怎么会报错呢?难道浏览器偷偷解了码,再发送给IIS。

特此检查了一下浏览器请求的URL,浏览器对编了码的URL丝毫未动。

难道是IIS惹的祸?看一下IIS日志中记录的URL:

日志记录说明了IIS收到的也是编过码的尖括号。难道罪魁祸首是IIS!

也就是说IIS在判断时,先将查询字符串进行解码,将%3C解码为<,将%3E解码>,然后发现有尖括号,然后出错!

是不是这样呢?不入虎穴,焉得真相。根据错误信息,用ILSPY查看HttpRequest的源代码。

错误信息如下:

用ILSPY一路追踪:

1. HttpRequest.QueryString

public NameValueCollection QueryString
{
get
{
if (this._queryString == null)
{
this._queryString = new HttpValueCollection();
if (this._wr != null)
{
this.FillInQueryStringCollection();
}
this._queryString.MakeReadOnly();
}
if (this._flags[1])
{
this._flags.Clear(1);
HttpRequest.ValidateNameValueCollection(this._queryString, "Request.QueryString");
}
return this._queryString;
}
}

2. FillInQueryStringCollection()

// System.Web.HttpRequest
private void FillInQueryStringCollection()
{
byte[] queryStringBytes = this.QueryStringBytes;
if (queryStringBytes != null)
{
if (queryStringBytes.Length != 0)
{
this._queryString.FillFromEncodedBytes(queryStringBytes, this.QueryStringEncoding);
return;
}
}
else
{
if (!string.IsNullOrEmpty(this.QueryStringText))
{
this._queryString.FillFromString(this.QueryStringText, true, this.QueryStringEncoding);
}
}
}

3. FillFromEncodedBytes

// System.Web.HttpValueCollection
internal void FillFromEncodedBytes(byte[] bytes, Encoding encoding)
{
int num = (bytes != null) ? bytes.Length : 0;
for (int i = 0; i {
this.ThrowIfMaxHttpCollectionKeysExceeded();
int num2 = i;
int num3 = -1;
while (i {
byte b = bytes[i];
if (b == 61)
{
if (num3 <0)
{
num3 = i;
}
}
else
{
if (b == 38)
{
break;
}
}
i++;
}
string name;
string value;
if (num3 >= 0)
{
name = HttpUtility.UrlDecode(bytes, num2, num3 - num2, encoding);
value = HttpUtility.UrlDecode(bytes, num3 + 1, i - num3 - 1, encoding);
}
else
{
name = null;
value = HttpUtility.UrlDecode(bytes, num2, i - num2, encoding);
}
base.Add(name, value);
if (i == num - 1 && bytes[i] == 38)
{
base.Add(null, string.Empty);
}
}
}

就是在这里进行解码的,调用的就是HttpUtility.UrlDecode。 

原来罪魁祸不是IIS,是ASP.NET!

问题原因小结: 

ASP.NET在检测XSS跨站脚本攻击时,会将查询字符串解码,然后调用System.Web.CrossSiteScriptingValidation.IsDangerousString()进行检查。所以任何对查询字符串中的尖括号进行直接的UrlEncode编码操作(比如Javascript的encodeURIComponent, escape, encodeURI)都无法逃过ASP.NET的检查。

那没有解决方法呢?有!我们找到了,并且已经在实际中使用,不信的话,可以用网摘收藏一下LINQ那些事(9)-解析Table.Attach引发的异常和解决方法。

解决方法:

1. 通过下面的代码获取原装的未进行过HTML解码的页面标题(Javascript代码),这里 <变成了 <, > 变成了 >:

var title = document.getElementsByTagName('title')[0].innerHTML;

(注意:前面已经提过,document.title会对中的内容自动进行HTML解码,所以不要用它。)

2. 然后通过Javscript的encodeURIComponent进一步编码,这样可以躲过ASP.NET的XSS跨站脚本攻击检查(检查时,ASP.NET得到的是 <与 > )。

3. 在ASP.NET程序中获取这个查询字符串时,需要进行额外的HtmlDecode操作,C#代码如下:

HttpUtility.HtmlDecode(Request.QueryString["t"]);

感言

解决一个问题,最好的庆祝方式就是写一篇博客!不仅可以分享给别人,自己还会有额外的收获!而且一定会有!

本来写这篇博客时,我用的标题是“[Javascript]document.title 引起的Html Decode 问题”,当时以为是Javascript的问题,写博客过程中才发现是ASP.NET的问题。因为在写博客过程中,你要清楚地表达出来,来不得半点马虎,你会对问题进行更深入的研究。

一个东西,你想明白了,并不代表你真正理解。只有你清楚地表达出来,让别人能明白,才说明你真正理解。

推荐阅读
  • 在Spring与Ibatis集成的环境中,通过Spring AOP配置事务管理至服务层。当在一个服务方法中引入自定义多线程时,发现事务管理功能失效。若不使用多线程,事务管理则能正常工作。本文深入分析了这一现象背后的潜在风险,并探讨了可能的解决方案,以确保事务一致性和线程安全。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 深入解析JWT的实现与应用
    本文深入探讨了JSON Web Token (JWT) 的实现机制及其应用场景。JWT 是一种基于 RFC 7519 标准的开放性认证协议,用于在各方之间安全地传输信息。文章详细分析了 JWT 的结构、生成和验证过程,并讨论了其在现代 Web 应用中的实际应用案例,为开发者提供了全面的理解和实践指导。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 通过优化模板消息机制,本研究提出了一种高效的信息化推送方案。该方案利用获取的访问令牌(access token)和指定的模板ID,实现了精准且快速的信息推送,显著提升了用户体验和信息传递效率。具体实现中,通过调用相关API接口,确保了消息的准确性和及时性,为用户提供更加便捷的服务。 ... [详细]
  • 基于Java和JSP的电子医疗记录管理平台
    随着信息技术的快速发展,各类管理系统已在各行各业得到广泛应用。传统的人工管理模式已逐渐无法满足现代需求。本文介绍了一种基于Java和JSP技术开发的电子医疗记录管理平台,旨在提高医疗行业的信息化水平和管理效率。该平台通过整合先进的数据库技术和Web开发框架,实现了医疗记录的高效存储、查询和管理,为医护人员提供了便捷的操作界面和强大的数据支持。 ... [详细]
  • 本文探讨了如何在 Google Sheets 中通过自定义函数实现 AJAX 调用。具体介绍了编写脚本的方法,以便在电子表格中发起 AJAX 请求,从而实现数据的动态获取与更新。这种方法不仅简化了数据处理流程,还提高了工作效率。 ... [详细]
  • 在使用群报数小程序进行高效接龙与统计时,可以通过创建 `LinkedList` 对象并利用 `for` 循环生成指定数量的 `Person` 对象,为每个人员分配唯一的编号,并将其添加到 `LinkedList` 集合中。这一过程确保了数据的有序性和高效管理,便于后续的接龙和统计操作。此外,该小程序还支持实时更新和查看参与人员的状态,进一步提升了活动组织的便利性和准确性。 ... [详细]
  • Spring Boot 实战(一):基础的CRUD操作详解
    在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • 开发心得:利用 Redis 构建分布式系统的轻量级协调机制
    开发心得:利用 Redis 构建分布式系统的轻量级协调机制 ... [详细]
  • Java中将Map及其他对象高效转换为JSON格式的方法探讨 ... [详细]
  • 深入解析 AngularJS 表达式的应用与优化技巧
    本文深入探讨了AngularJS表达式的应用及其优化策略。在AngularJS中,表达式主要通过$digest循环进行自动解析,但在某些场景下,手动解析表达式也是必要的。文章详细介绍了如何利用$parse服务实现手动解析,并提供了多种优化技巧,以提高应用性能和响应速度。 ... [详细]
  • 基于STM32的智能太阳能路灯设计与华为云IOT集成方案
    基于STM32的智能太阳能路灯设计与华为云IOT集成方案 ... [详细]
author-avatar
平凡天使心619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有