sqli-lab练习-less-28及特殊不可打印字符

前言

专门把第28关单拿出来,是因为在做题时遇到了一些问题,就拿出来单写一篇博客。
ps.整理了关于sqli-labs靶场的博客,将分散的几篇整合了起来。

less-28

先讲解题思路。通过标题提示与源码的分析,我们知道这题除了过滤注释符与空格之外,还将连续的union select给过滤了:

1
2
3
4
5
6
7
8
9
10
$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 select的过滤(单引号+括号注入):

1
2
3
?id=0')unionunion%0aselect%0aselect%0a1,database(),3;%00

?id=0')ununion%0aselection%0aselect%0a1,database(),3;%00

这种方法是双写绕过,我们发现输入后页面在hint部分回显内容都为正常的联合查询语句,原理都是让union%0aselect被过滤,剩下的内容刚好构成一个新的union%0aselect,从而进行联合查询,当然这里的%a0可以替换为其他不可打印字符代替。

到这里我们就可以进行爆库操作了。

关于%a0分析

这道题其实已经解完了,但是我们在回顾源码中关于union select的过滤语句:
$id= preg_replace('/union\s+select/i',"", $id);

union的后面有一个\s+,这就意味着所有的空格、空白符以及换行符在这里全部都被过滤了,而这个加号意味着多次匹配,因此我们也不能通过双写空格的方式来绕过。但在这其中,有一个例外:%a0

注意到这个玩意也是我发现其他人构建了一句这样的语句:
?id=0')union%a0select(1),(database()),(3);%00

%a0是经过URL编码的不可打印字符,代表的是空格,按道理来说是应该要被过滤掉的,但是居然没有,相当神奇。不过我们在linux下跑php7靶场时,发现了问题:

我们想要的数据库名称居然没有正常回显,看下hint的显示,union与select之间居然出现了一个奇怪的符号,这就相当离谱了,我们回主机的靶场上跑:

翻译翻译什么叫惊喜,这就叫惊喜,hint语句出来是一样的,但是主机靶场就是不讲道理地回显了数据库名。这里我们开始做推测:

  • linux系统下读取解析%a0结果与windows系统下结果不同,导致在linux系统下出现语法错误
  • php版本不同导致%a0解析结果不同

在此之前,我们首先了解到了这个%a0在此处被解析出的结果,它是空格,但又不完全是,因为如果是空格的话,例如我们使用%0a替换%a0,hint回显应该是连union select一起被过滤了,很显然这里却没有,但是在主机靶场中这个%a0又起到了空格的作用。

通过在主机另外搭建了一个php7的靶场测试,发现hint是一样的,但是没有数据库名的回显,这证明了php版本是肯定有问题的,但是第一点暂时没有证明,因为现在的linux系统只能安装php7及以上版本。

通过资料我们发现,%a0解析成空格只有在php5.2.17版本可以通过成功,目前看来应该是php版本的问题。28a采用盲注就行了,甚至28a连空格和注释符都没过滤。