XSS(跨站脚本攻击)

XSS(Cross-site scripting)跨站脚本攻击是一种常见的网络安全攻击方式,攻击者通过在目标网站上注入恶意脚本,使得用户在访问该网站时,浏览器执行这些恶意脚本,从而盗取用户的敏感信息或者操纵用户的浏览器进行非法操作。这些恶意脚本可以包括HTML代码、JavaScript代码等。攻击者可以利用各种漏洞或者社交工程手段将恶意脚本注入到目标网站中,例如通过留言板、评论区域、表单提交等地方注入恶意代码。因此,XSS攻击也被称为“注入攻击”。为了防止XSS攻击,网站开发者需要采取一系列的安全措施,如输入过滤、编码输出等,以确保用户的安全。

XSS的分类和特点

  1. 反射型XSS(Reflective XSS):

攻击者将恶意代码注入网站输入字段,当用户在这些字段输入内容时,恶意代码会被发送到用户浏览器并执行。这种攻击依赖用户交互。

  1. 存储型XSS(Stored XSS):

攻击者将恶意代码注入网站数据库,这些代码在用户访问相关页面时执行。这种攻击常见于用户生成内容的区域,如评论、留言板或帖子,因为这些内容会被存储在服务器上。

  1. 基于DOM的XSS(DOM-based XSS):

这种攻击利用DOM的缺陷来执行攻击者的脚本,不依赖服务器响应。如果攻击者成功注入脚本,它会在用户浏览器中执行,即使原始网页没有被修改。

所有类型的XSS都利用网站的安全漏洞来执行恶意脚本。为了防止这些攻击,开发者需要采取安全措施,如验证和过滤用户输入,以及适当编码和转义输出。

如何防御XSS攻击

针对XSS攻击,以下是两种有效的防御方式:

  • 设置重要Cookie为httpOnly属性:对于包含关键信息的Cookie字段,例如用于验证用户与好友关系的字段,应设置为httpOnly。这样,即使页面被恶意攻击,攻击者也无法通过脚本访问这些Cookie信息,从而增强安全性。

  • 对输入进行验证和转义:在将用户输入或从链接获取的参数展示到页面之前,必须进行合法性验证。同时,可以使用转义函数对潜在的风险进行转义处理。例如,可以使用以下escHTML函数对特殊字符进行转义:

function escHTML(str) {
    if (!str) return '';
    return str.replace(/&/g, '&') // 替换 & 字符
              .replace(/</g, '&lt;') // 替换 < 字符
              .replace(/>/g, '&gt;') // 替换 > 字符
              .replace(/'/g, '&#039;'); // 替换 ' 字符(单引号)
}

CSRF(跨站请求伪造)

CSRF(Cross-Site Request Forgery)是一种网络安全攻击手段,攻击者通过伪造用户身份,使用户的浏览器在不知情的情况下向目标网站发起恶意请求。这种攻击通常与用户的登录状态有关,攻击者利用用户在已登录的会话中执行未经授权的操作。简单来说,攻击者可以诱使用户点击一个链接或加载一个图片,这个链接或图片背后隐藏着恶意请求,在用户不知情的情况下发送给目标网站,从而执行一些非法操作。

CSRF的工作原理

当用户在一个网站上登录后,该网站会在用户的浏览器上生成一个会话令牌(session token),该令牌通常存储在Cookie中。在用户与网站交互时,这个令牌会被用来验证用户的身份。在CSRF攻击中,攻击者会利用用户的登录状态,通过伪造的请求向目标网站发送带有会话令牌的请求,从而执行非法操作。由于浏览器会携带已登录的会话令牌,目标网站可能会误认为这些请求是用户本人发出的。

CSRF的攻击场景

  1. 攻击者可以在社交媒体、论坛等地方发布一个看似正常的链接,诱使用户点击。

  2. 当用户点击链接时,链接背后会向目标网站发送一个恶意请求,完成一些非法操作,如更改用户密码、发送邮件等。

如何防御CSRF攻击

  • 检测请求来源

通过检测HTTP请求头中的Origin或Referer字段,可以验证请求的来源是否合法。例如,如果接收到一个来自demo.com的请求,而该请求意在影响example.com的服务,那么可以通过校验这两个字段来识别并阻断这种潜在的CSRF攻击。这种方法可以有效地过滤掉一部分非法的跨站请求。

  • 加入Token校验

CSRF攻击得以成功的原因之一在于用户信息被存储在cookie中。为增强安全性,可以在每次用户发起请求时附加一个Token,并在服务器端进行验证。这个Token应该与用户的会话信息相关联,并且每次请求时都需要重新生成或验证。以下是生成Token的一个简单函数示例:

function getToken(tokenInput) {
    var str = tokenInput || ''; // 输入的token或用户信息
    var hash = 5381; // 初始哈希值
    for (var i = 0, len = str.length; i < len; ++i) {
        hash += (hash << 5) + str.charCodeAt(i); // 计算哈希值
    }
    return hash & 0x7FFFFFFF; // 返回哈希值(与特定用户会话关联)
}

在服务器端,需要对每个接收到的请求中的Token进行验证,确保它来自于合法的用户会话。通过这种方式,可以有效防止未经授权的请求访问。