mysql-connector-python中堆叠查询里Sleep()无法执行的问题
问题:MySQL堆叠查询中sleep()无法执行的解决方法
我在Django开发安全类CTF应用,要实现基于时间的盲SQL注入练习。因为Django的Model.raw()不支持堆叠查询,所以用了mysql-connector-python,通过cursor.execute(query, multi=True)执行堆叠查询,但发现堆叠里的sleep(X)不生效——比如执行select sleep(2); select 1;时响应时间只有0.005秒左右,单独执行select sleep(2);则正常耗时约2秒。试过do sleep(X)也不行,但这套堆叠查询在MySQL控制台和Workbench里能正常运行。我的实际需求是通过时间盲注从临时表逐字符读取文件(比如/etc/passwd),求解决办法。
相关代码与执行结果
堆叠查询场景代码
视图代码:
query = f"select sleep(2); select 1;" mydb = mysql.connector.connect( host="localhost", user="****", password="****", database="****" ) cursor = mydb.cursor() cursor.execute(query, multi=True) return HttpResponse(f"query: {cursor}")
测试脚本:
url = f"http://127.0.0.1:8080/books/book/?q=1" start = time.perf_counter() response = requests.get(f'{url}') end = time.perf_counter() print(response.text) print(f'response time: {end-start}')
执行结果:
query: MySQLCursor: select sleep(2); select 1; response time: 0.005476321006426588
单查询场景代码
视图代码:
query = f"select sleep(2);" mydb = mysql.connector.connect( host="localhost", user="****", password="****", database="****" ) cursor = mydb.cursor() cursor.execute(query) return HttpResponse(f"query: {cursor}")
测试脚本:
url = f"http://127.0.0.1:8080/books/book/?q=1" start = time.perf_counter() response = requests.get(f'{url}') end = time.perf_counter() print(response.text) print(f'response time: {end-start}')
执行结果:
query: MySQLCursor: select sleep(2); response time: 2.010241993004456
解决方案
1. 遍历所有查询结果
当使用multi=True执行堆叠查询时,mysql-connector-python默认只会初始化第一个查询,不会自动触发后续查询的实际执行。必须手动迭代cursor来执行所有语句,包括sleep()所在的查询:
query = f"select sleep(2); select 1;" mydb = mysql.connector.connect( host="localhost", user="****", password="****", database="****" ) cursor = mydb.cursor() # 执行堆叠查询 results = cursor.execute(query, multi=True) # 遍历所有结果集,触发每个查询的执行 for result in results: # 若为查询语句,可获取结果;无需结果时直接pass即可 if result.with_rows: result.fetchall() return HttpResponse(f"query: {cursor}")
这样sleep(2)会被实际执行,响应时间会符合预期。
2. 合并查询逻辑(替代堆叠)
如果不需要真正的堆叠,可将sleep逻辑合并到单个查询中,比如用条件判断触发sleep,无需开启multi=True:
# 示例:条件满足时触发sleep,适配时间盲注场景 query = f"select case when (substring((select load_file('/etc/passwd')),1,1)='r') then sleep(2) else 0 end;" cursor.execute(query)
这种方式更贴合时间盲注的需求,避免堆叠查询的执行问题。
3. 检查连接配置
确保mysql-connector-python的连接参数无异常,可显式设置autocommit(虽对sleep执行影响不大,但能避免潜在的事务阻塞):
mydb = mysql.connector.connect( host="localhost", user="****", password="****", database="****", autocommit=True )
内容的提问来源于stack exchange,提问作者NotACodER
相关产品推荐
相关产品推荐

