接入层注入
关系型数据库
- 存放结构化数据
- 可高效操作大量数据
- 方便处理数据之间的关联关系
- 常见: access/sqlite(db 结尾,一般用于手机)/mysql/mssql server
sql 语言
select * from table where id = 1
- 标准化
- 类似于自然语言的描述性语言
- 用于关系型数据库
- 可完成增删改查以及各种复杂数据库操作
sql 注入
`select * from table where id = ${id};`
`1 or 1 = 1`
`select * from table where id =1 or 1 =1;`
select * from user where username = '${data.username}'
and password = '${data.password}'
1 'or '1'='1
select * from user where username = 'username'
and password = '1' or '1'='1'
SQL 的注入本质是将数据变成了具有逻辑的程序
一些神奇的 SQL 语法
select * from table where id="10" and 1=0
select * from table where id="10" and 1=1
select * from table where id="10" and mid(version(),1,1)=5--猜数据库的版本
select 1,2,3 from table
select id,1,2,3 from table
select * from table union select 1,2,3 from table2--猜字段个数
select * from table where min(username,1,1)="t"--猜用户名
SQl 注入的危害
- 猜解密码
- 获取数据
- 删库操作
- 拖库
SQL 注入防御
- 关闭错误输出
- 通过将错误信息模糊化
console.log("[/site/post] error:", e.message, e.stack);
ctx.body = {
status: -1,
body: "出错了"
};
- 检查数据类型
- 对数据类型进行转义
let id = ctx.parmas.id;
id = parseInt(id, 10);
const post = await query{
`select * from post where id =${connecttion.escape(id)}`//escape进行转义
// 有的时候支持下面这种操作
`select * from post where id = ?`, [id]
}
- 使用参数化查询
- 选安装第三方库 运行
npm install mysql2
- mysql2,和 mysql 不一样,不是同一个人写的,但是 mysql2 向下兼容 mysql
- 选安装第三方库 运行
这个时候就要改一下引入的 mysql 库,还有 query
const query = bluebird.promisify(
connection.execte.bind(connectionModel).getConnection()
);
//原来是
const query = bluebird.promisify(
connection.query.bind(connectionModel).getConnection()
);
- 使用 ORM(对象关系映射)
- 需要安装第三方插件
- 运行
npm install sequelize --save
初始化 ORM 实例
var Sequelize = require("sequelize");
var sequelize = new Sequelize({
host: "localhost",
database: "safety",
username: "root",
define: {
freezeTableName: ture
}
});
module.exports = sequelize;
处理数据表
var sequelize = require("./sequelize");
var Sequelize = require("sequelize");
var Post = sequelize.define(
"post",
{
id: {
type: Sequelize.INTERGER,
primaryKey: ture
},
title: Sequelize.STRING(256),
imgUrl: Sequelize.STRING(256),
content: Sequelize.TEXT
},
{
tableName: "post"
}
);
module.export = Post;
查询操作
let post = await Post.findById(id);
let comment = await Comment.findAll({
where: {
postId: post.id
}
});
nosql 注入和防御
看一段 nosql 代码
var mongoose = require('mongoose');
login async function(ctx) {
var username = ctx.request.body.username;
var password = ctx.request.body.password;
mongoose.findOne({
username: username,
password: password
})
}
看似没有什么问题,其实是有问题的,
比如:{"name":"user""password""{"$gt":0}}
这样密码当密码大于 0 时就可以进行登录,也就是任意密码都行,当然用户名也是可以这样操作的
跟关系型一样,从这几方面入手
- 检查数据类型
- 类型转换
- 写完整条件