add comments to connect.py

pull/3/head
wang 3 months ago
parent 574649a2f0
commit 9f3934a717

@ -5,6 +5,7 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
# 导入所需的标准库
import binascii import binascii
import inspect import inspect
import logging import logging
@ -18,6 +19,7 @@ import sys
import time import time
import traceback import traceback
# 尝试导入websocket库,如果不存在则定义一个简单的异常类
try: try:
import websocket import websocket
from websocket import WebSocketException from websocket import WebSocketException
@ -25,6 +27,7 @@ except ImportError:
class WebSocketException(Exception): class WebSocketException(Exception):
pass pass
# 导入sqlmap自定义的库和工具函数
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import asciifyUrl from lib.core.common import asciifyUrl
from lib.core.common import calculateDeltaSeconds from lib.core.common import calculateDeltaSeconds
@ -146,13 +149,18 @@ from thirdparty.socks.socks import ProxyError
class Connect(object): class Connect(object):
""" """
This class defines methods used to perform HTTP requests 这个类定义了用于执行HTTP请求的方法
""" """
@staticmethod @staticmethod
def _getPageProxy(**kwargs): def _getPageProxy(**kwargs):
"""
代理方法,用于处理页面请求
检查递归深度并调用getPage方法
"""
try: try:
if (len(inspect.stack()) > sys.getrecursionlimit() // 2): # Note: https://github.com/sqlmapproject/sqlmap/issues/4525 # 检查调用栈深度是否超过限制
if (len(inspect.stack()) > sys.getrecursionlimit() // 2):
warnMsg = "unable to connect to the target URL" warnMsg = "unable to connect to the target URL"
raise SqlmapConnectionException(warnMsg) raise SqlmapConnectionException(warnMsg)
except (TypeError, UnicodeError): except (TypeError, UnicodeError):
@ -165,9 +173,15 @@ class Connect(object):
@staticmethod @staticmethod
def _retryProxy(**kwargs): def _retryProxy(**kwargs):
"""
重试代理方法
处理请求失败时的重试逻辑
"""
# 获取当前线程数据
threadData = getCurrentThreadData() threadData = getCurrentThreadData()
threadData.retriesCount += 1 threadData.retriesCount += 1
# 如果配置了代理列表且重试次数达到上限,则更换代理
if conf.proxyList and threadData.retriesCount >= conf.retries and not kb.locks.handlers.locked(): if conf.proxyList and threadData.retriesCount >= conf.retries and not kb.locks.handlers.locked():
warnMsg = "changing proxy" warnMsg = "changing proxy"
logger.warning(warnMsg) logger.warning(warnMsg)
@ -177,9 +191,8 @@ class Connect(object):
setHTTPHandlers() setHTTPHandlers()
# 处理基于时间的测试模式
if kb.testMode and kb.previousMethod == PAYLOAD.METHOD.TIME: if kb.testMode and kb.previousMethod == PAYLOAD.METHOD.TIME:
# timed based payloads can cause web server unresponsiveness
# if the injectable piece of code is some kind of JOIN-like query
warnMsg = "most likely web server instance hasn't recovered yet " warnMsg = "most likely web server instance hasn't recovered yet "
warnMsg += "from previous timed based payload. If the problem " warnMsg += "from previous timed based payload. If the problem "
warnMsg += "persists please wait for a few minutes and rerun " warnMsg += "persists please wait for a few minutes and rerun "
@ -188,6 +201,7 @@ class Connect(object):
warnMsg += "lower the value of option '--time-sec' (e.g. '--time-sec=2')" warnMsg += "lower the value of option '--time-sec' (e.g. '--time-sec=2')"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
# 处理原始页面为空的情况
elif kb.originalPage is None: elif kb.originalPage is None:
if conf.tor: if conf.tor:
warnMsg = "please make sure that you have " warnMsg = "please make sure that you have "
@ -214,20 +228,28 @@ class Connect(object):
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
# 处理多线程情况
elif conf.threads > 1: elif conf.threads > 1:
warnMsg = "if the problem persists please try to lower " warnMsg = "if the problem persists please try to lower "
warnMsg += "the number of used threads (option '--threads')" warnMsg += "the number of used threads (option '--threads')"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
# 重试请求
kwargs['retrying'] = True kwargs['retrying'] = True
return Connect._getPageProxy(**kwargs) return Connect._getPageProxy(**kwargs)
@staticmethod @staticmethod
def _connReadProxy(conn): def _connReadProxy(conn):
"""
读取连接响应的代理方法
处理压缩和大响应的情况
"""
retVal = b"" retVal = b""
# 如果不是DNS模式且连接存在
if not kb.dnsMode and conn: if not kb.dnsMode and conn:
headers = conn.info() headers = conn.info()
# 处理压缩响应
if kb.pageCompress and headers and hasattr(headers, "getheader") and (headers.getheader(HTTP_HEADER.CONTENT_ENCODING, "").lower() in ("gzip", "deflate") or "text" not in headers.getheader(HTTP_HEADER.CONTENT_TYPE, "").lower()): if kb.pageCompress and headers and hasattr(headers, "getheader") and (headers.getheader(HTTP_HEADER.CONTENT_ENCODING, "").lower() in ("gzip", "deflate") or "text" not in headers.getheader(HTTP_HEADER.CONTENT_TYPE, "").lower()):
retVal = conn.read(MAX_CONNECTION_TOTAL_SIZE) retVal = conn.read(MAX_CONNECTION_TOTAL_SIZE)
if len(retVal) == MAX_CONNECTION_TOTAL_SIZE: if len(retVal) == MAX_CONNECTION_TOTAL_SIZE:
@ -236,6 +258,7 @@ class Connect(object):
kb.pageCompress = False kb.pageCompress = False
raise SqlmapCompressionException raise SqlmapCompressionException
else: else:
# 分块读取大响应
while True: while True:
if not conn: if not conn:
break break
@ -254,11 +277,13 @@ class Connect(object):
retVal += part retVal += part
break break
# 检查总响应大小是否超过限制
if len(retVal) > MAX_CONNECTION_TOTAL_SIZE: if len(retVal) > MAX_CONNECTION_TOTAL_SIZE:
warnMsg = "too large response detected. Automatically trimming it" warnMsg = "too large response detected. Automatically trimming it"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
break break
# 处理特殊的响应放大因子
if conf.yuge: if conf.yuge:
retVal = YUGE_FACTOR * retVal retVal = YUGE_FACTOR * retVal
@ -267,13 +292,14 @@ class Connect(object):
@staticmethod @staticmethod
def getPage(**kwargs): def getPage(**kwargs):
""" """
This method connects to the target URL or proxy and returns 这个方法连接到目标URL或代理并返回目标URL页面内容
the target URL page content
""" """
# 如果是离线模式直接返回
if conf.offline: if conf.offline:
return None, None, None return None, None, None
# 获取请求参数
url = kwargs.get("url", None) or conf.url url = kwargs.get("url", None) or conf.url
get = kwargs.get("get", None) get = kwargs.get("get", None)
post = kwargs.get("post", None) post = kwargs.get("post", None)
@ -297,16 +323,19 @@ class Connect(object):
finalCode = kwargs.get("finalCode", False) finalCode = kwargs.get("finalCode", False)
chunked = kwargs.get("chunked", False) or conf.chunked chunked = kwargs.get("chunked", False) or conf.chunked
# 处理请求延迟
if isinstance(conf.delay, (int, float)) and conf.delay > 0: if isinstance(conf.delay, (int, float)) and conf.delay > 0:
time.sleep(conf.delay) time.sleep(conf.delay)
start = time.time() start = time.time()
# 获取当前线程数据
threadData = getCurrentThreadData() threadData = getCurrentThreadData()
with kb.locks.request: with kb.locks.request:
kb.requestCounter += 1 kb.requestCounter += 1
threadData.lastRequestUID = kb.requestCounter threadData.lastRequestUID = kb.requestCounter
# 处理代理频率
if conf.proxyFreq: if conf.proxyFreq:
if kb.requestCounter % conf.proxyFreq == 0: if kb.requestCounter % conf.proxyFreq == 0:
conf.proxy = None conf.proxy = None
@ -316,6 +345,7 @@ class Connect(object):
setHTTPHandlers() setHTTPHandlers()
# 处理测试模式
if conf.dummy or conf.murphyRate and randomInt() % conf.murphyRate == 0: if conf.dummy or conf.murphyRate and randomInt() % conf.murphyRate == 0:
if conf.murphyRate: if conf.murphyRate:
time.sleep(randomInt() % (MAX_MURPHY_SLEEP_TIME + 1)) time.sleep(randomInt() % (MAX_MURPHY_SLEEP_TIME + 1))
@ -327,6 +357,7 @@ class Connect(object):
return page, headers, code return page, headers, code
# 处理cookie
if conf.liveCookies: if conf.liveCookies:
with kb.locks.liveCookies: with kb.locks.liveCookies:
if not checkFile(conf.liveCookies, raiseOnError=False) or os.path.getsize(conf.liveCookies) == 0: if not checkFile(conf.liveCookies, raiseOnError=False) or os.path.getsize(conf.liveCookies) == 0:
@ -351,6 +382,7 @@ class Connect(object):
cookie = openFile(conf.liveCookies).read().strip() cookie = openFile(conf.liveCookies).read().strip()
cookie = re.sub(r"(?i)\ACookie:\s*", "", cookie) cookie = re.sub(r"(?i)\ACookie:\s*", "", cookie)
# 处理multipart请求
if multipart: if multipart:
post = multipart post = multipart
else: else:
@ -361,20 +393,20 @@ class Connect(object):
post = _urllib.parse.unquote(post) post = _urllib.parse.unquote(post)
post = chunkSplitPostData(post) post = chunkSplitPostData(post)
# 处理WebSocket请求
webSocket = url.lower().startswith("ws") webSocket = url.lower().startswith("ws")
if not _urllib.parse.urlsplit(url).netloc: if not _urllib.parse.urlsplit(url).netloc:
url = _urllib.parse.urljoin(conf.url, url) url = _urllib.parse.urljoin(conf.url, url)
# flag to know if we are dealing with the same target host # 检查是否是相同的目标主机
target = checkSameHost(url, conf.url) target = checkSameHost(url, conf.url)
if not retrying: if not retrying:
# Reset the number of connection retries # 重置连接重试次数
threadData.retriesCount = 0 threadData.retriesCount = 0
# fix for known issue when urllib2 just skips the other part of provided # 修复URL中的空格
# url splitted with space char while urlencoding it in the later phase
url = url.replace(" ", "%20") url = url.replace(" ", "%20")
if "://" not in url: if "://" not in url:
@ -396,8 +428,7 @@ class Connect(object):
raise404 = raise404 and not kb.ignoreNotFound raise404 = raise404 and not kb.ignoreNotFound
# support for non-latin (e.g. cyrillic) URLs as urllib/urllib2 doesn't # 支持非拉丁字符的URL
# support those by default
url = asciifyUrl(url) url = asciifyUrl(url)
try: try:
@ -440,7 +471,7 @@ class Connect(object):
requestMsg += " %s" % _http_client.HTTPConnection._http_vsn_str requestMsg += " %s" % _http_client.HTTPConnection._http_vsn_str
# Prepare HTTP headers # 准备HTTP头
headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie, HTTP_HEADER.USER_AGENT: ua, HTTP_HEADER.REFERER: referer, HTTP_HEADER.HOST: getHeader(dict(conf.httpHeaders), HTTP_HEADER.HOST) or getHostHeader(url)}, base=None if target else {}) headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie, HTTP_HEADER.USER_AGENT: ua, HTTP_HEADER.REFERER: referer, HTTP_HEADER.HOST: getHeader(dict(conf.httpHeaders), HTTP_HEADER.HOST) or getHostHeader(url)}, base=None if target else {})
if HTTP_HEADER.COOKIE in headers: if HTTP_HEADER.COOKIE in headers:
@ -624,11 +655,11 @@ class Connect(object):
if not kb.proxyAuthHeader and getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION): if not kb.proxyAuthHeader and getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION):
kb.proxyAuthHeader = getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION) kb.proxyAuthHeader = getRequestHeader(req, HTTP_HEADER.PROXY_AUTHORIZATION)
# Return response object # 返回响应对象
if response: if response:
return conn, None, None return conn, None, None
# Get HTTP response # 获取HTTP响应
if hasattr(conn, "redurl"): if hasattr(conn, "redurl"):
page = (threadData.lastRedirectMsg[1] if kb.choices.redirect == REDIRECTION.NO else Connect._connReadProxy(conn)) if not skipRead else None page = (threadData.lastRedirectMsg[1] if kb.choices.redirect == REDIRECTION.NO else Connect._connReadProxy(conn)) if not skipRead else None
skipLogTraffic = kb.choices.redirect == REDIRECTION.NO skipLogTraffic = kb.choices.redirect == REDIRECTION.NO

Loading…
Cancel
Save