XSS分析及预防
XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行。在WEB前端应用日益发展的今天,XSS漏洞尤其容易被开发人员忽视,最终可能造成对个人信息的泄漏。如今,仍然没有统一的方式来检测XSS漏洞,但是对于前端开发人员而言,仍是可以在某些细微处避免的,因此本文会结合笔者的学习和经验总结解决和避免的一些方案,并简要从webkit内核分析浏览器内核对于XSS避免所做的努力,了解底层基础设施对预防XSS所做的贡献。
XSS的种类和特点
此处不详细讲解XSS的一些细节
XSS的目标是让其他站点的js文件运行在目标站点的上,这主要发生在页面渲染阶段。在该阶段发生了某些非预期的脚本行为,该脚本可能来自用户的输入,也可能来自域外的其他js文件,不一而足。XSS的发生起源来自于用户输入,因此XSS根据用户输入数据以何种形式、何时触发XSS、是否有后端服务器的参与划分为三种类型,分别是反射型XSS、持久型XSS和DOM XSS。
反射型XSS
反射型XSS,顾名思义在于“反射”这个一来一回的过程。反射型XSS的触发有后端的参与,而之所以触发XSS是因为后端解析用户在前端输入的带有XSS性质的脚本或者脚本的data URI编码,后端解析用户输入处理后返回给前端,由浏览器解析这段XSS脚本,触发XSS漏洞。因此如果要避免反射性XSS,则必须需要后端的协调,在后端解析前端的数据时首先做相关的字串检测和转义处理;同时前端同样也许针对用户的数据做excape转义,保证数据源的可靠性。
e.x.
localhost/test.php
<?php echo $_GET['name'] ?>
如果通过 localhost/test.php?name=alert(document.cookie) 访问页面,那么经过后端服务器的处理,就会造成反射性XSS的发生。
同理,通过传入data uri编码的字符串也会导致XSS,如 localhost/test.php?name=data:text/html;charset=utf-8;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpPC9zY3JpcHQ+ 会导致同样的问题。该段编码的字串解码后是“alert(document.cookie)”。
持久型XSS
持久型XSS仍然需要服务端的参与,它与反射型XSS的区别在于XSS代码是否持久化(硬盘,数据库)。反射型XSS过程中后端服务器仅仅将XSS代码保存在内存中,并未持久化,因此每次触发反射性XSS都需要由用户输入相关的XSS代码;而持久型XSS则仅仅首次输入相关的XSS代码,保存在数据库中,当下次从数据库中获取该数据时在前端未加字串检测和excape转码时,会造成XSS,而且由于该漏洞的隐蔽性和持久型的特点,在多人开发的大型应用和跨应用间的数据获取时造成的大范围的XSS漏洞,危害尤其大。这就需要开发人员培养良好的WEB前端安全意识,不仅仅不能相信用户的输入,也不能完全相信保存在数据库中的数据(即后端开发人员忽视的数据安全检测)。针对持久型XSS没有好的解决方式,只能由开发人员保证。当然规则是由开发者制定,如果忽略用户体验的话,可以制定一套严谨的输入规则,对相关关键词和输入类型(如data URI检测,禁止输入)的检测和禁止,尽可能规避用户发现XSS漏洞的可能性,从源头处理。
DOM XSS
DOM XSS完全在前端浏览器触发,无需服务端的参与,因此这是前端开发工程师的“地盘”,理应获得我们的关注。
e.x.
localhost/test.html
如果访问localhost/test.html#document.cookie ,那么就会触发最简单的危害非常大的DOM XSS。它完全没有服务端的参与,仅仅由用户的输入和不安全的脚本执行造成,当然在本例中仅仅是最简单的情况,如果用户输入字符串‘’或者text/html格式的data URI,则更难检测,也危害更大,黑客操作起来更为容易。
因此预防DOM XSS,需要前端开发人员警惕用户所有的输入数据,做到数据的excape转义,同时尽可能少的直接输出HTML的内容;不用eval、new Function、setTimeout等较为hack的方式解析外站数据和执行js脚本;禁止内联事件处理函数;如果在考虑安全性的前提下需要获取外站脚本的执行结果,可以采用前端沙盒(建立空的iframe执行脚本,该iframe无法操作当前文档对象模型)、worker线程的方式完成,保证DOM的安全。
XSS预防
XSS漏洞难以检测,但是为了WEB安全仍需要尽力避免,在本节将会针对三种类型XSS漏洞提出对应解决方法,并从其他角度提供更具启发性的意见。
针对反射型XSS,在对应的小节中也提到过,需要服务端和前端共同预防,针对用户输入的数据做解析和转义,对于前端开发而言,则是善于使用escape,针对data URI内容做正则判断,禁止用户输入非显示信息,如MIME类型为“text/html,text/plain”类型的内容。
对于存储型XSS,处理方式仍然类同于反射性XSS。
对于DOM XSS,则需要慎之又慎。由于造成XSS的原因在于用户的输入,因此在前端,需要特别注意以下的用户输入源:
“
document.URL,
location.hash,
location.research,
document.referrer(此处应尤为注意,referrer属性虽然可用于避免CSRF,但可触发XSS攻击),
XHR返回值(跨域返回值),
form表单及各种input框
“
针对以上输入源,需要做相对于的检测和转义。在以上输入源中获取数据后,可能会有各种DOM操作或纯粹的js计算,这些操作则是真正触发XSS的罪魁祸首:
“
1,直接输出HTML内容
document.body.innerHTML = ...
document.body.outterHTML = ...
document.write()
2,HTML标签内联脚本
浏览器安全策略说之内容安全策略CSP
2 UNDERSTANDING XSS AUDITOR
3 webkit技术内幕