Skip to content

Commit 1a5e316

Browse files
stamparmtanaydin
authored andcommitted
Implement experimental --http2 (#4402)
1 parent 27dc8a9 commit 1a5e316

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

lib/core/optiondict.py

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"liveCookies": "string",
3131
"loadCookies": "string",
3232
"dropSetCookie": "boolean",
33+
"http2": "boolean",
3334
"agent": "string",
3435
"mobile": "boolean",
3536
"randomAgent": "boolean",

lib/core/settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from thirdparty import six
2020

2121
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
22-
VERSION = "1.9.2.9"
22+
VERSION = "1.9.2.10"
2323
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2424
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2525
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/parse/cmdline.py

+3
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ def cmdLineParser(argv=None):
177177
request.add_argument("--drop-set-cookie", dest="dropSetCookie", action="store_true",
178178
help="Ignore Set-Cookie header from response")
179179

180+
request.add_argument("--http2", dest="http2", action="store_true",
181+
help="Use HTTP version 2 (experimental)")
182+
180183
request.add_argument("--mobile", dest="mobile", action="store_true",
181184
help="Imitate smartphone through HTTP User-Agent header")
182185

lib/request/connect.py

+42-7
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class WebSocketException(Exception):
9090
from lib.core.exception import SqlmapCompressionException
9191
from lib.core.exception import SqlmapConnectionException
9292
from lib.core.exception import SqlmapGenericException
93+
from lib.core.exception import SqlmapMissingDependence
9394
from lib.core.exception import SqlmapSkipTargetException
9495
from lib.core.exception import SqlmapSyntaxException
9596
from lib.core.exception import SqlmapTokenException
@@ -603,11 +604,6 @@ class _(dict):
603604
if not chunked:
604605
requestMsg += "\r\n"
605606

606-
if not multipart:
607-
threadData.lastRequestMsg = requestMsg
608-
609-
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
610-
611607
if conf.cj:
612608
for cookie in conf.cj:
613609
if cookie.value is None:
@@ -616,7 +612,46 @@ class _(dict):
616612
for char in (r"\r", r"\n"):
617613
cookie.value = re.sub(r"(%s)([^ \t])" % char, r"\g<1>\t\g<2>", cookie.value)
618614

619-
conn = _urllib.request.urlopen(req)
615+
if conf.http2:
616+
try:
617+
import httpx
618+
with httpx.Client(verify=False, http2=True, timeout=timeout, follow_redirects=True, cookies=conf.cj) as client:
619+
conn = client.request(method or (HTTPMETHOD.POST if post is not None else HTTPMETHOD.GET), url, headers=headers, data=post)
620+
except ImportError:
621+
raise SqlmapMissingDependence("httpx[http2] not available (e.g. 'pip%s install httpx[http2]')" % ('3' if six.PY3 else ""))
622+
else:
623+
conn.code = conn.status_code
624+
conn.msg = conn.reason_phrase
625+
conn.info = lambda c=conn: c.headers
626+
627+
conn._read_buffer = conn.read()
628+
conn._read_offset = 0
629+
630+
requestMsg = re.sub(" HTTP/[0-9.]+\r\n", " %s\r\n" % conn.http_version, requestMsg, count=1)
631+
632+
if not multipart:
633+
threadData.lastRequestMsg = requestMsg
634+
635+
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
636+
637+
def _read(count=None):
638+
offset = conn._read_offset
639+
if count is None:
640+
result = conn._read_buffer[offset:]
641+
conn._read_offset = len(conn._read_buffer)
642+
else:
643+
result = conn._read_buffer[offset: offset + count]
644+
conn._read_offset += len(result)
645+
return result
646+
647+
conn.read = _read
648+
else:
649+
if not multipart:
650+
threadData.lastRequestMsg = requestMsg
651+
652+
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
653+
654+
conn = _urllib.request.urlopen(req)
620655

621656
if not kb.authHeader and getRequestHeader(req, HTTP_HEADER.AUTHORIZATION) and (conf.authType or "").lower() == AUTH_TYPE.BASIC.lower():
622657
kb.authHeader = getUnicode(getRequestHeader(req, HTTP_HEADER.AUTHORIZATION))
@@ -699,7 +734,7 @@ class _(dict):
699734
# Explicit closing of connection object
700735
if conn and not conf.keepAlive:
701736
try:
702-
if hasattr(conn.fp, '_sock'):
737+
if hasattr(conn, "fp") and hasattr(conn.fp, '_sock'):
703738
conn.fp._sock.close()
704739
conn.close()
705740
except Exception as ex:

lib/utils/deps.py

+10
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ def checkDependencies():
9494
logger.warning(warnMsg)
9595
missing_libraries.add('python-ntlm')
9696

97+
try:
98+
__import__("httpx")
99+
debugMsg = "'httpx[http2]' third-party library is found"
100+
logger.debug(debugMsg)
101+
except ImportError:
102+
warnMsg = "sqlmap requires 'httpx[http2]' third-party library "
103+
warnMsg += "if you plan to use HTTP version 2"
104+
logger.warning(warnMsg)
105+
missing_libraries.add('httpx[http2]')
106+
97107
try:
98108
__import__("websocket._abnf")
99109
debugMsg = "'websocket-client' library is found"

sqlmap.conf

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ loadCookies =
6161
# Valid: True or False
6262
dropSetCookie = False
6363

64+
# Use HTTP version 2 (experimental).
65+
# Valid: True or False
66+
http2 = False
67+
6468
# HTTP User-Agent header value. Useful to fake the HTTP User-Agent header value
6569
# at each HTTP request.
6670
# sqlmap will also test for SQL injection on the HTTP User-Agent value.

0 commit comments

Comments
 (0)