《Web应用漏洞侦测与防御:揭秘鲜为人知的攻击手段和防御技术》——2.2 部署应对措施

简介:

本节书摘来自华章计算机《Web应用漏洞侦测与防御:揭秘鲜为人知的攻击手段和防御技术》一书中的第2章,第2.2节,作者:(美) 希马(Shema, M.)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 部署应对措施

“没有先例的复杂状况需要没有先例的法规。”——夏洛特·勃朗特,《简爱》。
跨站脚本漏洞从其他Web攻击中脱颖而出,因为它们对Web应用程序和浏览器均有效。在最常见的场景中,必须首先攻破某个网站才能够将它作为有效负载的分发点,然后Web浏览器就会成为攻击代码的受害者。这意味着我们也可以从服务器和浏览器两方面部署应对措施。
只有极少数的浏览器市场占有率能够超过1%。用户只能指望那些供应商(Apple、Google、Microsoft、Mozilla、Opera)提供浏览器内置防御。当前很多流行的浏览器(Safari、Chrome、IE、Firefox)包含一定程度的反XSS能力。特别值得一提的是FireFox的NoScript插件(http: //noscript. net/),它还可以作为配置管理中的练习。在第8章中将会对浏览器安全性做更多介绍。
防止XSS攻击最好是在Web应用程序本身中实现。HTML、JavaScript和国际化语言支持的复杂性使得这个任务对于安全意识很强的开发人员而言都是很大的挑战。
2.2.1 确定静态字符集
即便不考虑恶意内容,字符编码和解码也非常容易出现错误。应当为网站中将要显示动态内容的页面均明确设置字符集。可以通过Content-Type标头或经由http-equiv属性使用HTML META元素来实现这一点。
站点的书写语言、用户数和支持库等因素都会影响字符集的选择。来自流行网站的一些实例见表2.5。
image

HTML4没有在这方面提供任何指导,导致过去的浏览器必须在前256字节甚至前1024字节中的内容进行查看。HTML5规范草案强烈警告实现者在嗅探HTTP响应的MIME类型时,必须遵循严格的算法。MIME嗅探影响浏览器的行为,而不仅仅是HTML的内容。
HTML5规范中的警告就是通过设计增强安全性的例子。如果浏览器或任何想要符合HTML5的用户代理能够按照清晰统一的方法进行内容解析,那么就不会出现那么多由于不匹配的实现或臭名昭著的浏览器怪异模式所引发的问题,这些问题使得编写真正跨浏览器的HTML4文档非常困难。更多关于MIME嗅探的标准演变可以查看http: //mimesniff. spec. whatwg. org/和http: //tools. ietf. org/html/draft-ietf-websec-mime-sniff-03。
这种标准化步骤的推论就是为所有用户提供内容的类型信息应当尽可能明确。如果网站期望用户上传图像文件,那么除了确保文件是正确格式的图像,同时还要确保Web服务器给它们提供正确的MIME类型。Apache服务器具有DefaultType和ForceType指示,能够以目录为单位设置内容类型。例如:下面的httpd. conf文件片段确保将/css/目录解释为text/css。这对于希望允许用户上传自定义CSS模板的共享托管网站非常重要。它防止恶意用户将JavaScript放置在模板中(假定因为安全性的原因不允许JavaScript),还能够防止用户试图在服务器上执行代码,例如在CSS文件中加入< ?php…?>标签,从而欺骗服务器将文件传递到PHP模块。
image

Web应用程序提供的所有资源都应显式声明Content-Type,从而避免内容产生歧义。所有资源都应具有Content-Type标头,并且为HTML资源定义相应的< meta>元素。任何有疑问的内容都应默认为text/plain(或对DOM、Security Origin、其他浏览器属性等不具备访问权限的适当的媒体类型)。
DefaultType不会覆盖Apache能够无歧义确定的文件的内容类型。ForceType使用定义的类型对文件进行处理,无论文件实际是什么类型。这个配置选项是核心httpd引擎的一部分,关于这个配置选项的更多信息,可以查看http: //httpd. apache. org/docs/current/mod/core. html#default type和http: //httpd. apache. org/docs/current/mod/core. html#forcetype。
2.2.2 规范化字符集及编码
一类常见的漏洞被称为竞态条件(Race Condition)。竞态条件发生在敏感令牌的值(可能是安全上下文标识符或一个临时文件)在验证其有效性与使用其值之间被修改了。这通常被称为time-of-check-to-time-of-use(TOCTTOU或TOCTOU)漏洞。在本书撰写过程中,OWASP(一个面向Web漏洞的网站)对TOCTOU的描述的最新更新是在2009年2月21日。要知道计算机安全的出现早于社交网络和cute cat网站,竞态条件的最早讨论是在1976年。
XSS过滤程序和字符集也表现出同TOCTOU的概念类似的问题。首先会对输入字符串进行扫描以查找恶意字符(检测时间,time of check),然后对字符串中的一些字符进行解码并写入到一个Web页面中(使用时间,time of use)。即使有些解码是发生在检测时间之前,Web应用程序或它的代码仍可能会执行其他的解码步骤。这就是发挥规范化的作用的地方。
规范化是将输入字符串转换成固定字符集最简单表示形式的过程。例如,将所有百分号编码字符进行解码,验证多字节序列以表示单个字形,处理无效序列(删除、拒绝、替换)。用竞态条件比喻这个安全性过程,可以比作TONTOCTOU,即time of normaliztion,time of check,time of use。
对输入及输出都要考虑进行规范。
应该拒绝无效序列,将过长序列(使用比所需字节更多的字节表示)视为无效。
以技术为导向。Unicode规范化过程应该使用Normalization Form KC(NFKC)以减少基于字符攻击的成功机会。这基本意味着该规范化过程将产生一个最简洁的表示期望的字符串的字节序列。

2.2.3 对输出进行编码
如果来自浏览器的数据将会重新显示在Web页面中,那么无论使用HTML编码还是百分号编码,在DOM中都应当对数据正确地编码。这个步骤独立于规范化或确定固定字符集。HTML编码使用实体引用表示一个字符,而不是它的显式字符代码。不是所有的字符都有实体引用,但在XSS有效负载中用于重写DOM的特殊字符有实体引用。HTML4规范定义了可用的实体。表2.6显示了4种最常见的实体。
image

对具有操纵DOM潜力的特殊字符进行编码,对于防止XSS攻击很有帮助。
image

当来自客户端的数据要写入到href属性或类似属性时,使用百分号编码也能获得类似的好处。将双引号编码为%22能够使得它无害,同时还能够为链接保留它的含义。这经常发生在重定向链接中。
不同的输出目的地需要不同的编码步骤以保持数据的意义。最常见的输出区域如下所示:
HTTP标头(如Location或Referer),当然,在很多场景中,对这些位置进行漏洞利用不可能或者很困难。
元素内的文本节点,比如div标签之间的“Welcome to the Machine”。
元素的属性,如href、src,或value属性。
样式属性,比如有些网站会给用户提供“换肤”功能来更改外观和感受。
JavaScript变量。
在每个区域中都要审查带有特殊意义的字符。例如,如果一个属性括在双引号之内,那么要插入到该属性的任何用户提供的数据都不应该包含原始的双引号,要将这个双引号进行百分号编码(%22)或使用它的HTML实体(")。
2.2.4 当心排除列表和正则表达式
“有些人在遇到问题时会这么想,‘我知道,我将使用正则表达式解决此问题’”,但实际上又引入了一个新的问题:正则表达式问题。”
仅仅依靠排除列表注定会失败。排除列表需要维护才能够应对不断变化的攻击向量和编码方法。
正则表达式是一个强大的工具,但是它的复杂性是把双刃剑。开发人员有可能过于依赖正则表达式作为安全性措施,也可能会误用或误解正则表达式。RFC 2822定义了著名的正则表达式来精确地匹配电子邮件地址格式(http: //www.regularexpressions.info/email.html),这个表达式包含了426个字符。如果谁真的花时间去充分理解那个正则表达式,要么是被搞到疯狂,要么就是喜欢精神上受虐待。当然,获得接近100%的匹配可以通过少很多的字符来完成。请考虑一下两点:1)如果安全机制不完善或有错误,它们“接近100%”安全而不是100%安全,则会出现漏洞;2)正则表达式产生的解析器很差,即便对于适度简单的语法也是如此。
幸运的是,多数用户输入会归类到比较明确的类别当中。这里的关键词是“比较”。正则表达式擅长匹配字符串内的字符,但若用来匹配不应当在字符串中出现的字符或序列时,就会变得复杂低效起来了。
根据输出位置的不同,任何来自客户端的内容(无论是来自Web浏览器的标头值还是用户提供的文本)只应该用一个或两个自定义函数写入到Web页面中。无论Web应用程序使用什么偏程语言,替换该语言的内置函数,例如echo、print、writeln等,采用的替代函数应当被设计为对特殊字符使用正确编码,以便将不可信内容写入到页面。这会使得开发人员考虑将要显示到页面的内容,并有助于代码审查中识别出遗漏或容易产生错误的区域。
现在你已经知道不能过于信任正则表达式,而下面这些准则可以帮你成功地使用正则表达式:
使用规范化字符串。在合适的时机对HTML编码字符和百分号编码字符进行解码。
在安全边界应用正则表达式,所谓边界是指数据会被修改、存储,或渲染到网页的地方。
使用正则表达式引擎能够理解的字符集。
使用白名单或者基于包含的方法。匹配允许的字符,当有不允许的字符出现时,拒绝该字符串。
使用^和$锚点来匹配整个输入字符串边界。
拒绝无效数据,不要试图通过猜测数据中哪些字符应该被去掉或者被替换掉来重写它。所谓的“修复数据”会导致意想不到的结果。
如果要从输入中删除无效数据,递归地应用过滤程序并应完全清楚这次删除会对输入产生怎样的转变。如果你希望从所有输入中去除“< script”,从而防止script标签的出现,试着用你的过滤程序对“< src< scriptipt>”进行过滤,会看到令你吃惊的结果。
不要以安全扫描程序使用的成块有效负载作为你的测试用例,攻击者不会使用那些有效负载。alert()函数在探测网站漏洞时用起来很方便,但是真正的有效负载并不关心启动弹出窗口。
要清楚什么时候使用分析程序更适合完成任务,例如处理HTML元素和属性,或者处理JavaScript。正则表达式适合检查数据的句法,分析程序适合检查数据的语义。验证输入字符串的可接受的语义是防止HTML注入攻击的关键。
在合适的地方使用perlre空白前缀(?x)使得模式更易读(这等同于PCRE库中的PCRE_EXTENDED可选标志和BOOST. Regex库中的mod_x句法选项。这两个库的模式中都接受(?x))。这样可以忽略模式中的非转义空白字符,因此可以让创建者有更多的灵活性,使得模式对人来讲更加直观、容易理解。
一次魂不守舍的防御
2009年8月,Twitter API被爆出存在XSS漏洞。人们只要查看了带有有效负载的twitter,他们的浏览器就会被感染。James Slater发现了该漏洞并提供了概念验证。Twitter迅速回应说已经进行了修复。然后该修复又被攻破。
修复?只不过是不允许输入空格而已,这个“壮举”可以很容易通过正则表达式来完成,甚至在很多编程语言中通过本地函数也能实现。显然,没有空格字符并不会对XSS漏洞利用产生阻碍。这种黑名单解决方法不仅失败了,而且还说明了他们对击败XSS攻击的问题空间缺乏理解。
2.2.5 重用代码,不要重新实现代码
密码函数是从头实现算法带来危险的终极范例。如果不听从劝告:“不要创建自己的密码函数”,结果会同在恐怖电影中穿过怪异房间时无视“不要分散”一样可怕。其他与阻止HTML注入攻击相关的函数也是如此,例如字符集处理、将字符转换为HTML实体、过滤用户输入等。
另外一个重用代码比从头实现更好的例子是框架。在JSON一节中列出了几个JavaScript框架。比较流行的Web语言,如Java、. NET、PHP、Perl、Python、Ruby,都有库用于处理Web开发的各个方面。
当然,重用不安全的代码并不比重新写不安全的代码更好。Javascript框架的优势是能够减少程序员犯错的可能,或是将犯错的可能转移到应用程序的其他位置,通常是业务逻辑。本书第6章给出了关于利用网站业务逻辑的例子。
Microsoft. NET Anti-XSS库和OWSAP AntiSamy工程是两个专门针对安全的框架。它们提供针对XSS攻击的防御。
2.2.6 JavaScript沙盒
本章几乎都是在展示运行不可信JavaScript所固有的危险,网站仍然接纳了这一切,看上去是不是很离奇?大型的网站希望解决的问题是吸引并保持用户。安全性固然重要,但在经济收益面前,它不会成为创新的障碍。
各个网站相互竞争着提供更多动态内容,还提供API来开发适合主站点的第三方“weblets”或者基于浏览器的小应用程序。对一个网站而言,第三方应用程序是吸引更多用户和开发人员的好方法,这样做可以将网站变为信息收集的平台,最终可以通过一种可靠的方式来赚钱,即卖广告。
实现沙盒的基本方法是在一个命名空间中执行不被信任的代码,这个命名空间可能允许访问站点中特定的JavaScript函数,但除此之外都在封闭环境下执行。这点跟iPhone为其App所使用的模式和几年前实现Java采用的模式类似。
过去,像Google和Facebook这样的公司创建了浏览器内置框架来对不信任的JavaScript应用沙盒技术。像Caja和FBJS这样的项目以复杂的编码为代价提供安全性,没有使用任何来自浏览器的本地支持。HTML5的到来使得Web应用程序能够在浏览器的全力支持下实现安全性。浏览器的设计趋势是使用创建更严格同源策略的方法,从而减少出错的可能。之所以这样做,是为了满足Web开发人员创建复杂网站的需要,此类网站在保护用户数据的同时,还支持用户玩游戏或与网站中同一个域的其他第三方内容进行交互。
HTML5< iframe>沙盒
HTML5在安全方面的改进之一就是为< iframe>标签引入了sandbox属性。这使得iframe的内容进一步和文档分离,哪怕iframe和内附文档是从同一个域加载的。这样就提高了在iframe中处理不信任输出的安全性,例如社交网站中的网页游戏。
接下来我们会用两个小的HTML页面来展示sandbox属性。第一个页面包含一个定义了JavaScript变量的< script>块,这个变量的作用范围是文档的浏览上下文(browsing context)的全局范围(global scope)。HTML5规定,“浏览上下文是将Document对象展现给用户的环境”。这就主要意味着一个窗口定义了一个单独的浏览上下文,而< iframe>、< frame>、< framset>定义了新的、单独的浏览上下文。这对于理解同源策略和浏览器安全性非常关键。下面的代码有两个浏览上下文,一个用于根据内容所创建的文档,另一个是为< iframe>标签创建。我们将这个页面称为iframe. html(参见表2.7)。
image

Iframe的源码是从下面的代码中获取的,我们将这个代码称为script. html。为了示范sandbox属性的不同行为,这两个页面应当从同一个域中加载。

image
image

类似的浏览上下文限制可以通过设置将要传送到iframe或其他嵌入式上下文的资源的Content-Type标头来实现,将该标头的值设置为text/html-sandboxed即可。
要注意的是可以在iframe. html的浏览上下文内的任何地方访问JavaScript变量g,但是是如果从script. html中访问则会提示该变量未定义。不论是否提供sandbox属性,均会如此。根据sandbox属性的值的不同,script. html文件行为会受到进一步影响。下面的表总结了浏览器如何执行这一HTML5安全性设计。

2.2.7 浏览器内置XSS防御
当黑客发现一个短暂型HTML注入漏洞(有效负载仅反射到HTTP请求的立即响应中),将它转变成攻击的常用技巧是欺骗被攻击者点击包含有效负载的链接。浏览器供应商已经为浏览器创造了防御手段来检测常见的攻击场景。即便网站存在漏洞,这样做仍然能够保护用户。用户仍可能点击链接,但是浏览器会去除HTML注入的有效负载。下面的屏幕截图显示了Safari显示的错误消息。Chrome也报告相同的消息。如果你了解Safari和Chrome使用相同的呈现引擎WebKit,它们显示相同的消息就不足为奇了(根据呈现引擎之上的层级的差别,浏览器之间会产生区别,例如JavaScript引擎、隐私控制及通用特性)。Internet Explore和Firefox在它们的呈现引擎也部署了类似的防御(参见图2.21)。
如其错误消息所暗示的,浏览器内置XSS攻击防御仅能够抵御反射脚本攻击。浏览器必须执行它们从Web服务器接收到的HTML和JavaScript,否则Web连接会断开。浏览器不可能区分持久型XSS攻击和Web应用程序中包含的“安全”或合法的JavaScript。浏览器之所以可以识别出反射型XSS攻击,是因为它有参照物来判断恶意的或至少可疑的JavaScript。
image

Web浏览器的开发人员非常精明。XSS防御不采取通过正则表达式匹配已知攻击模式的黑名单方法。本章前面部分中,已经列出了模式匹配为何注定失败或因为太复杂而无法充分维护的原因。Anti-XSS防御将HTML和JavaScript元素的解析考虑在内,目的是检测潜在的攻击。了解在客户端如何检测反射XSS的最好的办法就是阅读源代码。Webkit的XSS Auditor的源码非常简洁,结构清晰,而且说明文档也很好。
如果你想要确定这种浏览器防御不会影响你的HTML注入测试,可以使用下面的标头来关闭XSS Auditor:
image

如果你不能在服务器端控制标头,配置一个代理程序来插入上述内容。
关于XSS的危险的章节怎么能不提到浏览器的同源策略呢?这一政策定义了DOM和JavaScript进行交互的一些限制。同源策略消除了利用XSS漏洞的一些方法,但是没有解决XSS的根本问题。事实上,大部分时间里被攻破的网站都在提供有效负载,而且将攻击放置在同源策略允许的区域内。为了解决浏览器的这一缺点,W3C正在制定内容安全策略(Content Security Policy)标准,为Web应用程序提供一种方法来限制浏览器如何执行JavaScript及处理潜在的不被信任的内容。内容安全策略目前还没有被浏览器广泛接受。而且也并不是添加几个HTTP标头就能使服务器变得安全。即便如此,该标准承诺能够通过安全设计以及安全实现来遏制HTML注入攻击。

相关文章
|
14天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
30天前
|
监控 Serverless 测试技术
Serverless 应用引擎常见问题之做的web服务计费如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
401 3
|
1月前
|
前端开发 数据库 UED
构建高性能Web应用的关键技术
本文将介绍构建高性能Web应用的关键技术,包括前端优化、后端优化、数据库优化等方面。通过深入讨论各项技术的原理和实践方法,帮助开发者们提升Web应用的响应速度和用户体验。
|
1天前
|
SQL 存储 前端开发
< 今日份知识点:web常见的攻击方式(网络攻击)有哪些?如何预防?如何防御呢 ? >
网络安全威胁日益严重,2017年的永恒之蓝勒索病毒事件揭示了网络攻击的破坏力。为了防御Web攻击,了解攻击类型至关重要。Web攻击包括XSS、CSRF和SQL注入等,其中XSS分为存储型、反射型和DOM型,允许攻击者通过注入恶意代码窃取用户信息。防止XSS攻击的方法包括输入验证、内容转义和避免浏览器执行恶意代码。CSRF攻击则伪装成用户执行操作,防范措施包括同源策略和CSRF Token验证。SQL注入则通过恶意SQL语句获取数据,预防手段包括输入验证和使用预编译语句。面对网络威胁,加强安全意识和实施防御策略是必要的。
|
7天前
|
缓存 负载均衡 数据库
优化后端性能:提升Web应用响应速度的关键策略
在当今数字化时代,Web应用的性能对于用户体验至关重要。本文探讨了如何通过优化后端架构和技术手段,提升Web应用的响应速度。从数据库优化、缓存机制到异步处理等多个方面进行了深入分析,并提出了一系列实用的优化策略,以帮助开发者更好地应对日益增长的用户访问量和复杂的业务需求。
11 1
|
7天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
8天前
|
Web App开发 Java 应用服务中间件
【Java Web】在 IDEA 中部署 Tomcat
【Java Web】在 IDEA 中部署 Tomcat
20 0
|
8天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
12天前
|
JavaScript 前端开发 API
Vue.js:构建高效且灵活的Web应用的利器
Vue.js:构建高效且灵活的Web应用的利器
|
20天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。