【nodejs学习笔记】安全:sql注入、xss攻击的概念和预防及密码加密的方式

本文涉及

  • sql 注入: 窃取数据库内容
  • xss 攻击:窃取前端的 cookie 内容
  • 密码加密: 保障用户信息安全

sql 注入

  • 最原始、最简单的攻击,从有了 web2.0 就有了 sql 注入攻击
  • 攻击方式∶输入一个 sql 片段,最终拼接成一段攻击代码
  • 预防措施∶使用 mysql 的 escape 函数处理输入内容即可

示例

比如一个只需要输入用户名和密码的登录界面:
在这里插入图片描述
假如用户在输入用户名的时候,在后面加上'-- (单引号–空格),比如用户gougou输入: gougou'-- ,那输入的密码不正确也能登录成功。因为这样做相当于把后面的 sql 注释掉了。甚至可以在输入用户名之后拼接 sql 语句执行其他更危险的操作。

举个例子:
一开始,
gougou 登录的时候正常输入用户名gouguo,密码liyi,sql 语句如下:select * from users where username='gougou' and password='liyi';
在这里插入图片描述
后来gougou使坏,用户名输入为gougou'-- ,这时候密码随便怎么输都无所谓,比如输入123,也能正确查询出该用户信息:
在这里插入图片描述

如何预防

通过 mysql 自带的 escape 函数处理输入内容。对用户输入的内容进行转义。

代码示例

db-mysql.js:

const mysql = require('mysql')
const {
    
     MYSQL_CONF } = require('../conf/db')
// 创建连接对象
const con = mysql.createConnection(MYSQL_CONF)
// 开始连接
con.connect()
// 统一执行 sql 的函数
function exec(sql) {
    
    
  return new Promise((resolve, reject) => {
    
    
    con.query(sql, (err, result)=>{
    
    
      if(err) return reject(err)
      resolve(result)
    })
  })
}

module.exports = {
    
    
  exec,
  escape: mysql.escape
}

controller/user.js:

const {
    
     exec, escape } = require("../db/mysql")

const login = (username, password) => {
    
    
  username = escape(username)
  password = escape(password)
  const sql =`select username, realname from users where username=${
      
      username} and password=${
      
      password}`
  return exec(sql).then(rows => {
    
    
    return rows[0] || {
    
    }
  })
}
module.exports = {
    
    
  login
}

通过 escape 处理过后,单引号会被转义:
原来的 sql: select username, realname from users where username='gougou'-- ' and password='123';
处理后 sql: select username, realname from users where username='gougou\'-- ' and password='123';

XSS 攻击

XSS 攻击指的是跨站脚本攻击(Cross Site Scripting),是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如 cookie 等。
比如一个博客网站,攻击者写了一篇博客,其中嵌入 script 脚本,脚本内容是获取 cookie 并发送到攻击者的服务器 (需要服务端配合跨域)。发布这篇博客之后,有人访问这篇博客,攻击者就能轻松获取访问者的 cookie 信息。

  • 攻击方式:在页面展示内容中掺杂 js 代码,以获取网页信息
  • 预防措施:转换生成 js 的特殊字符

比如我们在创建文章的时候输入 js 脚本:<script>alert(document.cookie)</script>
不做处理的话,script 标签里的语句就会被执行:页面会出现弹窗,内容为用户的 cookie 信息。处理后,这段内容就会被作为一段普通文本展示。

后端如何预防

可以在项目里安装一个 xss 包:npm i xss --save
它会对一些特殊字符进行转义,比如:

< 转为 &lt;
> 转为 &gt;
" 转为 &quot;
' 转为 &#x27;
/ 转为 &#x2F;

代码示例

用 xss 方法对用户输入的内容进行处理:

const xss = require('xss')
const {
    
     exec } = require('../db/mysql')
const newBlog = (blogData = {
     
     }) => {
    
    
    const {
    
     title,content,author } = blogData
    const createTime = Date.now()
    const sql = `
        insert into blogs (title, content, createtime, author) 
        values ('${
      
      xss(title)}', '${
      
      xss(content)}',${
      
      createTime}, '${
      
      author}')
    `
    return exec(sql).then(insertData => {
    
    
        return {
    
    
            id: insertData.insertId
        }
    })
}

前端如何预防

同样可以使用 xss 工具,具体可以查看相关链接
前端和后端同时预防,总不会出错。

密码加密

  • 万一数据库被用户攻破,最不该泄露的就是用户信息
  • 攻击方式: 获取用户名和密码,再去尝试登录其他系统
  • 预防措施:将密码加密,这样即便拿到密码也不知道明文

代码示例

写一个加密的工具方法:
utils/crypto.js:

const crypto = require('crypto')

// 定义一个密匙
const SECRET_KEY = 'LY_17*'

// md5加密。content:需要加密的内容
function md5(content) {
    
    
  let md5 = crypto.createHash('md5')
  return md5.update(content).digest('hex')
}

// 加密函数
function genPassword(passwort) {
    
    
  const str = `password=${
      
      passwort}&ken=${
      
      SECRET_KEY}`
  return md5(str)
}

module.exports = {
    
    
  genPassword
}

crypto.createHash(algorithm):
通过参数 algorithm 指定算法建立并返回一个哈希对象,可以用来产生哈希摘要。algorithm 参数依赖于 node 运行平台上OpenSSL 所支持的有效算法。例如 sha1,md5,sha256,sha512 等
crypto 相关参考资料

登录的时候加密:

const {
    
     exec, escape } = require("../db/mysql")
const {
    
     genPassword } = require('../utils/cryp')

const login = (username, password) => {
    
    
  username = escape(username)
  password = escape(genPassword(password))
  const sql =`select username, realname from users where username=${
      
      username} and password=${
      
      password}`
  return exec(sql).then(rows => {
    
    
    return rows[0] || {
    
    }
  })
}
module.exports = {
    
    
  login
}

猜你喜欢

转载自blog.csdn.net/dongkeai/article/details/127621288
今日推荐