Renaming --murphy-rate to --jitter

This commit is contained in:
Miroslav Štampar 2026-07-29 09:05:44 +02:00
parent 3a680be4eb
commit e81a99c4f3
4 changed files with 48 additions and 13 deletions

View file

@ -289,7 +289,7 @@ optDict = {
"noHuffman": "boolean",
"profile": "boolean",
"forceDns": "boolean",
"murphyRate": "integer",
"jitter": "integer",
"smokeTest": "boolean",
"fpTest": "boolean",
"payloadLint": "boolean",

View file

@ -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.243"
VERSION = "1.10.7.244"
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)
@ -180,8 +180,26 @@ IDENTYWAF_PARSE_COUNT_LIMIT = 10
# Identify WAF/IPS inside limited size of responses
IDENTYWAF_PARSE_PAGE_LIMIT = 4 * 1024
# Maximum sleep time in "Murphy" (testing) mode
MAX_MURPHY_SLEEP_TIME = 3
# Ceiling (seconds) for a simulated heavy-tailed latency spike in '--jitter' (testing) mode
MAX_JITTER_SPIKE_TIME = 6
# '--jitter=N' fault injection: ~1 in N requests is perturbed to stress the time-/boolean-based blind
# oracles' jitter defenses. Each fired event either adds realistic response LATENCY - Gaussian jitter
# spanning low->high network noise, or (JITTER_SPIKE_CHANCE of the time) a heavy-tailed spike - and lets
# the genuine request proceed, or short-circuits with a transient "junk" HTTP response (gateway 5xx,
# rate-limit, a same-HTTP-code interstitial/maintenance page, or an empty body). Values come from the
# offline jitter studies (tests/test_jitter_stress.py, tests/test_boolean_jitter.py).
JITTER_SIGMAS = (0.3, 0.5, 0.9) # low / medium / high continuous jitter (seconds)
JITTER_SPIKE_CHANCE = 0.25 # portion of latency events replaced by a heavy-tailed spike
JITTER_JUNK_RESPONSES = (
("<html><h1>502 Bad Gateway</h1></html>", 502),
("<html><h1>503 Service Unavailable</h1></html>", 503),
("<html><h1>504 Gateway Time-out</h1></html>", 504),
('{"error": "too many requests"}', 429),
("<html><head><title>Just a moment...</title></head><body>Checking your browser before accessing.</body></html>", 200),
("<html><body>We'll be back shortly. Scheduled maintenance in progress.</body></html>", 200),
("", 200),
)
# Regular expression used for extracting results from Google search
GOOGLE_REGEX = r"webcache\.googleusercontent\.com/search\?q=cache:[^:]+:([^+]+)\+&amp;cd=|url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(sa=U|rct=j)"

View file

@ -887,7 +887,7 @@ def cmdLineParser(argv=None):
parser.add_argument("--yuge", dest="yuge", action="store_true",
help=SUPPRESS)
parser.add_argument("--murphy-rate", dest="murphyRate", type=int,
parser.add_argument("--jitter", dest="jitter", type=int,
help=SUPPRESS)
parser.add_argument("--debug", dest="debug", action="store_true",

View file

@ -113,7 +113,10 @@ from lib.core.settings import MAX_CONNECTION_READ_SIZE
from lib.core.settings import MAX_CONNECTIONS_REGEX
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
from lib.core.settings import MAX_CONSECUTIVE_CONNECTION_ERRORS
from lib.core.settings import MAX_MURPHY_SLEEP_TIME
from lib.core.settings import MAX_JITTER_SPIKE_TIME
from lib.core.settings import JITTER_SIGMAS
from lib.core.settings import JITTER_SPIKE_CHANCE
from lib.core.settings import JITTER_JUNK_RESPONSES
from lib.core.settings import META_REFRESH_REGEX
from lib.core.settings import MAX_TIME_RESPONSES
from lib.core.settings import MIN_TIME_RESPONSES
@ -374,17 +377,31 @@ class Connect(object):
setHTTPHandlers()
if conf.dummy or conf.murphyRate and randomInt() % conf.murphyRate == 0:
if conf.murphyRate:
time.sleep(randomInt() % (MAX_MURPHY_SLEEP_TIME + 1))
page, headers, code = randomStr(int(randomInt()), alphabet=[_unichr(_) for _ in xrange(256)]), None, None if not conf.murphyRate else randomInt(3)
if conf.dummy:
page, headers, code = randomStr(int(randomInt()), alphabet=[_unichr(_) for _ in xrange(256)]), None, None
threadData.lastPage = page
threadData.lastCode = code
return page, headers, code
# Simulated jitter (--jitter=N, testing): ~1 in N requests is perturbed to stress the time-/
# boolean-based blind jitter defenses. Half the fired events add realistic response LATENCY
# (Gaussian jitter across low->high noise, or an occasional heavy-tailed spike) and let the
# genuine request proceed; the other half short-circuit with a transient "junk" response
# (gateway 5xx, rate-limit, a same-HTTP-code interstitial/maintenance page, or an empty body).
if conf.jitter and randomInt() % conf.jitter == 0:
if randomInt() % 2 == 0:
if random.random() < JITTER_SPIKE_CHANCE:
time.sleep(random.uniform(MAX_JITTER_SPIKE_TIME / 2.0, MAX_JITTER_SPIKE_TIME)) # heavy-tailed spike
else:
time.sleep(abs(random.gauss(0, random.choice(JITTER_SIGMAS)))) # continuous jitter
# NOTE: falls through to the genuine request, which now carries the injected latency
else:
page, code = random.choice(JITTER_JUNK_RESPONSES)
headers = None
threadData.lastPage = page
threadData.lastCode = code
return page, headers, code
if conf.liveCookies:
with kb.locks.liveCookies:
if not checkFile(conf.liveCookies, raiseOnError=False) or os.path.getsize(conf.liveCookies) == 0: