Update for an Issue #2616

This commit is contained in:
Miroslav Stampar 2017-07-20 02:41:47 +02:00
parent 7d147f613f
commit 36f3fd72e6
8 changed files with 75 additions and 75 deletions

View File

@ -36,7 +36,6 @@ from lib.core.enums import POST_HINT
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.settings import BOUNDARY_BACKSLASH_MARKER from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
from lib.core.settings import BOUNDED_INJECTION_MARKER from lib.core.settings import BOUNDED_INJECTION_MARKER
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_COOKIE_DELIMITER
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import GENERIC_SQL_COMMENT from lib.core.settings import GENERIC_SQL_COMMENT
@ -101,7 +100,7 @@ class Agent(object):
if place == PLACE.URI or BOUNDED_INJECTION_MARKER in origValue: if place == PLACE.URI or BOUNDED_INJECTION_MARKER in origValue:
paramString = origValue paramString = origValue
if place == PLACE.URI: if place == PLACE.URI:
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0] origValue = origValue.split(kb.customInjectionMark)[0]
else: else:
origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0) origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0)
origValue = origValue[origValue.rfind('/') + 1:] origValue = origValue[origValue.rfind('/') + 1:]
@ -110,7 +109,7 @@ class Agent(object):
origValue = origValue[origValue.rfind(char) + 1:] origValue = origValue[origValue.rfind(char) + 1:]
elif place == PLACE.CUSTOM_POST: elif place == PLACE.CUSTOM_POST:
paramString = origValue paramString = origValue
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0] origValue = origValue.split(kb.customInjectionMark)[0]
if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML): if kb.postHint in (POST_HINT.SOAP, POST_HINT.XML):
origValue = origValue.split('>')[-1] origValue = origValue.split('>')[-1]
elif kb.postHint in (POST_HINT.JSON, POST_HINT.JSON_LIKE): elif kb.postHint in (POST_HINT.JSON, POST_HINT.JSON_LIKE):
@ -120,7 +119,7 @@ class Agent(object):
origValue = _.split('=', 1)[1] if '=' in _ else "" origValue = _.split('=', 1)[1] if '=' in _ else ""
elif place == PLACE.CUSTOM_HEADER: elif place == PLACE.CUSTOM_HEADER:
paramString = origValue paramString = origValue
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0] origValue = origValue.split(kb.customInjectionMark)[0]
origValue = origValue[origValue.find(',') + 1:] origValue = origValue[origValue.find(',') + 1:]
match = re.search(r"([^;]+)=(?P<value>[^;]+);?\Z", origValue) match = re.search(r"([^;]+)=(?P<value>[^;]+);?\Z", origValue)
if match: if match:
@ -159,14 +158,14 @@ class Agent(object):
newValue = self.cleanupPayload(newValue, origValue) newValue = self.cleanupPayload(newValue, origValue)
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER): if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
_ = "%s%s" % (origValue, CUSTOM_INJECTION_MARK_CHAR) _ = "%s%s" % (origValue, kb.customInjectionMark)
if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and not '"%s"' % _ in paramString: if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and not '"%s"' % _ in paramString:
newValue = '"%s"' % newValue newValue = '"%s"' % newValue
elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and not "'%s'" % _ in paramString: elif kb.postHint == POST_HINT.JSON_LIKE and not isNumber(newValue) and not "'%s'" % _ in paramString:
newValue = "'%s'" % newValue newValue = "'%s'" % newValue
newValue = newValue.replace(CUSTOM_INJECTION_MARK_CHAR, REPLACEMENT_MARKER) newValue = newValue.replace(kb.customInjectionMark, REPLACEMENT_MARKER)
retVal = paramString.replace(_, self.addPayloadDelimiters(newValue)) retVal = paramString.replace(_, self.addPayloadDelimiters(newValue))
retVal = retVal.replace(CUSTOM_INJECTION_MARK_CHAR, "").replace(REPLACEMENT_MARKER, CUSTOM_INJECTION_MARK_CHAR) retVal = retVal.replace(kb.customInjectionMark, "").replace(REPLACEMENT_MARKER, kb.customInjectionMark)
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]: elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
_ = "%s%s" % (origValue, BOUNDED_INJECTION_MARKER) _ = "%s%s" % (origValue, BOUNDED_INJECTION_MARKER)
retVal = "%s=%s" % (re.sub(r" (\#\d\*|\(.+\))\Z", "", parameter), paramString.replace(_, self.addPayloadDelimiters(newValue))) retVal = "%s=%s" % (re.sub(r" (\#\d\*|\(.+\))\Z", "", parameter), paramString.replace(_, self.addPayloadDelimiters(newValue)))

