大家好,我是马听,一个DBA界的小学生。
这是曾经在IT界广为流传的一张神图:
当摄像头拍到这个车牌号进行后台处理时,就会触发SQL注入,进行删库操作。
当然,这只是一个段子。
但是站在技术的角度看,很多场景还真可能被SQL注入,这一篇文章就来介绍一下SQL注入是什么?需要怎样预防?
1 什么是SQL注入?
我们先通过一个简单的例子来演示一下SQL注入:
创建测试表并写入数据
use martin
CREATE TABLE users_info (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
contact VARCHAR(100) NOT NULL
);
INSERT INTO users_info (username, password, contact)
VALUES ('user1', 'pass1', '123456789'),
('user2', 'pass2', '987654321'),
('user3', 'pass3', '121212123'),
('user4', 'pass4', '989898987');
使用or的SQL注入举例
正常的查询SQL:
select * from users_info where username='user1' and password='pass1';
比如代码里,我们会判断上面的SQL是否执行成功,来判断用户输入的用户名和密码是否匹配。
但是,假如别人不按套路出牌,把密码部分改成
' or 'a'='a
形成的SQL如下:
select * from users_info where username='user1' and password='' or 'a'='a';
不但能通过验证,还能查看到所有用户的数据。
我们知道,数据泄漏可是天大的事。
所以,类似这种恶意构造输入来执行没有权限的数据库操作,我们就称为SQL注入。
使用union的SQL注入
还有一种方式,就是通过union来完成SQL注入。
正常的查询语句:
select * from users_info where username='user1' and password='pass1';
user1替换成
' UNION SELECT * FROM users_info ; --
形成的SQL如下:
select * from users_info where username='' UNION SELECT * FROM users_info ; -- ' and password='pass1';
就能查询到表user_info的所有数据了。
2 SQL注入的风险
2.1 数据泄露
攻击者可以绕过访问控制,查询敏感数据。
比如上面的例子,攻击者可以查看到全表的数据,那整张表的所有用户信息都会泄露。
2.2 篡改数据
比如上面的union例子,换成了update语句,就能修改全表的数据,换成delete或者truncate,就能删除全表数据了。
就可能会导致数据丢失,甚至经济损失。
2.3 服务中断
攻击者如果修改一些入口表,可能会导致业务中断。
3 SQL注入的预防
3.1 代码中使用预编译语句的形式
举个栗子:
// 查询数据库匹配姓名和密码
query := fmt.Sprintf("SELECT COUNT(*) FROM users_info WHERE username = '%s' AND password = '%s'", name, password)
var count int
fmt.Println(query)
err = db.QueryRow(query).Scan(&count)
if err != nil {
log.Fatal(err)
}
上面的代码,是将用户名和密码直接插入到查询字符串中。
这种方式容易受到SQL注入攻击,因为如果输入的name或password包含SQL语句,都会解释成SQL的一部分,从而也方便了SQL注入。
怎么改写呢?
// 查询数据库匹配姓名和密码
query := "SELECT COUNT(*) FROM users_info WHERE username = ? AND password = ?"
var count int
err = db.QueryRow(query, name, password).Scan(&count)
if err != nil {
log.Fatal(err)
}
类似这段代码,用问号作为参数占位符,然后使用db.QueryRow(query, name, password)来传递实际的参数。
这种方式可以有效防止SQL注入,因为参数不会被解释为SQL的一部分。
3.2 对输入进行校验和过滤
对用户输入的内容,进行校验,如果发现特殊关键字,则进行过滤。
3.3 权限最小化
为数据库用户配置最小的权限,这样万一出现SQL注入,可以把损失讲到最低,比如上面第二个注入的例子,如果真的权限够,甚至可以植入drop table或者drop database的操作。
3.4 关注自己使用的框架或者包是否存在漏洞
有些框架或者包,本身存在SQL注入的风险,这个时候需要考虑是否需要进行升级或者更换更安全的框架和包。
3.5 审计和监控
如果对于重要的数据库,可以考虑开启审计,监控数据库的一些异常查询。
比如包括1=1,注释符(-- 或 /* */) 等SQL,通过设置告警提醒我们。
好的,关于SQL注入的内容就介绍到这里。
欢迎关注公众号获取更多数据库内容:
近期热文: