php 防御url类型xss,资料分享 | XSS防御速查表

原标题:资料分享 | XSS防御速查表

写在前面

之前翻译了OWASP的XSS过滤绕过速查表,这篇也算是个后续。文中的翻译尽可能保持原文格式,但一些地方为了通顺和易于理解也做了一定改动,如有翻译问题,还请各位大牛指正。本文翻译时版本是20171014,后续如果有大更新的话也会跟进更新。

一、介绍

本文提供了一种通过使用输出转义/编码来防止XSS攻击的简单有效模型。尽管有着庞大数量的XSS攻击向量,依照下面这些简单的规则可以完全防止这种攻击。这篇文章不会去研究XSS技术及业务上的影响。简而言之,受害者能在其浏览器上做的任何事情攻击者都可以通过XSS实现。

fe944ec9660d095f68418016514887c6.png

反射型和存储型XSS都可以在服务器端进行适当的验证和转义。基于DOM的XSS可以通过基于DOM的XSS防御指南中的一系列子规则进行防御。如果想查找XSS相关攻击向量,可以参考XSS过滤绕过速查表。更多的浏览器安全背景知识以及各种浏览器知识可以在浏览器安全指南中找到。

阅读本文之前,有注入原理的基础知识是很重要的。

1.1. 一个有效的XSS防御模型

这篇文章将一个HTML页面视为一个模板,其向开发者提供可以向其中放置不可信数据的位置。这些位置覆盖了开发人员可能希望放置不可信数据的大多数地方。在向其它HTML位置放置不可信数据是不被允许的。这是一个“白名单”模型,其会拒绝任何没有特殊允许的内容。

f59a2d4a502c1683588e16b6be07c7cf.png

根据浏览器解析HTML的不同,不同位置的安全规则也会有所不同。当你将不可信数据放在这些位置时,你需要采取一定步骤来确保数据不会从该位置逃逸到其他内容中导致代码执行。在某种程度上,这种方法将HTML文档视为参数化的数据库查询-数据在特定的位置并且进行转义以便与代码隔离。

本文列举了大多数常见位置类型以及将不可信数据安全的放在其中的规则。基于多种已知类型的XSS攻击向量和大量在流行浏览器上的实际测试,我们在这里提供的安全规则都是可靠的。

我们定义了这些位置以及每个位置都提供了样例。开发人员不应该在没有经过仔细分析确保他们所做的事情是安全的前就将数据放在其他位置。浏览器如何进行解析是十分令人头疼的事情,很多看上去无害的字符在不同上下文中也必须格外注意。

1.2. 为什么不能仅对不可信数据进行HTML实体编码?

对于放在HTML文档body中的不可信数据进行HTML实体编码是没有问题的,比如在

标签中。编码后甚至可以在属性中引用不可信数据,特别是使用引号将属性包含的时候。但是HTML实体编码在当你将不可信数据放到任何地方的 直接放置在内 放在HTML注释内 放在属性名 放在标签名内 直接放在CSS中

最重要一点,绝对不要接受并执行不可信数据中的Java代码。例如,一个叫“callback”的参数包含了Java代码片段。再多的转义也不能解决这个问题。

2.2. 规则#1-将不可信数据插入HTML元素内容前进行HTML转义

规则#1是为了当你想将不可信数据直接放到HTML body里时设立的。这其中包括普通标签例如div, p, b, td等等。大多数Web框架都会有一个HTML转义方法来转义下面列出的字符。

...将不可信数据放在这前进行转义... ...将不可信数据放在这前进行转义... 其它普通HTML元素

使用HTML实体编码转义下列字符,以避免代码变成可执行内容,例如,style或eventhandlers。推荐使用十六进制转义。除了XML中显著的5个字符外(&, , “, ‘),前斜杠也应该包含在内,因为它有助于结束HTML实体。

& --> & < --> < > --> > " --> " ' --> ' '不推荐使用因为其不在HTML语法中。'存在于XML和XHTML语法. / --> / 包含前斜杠是因为它有助于结束HTML实体

2.3. 规则#2-将不可信数据插入HTML常规属性前将属性进行转义

规则#2是为了将不可信数据放到典型属性里例如width, name, value等而设立的。这些不应该用在复杂属性例如href,src,style或任何event handler例如onmouseover。尤其重要的是event handler属性应该遵循为Java数据值准备的规则#3。

content 在无引号属性间 content 在单引号属性间 content 在双引号属性间

除了字母以外,转义所有ASCII值小于256的字符为HH; 形式(或者命名实体形式)来防止值逃逸出属性。这么做的原因是开发者经常将属性设为无引号的。正确使用引号包含的属性只能被未转义的引号破坏。无引号包含的属性则可以由很多字符打断,包括[空格] % * + , – / ; < = > ^ 和|。

2.4. 规则#3-将不可信数据插入Java数据值时对Java转义

规则#3关注动态生成的Java代码-包括块和event-handler属性。唯一安全的位置放置不可信数据是被引号包含的“数据值”。在任何其他的Java内容中包含不可信数据都是十分危险的,因为遇到包括(但不限于)分号、等号、空格、加号和其他字符时很容易变成可执行内容,所以请谨慎使用。

在被引号包含的字符串 被引号包含的表达式 被引号包含的event handler

请注意有一些Java函数永远不可能安全的使用不可信数据作为输入-即使Java已经转义!

示例:

除了字母以外,转义所有ASCII值小于256的字符为\xHH的形式来防止数据值进入脚本内容或者其他属性。不要使用任何转义方法如\”因为引号可能被HTML属性解析时优先配对。这种转义方法容易受到“转义逃脱”攻击,攻击者可以发送\”然后存在漏洞的代码就会将其转换为\\”,这样引号就正常解析了。

如果一个event handler被引号正确包含了,打破包含就需要未被转义的引号。然而,我们有意让这条规则更加广泛,因为event handler属性经常是无引号包含的。无引号包含的属性则可以由很多字符打断,包括[空格] % * + , – / ; < = > ^ 和|。同样一个闭合标签会结束脚本块即使它是被引号包含的字符,因为HTML解析器在Java解析器前运行。

2.4.1 规则#3.1-转义HTML内容中JSON值并由JSON解析器读取数据

在Web2.0的世界里,需要由Java内容动态的生成数据是很常见的。一种方式是通过AJAX方法来获取值,但这不总是高效的。通常,加载一个初始化的JSON块到页面中来存储一系列数据。在这数据中插入攻击代码是困难的,但不是不可能的。只要正确的转义就可以不破坏格式和值的内容。

确保系统返回的Content-Type头部是application/json而不是text/html。这保证了浏览器不会误解内容并执行注入代码。

错误的HTTP响应

HTTP/1.1 200 Date: Wed, 06 Feb 2013 10:28:54 GMT Server: Microsoft-IIS/7.5.... Content-Type: text/html; charset=utf-8

正确的HTTP响应

HTTP/1.1 200 Date: Wed, 06 Feb 2013 10:28:54 GMT Server: Microsoft-IIS/7.5.... Content-Type: application/json; charset=utf-8

一个常见的反模式是:

2.4.1.1 JSON实体编码

JSON编码规则可以在下面的输出编码规则汇总查看。注意这将不允许你使用CSP1.0提供的XSS保护。

2.4.1.2 HTML实体编码

这种技术的优点是HTML实体编码是广泛支持的,并且其帮助从服务器端分离数据而不用跨越内容边界。考虑将JSON块作为页面中的一个元素然后解析innerHTML来获得内容。读取这部分的Java可以放在一个外部文件,这样就让CSP更加容易执行。

// 外部js文件 var dataElement = document.getElementById('init_data'); //解码并解析div的内容 var initData = JSON.parse(dataElement.textContent);

另一种在Java中转义和解析JSON的方法是在发送到浏览器前由标准的JSON服务器端转换’

2.5. 规则#4-将不可信数据插入HTML样式属性前对CSS进行转义和严格验证

规则4是为了当你想将不可信数据放在一个样式表或style标签中准备的。CSS惊人的强大,可以用于许多攻击。因此,只在属性值中使用不可信数据并且不在其它地方的样式数据使用是非常重要的。你应该让不可信数据远离复杂的属性,例如url, behavior, 和custom (-moz-binding)。你也不应该将不可信数据放在IE的表达式类型属性值里,它是允许Java的。

属性值 属性值 text属性值

注意一些CSS内容永远不可以安全的使用不可信数据作为输入-即使CSS进行了转义!你需要确保URL只能以”http”开头而不是java”,并且还需要确保属性值不可以以”expression”开头。

例如:

{ background-url : "java:alert(1)"; } // 和其他所有URL { text-size: "expression(alert('XSS'))"; } // 仅IE有效

除了字母以外,转义所有ASCII值小于256的字符为\HH形式。不要使用类似\”形式的转义方法因为引号字符可能会被先执行的HTML属性解析器所错误配对。这种转义方法容易受到“转义逃脱”攻击,攻击者可以发送\”然后存在漏洞的代码就会将其转换为\\”,这样引号就正常解析了。

如果属性被引号包含,那么需要未被转义的引号才能打破。所有的属性都应该被引号包含但是你的编码应该足够强以便在不可信数据放在未被引号包含位置时防止XSS。未被引号包含的属性可以被许多字符打破,包括[空格] % * + , – / ; < = > ^ 和 |。同样标签也可以闭合style块即使是在被引号包含的字符串内,因为HTML解析器在Java解析器之前运行。请注意我们建议同时进行CSS编码和验证来防止在引号包含区域和未被引号包含区域出现XSS攻击。