View File

@ -97,8 +97,8 @@ from lib.core.settings import BOUNDED_INJECTION_MARKER
from lib.core.settings import BRUTE_DOC_ROOT_PREFIXES from lib.core.settings import BRUTE_DOC_ROOT_PREFIXES
from lib.core.settings import BRUTE_DOC_ROOT_SUFFIXES from lib.core.settings import BRUTE_DOC_ROOT_SUFFIXES
from lib.core.settings import BRUTE_DOC_ROOT_TARGET_MARK from lib.core.settings import BRUTE_DOC_ROOT_TARGET_MARK
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DBMS_DIRECTORY_DICT from lib.core.settings import DBMS_DIRECTORY_DICT
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_COOKIE_DELIMITER
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_MSSQL_SCHEMA from lib.core.settings import DEFAULT_MSSQL_SCHEMA
@ -654,7 +654,7 @@ def paramToDict(place, parameters=None):
except Exception: except Exception:
pass pass
_ = re.sub(regex, "\g<1>%s\g<%d>" % (CUSTOM_INJECTION_MARK_CHAR, len(match.groups())), testableParameters[parameter]) _ = re.sub(regex, "\g<1>%s\g<%d>" % (kb.customInjectionMark, len(match.groups())), testableParameters[parameter])
message = "it appears that provided value for %s parameter '%s' " % (place, parameter) message = "it appears that provided value for %s parameter '%s' " % (place, parameter)
message += "has boundaries. Do you want to inject inside? ('%s') [y/N] " % getUnicode(_) message += "has boundaries. Do you want to inject inside? ('%s') [y/N] " % getUnicode(_)
@ -1394,7 +1394,7 @@ def parseTargetUrl():
else: else:
conf.url = "http://" + conf.url conf.url = "http://" + conf.url
if CUSTOM_INJECTION_MARK_CHAR in conf.url: if kb.customInjectionMark in conf.url:
conf.url = conf.url.replace('?', URI_QUESTION_MARKER) conf.url = conf.url.replace('?', URI_QUESTION_MARKER)
try: try:
@ -1412,7 +1412,7 @@ def parseTargetUrl():
conf.hostname = hostnamePort[0].strip() conf.hostname = hostnamePort[0].strip()
conf.ipv6 = conf.hostname != conf.hostname.strip("[]") conf.ipv6 = conf.hostname != conf.hostname.strip("[]")
conf.hostname = conf.hostname.strip("[]").replace(CUSTOM_INJECTION_MARK_CHAR, "") conf.hostname = conf.hostname.strip("[]").replace(kb.customInjectionMark, "")
try: try:
_ = conf.hostname.encode("idna") _ = conf.hostname.encode("idna")
@ -1453,7 +1453,7 @@ def parseTargetUrl():
debugMsg = "setting the HTTP Referer header to the target URL" debugMsg = "setting the HTTP Referer header to the target URL"
logger.debug(debugMsg) logger.debug(debugMsg)
conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.REFERER] conf.httpHeaders = [_ for _ in conf.httpHeaders if _[0] != HTTP_HEADER.REFERER]
conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, ""))) conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.url.replace(kb.customInjectionMark, "")))
if not conf.host and (intersect(HOST_ALIASES, conf.testParameter, True) or conf.level >= 5): if not conf.host and (intersect(HOST_ALIASES, conf.testParameter, True) or conf.level >= 5):
debugMsg = "setting the HTTP Host header to the target URL" debugMsg = "setting the HTTP Host header to the target URL"

View File

