返回所有文章

SQL 注入学习笔记:输入如何改变查询

记录 SQL 注入的形成原因、常见类型和输入点,以及参数化查询与最小权限的防御思路。

整理自个人 Notion 笔记 · 原笔记更新于

文章目录 8 个章节

第一课:SQL 注入

SQL 注入是什么?

用户输入本来应该只是”数据“,但是因为程序直接拼接 SQL,导致输入的一部分被数据库当成了 SQL 语句执行。
比如后端有一段不安全代码:

username = input();

sql = "SELECT * FROM users WHERE username = '" + username + "'"

正常输入:

alice

最后 SQL 是:

SELECT * FROM users
WHERE username = 'alice';

完全正常。
问题就在这里:

程序员控制的 SQL
        +
用户可以控制的 username

如果用户输入能改变 SQL 的语法结构,就产生了 SQL 注入。

其中单引号' 非常重要

正常 SQL:

SELECT * FROM users
WHERE username = 'alice';

数据库认为:’alice’ 是个字符串,这里的' 相当于,字符串的边界。
但是如果用户本身出现:' ,就可能提前结束字符串,于是:

用户就有机会从“数据区域”跑进“SQL 语法区域”。
这就是理解 SQL 注入的最关键一步。


SQL 注入怎么“修改逻辑”的?

我们来看一个经典输入:

` OR 1=1 --

假设放进用户名。原来:

SELECT * FROM users
WHERE username = '用户输入'
AND password = 'xxx';

拼接之后就变成了:

SELECT * FROM users
WHERE username = '' OR 1=1 --AND passwrod = 'xxx'

-- 是SQL中的注释,也就是说,攻击者让数据库忽略了后面程序原本拼接的内容。


SQL 注入常见的几个类型

① 基于报错
输入影响 SQL 后,数据库会回显错误信息,我们根据回显的错误信息可以获取:

数据库类型

SQL结构

表字段信息

② UNION 型
SQL 有一个操作:

UNION

他的作用是:

把两个 SELECT 的查询结果组合起来
例如:

SELECT name FROM students
UNION
SELECT name FROM TEACHERS

如果应用中存在SQL注入,有时可以利用这个机制让原本查询的正常内容 + 其他数据(攻击者想要获取的)一起出现在响应里。


③ 布尔盲注
有些网站,SQL 执行了,但是不把数据库里的结果直接显示出来,这个时候可以观察:

条件成立  /  条件不成立

在网页行为上有没有区别。例如概念上:

条件 True
→ 页面正常

条件 False
→ 页面不同

通过不断问数据库:

是不是这个?
是不是那个?

逐渐获取信息。


④ 时间盲注
如果网页连 True / False 的结果都看不出来怎么办?
某些情况下可以观察服务器的响应时间:

条件成立
→ 延迟几秒

条件不成立
→ 正常返回

防御SQL注入的常见手段:

参数化查询:

先告诉 SQL 查询语句的结构,再告诉他对应的数据:

cursor.execute(
    "SELECT * FROM users WHERE username = ?",
    (username,)
)

最小权限:

假如网站数据库账户只需要:

SELECT

那就不要给他 DROP、CREATE等其他功能。

SQL 注入的核心防御不在于“过滤所有危险字符”,而是参数化的查询。


第二课:如何判断一个点是否可能存在 SQL 注入


什么是输入点?

网站上有很多地方可以控制数据,例如:
URL 参数

/product?id=10 

搜索框:

搜索:
iphone

登录框:

username
password

Cookie

Cookie: user_id = 1001

HTTP Header

User-Agent

实战练习:

实战:

写下来,是为了更好地理解。
— 木之风

继续阅读 · 渗透学习

渗透测试学习笔记:从基础到实践

↑