SQL Injection
本文需要的实验环境及搭建请访问:DVWA篇之环境搭建
SQL注入就是通过把sql语句插入到web表单提交或输入页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
Sql注入的一般流程:
1、判断注入点
2、判断注入类型
3、判断数据库类型
4、获取数据库权限,提权
Low级别
我们先来分析一下源码,同时再一步步操作,验证我们的分析
源码关键部分:
我们可以看到,当进行查询参数id的时候没有进行任何过滤,很明显存在注入漏洞的。
1、 这时我们试试判断注入点
可以输入单引号看是否报错来判断
可以注入
同时我们看到在处理id参数的时候加了引号‘$id‘,说明这是字符型的注入。
2、如何判断字符型注入
测试方法:例如
http://127.0.0.1/test/test2.php?user=admin’and ‘1’=’1 返回成功
http://127.0.0.1/test/test2.php?user=admin’and ‘1’=’2 返回错误
当我们输入1‘ and ‘1’=’1 的时候,语句的变化:Select * from user where user =’1’and ‘1’=’1’
这时,and左边成立,右边两个字符型的1肯定也是相等的,成立,所以我们整条查询语句成立。
当‘1‘=’1改为‘1’=‘2的时候整个查询语句也就返回错误
这里我们利用的查询技巧就是,利用我们所能猜想的语句,经过单引号的出现,将原有的查询语句中的单引号进行闭合,以达到我们想得到的结果
当然查询判断语句千万,不仅仅这些,例如我们可以将里面的‘1‘=’1改为‘a’=’a效果也是一样的。
- Low级别下进行测试,输入1’and ‘1’=’1 查询成功
- 输入1’and ‘1’=’2查询失败
3、当我们有了以上的判断的时候,就可以进行获取权限的查询了。
(1)判断字段数
- 输入1’order by 3 #查询失败
- 输入 1’ order by 2 #查询成功
- 注意:这里加上#号的原因是起到注释的效果。当我们输入这条查询语句的时候,就会变成:Select first_name,last_name from users WHERE user_id = ‘1’order by #‘
可以看出多出来的单引号我们用#注释掉了。
(2)判断当前使用的数据库 - 输入1’union select 1,database() #
当前使用的是dvwa数据库
(3)判断数据库中的表。 - 输入1’union select 1,table_name from information_schema.tables where table_schema=’dvwa’#
Dvwa数据库中存放了两张表。
(4)判断users表中的字段 - 输入1’union select 1,column_name from information_schema.columns where table_name=’users’#
得到很多的字段,我们接下来破解user和password的字段内容
(5)爆出user,password字段的内容 - 输入:1’union select user,password from users #
成功将这个数据库中的用户名和密码爆出。
Medium级别
查看一下关键代码
- mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
? \x00
? \n
? \r
? \
? ‘
? "
? \x1a
这个函数在一定程度上控制了用户的输入。但是,查询语句上,读取id参数的时候没有引号,这个和low级别有差别,这个就是数字型注入。遇到这种注入,上面的那个函数的作用就不存在了。因为我们注入的时候就不会输入那些特殊字符串。
1、当我们不知道的情况下如何判断是数字型注入。
测试方法:例如
http://127.0.0.1/test/test.php?id=1 and 1=1返回成功
http://127.0.0.1/test/test.php?id=1 and 1=2 返回错误
当我们去sql注入的时候,在服务端会向数据库执行一个查询的操作,在数字型注入的时候,查询的语句一般就是这样的Select from user where id=$id
这里的$id是通过get,post(常见递交方式)递交的,当然这里是利用的get方式递交(判断依据:递交内容显示在url中)。
当我们输入判断语句: and 1=1 的时候,查询语句就变成了:Select from user where id =1 and 1=1
这时and左边是成立的,同时右边1=1也是成立的。我们知道使用and的时候,要想结果返回true必须两边都是true。所以根据我们的判断语句,返回的两边都是true,整个select查询语句都是成功的。
当然如果输入1=2,因为不成立,所以整条语句不成立,返回错误
根据实验开始尝试测试:
- 输入 1 and 1=1:
因为这里是下拉框,我们可以通过元素检查,修改value的值进行注入,同时还可以使用bp抓包,然后改包传递参数。我这里因为java环境出了点小问题没及时修复,就不用bp了。递交
查询成功 - 将value的值改为 1 and 1=2.递交
查询失败。可以证明是数字型注入。
下面的操作几乎和low级别的差不多了,只不过将里面使用的单引号,井号什么的去除掉就可以了。非常简单
查字段数: 1 order by 2
查数据库:1 union select 1,database()
查数据库中的表:1 union select 1,table_name from information_schema.tables where table_schema=’dvwa’
查users表中的字段: 1 union select column_name from information_schema.columns where table_name=’users’
爆出字段内容: 1 union select user,password from users
High级别
查看关键代码
这里的和low级别的差不多只是查询语句后面添加了limit 1,意思是只返回查询到的第一条记录。
通过上面的实验我们都知道,我们查询的结果都是很多条的,第一条记录是正常的结果。这样就不会让我们看到下面的一些恶意查询结果。
其实在这里,这个limit 1 的条件加与没加是无所谓的,因为他的参数id是字符型的。在我们的low级别查询的时候为了避免后面的单引号,我们选择了将其注释掉。这里你在后面加了limit 1 ,还是一样能被注释掉的。完全没什么用。
- 例如,输入 1’ and 1=1 # 查询语句就会变成
Select first_name last_name from users where user_id = ‘1’and 1=1 # ‘ limit 1
井号后面注释掉,查询条件成立。 - 我们在实验环境上进行测试一下
- 查询出所有的记录
事实证明我们的分析没有错误,接下来还是那一套猛如虎的操作,查字段数,查数据库,查表,查字段,爆内容。不在一一赘述。
Impossible级别
查看关键源码
代码中限制返回的查询结果数量为一时,才会输出,防止大量数据泄露。同时采用了PDO技术,隔离了代码与数据,使得用户输入的数据不再被当做代码去执行。达到杜绝SQL注入的目的。无敌!
本人对于PDO技术也是知之甚少,等以后对PDO技术有所掌握的时候再来进行补充吧。
原文地址:http://blog.51cto.com/12332766/2122112