导语:什么是XSS、如何预防它? 虽然每个人都可以很好地解释XSS,但很少有人知道如何预防它。 当恶意攻击者向服务器发送一个字符串时,就会发生跨站点脚本。当该字符串会被应用到受害者的Web浏览器,浏览器就会将该字符串解释为要执行的脚本,
什么是XSS、如何预防它?
虽然每个人都可以很好地解释XSS,但很少有人知道如何预防它。
当恶意攻击者向服务器发送一个字符串时,就会发生跨站点脚本。当该字符串会被应用到受害者的Web浏览器,浏览器就会将该字符串解释为要执行的脚本,这样,这些恶意脚本可以使用受害者的经过身份验证的会话来执行许多不同的恶意操作。
目前总共有三种类型的XSS:
1.反射XSS是XSS分类中最多的,他们原理是样的攻击者发现存在反射XSS的URL,然后根据输出点的环境构造XSS代码,从而进行编码、缩短(可有可无,是为了增加迷惑性),最后发送给受害者,当受害者打开后,攻击者就可以执行XSS代码,比如获取cookies、url、浏览器信息、IP等等。简单来说反射型XSS是非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。
2.存储XSS是指服务器保留字符串并稍后在查看特定页面时发送它,例如在公告板或名称字段中发布的消息。
存储型XSS,听名字就能猜出来是持久化数据脚本攻击。由攻击者输入恶意数据保存在数据库,再由服务器脚本程序从数据库中读取数据,然后显示在公共显示的固定页面上,那么所有浏览该页面的用户都会被攻击。由于攻击者输入恶意数据保存在数据库,再由服务器脚本程序从数据库中读取数据。所以大部分的存储型XSS漏洞都是在表单提交上会发生的。比如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie等。
与反射型XSS、存储型XSS的区别就在于xss代码并不需要服务器解析响应的直接参与,触发XSS靠的是浏览器端的DOM解析。
3.DOM型XSS其实是一种特殊类型的反射型XSS,它是基于DOM文档对象模型的一种漏洞。在网站页面中有许多页面的元素,当页面到达浏览器时浏览器会为页面创建一个顶级的Document object文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件。可以通过JS脚本对文档对象进行编辑从而修改页面的元素。也就是说,客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行。基于这个特性,就可以利用JS脚本来实现XSS漏洞的利用。
上图显示的就是一个嵌入在数字证书中的XSS,我能够用证书名称中的XSS创建一个数字证书,这样XSS就可以随意绕过系统的黑名单和白名单。当管理员查看我创建的证书时,服务器就会对该证书进行解码,并将解码后的字符串发送到显示XSS的管理员网页浏览器。在这种情况下,XSS是一个Rick Roll(我最喜欢的演示方式之一),但是任何javascript都可以嵌入到这个字段中。
如何保护XSS?
目前预防XSS有两种主要的方法:
1.根据输出的上下文进行编码,这是你对预防XSS的第一道防线,其目的就是要确保任何不受信任的输出都可以根据其所处的上下文被正确编码或转义。这样做还有另外一个好处,就是可以预防HTML的注入。对于编码规则稍有不同的上下文,如HTML数据、属性字段,url等,OWASP站点会有一个清单,可以列出了各种上下文以及所需的库编码和建议编码。
在此,我强烈建议你使用一个适当的框架,例如Angular,来自动处理输出编码。
2. 内容安全策略 (CSP, Content Security Policy) 是一个附加的安全层,用于帮助检测和缓解某些类型的攻击,包括XSS和数据注入等攻击。其原理就是向网络浏览器发送一组html标头指令,以帮助网页执行那些应该执行的脚本。比如,在浏览网页的过程中,尤其是移动端的网页,经常看到有很多无关的广告,其实大部分广告都是所在的网络劫持了网站响应的内容,并在其中植入了广告代码。为了防止这种情况发生,我们可以使用CSP来快速的阻止这种广告植入。而且CSP还可以比较好的预防DOM型XSS。
不过CSP需要与输出编码一起工作,才能确保任何遗漏的输出编码将不那么危险。虽然CSP会终止不需要的脚本,但它却不会阻止可用于重写页面以进行恶意目的的HTML注入。另外,CSP起不到防止XSS注入现有脚本的作用。如果在CSP允许的javascript内使用用户输入,则必须非常小心地对其进行转义和处理,更多关于CSP的信息请点此。
一些简单的辅助保护措施
1.除了输出编码和CSP保护措施之外,还可以使用设置HttpOnly标志的方法。如果你在cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止防止XSS收集会话信息。但这种方式能防住攻击者吗?HttpOnly标志可以防止cookie被“读取”,那么能不能防止被“写”呢?答案是否定的,那么这里面就有文章可做了,因为已证明有些浏览器的HttpOnly标记可以被JavaScript写入覆盖,而这种覆盖可能被攻击者利用发动session fixation攻击。
2. X-XSS-Protection也有助于在一些浏览器中防止某些XSS,但在某些情况下可以被绕过。
以下两大类缓解操作应该被避免使用
1.不要以为你对对某些字符的输入设置了黑名单,有关这些字符的所有XSS都不会起作用。所以我的建议是,不要采用这种黑名单过滤技术,即使是辅助的措施也不可以。虽然XSS黑名单技术是非常的先进,但也不可能过滤所有这些攻击。 Web应用防护系统(Web Application Firewall, 简称WAF)是使用黑名单的专业产品,就连它们不能正确地执行这些操作。如果你想了解更多关于绕过xss黑名单或过滤器的更多信息,我建议你阅读@BruteLogic的博客。
2.白名单技术,虽然OWASP和其他人都说这是一种有效的辅助缓解措施,它不但在安全性方面几乎没有任何帮助,反而可以在许多系统上被绕过,造成更大的安全隐患。
2.1首先如何对复杂来源的输入进行白名单设置就是一件非常困难的事情,在数字证书中使用XSS的XSS图像就是一个很好的例子,在这个例子中输入过滤不能阻止XSS。数字证书被编码,服务器的黑名单和白名单没有执行解码以验证所有内部字段。有时,字段必须接受一种广泛的数据形式,进入允许XSS的系统。在其他情况下,恶意的输入可能会从网页前端以外的地方进入系统,比如日志文件、文件名、机器名等等。虽然输入过滤器对于阻止许多类型的攻击至关重要,但它对XSS来说并不是有效的缓解方法。
2.2虽然基于上下文的适当的输出编码和强大的内容安全策略(CSP)将花费开发人员很长时间,但假如防止措施一旦设置好,就可以完全缓解任何XSS攻击。不过根据我的观察,目前大多数团队的开发人员资源都很有限,要完成这些安全措施几乎是不可能的。
在某些情况下,白名单可能是有效的,比如允许一些选择性标记,比如留言板,但这些情况很少,需要额外谨慎,以确保安全完成。
2.3对输入数据进行编码,这就更不可行了,因为不同位置的数据会需要不同的编码。在输入数据的时候,你是不可能知道所有可能的输入数据以后的用法。这就好比,在许多系统中,数据会从网页前端以外的地方(例如日志文件)进入系统。
关于WAF的防护效果
虽然我强烈支持使用Web应用防护系统(Web Application Firewall, 简称WAF) ,但WAF也采用了黑名单技术,所以也可以被绕过,不过绕过过程并不是不容易,不过这是保护XSS的辅助措施。所以我建议你不要太过于依赖它。主要的防止措施还是使用输出编码和CSP。
如何测试你的应用程序中的XSS?
由于防止XSS的首要措施是根据输出的上下文进行适当的编码,因此在测试中需要找到没有经过任何过滤处理的输出。在测试环境中,禁用CSP、WAF和任何输入过滤器,通过禁用这些辅助保护,测试工具将更容易找到没有被正确编码的字符输出。千万注意,不要在真实的运行环境中进行测试,因为存储或持久的XSS会对你浏览过的站点进行攻击,另外不适当的测试还会向攻击者透露潜在的其他问题。
目前有许多自动化工具都可以提供XSS漏洞的测试,如Burp或AppScan。AppScan是对网站等WEB应用进行安全攻击,通过真刀真枪的攻击,来检查网站是否存在安全漏洞
总结
根据数据所在的上下文,使用适当的输出编码或WAF可以防止XSS攻击。不过最好的预防措施是找一个可以自动为你处理输出编码的框架,然后把CSP作为一个强大的辅助措施。另外就是在测试正确的输出编码时,禁用所有的输入过滤器,如白名单、黑名单、WAF并删除CSP。