sqli靶场(23~37关)
第二部分来啦~~
Less-23 注释符绕过
输入1’出现如下报错信息:
1 | ''1'' LIMIT 0,1' at line 1 |
可猜测源码中可能为’$id’
当构造id=1’ and ‘1’=’1 时正常,而id=1’ and ‘1’=’1’#或者id=1’ and ‘1’=’1’–+ 时报错,发现是对#和–+等注释符进行了过滤。
注释符绕过只能构造一个单引号来闭合后面的但引号。
利用报错注入:
23.1获取数据库用户名
1 | payload: |

23.2获取数据库名
1 | payload: |

或者使用:
1 | id=1' and info() and '1'='1 |

23.3获取表名
其实我报错函数我比较喜欢用updatexml(),但是呢,当它只能显示32长度的内容,绕过获取的内容超过32字符就要采用字符串截取的方式。然后每次获取32字符串的内容。
比如:
1 | payload: |

然后接着获取:
1 | id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(table_name),32,62) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1 |

啊还有一小节,再来一个:
1 | id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(table_name),63,93) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1 |

好了,完工。
其实吧,该说不说,上面这种可能直接手工注入的时候会容易记忆一点,但如果要写成测试脚本的话,就还是使用floor()函数,比较好:
1 | id=1' and (select count(*) from information_schema.tables group by concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2))) and '1'='1 |
好的,亏我以为floor()函数能一次性查出来所有的,原来也只能查到64字节,那剩下的字节就还是用substr()函数查出来吧。

Less-24 二次注入
本关为二次注入。
二次注入含义:将可能导致sql 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。
大致原理:先创建一个用户admin’#,再登录这个账号修改密码。原来的密码那里可以任意输,新密码自己设定。修改完成后会发现成功修改了已有账号admin的密码。
24.1先创建一个admin’#的账号

24.2登录admin’#的账号,并修改密码为123456。原来的密码可以随便输,因为会被注释掉。
在源代码中的sql语句为:
1 | $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' "; |
即如果我们修改admin’#的密码会变成:
1 | $sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' "; |
所以我们就可以变成修改admin的密码了。

24.3可以看到数据库中,admin的密码由原来的admin被改成了我们所修改的123456

and和or绕过(Less-25~Less25a)
Less-25
本关对or和and进行了过滤。要绕过or和and,构造其他的注入语句。
方法一:
尝试双写绕过。即双写关键字,可将and写为anandd,or写成oorr,发现成功绕过了耶。
方法二:
可尝试将and替换成&&,or替换成||。这里我试了一下用||可以,但&&不可以,因为&在数据包里面相当于里面的参数连接符,可以将&&进行url编码成%26%26使用。
这里采用双写绕过并利用报错注入:
①获取数据库用户名
1 | payload: |

②获取数据库名
1 | payload: |

或者使用:
1 | id=1' anandd updatexml(1,concat(0x7e,(select database()),0x7e),1)--+ |

Less-25a
本关错误时不会显示错在哪里了,所以不能采用报错注入。并且也对and和or进行了过滤。
当使用id=1 || 1=1出现正确信息,说明在源码中id=$id。
可以使用延时注入和布尔盲注。
这里还是用anandd双写来代替and,下面采用基于布尔的盲注:
①获取数据库用户名
1 | payload: |
当字母正确时,会出现正确的页面,当字母不正确时,会出现不正确的页面。也可以用burp抓包,对substr的第一个1和字母a进行爆破。
②获取数据库名
1 | payload: |
当字母正确时,会出现正确的页面,当字母不正确时,会出现不正确的页面。也可以用burp抓包,对substr的第一个1和字母a进行爆破。

空格字符绕过(Less-26~Less26a)
Less-26
本关将or,and,空格,/*,#,–,/等各种字符就进行了过滤。
空格字符绕过:
1 | %20 %09 %0a %0b %0c %0d %a0 /**/ + |
本关可以用报错注入:
①获得数据库用户名
1 | payload: |

②获得数据库名
1 | payload: |

Less-26a
本关过滤的字符跟第二十六关一样,闭合方式是’) 并且不能用报错注入了,因为不会显示错在哪里了。可以采用union联合注入或盲注。
下面采用union联合注入:
①获得数据库名
1 | payload: |
这里的999为一个不存在的值,%0b可以用%a0代替,其他不行,可能是系统问题。

