某不知名博客 某不知名博客
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carsaid

安全界的小学生
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前言

  • 服务器端主题(翻译)

  • 客户端主题(翻译)

    • 客户端主题
    • 跨站脚本(XSS)

      • 跨站脚本(XSS)
      • 反射型XSS
      • 存储型XSS
      • DOM型XSS
      • XSS上下文
      • 利用XSS漏洞
      • 悬挂标记注入
      • 内容安全策略(CSP)
      • 客户端模板注入
      • 如何防范XSS
        • 对输出数据进行编码
        • 在接收时验证输入
          • 白名单vs黑名单
        • 允许“安全”的HTML
        • 如何使用模板引擎防范XSS
        • 如何在PHP中防范XSS
        • 如何在客户端JavaScript中防范XSS
        • 如何在jQuery中防范XSS
        • 使用内容安全策略(CSP)缓解XSS
      • XSS备忘单
    • 跨站请求伪造(CSRF)

    • 跨域资源共享(CORS)

    • 点击劫持

    • 基于DOM的漏洞

    • WebSockets

  • 高级主题(翻译)

  • 扩展阅读(翻译)

  • 个人学习笔记

  • 实验室做题记录

  • BurpSuite及官方实验室
  • 客户端主题(翻译)
  • 跨站脚本(XSS)
carsaid
2023-09-14
目录

如何防范XSS

翻译

原文:https://portswigger.net/web-security/cross-site-scripting/preventing

- name: 翻译
  desc: 原文:https://portswigger.net/web-security/cross-site-scripting/preventing
  bgColor: '#F0DFB1'
  textColor: 'green'
1
2
3
4

# 如何防范XSS

在本节中,我们将介绍一些防范跨站脚本 (opens new window)漏洞的一般原则,以及使用各种常见技术来防范XSS (opens new window)攻击的方法。

跨站脚本防护 通常可以通过两层防御来实现:

  • 对输出数据进行编码 (opens new window)
  • 在接收时验证输入 (opens new window)

你可以使用 Burp Scanner 扫描你的网站,以查找包括 XSS 在内的众多安全漏洞。Burp 的尖端扫描逻辑复刻了熟练的攻击者行为,并能够实现相应的高覆盖率 XSS 漏洞。你可以使用 Burp Scanner 来确认你所做的 XSS 防御是否有效。

了解有关Burp Scanner的更多信息 (opens new window)

# 1对输出数据进行编码

在将用户可控的数据写入页面之前,应该直接应用编码,你将要写入的上下文决定了需要使用哪种编码。例如,JavaScript 字符串中的值需要与 HTML 上下文中的值 使用不同类型的转义。

在 HTML 上下文中,你应该将非白名单的值转换为 HTML 实体:

  • < 转换为: &lt;
  • > 转换为: &gt;

在 JavaScript 字符串上下文中,非字母数字值应该是 Unicode 转义的:

  • < 转换为: \u003c
  • > 转换为: \u003e

有时,你需要以正确的顺序应用多层编码。例如,在事件处理程序中,若要安全地嵌入用户输入,需要同时处理 JavaScript 上下文和 HTML 上下文。首先,你需要对输入进行 Unicode 转义,然后对它进行 HTML 编码:

<a href="#" onclick="x='这个字符串需要两层转义'">test</a>
1

# 2在接收时验证输入

编码可能是 XSS 防御中最重要的一条线,但它并不足以在每个上下文中防止 XSS 漏洞。你还应该在首次接收用户输入时,尽可能严格地验证输入。

输入验证的示例包括:

  • 如果用户提交了将在响应中返回的 URL,则验证它是否以安全的协议(如 HTTP 和 HTTPS)开头。否则,可能会有人使用有害协议(如javascript或data)来利用你的网站。
  • 如果用户提供了一个预期为数值的值,则验证该值是否包含实际的整数。
  • 验证输入是否仅包含一组预期的字符集。

