WEB安全第六课 HTML语言 之二 理解HTML解析器的行为 |
上一节里勾画的HTML语法基础,对于理解格式正确的HTML和XHTML文档已经足够了。如果用的是XHTML格式,也没什么值得说道的:因为解析器对错误容忍度极低,所以任何不正常的语法几乎都会立刻引起解析错误的告警。
但是,对传统的喜欢发懒的HTML解析器来说,事情就完全两样了,即使在非常含混的场景甚至有潜在风险的场景里,HTML也总是大胆地猜测网页作者的意图。 既然准确理解用户提供的标记是设计各种类型的安全过滤器的基础,让我们简要地看一下其中一些表现和巧妙的陷阱。让我们用以下这段代码作为开始: ✍🗼🦞🈷🐋 如果网页开发人员知道上述语法经过一番改头换面,对浏览器来说意思仍然是一样的,往往都会大吃一惊。例如,IE浏览器允许把空字节NUL(0x00)插入到标记为❶的位置上,但这种变动却可能使其他头脑较为简单的HTML过滤器运行出错。另外,也没有多少人知道,在所有的浏览器里,位置❷和❹的空格都可以用不太常见的垂直制表符(0x0B)或进纸换页符(0x0C,form feed)替代,而在Opera里这个位置可以是UTF-8格式的不间断空格(0xA0)。最让人惊讶的是,在Firefox里,位置❷的空格可以用单个普通的正斜杠代替,但在位置❹却不能这么做。 再往下看,位置❸也值得引起注意。大部分解析器都会忽略这个位置的NUL字符以及各种类型的空格符。在不久之前,WebKit类型的浏览器在这个位置还允许使用正斜杠,但最近WebKit的解析器经过改进,已经消除了这个陷阱。 👂🔥🌶❓🐋 引号字符也是个令人感兴趣的主题。网站开发人员都知道可以用单引号和双引号把包含空格或尖括号的字符串放到HTML参数中。但令人吃惊的是,对于位置❺IE还能接受反引号(`)。类似地,也很少有人知道在任何浏览器里,在被引号括起的参数后面其实都会隐式地跟着一个空格符,所以位置❻的那个空格符其实可以去掉,而完全不会改变整段代码的含义。 这些模式对安全的影响并不容易理解,让我们来考虑这么一个HTML过滤器吧,它需要过滤<img>标签,因为攻击者可以控制该标签里的title参数Q在这个输人项对应的位置上,如果输入的内容没有包含空格符和尖括号,那这个参数就不需要用引号括起来——在很多博客站点上都能看到这种用法。初看上去这一做法还挺安全的,但在以下两个例子里,被恶意注人的onerror参数仍然能在这个标签内成功执行: 👈🗼🍏📶🦊 <img ... title=""onerror="alert(l)"> 和 <img ... title=``onerror=`alert(1)`> 而IE浏览器里另一个和引号用法相关的有趣陷阱使过滤器变得更加复杂。大多数其他浏览器只识别在参数值前面的引号,而IE浏览器会检查所有的内容,当发现等号后面还跟着引号时,IE的语法解析会很出人意料: 👎⛴🦞🅰🐅 <img src=test.jpg?value=">是的,这个位置仍然在标签里!"> 1.多重标签之间的交互 👃🍪ℹ🦮 解析一个单独的标签已经够累人了,但也许你也会想到,不正常的多个HTML标签堆叠在一起的时候,情况就更难以预测了。不妨考虑以下这个小例子:<i <b> 当碰到这样的语法时,大多数浏览器都只把它解析成<i>,而把“<b”的部分视为无效的标签参数。但在Firefox4.0之前的版本里,在碰到尖括号时,会先自动闭合<i>标签,最后把这串内容解析为<i>和<b>。🧑💻👓🗑🥰👀 当标签名包含无效字符时(在本例中,该无效字符为等号),在早期版本的Firefox里也能看到类似的表现。解析器不会把这整段内容全部忽略掉,而只会简单地重置一下<b>标签之前的内容,<b>部分再作为HTML标签解析,剩下的为文本节点的内容: <i="<b>"> ✍🚠🫑💲🐢 在整个文档结束时标签未闭合的情况也同样令人眼花缭乱。例如,以下片断会被大多数浏览器解析为<i>标签或干脆忽略整个字符串,但IE浏览器和Opera与众不同的从后往前看的处理方式,会使它们把这串内容识别为<b>: <i foo="<b>"[EOF] 实际上,Firefox4.0之前的版本在碰到某些特殊标签,如<title>标签在整个文档结束时,如果都未能闭合,会采取一种牵强附会、重新另作解析的处理方式: 👜🏮😒👈 <title>这部分文本会被解析为标题 <i>这部分文本会显示在文档正文里! [EOF] 🧠🌡🍖💲🐟 假如攻击者能中断页面的加载,那后两种解析陷阱就可能带来一些有趣的安全问题。即使在特定位置上过滤已经做得相当好了,但文档的含义可能出人意料地已经全都变了。 2.显式和隐式的条件判断 好像是要进一步把HTML解析的问题弄得更复杂似的,某些浏览器还支持以条件判断的方式略过文档内的某些标记。例如,为了方便微软ASP脚本开发平台的新手用户,IE浏览器会把<%...%>段落视为非标准的注释内容,在这两个字符中间出现的段落全都会被视为隐藏内容。另一个IE浏览器相关的特性是解析器支持显式的条件判断,它可以夹带在标准的HTML注释块中间: 👮♂️💎🗝🤪💪 <!--[if IE 6]> 只有碰到IE6浏览器,才解析在这里面的标记代码 👨🦱🛍🦯😡🖐 <![endif]--> 这个类别的许多陷阱则与SGML和XML的语法特点有关了。除了前面提到的这种以外,各种和注释符有关的问题还包括要如何解析!-和?-指令(例如<!D0CTYPE>或<?xml>,在非XHTML模式里能否出现XML风格的CDATA区块,还有多个特殊解析模式的标签要是堆叠在一起,需要以怎样的优先级进行解析(例如"<style><!--</style>-->"),各种浏览器全都互见分歧。 3.HTML解析的生存建议🧦✒😪👃 在上一节里讨论的解析行为其实一点都不全面。实际上,关于这个主题有一整本书进行广讨论:建议可以去看这本《Web Application Obfuscation》(Syngress 出版社,2011出版),作者包括Mario Heiderich、Eduardo Alberto Vela Nava、Gareth Heyes和David Lindsay——看完可真要为人类的可悲命运抹泪啊。#376: 这本书要说的是,企图创建出能拦截所有已知危险模式,但又不影响其他段落正常功能的HTML过滤器,实际上是不现实的。 👊🚐🍓⁉🪰 对标签清理唯一合理的做法是采用一个实际的解析器,把输入的文档先翻译成放在内存里的层级文档树,然后去除所有无法识别的标签和参数,以及所有不需要的标签/参数/参数值设置。这时候,这棵文档树就可以被重新排序为一份格式正确、转义良好的HTML页面了,这样就无须触动浏览器自身的错误纠正机制了。许多开发人员原本认为设计出一个可用的过滤器蛮简单的,但他们逐渐会发现这条道路实际困难重重。 WEB安全第六课第三节:
帖子热度 9460 ℃
|
|
在遇到你之前,我对人世间是否有真正的圣人是怀疑的;而现在,我终于相信了!我曾经忘情于两汉的歌赋,我曾经惊讶于李杜的诗才,我曾经流连于宋元的词曲。但现在,我才知道我有多么浅薄!楼主,你的高尚情操太让人感动了。在现在这样一个物欲横流的金钱社会里,竟然还能见到楼主这样的性情中人,无疑是我这辈子最大的幸运。让我深深感受到了人性的伟大。楼主的帖子,就好比黑暗中刺裂夜空的闪电,又好比撕开乌云的阳光.
|
回帖的永远有28种人
1个说前排围观的, 👀🪐🥩⁉🐕 1个路过打酱油的,1个留名的, 1个上来直接骂LZ去死LZSB的, 1个整天抢2楼的, 1个说自己SB的 🧒🛍⌨🥲🙏 1个tm就知道呵呵的, 1个进来P都不放按顶走人的, 1个涂鸦的, 1个发广告的, 1个成天装内涵的,🧑⚕️👜🪝😷🧠 1个表情帝, 1个没事就撸撸睡觉的, 1个要摸楼下狗头的, 1个总是@ 别人的 1个整天拜膜的, 🤛⛄🍞🆘🦖1个吹NB的, 1个只会说“哦”的, 1个宣扬春哥的, 1个灌水的, 1个爪机马克的, 🥷👜✏😷💪 1个蛋疼的, 1个TM的说挽尊的, 1个TM的说亲哦有木有的, 1个说内容太长没看的, 1个废话连篇的,👨🚒👒🛏😭👆 1个留邮箱的, 最后就是1个像我这样复制粘贴混经验的#y421: |