mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Fixing #6087
This commit is contained in:
parent
002828a734
commit
26e13122ca
3 changed files with 27 additions and 6 deletions
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.7.161"
|
||||
VERSION = "1.10.7.162"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
|
|
|
|||
|
|
@ -1572,6 +1572,7 @@ class Connect(object):
|
|||
# it skips the time-based statistical warm-up entirely. The comparison request is assembled exactly
|
||||
# as it would be sent (buildOnly) and the bit is read from a coalesced pair. Not engaged -> timing.
|
||||
if timeBasedCompare and kb.get("timeless") is not None:
|
||||
from lib.request.timeless import CONNECTIVITY_ERRORS
|
||||
from lib.request.timeless import negatePayload
|
||||
# Build the condition and negation requests through the SAME path (queryPage buildOnly on the
|
||||
# raw pre-placement value) so the pair differs ONLY by the negated comparison - building cond
|
||||
|
|
@ -1580,7 +1581,17 @@ class Connect(object):
|
|||
negValue = negatePayload(timelessOrigValue)
|
||||
condSpec = Connect.queryPage(timelessOrigValue, place=place, buildOnly=True)
|
||||
negSpec = Connect.queryPage(negValue, place=place, buildOnly=True) if negValue is not None else None
|
||||
return kb.timeless.readBitFromSpecs(condSpec, negSpec)
|
||||
try:
|
||||
return kb.timeless.readBitFromSpecs(condSpec, negSpec)
|
||||
except CONNECTIVITY_ERRORS as ex:
|
||||
# The oracle's own per-pair retries (see _pairOrder) are exhausted - the target has stopped
|
||||
# negotiating HTTP/2 altogether (e.g. a load-balanced backend that only some nodes speak it
|
||||
# on), not just dropped one connection. Disengage (restores the classic time-based vector)
|
||||
# and fall through below to the normal wall-clock comparison instead of crashing the scan.
|
||||
from lib.request.timeless import disengage
|
||||
warnMsg = "HTTP/2 timeless timing lost connectivity ('%s'). Falling back to classic time-based" % getSafeExString(ex)
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
disengage()
|
||||
|
||||
if timeBasedCompare and not conf.disableStats:
|
||||
if len(kb.responseTimes.get(kb.responseTimeMode, [])) < MIN_TIME_RESPONSES:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ from lib.request.http2 import _H2Connection
|
|||
# Serializes the one-shot autoEngage() so concurrent worker threads never double-calibrate/double-engage.
|
||||
_engageLock = threading.Lock()
|
||||
|
||||
# Transport-level failures that mean "this connection/attempt is unusable" - covers a mid-exchange drop
|
||||
# (GOAWAY, reset) as well as a failed (re)connect, including the h2 client's own IOError when the server
|
||||
# does not negotiate ALPN 'h2' on a fresh socket (seen on backends that speak h2 inconsistently, e.g. only
|
||||
# some nodes behind a load balancer). Shared by _pairOrder (per-pair retry) and connect.py (the give-up path).
|
||||
CONNECTIVITY_ERRORS = (socket.error, ssl.SSLError, IOError)
|
||||
|
||||
|
||||
def buildConditionPair(condition, heavy, cheap="0"):
|
||||
"""Turn a boolean `condition` (the same comparison bisection injects at INFERENCE_MARKER, e.g.
|
||||
|
|
@ -59,15 +65,19 @@ def _pairOrder(connSource, reqA, reqB, timeout, retries=2):
|
|||
lets a dropped connection be replaced transparently and the pair re-sent: a long extraction routinely
|
||||
outlives a single HTTP/2 connection (the server retires it with GOAWAY after its per-connection request
|
||||
cap), and a coalesced boolean-read pair is idempotent, so re-sending it on a fresh connection is safe.
|
||||
A raw connection (used by calibration and the self-test) is not retried - it simply raises."""
|
||||
Opening that fresh connection is retried the same way - it can fail just like an in-progress exchange
|
||||
(including ALPN renegotiation failing on the new socket). A raw connection (used by calibration and the
|
||||
self-test) is not retried - it simply raises."""
|
||||
attempt = 0
|
||||
while True:
|
||||
conn = connSource() if callable(connSource) else connSource
|
||||
conn = None
|
||||
try:
|
||||
conn = connSource() if callable(connSource) else connSource
|
||||
order, _results = conn.exchange_pair([reqA, reqB], timeout)
|
||||
return order[0], conn.next_sid - 4, conn.next_sid - 2
|
||||
except (socket.error, ssl.SSLError, IOError):
|
||||
conn.close() # retire; a callable source reopens on the next pass
|
||||
except CONNECTIVITY_ERRORS:
|
||||
if conn is not None:
|
||||
conn.close() # retire; a callable source reopens on the next pass
|
||||
attempt += 1
|
||||
if not callable(connSource) or attempt > retries:
|
||||
raise
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue