所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。是最原始、最简单的攻击,从有了web2.0就有了sql注入攻击。
这里举一个简单的典型例子:
我们知道,用户登录的时候我们要去查询用户表(users),对比用户名(username)和密码(password)
SQL语句:
// 正常
select * from users WHERE username="zhangsan" and password="524ab85686df0e52ada43b11b53cce35"
// sql注入 用户名写入:zhangsan'--
select * from users WHERE username='zhangsan'-- ' and password='524ab85686df0e52ada43b11b53cce35'
上面两条sql语句都能查询到用户的存在,并且第二条语句中密码校验的语句已经被注销了,那么这个时候如果别人知道你的用户名就能登录你的账号,这样子岂不是很危险??????
我们来执行一下前面的login API:(密码随便输入一个)
AAAAAAAAAAAAAAAAAAAAA,竟然真的可以登录~~~~~~~~,慌慌慌慌慌慌慌慌慌慌慌慌,怎么办怎么办~~~~~
我们来看下执行的sql语句,果然是 -- 后面被注释了~~~
select id, username, realname from users where username='zhangsan '-- ' and password='69d6b0c4c032f5c0673ca2471145c596'
不必慌,我们来看一下之前的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) {
const promise = new Promise((resolve, reject) => {
con.query(sql, (err, result) => {
if (err) {
reject(err)
return
}
resolve(result)
})
})
return promise
}
module.exports = {
exec,
escape: mysql.escape // 防止sql注入 编码特殊字符
}
看到这段关键代码了吗???
escape: mysql.escape // 防止sql注入 编码特殊字符
我们来改动一下之前的controller/users.js login方法:
const { exec, escape } = require('../db/mysql')
const { genPassword } = require('../utils/cryp')
const register = async (username, password) => {
...
}
const userNameFilter = async (username) => {
...
}
const login = async (username, password) => {
username = escape(username) // 格式化 预防sql注入
password = genPassword(password) // 生成加密密码
password = escape(password) // 格式化 预防sql注入
const sql = `
select id, username, realname from users where username=${username} and password=${password}
`
// console.log('sql is', sql)
const rows = await exec(sql)
return rows[0] || ''
}
const userInfo = async (id) => {
...
}
module.exports = {
login,
register,
userNameFilter,
userInfo
}
我们再来试下:
果然登录失败了~~~啧啧啧!!!
格式化之后执行的sql语句:
select id, username, realname from users where username='zhangsan \'-- ' and password='69d6b0c4c032f5c0673ca2471145c596'
重要五颗星:
从上面对比我们可以知道,escape 就是对一下能对sql语句有影响的特殊字符进行格式化,预防拼接sql语句。
所以为了预防万一,我们需要把能拼接成sql语句的变量都要加上escape!
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
攻击方式
常用的XSS攻击手段和目的有:
1、盗用cookie,获取敏感信息。
2、利用植入Flash,通过crossdomain权限设置进一步获取更高权限;或者利用Java等得到类似的操作。
3、利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作。
4、利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。
5、在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。
xss攻击就不一一叙述了,想了解的话,多查查资料即可。
下面来说nodejs怎么来防范XSS攻击:
首页我们安装一个xss依赖
npm install xss --save-dev
下来我们来举一个简单的例子吧!看注释!!
const xss = require('xss') // 引入xss
const { exec } = require('../db/mysql')
const getList = async (author, keyword) => {
...
}
const getDetail = async (id) => {
...
}
const newBlog = async (blogData = {}) => {
// blogData 是一个博客对象,包含 title content author 属性
const title = xss(blogData.title) // 防范xss攻击
const content = xss(blogData.content) // 防范xss攻击
const author = blogData.author
const createTime = Date.now()
const sql = `
insert into blogs (title, content, createtime, author)
values ('${title}', '${content}', ${createTime}, '${author}');
`
const insertData = await exec(sql)
return {
id: insertData.insertId
}
}
module.exports = {
getList,
getDetail,
newBlog
}
简明扼要的说一下:防范xss攻击的方式就是把特殊字符编码
什么是特殊字符呢?
用户输入的数据进行HTML Entity编码, 也就是对、
等标签的
< >
进行转换,然后再保存到后台数据库。
例如:
在 input 输入框 恶意输入 , 就会被转换为下面的语句并存入数据库:
<script>
document.cookie </script>
,已达到无法执行 的目的!!!!
sql注入:窃取数据库内容
XSS攻击:窃取前端的cookie等敏感信息
密码加密:保障用户信息安全(重要)
DDOS攻击:需要硬件和服务来支持(需要OP支持)