②获得用户名
1 | payload: |

③获得表名
1 | payload: |

union和select绕过(Less-27~Less-28a)
Less-27
本关主要是union、select字符和26关过滤掉的字符。
如果要用到union和select的话,可以使用大小写混写或者双写关键字绕过。
可以采用报错注入:
①获得数据库用户名
1 | payload: |

②获得数据库名:
1 | payload: |

Less-27a
本关过滤的字符跟第二十七关一样,闭合方式为”并且不能采用报错注入了。
可以采用union联合注入(union和select大小写混写):
①获得数据库用户名
1 | payload: |

②获得数据库名
1 | payload: |

Less-28
本关第二十七差不多,只是闭合的方式是’)
①获取数据库名:
1 | payload: |

②获得数据库用户名
1 | payload: |

Less-28a
用第二十八关的payload一样可以
HPP(HTTP Parameter Pollution),http 参数污染(Less29~Less-31)
这三关是要搭建环境才能实现的。好像要在Ubuntu下,并且要下载tomcat,jdk等等。想了想,了解下原理,还是在PHP环境下绕过得了。
这里的两层架构的工作流程为:
client 访问服务器,能直接访问到 tomcat 服务器,然后 tomcat 服务器再向 apache 服务器请求数据。数据返回路径则相反。
这里需要注意的就是:
index.php?id=1&id=2,在Apache(php)解析最后一个参数,Tomcat(jsp)解析第一个参数。那先经过Tomcat再到Apache的也是显示最后一个参数。
Less-29
这里使用一个单引号报错,使用两个单引号正常。
(1)直接用报错注入
①得到数据库用户名
1 | payload: |

②获取数据库名
1 | payload: |

(2)使用联合注入
其实吧,我一般不怎么用union,因为还要先判断字段和注入点。好久没用了,还是用一下吧。
①先判断有几个字段
当输到id=1’ order by 4–+时报错,说明有三个字段
②找注入点
id=-1’ union select 1,2,3–+
可以看到在2,3的位置都可以写注入语句。

③构造union语句
29.1获得数据库用户名
1 | payload: |

29.2获得数据库名
1 | payload: |

29.3获得表名
1 | payload: |

29.4获得字段名
1 | payload: |

29.5获取用户名和密码
1 | payload: |

Less-30
这一关不显示报错信息,不能用报错注入了,但还是可以用union联合注入的,payload跟第二十九的一样,只需要将第二十九关的union联合注入的’换成”即可
Less-31
这关跟二十九关也一样,只需要将’换成”)即可,对于报错注入和union联合注入都能用。
宽字节注入(Less-32~Less-37)
这几关是针对’和\的过滤。在这里,会将’转换为'
宽字节注入产生的原因:数据库编码与PHP编码设置为不同的两个编码。
Big5和GBK字符集有可能会存在宽字节注入,utf-8和gb2312没有。Mysql在使用GBK编码时,会认为两个字符为一个汉字。
思路一:%df吃掉\ 原因在于urldecode(‘)=%5c%27,而我们在前面添加%df,就形成了%df%5c%27,mysql在GBK编码中前两个字当做一个汉字,此时%27就会作为一个单独的字符,也就是’
思路二:将'中的\过滤掉。可以构造%**%5c%5c%27,后面的%5c会被前面的%5c给注释掉。
Less-32
本关将’转换为',我们利用%df消掉生成的那个\。
采用报错注入:
①获得数据库名
1 | payload: |
②获得数据库用户名
1 | payload: |
Less-33
本关的payload和第三十二关一样。
Less-34
本关是post型的注入。
这里不能用%df绕过了,因为这里不是get方式不会经过urldecode,可以考虑将utf-8转换成utf-16。例如将’转为utf-16为�’
然后可以采用报错注入:
在用户框输入payload:
1 | 1�' or updatexml(1,concat(0x7e,user(),0x7e),1)# |
即可获得数据库用户名。
Less-35
本关源码中id=$id,所以不用输单引号,也就不用考虑单引号转义的问题了。
采用union联合注入
1 | payload: |
即可获得数据库用户名
Less-36
本关还是可以用%df绕过,payload和第三十二关一样。
Less-37
本关一样可以将单引号转换为utf-16,payload和第三十四关一样。