后端安全


后端安全

后端常见安全方面的问题

  • SQL 注入:窃取修改数据库内容
  • XSS 攻击:窃取前端的 cookie 内容(前端可以处理)
  • 密码加密:⚠️ 保障用户信息安全
Tip

有些攻击需要硬件和服务来支持(OP 支持),如 DDOS 攻击

SQL 注入

最原始、最简单的攻击,通过输入一个 SQL 片段,最终在服务器端拼接为完整 SQL 语句时就可以成为攻击代码。

  • 攻击:可以通过输入特殊字符 -- (最后含一个空格) 来注释掉 SQL 后面的内容。
    当登录时使用用户提供的 usernamepassword 来拼接 SQL 语句时
    js
    const login = (username, password) => {
        const sql = `select username, realname from users where username='${username}' and password='${password}';`
        //...
    }
    

    可以在用户名一栏填入 username' -- 拼接形成的 SQL 语句的后半部分将被注释,这样就可以使用任意密码完成登录。如输入用户名 Ben' -- 和密码 666(不正确),拼接后可以得到的 SQL 语句是 select username, realname from users where username='Ben' -- ' and password='666';
  • 防御:使用函数 escape() 处理拼接 SQL 语句的变量,该函数对于用户输入的特殊字符进行转义
    通过 sql.escape() 函数来处理用户提供的内容(非字符串形式),再用来拼接 SQL 语句
    js
    const mysql = require('mysql2')
    // ...
    const login = (username, password) => {
        username = escape(username);
        password = escape(password);
          const sql = `select username, realname from users where username=${username} and password=${password};`
        // ...
    }
    

    如果输入的内容含有特殊的字符,该函数会对其进行转义,如输入用户名 Ben' -- 和密码 666(不正确),则拼接后可以得到的 SQL 语句是 select username, realname from users where username='Ben\' -- ' and password='1';

XSS 攻击

在页面展示内容掺杂 JavaScript 代码,以获取用户的敏感信息,如 cookie、session id 等。

  • 攻击:在博客系统创建内容,如果有的用户混入恶意的 JavaScript 代码,当博文内容没有经过处理直接展示出来,其他用户访问该文章时这些 JavaScript 代码就会运行,可能会泄露敏感信息。
  • 防御:对用户输入的内容中特殊字符进行转义,特别是可能在 HTML 页面表示代码的 <> 符号

常见需要转义的字符

字符转移后的字符
&&amp:
<&lt;
>gt;
"&quot;
'&#x27;
/&#x2F;

使用模块 xss 对用户输入内容进行转译。

js
const xss = require('xss')

let content = xss(content);   // 使用 xss 模块对输入的内容进行转译

如果用户输入的内容是 <script>alert(1)</script> 则经过 xss 转译后的内容是 &lt;script&gt;alert(1)&lt;/script&gt;

Tip

存储在数据库中的内容是通过 xss 模块转译后的内容,不具有攻击功能。如果再从数据库读取相应的内容展示在页面时,需要前端进行反转译,以使内容正确显示。

密码加密

当数据库被攻破,如果内容经过加密,可以避免用户真实信息马上被泄露。

  • 攻击:获取用户在某个网站的用户名和密码,再去尝试登录其他系统
  • 防御:将密码存储到数据库前进行加密,即使攻破了数据库获取数据也不知道密码明文

用户注册时提供明文密码,服务器使用特定的密钥和加密算法对它进行加密(密钥存储在 Node.js 服务器中),再将加密后的一串「乱码」存储在 MySQL 数据库中(在 MySQL 数据库中并不存储明文密码);然后用户登录时提供明文密码,服务器使用相同的密钥和加密算法对明文密码进行加密,得到的「乱码」再用于在数据库中的匹配查找。

密钥和(加密后的)数据分别存储在不同的服务器中,通过这种方式存储密码即使数据库被攻破后,也不会造成密码明文立即泄露。

js
// crypto 是 Node.js 提供的一个用于加密的模块
const crypto = require('crypto')

// 密钥
const SECRET_KEY ='advbs'

// md5 加密
function md5(content) {
  let md5 = crypto.createHash('md5')
  return md5.update(content).digest('hex')   // 以 16 进制方式输出
}

// 加密函数
function genPassword(password) {
  const str = `password=${password}&&key=${SECRET_KEY}`   // 拼接字符串,其中需要包含密码和密钥
  return md5(str)   // 使用 md5 方式加密
}

// const result = genPassword('123')

// console.log(result);

module.exports = {
  genPassword
}

Copyright © 2024 Ben

Theme BlogiNote

Icons from Icônes