sqlmap qps控制
0X01 发包函数限制器
首先寻找一下SQLMAP的请求发包函数
sqlmap.py
131 行 main 进入主函数
135 行 进入主流程
经过一系列环境监测、cmdLineOptions参数初始化、init参数应用后等等后
start() 检测SQL注入函数 --> 跳转到 controller.py
==> /lib/controller/controller.py -- 检测注入处
299 行 for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
遍历了所有url,如果用 -u,就for一次; 如果有list,就for多次吧。
本次是寻找发包函数,所以直接找到下面的 checkConnection(suppressOutput=conf.forms),一个检测
URL是否能连接的函数,-v 6第一个会发的请求。
==> /lib/controller/checks.py -- 检测扫描条件
checkconnection函数中,定位到
Request.queryPage(content=True, noteResponseTime=False)
发送请求的代码段,跟进
==> /lib/request/connect.py -- 请求类
connect.py queryPage根据各种条件发送请求的函数
初始化配置、根据请求方式来发包等功能,但这不是最终最小颗粒度的发包函数
跟进 getPage()函数,这是最小颗粒度的请求发包函数
该函数根据收到的参数拼接原始数据包,websocket的方式发出去。
请求函数为 lib
equestconnect.py里的 getPage()函数
所以在getPage函数上加个自定义的装饰器,用来计算每一次的QPS、延迟QPS超标后的请求就好了
0X02 文件修改检测跳过
/lib/core/common.py -- checkIntegrity() 遍历文件检测文件的最新修改时间有没有问题,修改过则不运行了
这里直接在函数开始 return掉
0X03 类型报错
/lib/core/options.py 中 定义了重定向处理 redirectHandler
/libn/requests/redirecthandler.py 跳转302的处理函数 http_error_302 141行
for part in req.headers.get(HTTP_HEADER.COOKIE, "").split(delimiter) + ([headers[HTTP_HEADER.SET_COOKIE]] if HTTP_HEADER.SET_COOKIE in headers else []):
req.headers.get(HTTP_HEADER.COOKIE, "") 如果非空是bytes,delimiter是str,会导致报错
这里修改为 ==>
REQ_COOKIE = req.headers.get(HTTP_HEADER.COOKIE, "")
if type(REQ_COOKIE) == bytes:
REQ_COOKIE = REQ_COOKIE.decode()
for part in REQ_COOKIE.split(delimiter) + ([headers[HTTP_HEADER.SET_COOKIE]] if HTTP_HEADER.SET_COOKIE in headers else []):
0X04 SQLMAP异常跑出
我们控制QPS的方式是跑出异常 --> celery收到特定的异常,重试任务
另外其他的做法也可以是sleep,但容易造成节点hang住,所以这里QPS采取了抛出异常重试、超过最大重试次数后报错的方式
所以这里将sqlmap的异常修改成抛出
sqlmap.py main() 251行
except SystemExit:
pass
except QpsLimitError:
raise QpsLimitError
except:
如果想在main中收到异常,还需要改一下 __main__
0X05 题外
只提供了思路和修改的地方,没有直接贴代码,因为QPS限制后的动作无法一致。