接入层注入

关系型数据库

  • 存放结构化数据
  • 可高效操作大量数据
  • 方便处理数据之间的关联关系
  • 常见: 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

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
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 时就可以进行登录,也就是任意密码都行,当然用户名也是可以这样操作的

跟关系型一样,从这几方面入手

  • 检查数据类型
  • 类型转换
  • 写完整条件
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