0%

Web安全-SQL注入攻击

SQL注入攻击

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

关系型数据库

  • 存储结构化数据
  • 可高效操作大量数据
  • 方便处理数据之间的关联关系
  • 常见的关系型数据库:MySQL,Oracle,SQLServer,PostGreSQL

SQL语言

  • 结构化查询语言,一种描述性语言,面向语义化
  • SQL语言的作用:对存储在RDBMS(关系型数据库管理系统)中的数据进行增删改查等操作,有些非关系数据库也支持SQL

SQL注入原理

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

SQL注入类型

根据相关技术原理,SQL注入可以分为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

## SQL注入产生原因

- 不当的类型处理;
- 不安全的数据库配置;
- 不合理的查询集处理;
- 不当的错误处理;
- 转义字符处理不合适;
- 多个提交处理不当。

## SQL注入示例

```js
//查询语句
SELECT * FROM table WHERE id=${id}
//注入数据
1 or 1=1
//注入后的查询语句
SELECT * FROM table WHERE id=1 or 1=1

//查询语句
SELECT * FROM user WHERE username=`${username}` AND password=`${password}`
//注入数据
1' or '1'='1
//注入后的查询语句
SELECT * FROM user WHERE username=`123` AND password=1' or '1'='1'

SQL注入危害

  • 猜解密码
  • 获取数据
  • 删库删表
  • 拖库

SQL注入防御

  • 对数据进行转义,永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双”-“进行转换等
  • 永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取
  • 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接
  • 不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息
  • 关闭错误输出:应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中
  • 使用ORM(对象关系映射)

Node 防止SQL注入攻击

转义查询值

使用mysql,转义查询值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'me',
password: 'secret',
database: 'my_db'
});

connection.connect();

var userId = 'some user provided value';
var sql = 'SELECT * FROM users WHERE id = ' + connection.escape(userId); //转义查询值
connection.query(sql, function (error, results, fields) {
if (error) throw error;
// ...
});

使用参数化查询

使用node-mysql2进行参数化查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// get the client
const mysql = require('mysql2');

var connection = mysql.createConnection({
host: 'localhost',
user: 'me',
password: 'secret',
database: 'my_db'
});

connection.connect();

var userId = 'some user provided value';
connection.execute('SELECT * FROM users WHERE id = ?',[userId], function (error, results, fields) {
if (error) throw error;
// ...
});

使用ORM(对象关系映射)

使用Sequelize

参数化查询

参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,这个方法目前已被视为最有效可预防SQL注入攻击 (SQL Injection) 的攻击手法的防御方式

参数化查询原理

在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有恶意的指令,由于已经编译完成,就不会被数据库所运行。 有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便,然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失

SQL 指令撰写方法

MySQL 的参数格式是以 “?” 字符加上参数名称而成

1
2
3
4
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4

//执行sql查询
query(`SELECT * FROM user WHERE id=?`,[id])

NOSQL注入防御

  • 检测数据类型
  • 类型转换
  • 写完整条件
-------------本文结束感谢您的阅读-------------