1.1 SQL注入原理
用户登录的基本SQL语句:select * from users where username = '用户输入的用户名'and password = '用户输入的密码'
用户输入的内容是可控的,例如我们可以在用户名中输入' or 1=1 --空格:select * from users where username = " or 1=1 --空格'and password = '用户输入的密码'
此时我们输入的第一个单引号将username的单引号闭合,相当于输入了一个空用户,or表示左右两边只要有一边条件判断成立则该语句返回结果为真,其中1=1永远为真,所以当前SQL语句无论怎么执行结果永远为真,--空格表示注释后面所有代码不再执行。
可以看到上面我们闭合的方法是没有输入用户名的,所以并不能成功登陆:select * from users where username = 'admin' or 1=1 --空格' and password ='用户输入的密码'
在单引号前面加上用户名表示我们要登陆的用户,这样就成功绕过了用户密码认证。
单引号的作用:在提交数据或者URL中添加单引号进行提交,如果返回SQL错误即可判断当前位置存在SQL注入漏洞,原因是没有被过滤。
1.2 SQL注入分类
SQL注入的分类基本上都是根据在注入的方式进行分类,大概分为以下4类:
- 布尔注入:可以根据返回页面判断条件真假的注入;
- 联合注入:可以使用union的注入;
- 延时注入:不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断;
- 报错注入:页面会返回错误信息或者把注入的语句的结果直接返回在页面中;
以上是根据常见的注入方式进行分类,但是通常来说SQL注入只分为字符型或者数字型,比如:
- 数字型1 or 1=1
- 字符型1' or '1'='1
还可以按照注入方式分成GET和POST注入,GET方式和POST方式的区别:
- GET方式可以明显的从URL中进行注入
- POST可以在数据包中进行修改对应的字段来进行SQL注入
1.3 SQL盲注介绍
1.3.1 盲注概念
Blind SQL (盲注)其实是sql注入的一种,他不需要根据你注入的攻击语句来返回你想要知道的错误信息,而通常代码中如果屏蔽了报错信息我们就需要使用盲注。
比如当程序员在开发过程中隐藏了数据库的内建报错信息并替换为通用的错误提示,那么sql注入将无法依据报错信息判断注入语句的执行结果,这就是“盲”的意思。
1.3.2 盲注分类
盲注分为两类:
- 布尔盲注:它只会根据你的注入信息返回True跟False, 根据结果判断是否和自己输入的值一致从而猜解出完整的数据。
- 时间盲注:界面返回值只有一种True,无论输入任何值返回情况都会按正常的来处理,加入特定的时间函数通过查看web页面返回的时间差来判断注入的语句是否正确。
1.3.3 盲注流程
- 判断是否存在注入点
- 猜解当前数据库名称,注:需要先猜解名称的长度
- 猜解数据库中的表名,注:需要先猜解名称的长度
- 猜解表中的字段名,注:需要先猜解字段的数量
- 猜解数据,注:需要先猜解数据的记录数,再对每个字段的长度和数据进行猜解
1.4 防御SQL注入
通过大量的SQL注入攻击的案例和技巧发现,都是因为程序要接收用户输入的变量或者URL传递的参数,并且参数或变量会被组成SQL语句的一部分被执行,这些数据我们统称为外部数据,在安全领域有一条规则:外部数据不可信任,所以我们需要通过各种方式对数据进行检测和过滤。
- 检查变量数据类型和格式
- 过滤特殊符号
- 绑定变量,使用预编译语句。(MySQL 的mysqli驱动提供了预编译语句的支持)