@ -110,7 +110,7 @@ from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
from lib.core.settings import DUMMY_URL from lib.core.settings import DUMMY_URL
from lib.core.settings import INJECT_HERE_MARK from lib.core.settings import INJECT_HERE_REGEX
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET
@ -280,7 +280,7 @@ def _feedTargetsDict(reqFile, addedTargetUrls):
method = match.group(1) method = match.group(1)
url = match.group(2) url = match.group(2)
if any(_ in line for _ in ('?', '=', CUSTOM_INJECTION_MARK_CHAR)): if any(_ in line for _ in ('?', '=', kb.customInjectionMark)):
params = True params = True
getPostReq = True getPostReq = True
@ -320,7 +320,7 @@ def _feedTargetsDict(reqFile, addedTargetUrls):
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION): elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION):
headers.append((getUnicode(key), getUnicode(value))) headers.append((getUnicode(key), getUnicode(value)))
if CUSTOM_INJECTION_MARK_CHAR in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""): if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""):
params = True params = True
data = data.rstrip("\r\n") if data else data data = data.rstrip("\r\n") if data else data
@ -593,7 +593,7 @@ def _setBulkMultipleTargets():
found = False found = False
for line in getFileItems(conf.bulkFile): for line in getFileItems(conf.bulkFile):
if re.match(r"[^ ]+\?(.+)", line, re.I) or CUSTOM_INJECTION_MARK_CHAR in line: if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line:
found = True found = True
kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None)) kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None))
@ -1685,11 +1685,13 @@ def _cleanupOptions():
if conf.optimize: if conf.optimize:
setOptimize() setOptimize()
if conf.data: match = re.search(INJECT_HERE_REGEX, conf.data or "")
conf.data = re.sub("(?i)%s" % INJECT_HERE_MARK.replace(" ", r"[^A-Za-z]*"), CUSTOM_INJECTION_MARK_CHAR, conf.data) if match:
kb.customInjectionMark = match.group(0)
if conf.url: match = re.search(INJECT_HERE_REGEX, conf.url or "")
conf.url = re.sub("(?i)%s" % INJECT_HERE_MARK.replace(" ", r"[^A-Za-z]*"), CUSTOM_INJECTION_MARK_CHAR, conf.url) if match:
kb.customInjectionMark = match.group(0)
if conf.os: if conf.os:
conf.os = conf.os.capitalize() conf.os = conf.os.capitalize()
@ -1894,6 +1896,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.connErrorCounter = 0 kb.connErrorCounter = 0
kb.cookieEncodeChoice = None kb.cookieEncodeChoice = None
kb.counters = {} kb.counters = {}
kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR
kb.data = AttribDict() kb.data = AttribDict()
kb.dataOutputFlag = False kb.dataOutputFlag = False

View File

