héros bg sans séparateur
Lignes directrices

注入-XSS

跨站脚本(也称为 XSS)是另一种注入漏洞,它会导致在其他用户的浏览器中评估攻击者控制的脚本。XSS 也可以被视为 HTML/JavaScript 注入漏洞。

XSS 漏洞的影响在很大程度上取决于漏洞存在的环境。其范围包括能够从运行脚本的页面中提取信息,以及编辑页面的状态以在页面上以受害者身份执行操作。

让我们来看看你可以遇到的 XSS 类型。

XSS 类型

XSS 可以分成几个存储桶以帮助区分它们。它们按有效载荷的交付方式和入口点的位置进行分类。

有效载荷交付矢量(存储与反射)

攻击者可以通过两种方式提供 XSS 有效载荷:

  • 存储的 XSS: 例如,通过存储在数据库中的用户控制数据,将数据呈现给其他用户
  • 反射式 XSS:通过用户提供的有效负载传递给用户浏览的 URL/查询字符串

关键区别在于,Reflected XSS通常取决于用户交互,并且仅影响使用恶意负载打开链接的用户。但是,只需打开一些呈现有效负载的页面,就可以对一个或多个用户执行 Stored XSS。

有效载荷位置(DOM 与非 DOM)

负载注入的位置决定了您是否将该漏洞归类为 “DOM” 漏洞。这是指有效载荷的渲染位置之间的区别:

  • 非 DOM XSS: 负载在 HTML 中呈现,无论是在标签内还是属性内
  • DOM XSS: 有效负载在 JavaScript 中呈现,比如 `<script>`标签,或诸如 `onclick= "" 之类的事件处理程序

XSS-防御原语

在本节中,将探讨作为防御 XSS 基础的原理原理。了解其基础知识至关重要,但实际上,您应该依靠模板库来实现 99% 的 XSS 防护。

当你编写呈现给在浏览器中运行的标记或代码的模板时,防范 XSS 的关键是*编码*。在这种情况下,编码意味着采用一系列字符并将其更改为一种由解释器以特定方式处理的格式。

但是使用的编码类型取决于使用数据的位置或上下文。

  • 在标签内,比如 “<div>用户在此处输入</div>”:**HTML 编码**
  • 在属性内部,比如<input placeholder="User input here"></input> `: **属性编码**
  • 在 JavaScript 中,比如 `<script>x = “用户在此处输入”;</script>`:**JavaScript 编码**

一些框架会放弃将编码作为其主要的防御手段,而是利用消毒来清除任何可能有危险的内容的价值。这是一个复杂得多的过程,需要考虑许多边缘案例。不建议自己实现消毒程序。

例子

让我们来看一些不同语言的示例,看看实际情况如何。

C#-不安全:剃刀

如果 `IhtmlContent` 对象以 `@`为前缀,则该值将直接放入模板中,无需进行任何编码。

<!---UNSAFE: The htmlSnippet will get interpreted without any escaping--->
@Html .Raw (HtmlSnippet)

C#-安全:剃刀

默认情况下,在 Razor 模板中,任何以 @为前缀的 “字符串” 都是 HTML 转义的。

<!---SAFE: The htmlSnippet will get HTML escaped--->
@htmlSnippet

Java-安全:JSP

当使用 `c: out` 时,默认情况下它会进行 XML 转义(可以使用 `escapeXML` 属性进行更改),这可以防止 HTML 上下文中的 XSS,但在其他上下文中却不可以。

<div><c:out value="<%= author %>" /></div>

Java-安全:(fnxml)

与上面类似,你也可以直接调用 `fn: escapeXML`,这将使 XML 对提供给它的输入进行转义。这也只能在 HTML 上下文中提供保护。

<div>$ {fn: escapeXML(作者)}</div>

Javascript-不安全:Angular innerHT

顾名思义,通过指定 `innerHTML`属性,由于禁用输出编码,您将面临XSS的风险。

<!---UNSAFE: The htmlSnippet will get interpreted without any encoding--->
<p [innerHTML] ="htmlSnippet"></p>

Javascript-安全:角度插值

Angular 使用双花括号(`{{` 和 `}}`)对文本进行插值将 HTML 逃避其输出,从而防止 XSS。

<!---SAFE: The htmlSnippet will get encoded and then interpreted--->
<p>{{HTMLSnippet}}</p>

Javascript-不安全:React DangerousInnerHTML

顾名思义,通过指定 “DangerouslysetInnerHtml” 属性,由于禁用输出编码,你将面临XSS的风险。

<!---UNSAFE: As the name suggests, the dangerouslySetInnerHTML attribute is dangerous as it does not escape the output--->
<div dangerouslySetInnerHTML= {{__html: htmlSnippet}} />;

Javascript-安全:React 插值

React 使用大括号(`{` 和 `}`)对文本进行插值会使 HTML 逃脱其输出,从而防止 XSS 的攻击。

<!---SAFE: The htmlSnippet will get encoded and then interpreted--->
<div>{HtmlSnippet}</div>

Python-不安全:Django

如果在 Django 模板中使用 “安全” 过滤器,它将禁用输出的自动转义,因此无法防止 XSS。

<!---UNSAFE: The htmlSnippet will not get HTML encoded--->
<div>{{HtmlSnippet | 安全}}</div>

Python-安全:Django

Django 使用双花括号(`{{` 和 `}}`)对文本进行插值将 HTML 逃避其输出,从而防止 XSS。

<!---SAFE: The htmlSnippet will HTML encoded--->
<div>{{名称}}</div>