2.6. 规则#5-将不可信数据插入HTML URL参数值前对URL进行转义

规则#5是为当你想要将不可信数据放在HTTPGET参数值时使用的。

link

除了字母以外,转义所有ASCII值小于256的字符为%HH形式。包括的数据中的不可信数据:URL不应该被允许,因为通过转义也不能很好防止逃逸出URL进行攻击。所有的属性都应该被引号包含。未被引号包含的属性可以被许多字符打破,包括[空格] % * + , – / ; < = > ^ 和 |。注意实体编码在这里是无用的。

警告:不要用URL编码对完整或相对URL进行编码!如果不可信的数据是指被放置在href, src或其它基于URL的属性时,需要进行验证确保它不会被指向其它的协议,尤其是Java链接。URL随后才可以根据上下文进行编码。例如,用户在HREF中输入的URL应该被编码。示例:

String userURL = request.getParameter( "userURL" ) boolean isValidURL = Validator.IsValidURL(userURL, 255); if (isValidURL) { link }

2.7. 规则#6-使用专门设计的库来过滤HTML Markup

如果你的应用支持Markup——不可信的输入可能包含在HTML中——这可能很难进行验证。编码同样也很困难,因为它会破坏输入中所有可能的标记。因此,您需要一个能够解析和清除HTML格式文本的库。OWASP就提供了一些可用的并且很容易使用:

HtmlSanitizer -https://github.com/mganss/HtmlSanitizer

一个开源的.Net库。它用白名单的方法清理HTML。可以设置允许的标签和属性。这个库通过了OWASP的XSS过滤绕过速查表验证。

var sanitizer = new HtmlSanitizer(); sanitizer.AllowedAttributes.Add("class"); var sanitized = sanitizer.Sanitize(html);

OWASP Java HTML Sanitizer -https://www.owasp.org/index.php/OWASP_Java_HTML_Sanitizer_Project

import org.owasp.html.Sanitizers; import org.owasp.html.PolicyFactory; PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS); String cleanResults = sanitizer.sanitize("

Hello, World!");

更多的OWASP Java HTML Sanitizer使用规则信息,请参考https://github.com/OWASP/java-html-sanitizer

Ruby on Rails SanitizeHelper -http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html

SanitizeHelper模块提供了一系列处理HTML元素中非预期内容的方法。

其它提供HTML清理功能的库包括:

PHP HTML Purifier – http://htmlpurifier.org/

Java/Node.js Bleach – https://github.com/ecto/bleach

Python Bleach – https://pypi.python.org/pypi/bleach

2.8. 规则#7-防御基于DOM的XSS

了解更多基于DOM的XSS,以及如何防御此类XSS,请查阅OWASP的基于DOM的XSS防御指南。(https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet)

2.9. 附加规则#1:使用HTTPOnly cookie标志

正如你所见,在应用里防御所有的XSS是很困难的。为了帮助减轻XSS对网站的影响,OWASP推荐为会话cookie和任何自定义的cookie启用HTTPOnly标志,以防止它们被你所写的任何Java访问。这种cookie标志在.NET应用中是默认启用的,但在其它语言中你必须手动设置。了解HTTPOnlycookie标志的更多细节,包括它是什么和它如何工作,请查阅OWASP关于HTTPOnly的相关文章。

2.10. 附加规则#2:使用内容安全策略

另一个减少XSS影响的复杂方案是使用内容安全策略。这是一个浏览器端的方案,它允许你为你的Web应用客户端资源创建一个白名单,限制范围包括Java、CSS、图像等等。CSP(ContentSecurity Policy)通过特定的HTTP头部告诉浏览器只执行或呈现指定来源的内容。CSP的示例如下:

Content-Security-Policy: default-src: 'self'; -src: 'self' static.domain.tld

上面的示例会告诉浏览器只加载来源是当前域的资源,对于Java文件则除当前域外,可以额外从static.domain.tld加载。了解更多内容安全策略的细节,包括如何工作和如何使用,请参考OWASP相关文档(https://www.owasp.org/index.php/Content_Security_Policy)

2.11. 附加规则#3:使用自动转义功能

很多Web框架都会提供自动转义功能,例如AngularJS就提供了类似功能。尽量在有条件的情况下使用这些功能。

2.12. 附加规则#4:使用X-XSS-Protection响应头

这个HTTP响应头部会启用在一些新版本浏览器中内置的跨站脚本过滤功能。这个头部通常是默认启用的,所以大多数时候添加头部的作用是为了当用户关闭浏览器过滤功能时,为特定站点重新启用过滤功能。

三、XSS防御规则汇总

下面几段HTML示例展示了如何在不同情况下安全的处理不可信数据。

数据类型内容位置代码样例防御方法字符串HTML Body不可信数据HTML实体转义字符串安全的HTML属性不可信数据“>l严格HTML实体转义l只将不可信数据放在白名单(下面给出)中的安全属性中l严格检查不安全的属性,例如background, id及name字符串GET参数不可信数据 “>clickmeURL转义字符串SRC中的不可信URL或HREF属性不可信URL“>clickme不可信URL” />

l 规范化输入 l URL 验证 l 安全URL认证 l 只允许白名单内http和https URL(注意防止Java打开新窗口) l 属性编码器 字符串 CSS
不可信数据 ;”>Selection
l 严格对结构进行验证 l 使用Hex转义CSS l 正确设计CSS特性 字符串 Java 变量 <>var currentValue=’ 不可信数据 ‘;> <>someFunction(‘ 不可信数据 ‘);> l 确保Java变量被引号包含 l 使用Hex转义Java l 使用Unicode转义Java l 避免反斜杠转义(\” 或 \’ 或\\) HTML HTML Body
不可信HTML
规范化HTML (JSoup, AntiSamy, HTML Sanitizer) 字符串 DOM XSS <>document.write(“ 不可信输入 : ” + document.location.hash);> 参考防御基于DOM的XSS

安全的HTML属性包括: align, alink, alt, bgcolor,border, cellpadding, cellspacing, class, color, cols, colspan, coords, dir,face, height, hspace, ismap, lang, marginheight, marginwidth, multiple, nohref,noresize, noshade, nowrap, ref, rel, rev, rows, rowspan, scrolling, shape,span, summary, tabindex, title, usemap, valign, value, vlink, vspace, width

四、输出编码规则汇总

输出编码(与跨站脚本有关)的目的是在用户输入作为数据显示的时候,转换不可信的输入为安全形式,以避免被浏览器当做代码执行。下面的表格列出了阻止跨站脚本的关键输出编码方法。

编码类型 编码规则
HTML实体转义 转换 & 为 & 转换 < 为 < 转换 > 为 > 转换 ” 为 " 转换 ‘ 为 ' 转换 / 为 /
HTML属性编码 除了字母,转换所有字符为HH;形式,包括空格(HH = Hex数值)
URL编码 标准的编码请参考http://www.w3schools.com/tags/ref_urlencode.asp。URL编码应该只用于参数部分,而不是整个URL或URL路径部分。
Java编码 除了字母,转换所有字符为\uXXXX的unicode转义形式(X=整数)
CSS Hex编码 CSS转义支持\XX和\XXXXXX的形式。如果下一个字符会继续转义序列,那使用两个字符的转义形式可能会出现问题。有两种解决办法(a)在CSS转义后添加一个空格(会被CSS解析器忽略)(b)使用0填充以实现完整的CSS转义格式。

五、作者和主要编辑者

Jeff Williams – jeff.williams[at]contrastsecurity.com

Jim Manico – jim[at]owasp.org

Neil Mattatall – neil[at]owasp.org

版权与许可

版权所有:OWASP基金会©

本文档基于 Creative Commons Attribution ShareAlike4.0license 发布。任何重用或发行,都必须向他人明确该文档的许可条款。 http://creativecommons.org/licenses/by-sa/4.0/

中文翻译:walletong@ansion

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中可以通过以下几种方式来防御XSS攻击: 1. 输入验证和过滤:对用户输入的数据进行验证和过滤,确保只接受合法的输入。可以使用正则达式或者特定的输入验证库来过滤用户输入,例如Apache Commons Validator库。 2. 输出编码:在将用户输入的数据输出到网页上时,使用合适的编码方式对数据进行转义,以防止恶意代码的执行。常用的编码方式包括HTML实体编码、URL编码和JavaScript编码。 3. 使用安全的HTML标签和属性:限制用户输入中可以使用的HTML标签和属性,只允许使用安全的标签和属性,可以使用HTML过滤器库来实现。 4. 使用安全的模板引擎:如果在项目中使用了模板引擎,确保选择一个安全的模板引擎,该引擎能够自动对输出进行编码,以防止XSS攻击。 5. 使用HTTP头部设置:在HTTP响应中设置适当的Content-Security-Policy(CSP)头部,限制页面中可以加载的资源和执行的脚本,以减少XSS攻击的风险。 6. 使用XSS过滤器:可以自定义一个XSS过滤器,在过滤器中对用户输入进行检查和处理,过滤掉恶意代码。可以参考引用中的示例代码。 ```java public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 使用包装器 XssFilterWrapper 对请求参数进行过滤 XssFilterWrapper xssFilterWrapper = new XssFilterWrapper((HttpServletRequest) servletRequest); filterChain.doFilter(xssFilterWrapper, servletResponse); } @Override public void destroy() { } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值