@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.1.7.16" VERSION = "1.1.7.17"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} 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) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@ -366,7 +366,7 @@ CANDIDATE_SENTENCE_MIN_LENGTH = 10
CUSTOM_INJECTION_MARK_CHAR = '*' CUSTOM_INJECTION_MARK_CHAR = '*'
# Other way to declare injection position # Other way to declare injection position
INJECT_HERE_MARK = '%INJECT HERE%' INJECT_HERE_REGEX = '(?i)%INJECT[_ ]?HERE%'
# Minimum chunk length used for retrieving data over error based payloads # Minimum chunk length used for retrieving data over error based payloads
MIN_ERROR_CHUNK_LENGTH = 8 MIN_ERROR_CHUNK_LENGTH = 8
@ -478,7 +478,7 @@ DUMMY_USER_INJECTION = r"(?i)[^\w](AND|OR)\s+[^\s]+[=><]|\bUNION\b.+\bSELECT\b|\
# Extensions skipped by crawler # Extensions skipped by crawler
CRAWL_EXCLUDE_EXTENSIONS = ("3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff", "apk", "ar", "asf", "au", "avi", "bak", "bin", "bk", "bmp", "btif", "bz2", "cab", "caf", "cgm", "cmx", "cpio", "cr2", "dat", "deb", "djvu", "dll", "dmg", "dmp", "dng", "doc", "docx", "dot", "dotx", "dra", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ear", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "fli", "flv", "fpx", "fst", "fvt", "g3", "gif", "gz", "h261", "h263", "h264", "ico", "ief", "image", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "ktx", "lvp", "lz", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mid", "mj2", "mka", "mkv", "mmr", "mng", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "mxu", "nef", "npx", "o", "oga", "ogg", "ogv", "otf", "pbm", "pcx", "pdf", "pea", "pgm", "pic", "png", "pnm", "ppm", "pps", "ppt", "pptx", "ps", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "rgb", "rip", "rlc", "rz", "s3m", "s7z", "scm", "scpt", "sgi", "shar", "sil", "smv", "so", "sub", "swf", "tar", "tbz2", "tga", "tgz", "tif", "tiff", "tlz", "ts", "ttf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wm", "wma", "wmv", "wmx", "woff", "woff2", "wvx", "xbm", "xif", "xls", "xlsx", "xlt", "xm", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx") CRAWL_EXCLUDE_EXTENSIONS = ("3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff", "apk", "ar", "asf", "au", "avi", "bak", "bin", "bk", "bmp", "btif", "bz2", "cab", "caf", "cgm", "cmx", "cpio", "cr2", "dat", "deb", "djvu", "dll", "dmg", "dmp", "dng", "doc", "docx", "dot", "dotx", "dra", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ear", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "fli", "flv", "fpx", "fst", "fvt", "g3", "gif", "gz", "h261", "h263", "h264", "ico", "ief", "image", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "ktx", "lvp", "lz", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mid", "mj2", "mka", "mkv", "mmr", "mng", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "mxu", "nef", "npx", "o", "oga", "ogg", "ogv", "otf", "pbm", "pcx", "pdf", "pea", "pgm", "pic", "png", "pnm", "ppm", "pps", "ppt", "pptx", "ps", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "rgb", "rip", "rlc", "rz", "s3m", "s7z", "scm", "scpt", "sgi", "shar", "sil", "smv", "so", "sub", "swf", "tar", "tbz2", "tga", "tgz", "tif", "tiff", "tlz", "ts", "ttf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wm", "wma", "wmv", "wmx", "woff", "woff2", "wvx", "xbm", "xif", "xls", "xlsx", "xlt", "xm", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx")
# Patterns often seen in HTTP headers containing custom injection marking character # Patterns often seen in HTTP headers containing custom injection marking character '*'
PROBLEMATIC_CUSTOM_INJECTION_PATTERNS = r"(;q=[^;']+)|(\*/\*)" PROBLEMATIC_CUSTOM_INJECTION_PATTERNS = r"(;q=[^;']+)|(\*/\*)"
# Template used for common table existence check # Template used for common table existence check

View File

