天呢,不知道的以为我在注CIA。
经典的字符串型盲注,无报错回显。注入单引号*1返回404或500(交替出现,无规律),注入单引号*2正常显示:
由于可能存在混淆情况(前几天就遇到一个模糊搜索导致1-0、1-1回显不同让人以为是注入),用单引号*3、单引号*4等再次测试,确定这里存在一个注入点。
开始注入,先使用百用百不腻的' and '1'='1。这个payload有两个作用,一是进一步确定注入是否存在,二是测试WAF是否存在,因为几乎没有WAF会不拦截它。
也是果不其然的拦截了:
由于返回的是空包,也不好确定是不是云WAF,先使用最懒的办法,也就是垃圾参数绕过:
一发入魂,四千九百多个参数绕过成功,但看返回包很明显还有WAF。
逐个删除敏感关键词,看看这第二个WAF到底拦截了哪些词。
删除=,拦截;删除单引号,正常;删除and,正常。
看来是拦截了'+and,然后换用其它常见关键字测试,'+select拦截,'+union拦截,'+or拦截;而'+if,'+case都可以。试着使用注释/换行代替空格,无效。对于常见函数,substr、substring、sleep自然是全部拦截,但left和right并未拦截。
看来这个WAF主要拦截的是连接词和常用函数(这个之后再说,函数不是简单拦截两个就能让人无计可施的)。使用||代替or,成功(当然,这里也有不用连接词的注法)。
实际上,这个WAF(或者说拦截)我搞了半天才发现。
很显然这个系统过了很多个开发的手,不然我不觉得有点追求的开发会写这么多个过滤拦截在代码里(毕竟这一点都不优雅),被打这么多次就直接上ORM好吗?好的。
言归正传,一开始我认为所有WAF都被绕过了,但碍于这个关键字拦截不好直接上sqlmap跑,于是只能手动注入之。要手注最开始肯定要判断下数据库类型。
使用USER无报错,USER()报错,排除MYSQL。
使用db_name()报错,排除MSSQL。
使用exp(291)报错,exp(290)不报错,确定当前数据库为Oracle。
确定数据库之后选用payload,由于是只能使用or的盲注,我选择使用1/0也就是除零报错进行盲注。
构造payload为' || 1/(case when 1=1 then 1 else 1 end) || ',使用永真看一下语句是否报错,结果却报错了。
换用if(1=1,1,1)继续尝试,结果还是报错。
理论上用在大多数数据库上都生效的基础语句为什么会报错呢?这实在让人百思不得其解。
由于想了半天(真是打死我也不敢想开发会弄三个WAF来恶心我)想不出个所以然,所以我决定先放开这头,去测试字符串函数。毕竟手注中最能令人信服的证据莫过于注出当前用户名了。
substr、substring就别想了,会被第二个WAF拦截。使用left('a',1)代替字符串,居然还是报错?
**一次报错是我写的不对,次次报错就真的有点问题了。**这下我开始怀疑存在第三个无回显的WAF。
使用'|| 1=1 ||',居然也报错?
那么非常有可能是拦截了=等于号。换用不等于<>进行测试,未报错:
但是对case when套了<>进去,还是报错:
那很有可能是既对=拦截又对case when等条件语句拦截。这下咋办?只能重新找一个函数啦。
几番搜索,找到一个函数INSTR,用于搜索子字符串的出现位置:
这个函数是可以利用的,只是过程稍微麻烦些。至于如何利用呢——我们做一道小小的数学题即可:
' || 1/(1-INSTR(USER,'a')) || '
由于INSTR会返回整个字符串中子串出现第一次的位置,所以我们只需要同时爆破被减数与子串,即可定位整个用户名字符串:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!