HTML本身的特性为前端安全问题XSS注入了强大的生命力,这些年各大组织都努力尝试从根本上降低XSS存在的可能性。早些年Google安全团队曾推出浏览器弹窗拦截功能,一群顶尖的安全研究员费九牛二虎的力气,研究一个功能并不断更新迭代,想要从根本上去对抗XSS的问题。但结果就是新问题不断,全新版本的google浏览器已经放弃这个功能。为什么想要从根本上降低XSS存在的最终都被放弃了。其中原因,都得从HTML的起源开始说起。
1.重新认识一下HTML
今天的HTML是大量网页信息的基本构建块。HTML旨在提供一种真正可扩展的用于布局的语言编写方式,它非常的灵活且不会受到太多的的约束。为什么发展至今,相较于SGML、XML,HTML可以获得成功,并且在全世界范围内获得更广泛的应用呢?毫无疑问,这与HTML本身的灵活性与宽容性的特性脱离不了关系。这很好理解,人们在选择使用一种语言进行内容创作时,相较于考虑选择使用何种语言,考量这种语言是否更合规,更应该考虑的是想要创作的内容本身是否是优质且利于人们学习发展的。
回顾HTML的整个发展历史,初期的HTML并不被当时的技术者们看好。因为它非常的草率和宽容,甚至可以说是模棱两可。从布局的角度来看,HTML与当时微软推出的Word软件比起来,word文档的布局非常丰富以及受控制,这样一看HTML就好像个“一贫如洗”的小屁孩。但是“一贫如洗”如果换一种说法的话,也叫“无限可能”,因为你可以在一张白纸上进行各种奇思妙想的创作,而不受原始纸张颜色大小的限制。但是初期的HTML追随者中也有非常多CSS狂热者,他们非常努力地尝试用“装饰外套”将它捆绑起来,创造工具在它之上进行精确的平面布局。他们尝试在“白纸”上限定一些非常精巧的布局,让你只需要将内容倒入设定好的容器之中,但是同样,基于这样的工具,你的内容也需要根据容器进行调整,使之更加合理化。和google一样,这些好像都违背了一开始的初衷,我们又回到了追求程序“标准性”的轨迹上,花费时间精力去设定程序和语言的框架,而直接忽略了人性化。
而SGML是一种用于定义标记语言的系统。它能够为用户提供一种定于语言标准的机制,用于定义文档的结构和指示文档结构的标签。完整的SGML标准文档,长达五百页,它非常的强大且昂贵,像家族一位德高望重的老爷爷。请老爷爷出山,需要严格按照他指定的标准进行编写,对于一个庞大的组织来说,这样的标准规范可以为他们带来秩序,这当然是非常好的。但是对于大多数中小组织以及个人来说,使用SGML进行编写,只会感觉繁琐且沉重,寸步难行。所以为了满足大多数想要化繁为简的用户,从SGML中衍生出了HTML和XML,两兄弟师出同门但却又有着本质的区别。怎么说呢?
XML相当于SGML的一个子集,比SGML要简单,但是能实现SGML的大部分功能。这里画一个重点,XML是SGML的一个子集,所以说这两位本质上是一样的,XML也是一种可以用于标记语言的系统。而HTML是一个基于SGML的一个实例,所以在早期的HTML使用中是需要引用DTD(文档类型定义)的,本质上HTML只是SGML的一个运用实例,HTML本身并不能定义标记。简单来说,我们在使用HTML时,<p>标签是段落标签,是因为在SGML中就已经规定了这样一种定义,HTML只是一个使用者的角色,并不能自己定义更多的标签。但是这样的特性,决定了HTML非常灵活且宽松,就像大家在日常使用时。我们可以这样写:
代码语言:javascript复制<p>我是一个段落</p>
也可以这样写:
代码语言:javascript复制 <p>我是一个段落
再看这样一段简单的代码
代码语言:javascript复制<note>
<to>George</to>
<from>John</Ffrom>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
很明显,我故意将<from>的结束标签写错了,写成了<From>,在xml里变成了怎么样呢?
它报错了,我们的内容并没有正常展示出来。而同样的一段代码,我们使用HTML进行编写,就会变成这样:
看看dom变成什么样了?
在HTML里,它丢掉了我们写错的标签,并在最后自动补充上了结束标签,HTML就是这么灵活。你甚至可以试试这样”随意“的标签嵌套:
代码语言:javascript复制<form><table><td><iframe>
或者这样一些看起来很奇怪的标签叠加:
代码语言:javascript复制<svg>
<style>
<img src="<img src=x onerror=alert(1)//">
</style>
</svg>
你会发现,即使没有按照严格的规范标准进行闭合和使用,但是HTML依然是可以正常渲染的。而发展至今,到了HTML5的时代,我们不能再说HTML只是SGML的一个使用实例了。因为目前的HTML5并不单纯只是原本HTML的补充,更是一种新的标准,其主要目的是定义了互联网语言化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入。但从过去到现在,HTML5依然保留了HTML自身灵活且宽松的特性。
所以我们可以看到,HTML能在全世界范围内获得成功,获得今天的成就,与其本身特性脱不了关系。尽管它有局限性,但它可以真正地让创作者可以专注于创作内容本身,而不用过度关注于语法是否合规且标准。
灵活也是一把双刃剑
无绝对的好坏,任何特性都具有他的两面性。对于创作者来说,HTML的灵活性为创作者提供了诸多的便利,但就安全性来说,无疑灵活也同样为网站带来了更多的可侵入点。就好像我前面举的例子:
代码语言:javascript复制<svg>
<style>
<img src="<img src=x onerror=alert(1)//">
</style>
</svg>
如果你已经动手试过,就会发现这串奇奇怪怪,毫无章法的代码是可以触发浏览器弹窗的。而dom变成什么样了呢?
可以发现,HTML5非常智能,它抛弃了一些标签,自动在正确的位置补充了结束标签并执行。我们在知道HTML有这样的“自动”特性之后,就多了很多的想象空间。
举一些有趣的例子,比如看看这样一段代码:
代码语言:javascript复制<p>test</p>
<!--<img src="logo.png">-->
这是一段平平无奇的注释代码,我的编辑器也将变成了浅灰色,告诉我这是一段注释。用浏览器执行之后,图片是不会正常展示的。这很容易理解,因为图片被我们注释掉了。
如果变成这样呢?
代码语言:javascript复制<p>test</p>
<!--><script>alert(1)</script> -->
猜猜这样一段代码用浏览器执行执行会有什么效果?弹OR不弹?
请见分晓~
浏览器认为注释到<!-->就结束了,并将我们最后的注释闭合部分识别为了普通文本。而很多的开发者会像我们使用的代码编辑器一样,认为这段内容是注释内容,是安全的,便不会做过多的安全考虑。试想一下,如果一个网站的开发者将用户输入的内容不做任何处理放在注释里,这样是不是就会攻击者带来了可乘之机呢?
再比如说这样一段代码,又会发生什么呢?
代码语言:javascript复制<a href="https:///////////////baidu.com">test</a>
动手操作试一下。
这么一长长长长串的反斜杠,其实都不会影响HTML5的执行,点击test依旧可以正常访问百度首页。而类似于我上面列举的这几个例子,关于前端安全方面可以利用的点还有很多。因为前端本身是灵活且千变万化的,它会自动补充一些“缺少的”,自动过滤一些“错误的”,这样的灵活设置为创作者带来了诸多便利,同时也让前端安全变得更加有趣且千变万化。
干货分享
这里小编给大家分享一个非常有“干货”的网站:HTML5SEC
HTML5SEC,网站为学习者提供了非常多基于HTML5各种特性的分析,包括这样一个语句在不同浏览器不同版本中会产生的不同效果,而这些特殊效果的产生背后也就意味着诸多安全问题的产生。经常活跃于测试各大网站的白帽们肯定不会对这个网站感到陌生,因为整个网站看起来像是提供了各种不同的Payloads,在测试前端安全时,一个一个换着换着试说不定也会有意想不到的收获。
但对于想要更深入学习前端安全的同学来说,这个网站更应该是一个百宝库。通过这个网站去深度的掌握了解HTML5的特性,每真正掌握并彻底理解一个特性,也就为自己的挖掘思路多增加了一片瓦。怎么样算是深度呢?认真去了解每一个特性的前世今生,去动手测试这种特性会被不同的浏览器解析成何种样子。这当然不是一个简单的过程,毕竟真正地成长肯定伴随着破茧的疼痛。