Skip to content

安全

XSS 跨站脚本攻击

XSS攻击:在一个网页中恶意插入HTML或者script代码,使之可以盗取cookie或者其他敏感数据。

举例:假设我们有一个论坛网站,允许用户发布帖子。当用户提交帖子内容时,网站将这些内容嵌入到 HTML 中,以便其他用户阅读。 如果网站没有正确地过滤或者转义用户的输入,攻击者就可以提交一段 JavaScript 代码,例如:

html
<script>
  // 当其他用户打开这个帖子时,这段代码会在他们的浏览器中执行
  alert('This is an XSS attack!');
</script>

解决:

  • 过滤掉用户输入的非法字符: 可以将用户输入的 <> 转义为 &lt;&gt;
  • CSP: Content Security Policy(内容安全策略) CSP 通过 HTTP 响应头 Content-Security-Policy 来设置。例如,以下的 CSP 仅允许从当前域名加载 JavaScript 和 CSS:
Content-Security-Policy: default-src 'self'
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com

CSRF 跨站请求伪造

Cross-Site Request Forgery,CSRF,攻击者通过诱导用户浏览器发送请求到一个他们已经认证过的网站,从而在不知情的情况下执行一些操作。

假设你登录了一个银行网站,并且在浏览器中保存了登录状态(通常是通过 Cookie 实现的)。这个银行网站有一个 URL,可以用来转账,例如:https://mybank.com/transfer?account=BOB&amount=100。如果你访问这个 URL,就会向 BOB 转账 100 元。 现在,假设攻击者通过某种方式(例如在社交网站的帖子中,或者在电子邮件中)诱导你访问一个他们控制的 URL,这个 URL 中嵌入了一个图片标签: <img src="https://mybank.com/transfer?account=ATTACKER&amount=10000" /> 当你的浏览器加载这个图片时,实际上是向 https://mybank.com/transfer?account=ATTACKER&amount=10000 发送了一个 GET 请求。因为你的浏览器中保存了银行网站的登录状态,所以这个请求会被银行网站接收并执行,结果就是向攻击者转账了 10000 元。

解决:

  • SameSite Cookie:这是一种 Cookie 属性,可以防止在跨站请求中发送 Cookie。
  • CSRF Token 网站为每一个用户的会话生成一个随机的 CSRF Token,并在每一个需要保护的表单中包含这个 Token。当接收到请求时,网站会检查请求中的 CSRF Token 是否和会话中的 Token 匹配。因为攻击者无法预测 CSRF Token,所以无法构造有效的请求。
  • 验证 Referer 或 Origin 头部:网站可以检查 HTTP 请求的 Referer 或 Origin 头部,确认请求是否来自合法的源。但是这种方法并不可靠,因为 Referer 和 Origin 头部可以被修改。

加密

异或加密、Base64加密、MD5加密、SHA1加密

js
// 异或加密
function encryptByXOR(message, key) {
    var encrypted = '';
    for (var i = 0; i < message.length; i++) {
        // 取 message 每个字符对应的 ASCII 码,与 key 每个字符对应的 ASCII 码进行异或运算,得到加密后的 ASCII 码
        // 解密时,只要再次使用相同的 key 进行异或运算,就可以得到原来的 ASCII 码,即使用密文再调用一次该函数
        // i % key.length 保证 key 的每个字符都参与运算 (10%3,即取模,取10/3的余数,值一定小于3)
        var c = message.charCodeAt(i) ^ key.charCodeAt(i % key.length);
        encrypted += String.fromCharCode(c);
    }
    return encrypted;
}

var message = 'Hello world';
var key = '1234567890';

var encrypted_message = encryptByXOR(message, key);
console.log('加密后的字符串:', encrypted_message);

代码混淆&压缩

通常包括将变量名和函数名替换为无意义的字符、删除代码中的空白和注释、将多行代码压缩成一行等操作。混淆后的代码和原代码在功能上是等效的,但是由于其结构和命名被混淆,甚至看起来无法读懂。

CSP

Content Security Policy(CSP)是一种安全策略,可以限制网页内容中的 JavaScript 文件、CSS 文件、图片、音频、视频等资源的来源,防止恶意用户注入恶意的 JavaScript 代码、CSS 样式或者其他恶意资源,从而增加网站的安全性。

CSP 通过设置 HTTP 头部中的 Content-Security-Policy 或者 X-Content-Security-Policy 字段来实现。这些字段的值是一个字符串,用于指定 CSP 的策略。CSP 的策略包括以下几个主要的指令:

  • default-src:指定默认的资源来源。如果其他指令没有指定资源来源,将使用默认来源。
  • script-src:指定 JavaScript 文件的资源来源。
  • style-src:指定 CSS 文件的资源来源。
  • img-src:指定图片的资源来源。
  • media-src:指定音频和视频的资源来源。
  • font-src:指定字体文件的资源来源。
  • connect-src:指定 XMLHttpRequest、WebSocket 和 EventSource 的资源来源。
  • object-src:指定插件(如 Flash)的资源来源。
  • frame-src:指定 iframe 的资源来源。
  • base-uri:指定 base 标签的资源来源。
  • form-action:指定表单提交的地址。
  • report-uri:指定 CSP 违规事件的报告地址。

CSP 的策略可以设置多个指令,每个指令可以设置多个资源来源,以逗号分隔。例如,以下 CSP 策略指定 JavaScript 文件和 CSS 文件只能从网站的域名加载:

txt
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';

JWT

JWT(JSON Web Token)

JWT通常由三部分组成:头部(Header)、负载(Payload)和签名(Signature)。

  • 头部(Header):头部通常包含两部分:token类型和所使用的加密算法。

  • 负载(Payload):负载是实际要传递的数据,它包含一些声明(Claim)。声明是关于实体(通常是用户)以及其他一些元数据的陈述。

  • 签名(Signature):签名是由头部(编码后的)、负载(编码后的)、一个秘钥,还有头部中指定的算法生成的。签名用于验证消息的发送者是否是他们自称的那个人,并确保消息在传输过程中没有被篡改。

生成过程

  • 编码头部和负载:首先,将头部和负载的JSON对象分别转化为JSON字符串,然后对这两个JSON字符串进行Base64Url编码。

    json
    {
      "alg": "HS256",
      "typ": "JWT"
    }
    json
    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
  • 连接头部和负载:将编码后的头部和负载用一个点号(.)连接起来。

  • 生成签名:将连接后的字符串和秘钥一起,按照头部中指定的加密算法进行加密,生成签名。

  • 编码签名:最后,将签名进行Base64Url编码。

验证

解析拿到头部、负载、签名,用私钥重新加密得到签名,与原签名对比。

其他

  • 桥接白名单域名可调用等