SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害是巨大的,常常会导致整个数据库被”脱裤“,尽管如此,SQL注入仍是现在最常见的Web漏洞之一。
手工注入思路
自动化的注入神器sqlmap固然好用,但还是要掌握一些手工注入的思路,下面简要介绍手工注入(非盲注)的步骤。
- 判断是否存在注入,注入是字符型还是数字型
- 猜解SQL查询语句中的字段数
- 确定显示的字段顺序
- 获取当前数据库
- 获取数据库中的表
- 获取表中的字段名
- 下载数据
Low
注入类型
看源码:
$id
带着单引号,明显是字符型注入。
测试方法:
能够返回正确结果:
查询字段数
使用order by来猜测字段数。
当payload为1' order by 1 #
时, 报错:Unknown column ‘3’ in ‘order clause’,说明有2个字段。同样可以使用1' union select 1,2 #
来查询出字段数。
当payload为1’ union select 1,2,3 # 就报错了:The used SELECT statements have a different number of columns
,说明只有2个字段。
确定显示的字段顺序
通过上面的union select可以确定显示顺序为:First name、Surname。
确定数据库名
1' union select 1,database() #
可以查询到:
确定表名
可以确定表名。
说明数据库dvwa中一共有两个表,guestbook与users。
确定字段名
可以确定字段名为Surname: user_id,first_name,last_name,user,password,avatar,last_login,failed_login
。
查询数据
Medium
利用mysql_real_escape_string函数对特殊符号\x00,\n,\r,\,',",\x1a
进行转义,这对字符型注入有用,对数值型注入用处不大。
Medium前端为下拉列表,我们可以使用Burp来修改id的值。
检查注入类型
查看源码,可以确定为数值型注入。
另外通过payload来查看:
检查字段个数
字段顺序
查询数据库
查询表名
查询字段名
报错:
这是因为mysqli_real_escape_string
把单引号转义成\'
了。
这里可以利用16进制进行绕过,把users
字符串转成16进制:0x7573657273
。
获取数据
High
跟Medium相比,sql语句后面多加了LIMIT 1
,可以在payload后面加上#
注释掉即可。
Impossible
用到了POD,分离了sql命令和请求id,分离了代码和数据。有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。