SQL 注入原理,两个人在通讯的时候,对方把一段信息当作了可执行代码并且执行

SQL 基础语法

MySQL Crash Course

关系型数据库的 DBMS 系统

准备:下载

1
2
3
4
5
6
7
8
USE myDB;

CREATE TABLE myRecord (
Idx INT PRIMARY KEY AUTO_INCREMENT, -- 类型:整数 自增 主键(数据必须是唯一的,并且一定是非空的,所以可以不用额外设置 NUT NULL)
Name VARCHAR() NOT NULL, -- 类型:字符 非空
Arrive DATE NULL -- 类型:日期 可以为空

);

操作

插入

1
2
INSERT INTO myDB.myRecord (Idx, Name, Arrive)
VALUES (1, '张三', '2077-12-25');

INSERT INTO 插入 数据库名.表格名 (列名1, 列名2, 列名3)
VALUE(数值)

更改/删除

添加一列

1
2
ALTER TABLE myDB.myRecord
ADD Birth DATE NULL;

更新一个

1
2
3
UPDATE myDB.myRecord
SET Birth = '2077-12-31';
WHERE Idx = 3;

删除一个

1
2
DELETE FROM myDB.myRecord
WHERE Idx = 1;

删除表格/数据库

1
2
3
DROP TABLE myDB.myRecord;

DROP DATABASE myDB;

查看

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
27
28
29
30
31
32
33
34
35
USE myBD;

SELECT * -- 查看范围:全部数据
FROM myRecord; -- 从哪个表格

SELECT Idx, Arrive, Birth; -- 只看这些列
FROM myRecoed;

SELECT DISTINCT Arrive -- 去重
FROM myRecord;

SELECT *
FROM myRecord
ORDER BY Idx ASC; -- 或者DESC(默认ASC)

SELECT *
FROM myRecord
WHERE Idx >= 4 AND NOT NAME = '张三' AND Arrive BETWEEN '2000-1-1' AND '2077-1-1'
ORDER BY Idx DESC;

SELECT *
FROM myRecord
WHERE Name LIKE 'T%' -- 名字以T开头
ORDER BY Idx DESC;

SELECT *
FROM myRecord
WHERE Name LIKE '__b%' -- 第三个字符是b
ORDER BY Idx DESC

SELECT concat(col_name1, col_name2) FROM table_name1; -- congcat可以把两列/两个字符串并在一起
SELECT group_concat(col_name1, col_name2) FROM table_name1; -- 不但把列拼在一起,每行也都拼在一起,用逗号隔开

SELECT col_name1, col_name2 FROM table_name1 LIMIT N, M -- 从第N开始,取M个

合并

1
2
3
4
5
6
7
8
9
10
SELECT *
FROM myRecord1
INNER JOIN myRecord2
ON myRecord1.Name = myRecord2.Name -- 选择所有的数据,按照Name的条件合并,FROM的表格在左边

SELECT Name
FROM myRecord1
UNION ALL -- 可能有重复值 只 UNION 就会去重
SELECT Name
FROM myRecord2

链接

1
2
3
4
5
6
7
8
9
SELECT *
FROM myRecord1 -- 保留左边所有数据
LEFT JOIN myRecord2
ON myRecord1.Name = myRecord2.Name -- 右边符合这个条件的所有数据向左边靠拢链接

SELECT *
FROM myRecord1 -- 保留右边所有数据
RIGHT JOIN myRecord2
ON myRecord1.Name = myRecord2.Name -- 左边符合这个条件的所有数据向右边靠拢链接

其他函数

1
SELECT SLEEP(2)

注释

1
2
3
4
5
6
/*
注释
*/
-- 注释
# 注释
/*!version—_number 当版本大于这个版本号或者版本号为空的时候会被执行,否则就是普通注释

常用编码

Space: %20
#: %23
': %27
": %22
+: %2B

正题:SQL 注入攻击

可见:恶意使用 SQL 增删改查四种操作都是违法犯罪行为!

SQL 注入原理,两个人在通讯的时候,对方把一段信息当作了可执行代码并且执行

Microsoft Learn: SQL 注入

信息收集->功能分析->利用逻辑->绕过(知识储备)+ 耐心

最简单:有回显的 SQL 注入

SQL 注入类型的判断:数字型/字符型

让引号为奇数个,导致字符型查询报错 或者通过传入一个算式,这样数字型可以正常查询但是字符型查询不到任何内容

获取更多信息(有回显的情况下)

通过联合查询

1
SELECT ... UNION SELECT ...

获取列数

前提是有报错信息,当 M 大于实际的列数的时候无法`ORDER BY`于是会报错 后者用 `UNION SELECT 1, 2, 3`来让各列嵌入 1, 2, 3...

获取所有数据库名+表名(仅限 MySQL)

无回显的 SQL 注入(只有 Found 和 Not Found 1bit 信息)

判断查找语句

判断是单引号还是双引号

进一步利用 1bit 的信息

利用 SQL 的注释符号,把后面的单/双引号注释掉。同时注入自己的条件代码

无回显的 SQL(甚至不会显示 error) 利用延时注入

OR 的话从左到右寻找真值,所以用 OR 的话每次找用户 admin 找不到以后都会延时一次,导致延时时间过长,注入效率降低

会回显报错信息->报错注入

堆叠注入

很多数据库支支持多个 SQL 指令在一行中执行。但是服务端的语言不会支持获取多行的结果

1
SELECT 1; SELECT 2;

二次注入

在第二次没有进行过滤而是直接拼接

SQL 注入的绕过

常见防护方法/检测方法

  1. 直接拦截
  2. 关键字替换
  3. 编码转移 基本无解
  4. 参数化查询 不会把输入直接拼接到 SQL 中 基本无解
    检测方式
  5. 关键字匹配(直接查找/正则)
  6. 语义匹配(例如一个引号就加一个反斜杠转义,一对引号就不转义)

注入绕过

总结

以上的例子:
  • Module1:PHP
  • Moudel2:mySQL
    双方互相理解出现了偏差

其他类型的注入同理

实现了任意文件读取

假如某个网页能实现预览其他网页的功能,直接把目标网页拼接到后面

拼接一个10.0.0.0等等内网的地址,于是你能看到原本不能看到的内网信息