详细地认识 XSS——XSS是什么?如何预防XSS攻击?以及CORS的介绍/详细地认识 XSS——XSS是什么?如何预防XSS攻击?以及CORS的介绍_入门黑客教程

详细地认识 XSS——XSS是什么?如何预防XSS攻击?以及CORS的介绍/详细地认识 XSS——XSS是什么?如何预防XSS攻击?以及CORS的介绍_入门黑客教程

介绍

当今互联网时代,网络安全已经成为不容忽视的重要议题之一。在网站开发和应用程序设计中,XSS(跨站脚本攻击)、CSRF(跨站请求伪造)和CORS(跨源资源共享)问题等安全漏洞成为了攻击者们经常利用的目标。这些漏洞的存在可能导致用户的敏感信息泄露、账户被盗用,甚至直接影响到网站的运行。

在本文中,我们将深入探讨XSS攻击、CSRF攻击和CORS机制,以及应对这些安全挑战的一些基本思路。

在 Web 安全领域中,XSS(Cross Site ) 和 CSRF(Cross-Site ) 是最常见的攻击方式。首先,我们来简单地理解一下什么叫 XSS 攻击与 CSRF 攻击:

XSS 原本的缩写是 CSS,但为了和层叠样式表( Style Sheet, CSS)有所区分,因而在安全领域叫做 XSS。

CORS(Cross- )是一种跨域资源共享的安全机制或协议,用于在浏览器和服务器之间进行跨源 HTTP 请求的授权。

XSS

具体来说,XSS 攻击是指攻击者在网站上注入恶意的客户端代码,通过恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。

现代 Web 框架构建的应用程序具有较少的 XSS 错误,因为这些框架引导开发人员采用良好的安全实践,并通过使用模板、自动转义等帮助减轻 XSS。但是,开发人员需要知道,如果框架使用不安全,可能也会出现问题。

我们可以根据其行为模式分为三种类型:存储型、反射型和 DOM 型。每一种类型都有其独特的攻击路径和防御策略,但共同的核心在于对输入的严格过滤和对输出的编码处理。

分类存储型

存储型XSS,也叫持久型XSS,主要是将XSS代码发送到服务器(不管是数据库、内存还是文件系统等),在下次请求页面的时不用进行 XSS 代码的二次发送。

例如, 图书曾经就有这么一个漏洞:用户在搜索栏输入以下代码:

“>src=x onerror=alert(1)>

搜索结果反馈为一本书,将其上传到 https: //play..com 后,点击网页按钮后 XSS 被触发。

在攻击者提交了一条包含 XSS 代码的数据到数据库后,当目标用户执行查询动作时,相应的数据内容会被服务器解析之后加载出来。浏览器发现有 XSS 代码,把它当做正常的 HTML 和 JS 解析执行,XSS攻击就发生了。

反射型

反射型 XSS 是最常见的一种 XSS 攻击类型,通常是将恶意脚本藏在网址里,放在 GET 参数里传递:

id=>

这种攻击手法要成功,通常需要攻击者运用社交工程的技巧,诱使用户点击恶意链接。

反射型XSS攻击方式示意图

对于有一些安全意识的用户来说,恶意链接通常看起来非常可疑,因此攻击者通常会使用短网址或 HTML 编码等方式试图欺骗用户。

但要使用反射型 XSS,目标网页中要使用一个参数值作为动态显示到页面的数据,并且目标网页对该参数值没有进行有效的检验,这样,攻击者就能在 URL 中通过构造参数的方式插入XSS (恶意脚本),让用户在不知情的情况下点击 URL,从而执行 XSS 。反射型XSS虽然只是一次性,但方便攻击者利用。

基于 DOM 的 XSS 攻击

前面介绍的两种恶意脚本攻击都会经过服务器端然后返回给客户端,相对 DOM 型来说要更好检测与防御,DOM 型 XSS 不用将恶意脚本传输到服务器再返回客户端。总之,反射和存储 XSS 是服务器端注入问题,而基于 DOM 的 XSS 是客户端(浏览器)端注入问题。

客户端 可以访问浏览器的 DOM 文本对象模型是被利用的前提,当确认客户端代码中有 DOM 型 XSS 漏洞时,并且能诱使(钓鱼)一名用户访问自己构造的 URL,就说明可以在受害者的客户端注入恶意脚本。利用步骤和反射型很类似,但唯一的区别就是,构造的 URL 参数不用发送到服务器端,可以达到绕过 WAF、躲避服务端的检测效果。