理想情况下,验证输入的有效方法是——通过阻止无效输入来实现。另一种方法——尝试清理无效输入,但这种方法更容易出错,应尽可能避免使用。

# 2.1白名单vs黑名单

验证输入 通常应该使用白名单,而不是黑名单。例如,与其列出所有的有害协议(javascript,data等),不如简单地列出安全协议(HTTP,HTTPS)并禁止列表中未列出的任何内容。这将确保你的防御 在出现新的有害协议时不会中断,这使其不容易受到 试图混淆无效值 以逃避黑名单的攻击。

# 3允许“安全”的HTML

尽可能不允许用户提交 HTML 标签,但有时这是业务需求。例如,博客网站可能允许发布某些包含有限 HTML 标签的评论。

经典的方法,尝试过滤掉潜在有害的标签和 JavaScript。你可以尝试使用安全标签和属性的白名单来实现这一点,但由于浏览器解析引擎的差异 和 变种 XSS 等怪异载荷,这种方法极难安全地实现。

最好的选择,使用某些 JavaScript 库,这些库可以在用户浏览器中执行过滤和编码,例如 DOMPurify (opens new window)。一些库允许用户以 markdown 格式提供内容,并将 markdown 转换为 HTML。但不幸的是,所有这些库时不时都会出现 XSS 漏洞,因此这不是一个完美的解决方案。如果你确实使用了其中一个库,则应密切监控该库的安全更新。

笔记

除了 JavaScript 之外,CSS 甚至常规 HTML 等其他内容,在某些情况下也可能是有害的。

使用恶意 CSS 进行攻击 -> (opens new window)

# 4如何使用模板引擎防范XSS

许多现代网站使用服务器端模板引擎(如 Twig 和 Freemarker)在 HTML 中嵌入动态内容。它们通常定义自己的转义功能。例如,在 Twig 中,你可以使用e()过滤器,并使用一个参数来定义上下文:

{{ user.firstname | e('html') }}
1

其他一些模板引擎,如 Jinja 和 React,默认情况下会转义动态内容,这有效地防止了大多数 XSS 的出现。

我们建议你,在评估是否使用给定的模板引擎或框架时,仔细检查转义特性。

笔记

如果你直接将用户输入拼接到模板字符串中,则容易受到服务器端模板注入 (opens new window)的攻击,这通常比 XSS 更严重。

# 5如何在PHP中防范XSS

在 PHP 中,有一个名为htmlentities的内置函数可以用来编码实体。在 HTML 上下文中时,应调用此函数来转义输入。该函数具有三个参数:

  • 你的输入字符串。
  • ENT_QUOTES,这是一个标志,用于指定所有引号都应该编码。
  • 字符集,在大多数情况下应为 UTF-8。

例如:

<?php echo htmlentities($input, ENT_QUOTES, 'UTF-8');?>
1

在 JavaScript 字符串上下文中时,你需要对输入进行 Unicode 转义,就像前面提到的那样。不幸的是,PHP 没有提供对字符串进行 Unicode 转义的内置 API。以下是一些在 PHP 中执行此操作的示例代码:

