sql注入入门
sql注入
SQL注入(SQL injection),也称SQLI
发生的原因:程序设计不良,导致忽略了字符检查,服务器会把用户输入的内容认为是正常的SQL指令,从而造成数据的泄露和破坏
产生原因
没有对用户输入的内容进行严格的过滤检查,合法校验,超出了SQL语句原来设计的预期结果,导致了SQL注入
例如下面是一个正常的登录逻辑:
select * from users where username = 'admin' and password='password'
而攻击者在尝试登录时会尝试输入
admin' or '1'='1
那么在拼接的时候sql语句就变成了
select * from users where username = 'admin' or '1' = '1' and password='123'
这个时候sql语句里面出现了
or '1'='1'
所以这个条件永远为真,就会查询出所有数据,导致登录成功,也就是我们常说的万能密码
场景
SQL注入可以存在于一切和数据库存在交互的地方
| 动作 | 举例 |
|---|---|
| 增 | 注册新用户、创建订单、添加文章…… |
| 删 | 删除用户、删除订单、删除文章…… |
| 改 | 修改订单、更新用户信息…… |
| 查 | 查询信息、筛选订单、搜索文章、搜索用户…… |
常见数据库
数据库分为关系型和非关系型
这里不做介绍
关系型数据库
- mysql
- Oracle
- PostgreSQL
- MSSQL
- DB2
- Access
非关系型数据库
- MongoDB
- Redis
- MemcacheDB
- InfluxDB
- Hbase
漏洞危害
- 获取数据库访问权限、甚至获得DBA权限,从而获取数据库中的所有数据,造成信息泄露(可以获取数据)
- 对数据库的数据进行增删改查,例如删除数据库中重要数据的表(可进行增删改查)
- 通过构造特殊的数据库语句,可操作数据库进入后台或者插入木马,获取整个网站和数据库的控制权限,篡改网页,发布不良信息(可获取网站权限)
- 获取服务器最高权限,远程控制服务器,设置导致局域网(内网)被入侵(获取服务器权限)
通用的修复建议
代码
输入过滤
- 严格控制输入数据的类型:例如通过id过去用户信息的时候,只允许传入的id类型
- 严格控制输入数据的长度:如限制用户名长度应该小于20
- 输入合法性判断:禁止出现一些特殊的字符或者关键字,如:'、"、if、or……
- 对所有可能的输入的点进行检测,如UA、IP、Cookie等
预编译SQL语句(参数化查询)
参数化查询是一种查询类型,其中占位符用于填充参数,参数在执行时提供,原理时采用了预编译的方法,先将SQL语句中可以被用户控制的参数进行编译,生成对应的临时变量,在使用对应的设置方式,为临时变量中的元素进行赋值,赋值过程会对用户传入的参数进行强制类型检查和安全检查
所有和数据库交互的业务接口都应该采用参数化查询,参数化的语句使用参数而不是将用户输入的变量直接嵌入到SQL语句中,参数化查询时防御SQL注入的最佳方法,例如Java中的PrepareStatement,PHP中的PDO等
数据库层面
最小权限原则
严格限制网站用户的数据库操作权限,禁止将任何高权限账户用于应用程序数据库访问,可以减少注入攻击对数据库的危害
禁用敏感函数
防止攻击者通过SQL注入获取到除数据库外的其他更高权限,如系统权限
例如MSSQL,拒绝用户访问敏感的系统存储过程,如xp_dirtree、xp_cmdshell等
权限控制
限制用户只能够访问必须使用的数据库表
统一编码
网站和数据层的编码统一,建议全部使用UTF-8编码,避免因上下层编码不一致导致一些过滤模型被绕过,例如宽字节注入等
其他层面
- 网站应避免抛出SQL语句执行过程中的错误信息,如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断
- 使用通用防注入系统,或部署WAF等
学习靶场
- DVWA
- sqli-labs
结尾
提供一些备忘网站
https://pentestmonkey.net/category/cheat-sheet/sql-injection