例如,假设以下代码用于创建一个表单,让用户选择他们的首选语言。查询字符串中还提供了默认语言,作为参数“”:

Select your language:
<select><script>
document.write(""+decodeURIComponent(document.location.href.substring(document.location.href.indexOf("default=")+8))+"");
document.write("English");
script>select>

该页面通过 URL 调用,例如:

default=French>

针对此页面的基于 DOM 的 XSS 攻击可以通过向受害者发送以下 URL 来完成:

<script>alert(document.cookie)script>

当受害者点击此链接时,浏览器会发送以下请求来访问 :

/page.html?default=<script>alert(document.cookie)script>

服务器响应包含上述 代码的页面。浏览器为页面创建一个 DOM 对象,其中 . 对象包含字符串:

<script>alert(document.cookie)script>

页面中的原始 代码并不期望默认参数包含 HTML 标记,因此它只是在运行时将其解码并回显到页面 (DOM) 中。然后浏览器呈现结果页面并执行攻击者的脚本:

alert(document.cookie)

此时,从服务器发送的 HTTP 响应不包含攻击者的 。当有缺陷的脚本访问 DOM 变量 . 并假设它不是恶意的时,此 会在运行时在客户端脚本中显现出来。此外,大多数浏览器默认对 . 进行 URL 编码,这减少了许多 DOM XSS 攻击的影响或可能性。

XSS 防御理念

防御 XSS 的核心理念就是确保所有的变量都经过验证,然后进行转义或清理。

输入编码转义

String result = HtmlUtils.htmlEscape(source);

输出编码(与跨站点脚本相关)的目的是将不受信任的输入转换为安全的形式,其中输入作为数据显示给用户,而不在浏览器中作为代码执行。

在客户端,通常会使用前端框架或库来处理用户输入数据的编码和转义,这些框架或库常会提供自动编码和转义功能,以确保用户输入的数据被正确处理。

在服务器端,接收到用户输入数据后对其进行进一步的验证、清理和处理。这些处理包括使用输出编码库来转义或编码数据,以确保在将数据显示在用户界面上时不会触发安全漏洞。

以下是一个对用户输入进行纯文本过滤的示例:

// 用户的输入
const userInput = "";
const divElement = document.createElement("div");
// 先赋给 div 元素的文本内容
divElement.innerText = userInput;
// 再将包含用户输入内容的 div 元素添加到文档的主体部分
document.body.appendChild(divElement);

与刚才提到的 HTML 上下文输出相比,HTML 属性上下文输出会涉及到将变量放置在 HTML 属性值中。在 HTML 属性中,变量的值可能会影响元素的行为或样式,例如超链接的目标 URL、隐藏元素的 ID 或类名、图像的替代文本等。因此,在将变量插入 HTML 属性中时,需要进行 HTML 属性编码,以确保变量值不会被解释为 HTML 或 代码。

当涉及到将变量放置在 HTML 属性值中,则应使用 . 和 方法,例如:

const varUnsafe = '" onblur="alert(1)"';
const divElement = document.createElement("div");
// 设置 div 元素的属性,并将 varUnsafe 变量作为属性值
divElement.setAttribute('attr', varUnsafe);
// 添加到文档的主体部分
document.body.appendChild(divElement);

在 上下文中,放置变量的唯一”安全“位置是“引用的数据值”内。所有其他上下文都是不安全的,开发时应注意不应在其中放置变量数据。

我们使用编码库中的 函数或类似函数可以很容易地对变量进行 编码。这些函数通常会将字符串中的特殊字符转换为 \xHH 格式,其中 HH 是字符的十六进制 ASCII 值。这样可以确保变量中的特殊字符不会被解释为 代码,从而防止 XSS 攻击。

下面是一个示例,其中, 函数接受一个字符串作为输入,并将其转换为 编码后的形式:

function encodeForJavaScript(input) {
    // 对每个字符进行遍历
    var encoded = '';
    for (var i = 0; i < input.length; i++) {
        // 将字符转换为十六进制 ASCII 值,并添加到编码后的字符串中
        encoded += '\\\\x' + input.charCodeAt(i).toString(16);
    }
    return encoded;
}
var userInput = "";
var encodedInput = encodeForJavaScript(userInput);
console.log(encodedInput); // 输出:\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3e\\x61\\x6c\\x65\\x72\\x74\\x28\\x27\\x48\\x65\\x6c\\x6c\\x6f\\x21\\x27\\x29\\x3b\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e

同理,在 CSS 上下文和 URL 上下文中,变量也只能放在 CSS 属性值或使用编码格式对所有的字符进行编码,不能在其他位置放置可变数据。

对于 URL 编码,可以使用 .() 来自动对其中的数据进行编码:

const parameter = "some data with spaces&symbols!";
// URL 编码
const encodedParameter = encodeURIComponent(parameter);
const url = "" + encodedParameter;
······
function attributeEncode(url) {
  // 替换字符 '<', '>', 和 '"' 分别为 '<', '>', 和 '"'
  return url.replace(/["<>&]/g, function(char) {
    switch (char) {
      case '"':
        return """;
      case "<":
        return "<";
      case ">":
        return ">";
      case "&":
        return "&";
    }
  });
}

白名单过滤

除输入编码转义外,还可以根据白名单的标签和属性对数据进行过滤,以此来对可执行的脚本进行清除(如 标签,img 标签的 属性等)。

在这里我们用 jsoup 库来简单演示添加白名单来过滤输入的操作,另外还可以使用 DOM 操作来进行白名单处理。以下是一个使用 来实现白名单处理的示例:

const jsoup = require('jsoup');
// 只允许特定的标签和属性
const whitelist = {
  allowedTags: ['p', 'a', 'img'], 
  allowedAttributes: {
    'a': ['href', 'title'], // href 与 title 为 a 标签的白名单属性
    'img': ['src', 'alt']   // src 和 alt 为 img 标签的白名单属性
  }
};
const dirtyHtml = '

Hello World!

'; const cleanHtml = jsoup.clean(dirtyHtml, whitelist); // 输出过滤后的HTML内容 console.log(cleanHtml);

CORS

CORS(跨域资源共享)是 W3C 标准,用于灵活地指定允许哪些跨域请求。通过配置适当的 CORS 标头,REST API可以向浏览器发出信号,指示哪些域(也称为源)允许 调用 REST 服务。若不支持或不希望跨域调用,应该禁用 CORS 标头。在设置跨域调用的来源时,应尽可能具体,同时也要尽可能灵活。

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个 字段。

下面是一个例子,浏览器发现这次跨源 AJAX 请求是简单请求,就自动在头信息之中,添加一个 字段。

GET /cors HTTP/1.1
Origin: : api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面的头信息中, 字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

如果 指定的源,不在许可范围内,那么服务器会返回一个正常的 HTTP 回应。浏览器发现,这个回应的头信息没有包含 --Allow- 字段,就知道出错了,从而抛出一个错误,被 的 回调函数捕获。我们要注意,这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是 200。

如果指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: : true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

上面的头信息之中,有三个与CORS请求相关的字段,都以--开头。

--Allow-

该字段是必须设置的。它的值要么是请求时字段的值,要么是一个*,表示接受任意域名的请求。

--Allow-

该字段是可选的。它的值是一个布尔值,表示是否允许发送 。默认情况下, 不包括在 CORS 请求之中。设为true,即表示服务器明确许可, 可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送 ,删除该字段即可。

---

该字段是可选的。CORS请求时,对象的()方法只能拿到6个基本字段:Cache-、-、-Type、、Last-、。如果想拿到其他字段,就必须在---里面指定。上面的例子指定,('')可以返回字段的值。

在配置 CORS 安全策略前,需关注站点是否有跨域需求和跨域配置。若存在跨域配置,则需重点关注跨域配置的授权是否存在漏洞,如果存在漏洞则有信息泄漏等风险。 添加一个非预期的头,即 --Allow- 头部,如果为”*”或者存在存在非预期的值,则存在安全问题。

网络安全学习路线图(思维导图)

网络安全学习路线图可以是一个有助于你规划学习进程的工具。你可以在思维导图上列出不同的主题和技能,然后按照逻辑顺序逐步学习和掌握它们。这可以帮助你更清晰地了解自己的学习进展和下一步计划。

1. 网络安全视频资料

2. 网络安全笔记/面试题

3. 网安电子书PDF资料

如果你向网安入门到进阶的全套资料,我都打包整理好了,需要学习的小伙伴可以V我找我拿~

学网络安全/学黑客,零基础资料整理来啦~~~

~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值