<?php
function jsEscape($str) {
    $output = '';
    $str = str_split($str);
    for($i=0;$i<count($str);$i++) {
        $chrNum = ord($str[$i]);
        $chr = $str[$i];
        if($chrNum === 226) {
            if(isset($str[$i+1]) && ord($str[$i+1]) === 128) {
                if(isset($str[$i+2]) && ord($str[$i+2]) === 168) {
                    $output .= '\u2028';
                    $i += 2;
                    continue;
                }
                if(isset($str[$i+2]) && ord($str[$i+2]) === 169) {
                    $output .= '\u2029';
                    $i += 2;
                    continue;
                }
            }
        }
        switch($chr) {
            case "'":
            case '"':
            case "\n";
            case "\r";
            case "&";
            case "\\";
            case "<":
            case ">":
                $output .= sprintf("\\u%04x", $chrNum);
            break;
            default:
                $output .= $str[$i];
            break;
    }
    }
    return $output;
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

下面是如何在 PHP 中使用jsEscape函数的方法:

<script>x = '<?php echo jsEscape($_GET['x'])?>';</script>
1

或者,你可以改为使用模板引擎。

# 6如何在客户端JavaScript中防范XSS

要在 JavaScript 的 HTML 上下文中转义用户输入,你需要自己的 HTML 编码器,因为 JavaScript 不提供编码 HTML 的内置 API。下面是一些将字符串转换为 HTML 实体的 JavaScript 示例代码:

function htmlEncode(str){
    return String(str).replace(/[^\w. ]/gi, function(c){
        return '&#'+c.charCodeAt(0)+';';
    });
}
1
2
3
4
5

然后,你将按如下方式使用此函数:

<script>document.body.innerHTML = htmlEncode(untrustedValue)</script>
1

如果你的输入是在 JavaScript 字符串中,则需要一个执行 Unicode 转义的编码器。下面是一个示例 Unicode 编码器:

function jsEscape(str){
    return String(str).replace(/[^\w. ]/gi, function(c){
        return '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
    });
}
1
2
3
4
5

然后,你将按如下方式使用此函数:

<script>document.write('<script>x="'+jsEscape(untrustedValue)+'";<\/script>')</script>
1

# 7如何在jQuery中防范XSS

jQuery 中最常见的 XSS 形式是将用户输入传递给 jQuery 选择器。Web 开发人员经常使用location.hash并将其传递给选择器,这将导致 XSS,因为 jQuery 会呈现 HTML。

jQuery 官方意识到了这个问题,并修补了他们的选择器逻辑,以检查输入是否以 hash 开头。现在,jQuery 只会在第一个字符是<时呈现 HTML。如果你想将不受信任的数据传递给 jQuery 选择器,请确保使用上面的jsEscape函数正确地转义了该值。

# 8使用内容安全策略(CSP)缓解XSS

内容安全策略 (opens new window)(CSP)是防范跨站脚本攻击的最后一道防线。如果前面执行的 XSS 防护都失败了,则可以使用 CSP 限制攻击者的行为来缓解 XSS。

CSP 允许你控制各种内容,例如 是否可以加载外部脚本 以及是否执行内联脚本。若要部署 CSP,需要包含一个名为Content-Security-Policy的 HTTP 响应标头,其具有一个包含策略的值。

CSP 示例如下:

default-src 'self'; script-src 'self'; object-src 'none'; frame-src 'none'; base-uri 'none';
1

此策略指定了 只能从与主页相同的源加载图像和脚本等资源。因此,即使攻击者可以成功注入 XSS 有效负载,他们也只能从当前页面加载资源。这大大降低了攻击者利用 XSS 漏洞的机会。

如果你需要加载外部资源,请确保你所加载的脚本,不会帮助攻击者利用站点。例如,如果你将某些域列入白名单,则攻击者可以从这些域加载任何脚本。如果可以,请在你自己的域中托管资源。

如果无法做到这一点,则可以使用 基于哈希或随机数 的策略来允许不同域上的脚本。nonce 是一个随机字符串,被作为脚本或资源的属性进行添加,仅当随机字符串与服务器生成的字符串匹配时才会执行。攻击者无法猜测随机化的字符串,因此无法调用含有 有效随机数的脚本或资源,因此资源将不会被执行。

学习更多

使用CSP缓解XSS攻击 (opens new window)

编辑 (opens new window)
客户端模板注入
XSS备忘单

← 客户端模板注入 XSS备忘单→

最近更新
01
API测试笔记
04-30
02
msfvenom
03-29
03
Metasploit
03-29
更多文章>
Theme by Vdoing | Copyright © 2023-2024 Carsaid | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式