@ -52,7 +52,6 @@ from lib.core.option import _setKnowledgeBaseAttributes
from lib.core.option import _setAuthCred from lib.core.option import _setAuthCred
from lib.core.settings import ASTERISK_MARKER from lib.core.settings import ASTERISK_MARKER
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import HOST_ALIASES from lib.core.settings import HOST_ALIASES
from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX
@ -114,12 +113,12 @@ def _setRequestParams():
retVal = retVal.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1))) retVal = retVal.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1)))
else: else:
break break
if CUSTOM_INJECTION_MARK_CHAR in retVal: if kb.customInjectionMark in retVal:
hintNames.append((retVal.split(CUSTOM_INJECTION_MARK_CHAR)[0], match.group("name"))) hintNames.append((retVal.split(kb.customInjectionMark)[0], match.group("name")))
return retVal return retVal
if kb.processUserMarks is None and CUSTOM_INJECTION_MARK_CHAR in conf.data: if kb.processUserMarks is None and kb.customInjectionMark in conf.data:
message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message = "custom injection marker ('%s') found in option " % kb.customInjectionMark
message += "'--data'. Do you want to process it? [Y/n/q] " message += "'--data'. Do you want to process it? [Y/n/q] "
choice = readInput(message, default='Y') choice = readInput(message, default='Y')
@ -139,16 +138,16 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % kb.customInjectionMark), conf.data)
match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data) match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data)
if match and not (conf.testParameter and match.group("name") not in conf.testParameter): if match and not (conf.testParameter and match.group("name") not in conf.testParameter):
_ = match.group(2) _ = match.group(2)
_ = re.sub(r'("[^"]+)"', '\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR, _) _ = re.sub(r'("[^"]+)"', '\g<1>%s"' % kb.customInjectionMark, _)
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', '\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR, _) _ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', '\g<0>%s' % kb.customInjectionMark, _)
conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _)) conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _))
kb.postHint = POST_HINT.JSON kb.postHint = POST_HINT.JSON
@ -161,11 +160,11 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % kb.customInjectionMark), conf.data)
conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % kb.customInjectionMark), conf.data)
kb.postHint = POST_HINT.JSON_LIKE kb.postHint = POST_HINT.JSON_LIKE
@ -177,9 +176,9 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % CUSTOM_INJECTION_MARK_CHAR, conf.data) conf.data = re.sub(r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % kb.customInjectionMark, conf.data)
kb.postHint = POST_HINT.ARRAY_LIKE kb.postHint = POST_HINT.ARRAY_LIKE
@ -191,10 +190,10 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % kb.customInjectionMark), conf.data)
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
@ -206,15 +205,15 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"'](?P<name>[^\n]+?)[\"']).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"'](?P<name>[^\n]+?)[\"']).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % kb.customInjectionMark), conf.data)
kb.postHint = POST_HINT.MULTIPART kb.postHint = POST_HINT.MULTIPART
if not kb.postHint: if not kb.postHint:
if CUSTOM_INJECTION_MARK_CHAR in conf.data: # later processed if kb.customInjectionMark in conf.data: # later processed
pass pass
else: else:
place = PLACE.POST place = PLACE.POST
@ -226,12 +225,12 @@ def _setRequestParams():
conf.paramDict[place] = paramDict conf.paramDict[place] = paramDict
testableParameters = True testableParameters = True
else: else:
if CUSTOM_INJECTION_MARK_CHAR not in conf.data: # in case that no usable parameter values has been found if kb.customInjectionMark not in conf.data: # in case that no usable parameter values has been found
conf.parameters[PLACE.POST] = conf.data conf.parameters[PLACE.POST] = conf.data
kb.processUserMarks = True if (kb.postHint and CUSTOM_INJECTION_MARK_CHAR in conf.data) else kb.processUserMarks kb.processUserMarks = True if (kb.postHint and kb.customInjectionMark in conf.data) else kb.processUserMarks
if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint and not CUSTOM_INJECTION_MARK_CHAR in (conf.data or "") and conf.url.startswith("http"): if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint and not kb.customInjectionMark in (conf.data or "") and conf.url.startswith("http"):
warnMsg = "you've provided target URL without any GET " warnMsg = "you've provided target URL without any GET "
warnMsg += "parameters (e.g. 'http://www.site.com/article.php?id=1') " warnMsg += "parameters (e.g. 'http://www.site.com/article.php?id=1') "
warnMsg += "and without providing any POST parameters " warnMsg += "and without providing any POST parameters "
@ -245,15 +244,15 @@ def _setRequestParams():
if choice == 'Q': if choice == 'Q':
raise SqlmapUserQuitException raise SqlmapUserQuitException
elif choice == 'Y': elif choice == 'Y':
conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR) conf.url = "%s%s" % (conf.url, kb.customInjectionMark)
kb.processUserMarks = True kb.processUserMarks = True
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))): for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))):
_ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or "" _ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or ""
if CUSTOM_INJECTION_MARK_CHAR in _: if kb.customInjectionMark in _:
if kb.processUserMarks is None: if kb.processUserMarks is None:
lut = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie'} lut = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie'}
message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message = "custom injection marker ('%s') found in option " % kb.customInjectionMark
message += "'%s'. Do you want to process it? [Y/n/q] " % lut[place] message += "'%s'. Do you want to process it? [Y/n/q] " % lut[place]
choice = readInput(message, default='Y').upper() choice = readInput(message, default='Y').upper()
@ -265,7 +264,7 @@ def _setRequestParams():
if kb.processUserMarks: if kb.processUserMarks:
kb.testOnlyCustom = True kb.testOnlyCustom = True
if "=%s" % CUSTOM_INJECTION_MARK_CHAR in _: if "=%s" % kb.customInjectionMark in _:
warnMsg = "it seems that you've provided empty parameter value(s) " warnMsg = "it seems that you've provided empty parameter value(s) "
warnMsg += "for testing. Please, always use only valid parameter values " warnMsg += "for testing. Please, always use only valid parameter values "
warnMsg += "so sqlmap could be able to run properly" warnMsg += "so sqlmap could be able to run properly"
@ -297,13 +296,13 @@ def _setRequestParams():
if place == PLACE.CUSTOM_HEADER: if place == PLACE.CUSTOM_HEADER:
for index in xrange(len(conf.httpHeaders)): for index in xrange(len(conf.httpHeaders)):
header, value = conf.httpHeaders[index] header, value = conf.httpHeaders[index]
if CUSTOM_INJECTION_MARK_CHAR in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value): if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value):
parts = value.split(CUSTOM_INJECTION_MARK_CHAR) parts = value.split(kb.customInjectionMark)
for i in xrange(len(parts) - 1): for i in xrange(len(parts) - 1):
conf.paramDict[place]["%s #%d%s" % (header, i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "%s,%s" % (header, "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))) conf.paramDict[place]["%s #%d%s" % (header, i + 1, kb.customInjectionMark)] = "%s,%s" % (header, "".join("%s%s" % (parts[j], kb.customInjectionMark if i == j else "") for j in xrange(len(parts))))
conf.httpHeaders[index] = (header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) conf.httpHeaders[index] = (header, value.replace(kb.customInjectionMark, ""))
else: else:
parts = value.split(CUSTOM_INJECTION_MARK_CHAR) parts = value.split(kb.customInjectionMark)
for i in xrange(len(parts) - 1): for i in xrange(len(parts) - 1):
name = None name = None
@ -313,8 +312,8 @@ def _setRequestParams():
name = "%s %s" % (kb.postHint, _) name = "%s %s" % (kb.postHint, _)
break break
if name is None: if name is None:
name = "%s#%s%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR) name = "%s#%s%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, kb.customInjectionMark)
conf.paramDict[place][name] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) conf.paramDict[place][name] = "".join("%s%s" % (parts[j], kb.customInjectionMark if i == j else "") for j in xrange(len(parts)))
if place == PLACE.URI and PLACE.GET in conf.paramDict: if place == PLACE.URI and PLACE.GET in conf.paramDict:
del conf.paramDict[PLACE.GET] del conf.paramDict[PLACE.GET]
@ -326,7 +325,7 @@ def _setRequestParams():
if kb.processUserMarks: if kb.processUserMarks:
for item in ("url", "data", "agent", "referer", "cookie"): for item in ("url", "data", "agent", "referer", "cookie"):
if conf.get(item): if conf.get(item):
conf[item] = conf[item].replace(CUSTOM_INJECTION_MARK_CHAR, "") conf[item] = conf[item].replace(kb.customInjectionMark, "")
# Perform checks on Cookie parameters # Perform checks on Cookie parameters
if conf.cookie: if conf.cookie:
@ -375,8 +374,8 @@ def _setRequestParams():
if condition: if condition:
conf.parameters[PLACE.CUSTOM_HEADER] = str(conf.httpHeaders) conf.parameters[PLACE.CUSTOM_HEADER] = str(conf.httpHeaders)
conf.paramDict[PLACE.CUSTOM_HEADER] = {httpHeader: "%s,%s%s" % (httpHeader, headerValue, CUSTOM_INJECTION_MARK_CHAR)} conf.paramDict[PLACE.CUSTOM_HEADER] = {httpHeader: "%s,%s%s" % (httpHeader, headerValue, kb.customInjectionMark)}
conf.httpHeaders = [(header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) for header, value in conf.httpHeaders] conf.httpHeaders = [(header, value.replace(kb.customInjectionMark, "")) for header, value in conf.httpHeaders]
testableParameters = True testableParameters = True
if not conf.parameters: if not conf.parameters:

View File

@ -321,7 +321,7 @@ def cmdLineParser(argv=None):
detection.add_option("--risk", dest="risk", type="int", detection.add_option("--risk", dest="risk", type="int",
help="Risk of tests to perform (1-3, " help="Risk of tests to perform (1-3, "
"default %d)" % defaults.level) "default %d)" % defaults.risk)
detection.add_option("--string", dest="string", detection.add_option("--string", dest="string",
help="String to match when " help="String to match when "

View File

@ -81,7 +81,6 @@ from lib.core.exception import SqlmapTokenException
from lib.core.exception import SqlmapValueException from lib.core.exception import SqlmapValueException
from lib.core.settings import ASTERISK_MARKER from lib.core.settings import ASTERISK_MARKER
from lib.core.settings import BOUNDARY_BACKSLASH_MARKER from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DEFAULT_CONTENT_TYPE from lib.core.settings import DEFAULT_CONTENT_TYPE
from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_COOKIE_DELIMITER
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
@ -901,7 +900,7 @@ class Connect(object):
post = value post = value
if PLACE.CUSTOM_POST in conf.parameters: if PLACE.CUSTOM_POST in conf.parameters:
post = conf.parameters[PLACE.CUSTOM_POST].replace(CUSTOM_INJECTION_MARK_CHAR, "") if place != PLACE.CUSTOM_POST or not value else value post = conf.parameters[PLACE.CUSTOM_POST].replace(kb.customInjectionMark, "") if place != PLACE.CUSTOM_POST or not value else value
post = post.replace(ASTERISK_MARKER, '*') if post else post post = post.replace(ASTERISK_MARKER, '*') if post else post
if PLACE.COOKIE in conf.parameters: if PLACE.COOKIE in conf.parameters:

View File

@ -25,9 +25,9 @@ f77daa397016460433d5e06704efd538 lib/controller/checks.py
130d1c16708668b8d89605b6b5b38bf5 lib/controller/controller.py 130d1c16708668b8d89605b6b5b38bf5 lib/controller/controller.py
a97df93b552ee4e4ba3692eae870de7c lib/controller/handler.py a97df93b552ee4e4ba3692eae870de7c lib/controller/handler.py
310efc965c862cfbd7b0da5150a5ad36 lib/controller/__init__.py 310efc965c862cfbd7b0da5150a5ad36 lib/controller/__init__.py
bc51363cbbe4b4d6bafef04508046c31 lib/core/agent.py 49b4e3b75322bf5f95b1568633bc7914 lib/core/agent.py
6cc95a117fbd34ef31b9aa25520f0e31 lib/core/bigarray.py 6cc95a117fbd34ef31b9aa25520f0e31 lib/core/bigarray.py
852ed8b5f19401b7fe21b8032104e3dd lib/core/common.py ac0335f8022f658a1c8d6cabb6b7fc9e lib/core/common.py
5065a4242a8cccf72f91e22e1007ae63 lib/core/convert.py 5065a4242a8cccf72f91e22e1007ae63 lib/core/convert.py
a8143dab9d3a27490f7d49b6b29ea530 lib/core/data.py a8143dab9d3a27490f7d49b6b29ea530 lib/core/data.py
7936d78b1a7f1f008ff92bf2f88574ba lib/core/datatype.py 7936d78b1a7f1f008ff92bf2f88574ba lib/core/datatype.py
@ -40,16 +40,16 @@ b9ff4e622c416116bee6024c0f050349 lib/core/enums.py
310efc965c862cfbd7b0da5150a5ad36 lib/core/__init__.py 310efc965c862cfbd7b0da5150a5ad36 lib/core/__init__.py
9ba39bf66e9ecd469446bdbbeda906c3 lib/core/log.py 9ba39bf66e9ecd469446bdbbeda906c3 lib/core/log.py
5a34a1be62eab520cacc197b5eacda39 lib/core/optiondict.py 5a34a1be62eab520cacc197b5eacda39 lib/core/optiondict.py
837f3859f007b9104b32f18e217e326a lib/core/option.py f664e993a4e4d0f8b3153778bec49794 lib/core/option.py
5f2f56e6c5f274408df61943f1e080c0 lib/core/profiling.py 5f2f56e6c5f274408df61943f1e080c0 lib/core/profiling.py
40be71cd774662a7b420caeb7051e7d5 lib/core/readlineng.py 40be71cd774662a7b420caeb7051e7d5 lib/core/readlineng.py
d8e9250f3775119df07e9070eddccd16 lib/core/replication.py d8e9250f3775119df07e9070eddccd16 lib/core/replication.py
785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py 785f86e3f963fa3798f84286a4e83ff2 lib/core/revision.py
40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py 40c80b28b3a5819b737a5a17d4565ae9 lib/core/session.py
d8dae956ce5141a2189ceae2c9356490 lib/core/settings.py a92c171fa66aa766557d37535cad10e5 lib/core/settings.py
d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py d91291997d2bd2f6028aaf371bf1d3b6 lib/core/shell.py
2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py 2ad85c130cc5f2b3701ea85c2f6bbf20 lib/core/subprocessng.py
4416fdcab26b286a5a3a88e75aa60044 lib/core/target.py 080dad10c8350a66fd5321935b53fa70 lib/core/target.py
8970b88627902239d695280b1160e16c lib/core/testing.py 8970b88627902239d695280b1160e16c lib/core/testing.py
b8306192d980abdc8d669c024511e9a1 lib/core/threads.py b8306192d980abdc8d669c024511e9a1 lib/core/threads.py
ad74fc58fc7214802fd27067bce18dd2 lib/core/unescaper.py ad74fc58fc7214802fd27067bce18dd2 lib/core/unescaper.py
@ -57,7 +57,7 @@ ad74fc58fc7214802fd27067bce18dd2 lib/core/unescaper.py
4d13ed693401a498b6d073a2a494bd83 lib/core/wordlist.py 4d13ed693401a498b6d073a2a494bd83 lib/core/wordlist.py
310efc965c862cfbd7b0da5150a5ad36 lib/__init__.py 310efc965c862cfbd7b0da5150a5ad36 lib/__init__.py
8c4b04062db2245d9e190b413985202a lib/parse/banner.py 8c4b04062db2245d9e190b413985202a lib/parse/banner.py
d548e2bff2edae0b0e40364a439bb6d4 lib/parse/cmdline.py 457a8bd6e651f3db523e4c2c1207b447 lib/parse/cmdline.py
3a31657bc38f277d0016ff6d50bde61f lib/parse/configfile.py 3a31657bc38f277d0016ff6d50bde61f lib/parse/configfile.py
14539f1be714d4f1ed042067d63bc50a lib/parse/handler.py 14539f1be714d4f1ed042067d63bc50a lib/parse/handler.py
64e5bb3ecbdd75144500588b437ba8da lib/parse/headers.py 64e5bb3ecbdd75144500588b437ba8da lib/parse/headers.py
@ -68,7 +68,7 @@ d548e2bff2edae0b0e40364a439bb6d4 lib/parse/cmdline.py
403d873f1d2fd0c7f73d83f104e41850 lib/request/basicauthhandler.py 403d873f1d2fd0c7f73d83f104e41850 lib/request/basicauthhandler.py
3ba1c71e68953d34fc526a9d79d5a457 lib/request/basic.py 3ba1c71e68953d34fc526a9d79d5a457 lib/request/basic.py
ef48de622b0a6b4a71df64b0d2785ef8 lib/request/comparison.py ef48de622b0a6b4a71df64b0d2785ef8 lib/request/comparison.py
bfd08465f7bc259cc9af008da0ffb4c3 lib/request/connect.py b5094652c5e0a8b2bc29f95a484ceb27 lib/request/connect.py
fb6b788d0016ab4ec5e5f661f0f702ad lib/request/direct.py fb6b788d0016ab4ec5e5f661f0f702ad lib/request/direct.py
cc1163d38e9b7ee5db2adac6784c02bb lib/request/dns.py cc1163d38e9b7ee5db2adac6784c02bb lib/request/dns.py
5dcdb37823a0b5eff65cd1018bcf09e4 lib/request/httpshandler.py 5dcdb37823a0b5eff65cd1018bcf09e4 lib/request/httpshandler.py