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

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

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

A potentially dangerous Request.QueryString value was detected from the client (t="...9)-解析Table<T>.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&lt;T&gt;.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.HttpRequestprivate 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.HttpValueCollectioninternal void FillFromEncodedBytes(byte[] bytes, Encoding encoding){int num = (bytes != null) ? bytes.Length : 0;for (int i = 0; i < num; i++)    {this.ThrowIfMaxHttpCollectionKeysExceeded();int num2 = i;int num3 = -1;while (i < num)        {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<T>.Attach引发的异常和解决方法。

解决方法:

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

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

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

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

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

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

感言

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

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

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

转载于:https://www.cnblogs.com/dudu/archive/2012/03/21/title_encodeURIComponent_iis_xss.html

躲不过也要躲:让encodeURIComponent过的尖括号躲过ASP.NET的误拦截相关推荐

  1. csgo躲猫猫模式显示服务器已满,csgo躲猫猫攻略大全

    CSGO中的躲猫猫模式热度一直是比较大的,对于这个问题来说新手也是有着很多的疑问.不过不要担心,下面就让我们一起来看看CSGO躲猫猫模式常见问题.玩法攻略汇总吧. CSGO躲猫猫模式进入方法介绍 1. ...

  2. csgo显示服务器ip,csgo国服躲猫猫IP地址大全及介绍

    您可能感兴趣的话题: csgo国服躲猫猫 核心提示:csgo国服躲猫猫IP地址大全及介绍 CSGO的躲猫猫模式得到许多玩家的欢迎.在CSGO中当然少不了诸如僵尸.躲猫猫这些地图制作者制作的娱乐模式,竞 ...

  3. csgo社区服务器维护怎么玩躲猫猫,csgo国服怎么玩躲猫猫 国服躲猫猫快速进入方法...

    CSGO的躲猫猫模式得到许多玩家的欢迎.在CSGO中当然少不了诸如僵尸.躲猫猫这些地图制作者制作的娱乐模式,竞技之余享受一下躲猫猫的.下面我们就为大家整理了一些有关csgo国服怎么玩躲猫猫的方法.一起 ...

  4. csgo躲猫猫模式显示服务器已满,CSGO躲猫猫模式服务器地址 CSGO躲猫猫

    从CS1.6开始,到CS:S,然后是最近的<反恐精英:全球攻势>(CSGO),虽然一直是电子竞技游戏,但有许多高手也为这款游戏创建了许多娱乐模式,比如僵尸暴动.僵尸逃跑,还有躲猫猫服等等. ...

  5. csgo躲猫猫显示服务器已满,csgo躲猫猫模式在哪里可以玩?

    csgo躲猫猫模式在哪里可以玩? 极速软件园点击数:1374  编辑时间:2020-07-20 10:28:32 标签: 虽然说csgo这是一款射击类的游戏,但是光有一种游戏模式的话,这款游戏是走不了 ...

  6. #人生中对我最重要的三位老师

    其实吧,我觉得我人生中每个人都是我的老师,都对我特别的重要,因为每经历一个人,你都会对他(她)都有很深的印象和感悟.4,会对你有一定程度上的影响.如果硬要说几位在我心中重要的三位老师来的话,(诶呀不好 ...

  7. 电力系统继电保护第二版张保会_《继电保护》复习笔记

    第1章 绪论 继电保护的基本任务是什么: 1.自动,迅速,有选择性的将故障元件从电力系统中切除,使故障元件免于继续遭受损害,保证其他无故障部分迅速恢复正常运行. 2.反应电气设备的不正常运行状态,并根 ...

  8. 怎么取html网页中的样式,从建站到拿站 -- HTML和CSS基础

    总有人会陪你在慌乱无序的生活里同步前行... ----  网易云热评 一.简介 HTML指的是超文本标记语言,使用标记标签来描述网页,标签是由尖括号和关键词组成,并且是成对出现,例如. 二.一个完整的 ...

  9. c 多线程map_Rust:一个不再有 C/C++ 的,实现安全实时软件的未来

    作者丨lochsh 译者丨马可薇 策划丨王文婧 Rust 作为新兴编程语言深受 Haskell 和 OCaml 等函数式编程语言的影响,使得它在语法上与 C++ 类似,但在语义上则完全不同.Rust ...

最新文章

  1. cie计算机科学,爱德思IGCSE 计算机科学 edexcel computer science
  2. 认识 UART 接口
  3. 计算机应用领域的CIMS,计算机的应用领域
  4. AngularJS与Angular的区别
  5. python笔记-标准库unittest
  6. 解决java.io.IOException: HTTPS hostname wrong: should be
  7. python网络编程初级
  8. 【微服务直播】60分钟掌握微服务治理之道
  9. 64位win7连接32位xp的共享打印机HP Laserjet P1008
  10. latex 数学符号
  11. 围观了张一鸣近10年的微博,我整理了这231条干货
  12. Java实现 定义一个名为Rectangle的类表示矩形 求面积周长
  13. pathon和python_【pathon基础】初识python
  14. Unit Testing with Sinon.JS
  15. DBA所需要具备技能
  16. 作为校招loser,我如何在一年半后的社招中咸鱼翻身
  17. 如何强化淘宝店铺标签 店铺标签优化方法
  18. php intval 四舍五入,PHP与JS---取整数方法int,celi,floor,round 收藏
  19. 小米手机开发版、稳定版刷机和root等操作
  20. 工业相机基础知识以及相机内参标定

热门文章

  1. 本科学校需要考计算机二级吗,本科毕业需要考计算机二级吗 考试难吗
  2. 英文说明书丨艾美捷D3204 2‘-脱氧胸苷(胸苷)
  3. 16瓶药水一瓶有毒,去小白鼠测试哪一瓶水有毒?
  4. vue(html)实现平方,三次方,四次方的上角标,下角标
  5. deque与queue区别
  6. git报错: git: not authorized :未经授权解决办法
  7. Node 中的 Buffer 对象
  8. WSX配合VM9.0实现浏览器登录共享虚拟机
  9. 固态硬盘现在已经不贵了,有没有必要放弃128GB直接买2TB的?
  10. 20151031本地编译freescale的i.MX6Q的android4.2.2android4.4.2 全志a80的步骤x1