2019-05-08 13:47:52 +03:00
|
|
|
#!/usr/bin/env python
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
"""
|
2024-01-04 01:11:52 +03:00
|
|
|
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
|
2017-10-11 15:50:46 +03:00
|
|
|
See the file 'LICENSE' for copying permission
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
|
|
|
|
2013-02-14 18:32:16 +04:00
|
|
|
import functools
|
2008-10-15 19:38:22 +04:00
|
|
|
import os
|
2010-06-30 01:07:23 +04:00
|
|
|
import re
|
2017-06-29 15:57:35 +03:00
|
|
|
import subprocess
|
|
|
|
import sys
|
2010-12-09 00:16:18 +03:00
|
|
|
import tempfile
|
2008-10-15 19:38:22 +04:00
|
|
|
import time
|
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
from lib.core.common import Backend
|
2016-01-12 12:27:04 +03:00
|
|
|
from lib.core.common import getSafeExString
|
2012-02-25 14:43:10 +04:00
|
|
|
from lib.core.common import hashDBRetrieve
|
2011-02-14 00:58:48 +03:00
|
|
|
from lib.core.common import intersect
|
2017-07-05 14:51:48 +03:00
|
|
|
from lib.core.common import isNumPosStrValue
|
2014-11-03 01:38:52 +03:00
|
|
|
from lib.core.common import normalizeUnicode
|
2014-12-12 06:40:44 +03:00
|
|
|
from lib.core.common import openFile
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.common import paramToDict
|
2016-05-31 15:05:35 +03:00
|
|
|
from lib.core.common import randomStr
|
2010-10-10 22:56:43 +04:00
|
|
|
from lib.core.common import readInput
|
2019-05-14 14:58:42 +03:00
|
|
|
from lib.core.common import removePostHintPrefix
|
2012-03-08 14:19:34 +04:00
|
|
|
from lib.core.common import resetCookieJar
|
2022-01-17 15:24:02 +03:00
|
|
|
from lib.core.common import safeStringFormat
|
2022-02-11 00:30:17 +03:00
|
|
|
from lib.core.common import unArrayizeValue
|
2012-07-31 13:03:44 +04:00
|
|
|
from lib.core.common import urldecode
|
2019-03-28 18:04:38 +03:00
|
|
|
from lib.core.compat import xrange
|
2022-02-11 00:30:17 +03:00
|
|
|
from lib.core.convert import decodeBase64
|
2019-05-06 01:54:21 +03:00
|
|
|
from lib.core.convert import getUnicode
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.data import conf
|
|
|
|
from lib.core.data import kb
|
2009-09-26 03:03:45 +04:00
|
|
|
from lib.core.data import logger
|
2013-04-10 21:33:31 +04:00
|
|
|
from lib.core.data import mergedOptions
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.data import paths
|
2014-05-29 11:33:14 +04:00
|
|
|
from lib.core.datatype import InjectionDict
|
2012-10-23 16:37:45 +04:00
|
|
|
from lib.core.dicts import DBMS_DICT
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.dump import dumper
|
2011-12-28 17:50:03 +04:00
|
|
|
from lib.core.enums import HASHDB_KEYS
|
2013-03-20 14:10:24 +04:00
|
|
|
from lib.core.enums import HTTP_HEADER
|
2010-11-08 12:44:32 +03:00
|
|
|
from lib.core.enums import HTTPMETHOD
|
2016-05-31 14:02:26 +03:00
|
|
|
from lib.core.enums import MKSTEMP_PREFIX
|
2010-11-08 12:44:32 +03:00
|
|
|
from lib.core.enums import PLACE
|
2012-10-04 13:25:44 +04:00
|
|
|
from lib.core.enums import POST_HINT
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapFilePathException
|
|
|
|
from lib.core.exception import SqlmapGenericException
|
|
|
|
from lib.core.exception import SqlmapMissingPrivileges
|
2018-10-15 01:53:26 +03:00
|
|
|
from lib.core.exception import SqlmapNoneDataException
|
2014-12-24 00:04:23 +03:00
|
|
|
from lib.core.exception import SqlmapSystemException
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapUserQuitException
|
2019-06-04 15:44:06 +03:00
|
|
|
from lib.core.option import _setAuthCred
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.option import _setDBMS
|
|
|
|
from lib.core.option import _setKnowledgeBaseAttributes
|
2019-06-04 15:44:06 +03:00
|
|
|
from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX
|
2013-02-13 15:24:42 +04:00
|
|
|
from lib.core.settings import ASTERISK_MARKER
|
2014-10-23 16:03:44 +04:00
|
|
|
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
|
2018-10-27 00:38:37 +03:00
|
|
|
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
2014-10-09 17:21:26 +04:00
|
|
|
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
2011-12-20 16:52:41 +04:00
|
|
|
from lib.core.settings import HOST_ALIASES
|
2018-10-27 00:38:37 +03:00
|
|
|
from lib.core.settings import INJECT_HERE_REGEX
|
2014-02-26 11:56:17 +04:00
|
|
|
from lib.core.settings import JSON_LIKE_RECOGNITION_REGEX
|
2019-06-04 15:44:06 +03:00
|
|
|
from lib.core.settings import JSON_RECOGNITION_REGEX
|
2012-10-16 14:32:58 +04:00
|
|
|
from lib.core.settings import MULTIPART_RECOGNITION_REGEX
|
2013-02-14 19:18:16 +04:00
|
|
|
from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
|
2011-02-14 00:58:48 +03:00
|
|
|
from lib.core.settings import REFERER_ALIASES
|
2013-04-10 21:33:31 +04:00
|
|
|
from lib.core.settings import RESTORE_MERGED_OPTIONS
|
2011-05-16 02:21:38 +04:00
|
|
|
from lib.core.settings import RESULTS_FILE_FORMAT
|
2017-12-04 15:41:02 +03:00
|
|
|
from lib.core.settings import SESSION_SQLITE_FILE
|
2012-06-21 14:09:10 +04:00
|
|
|
from lib.core.settings import SUPPORTED_DBMS
|
2013-01-19 21:06:36 +04:00
|
|
|
from lib.core.settings import UNENCODED_ORIGINAL_VALUE
|
2011-01-30 14:36:03 +03:00
|
|
|
from lib.core.settings import UNICODE_ENCODING
|
2012-06-21 14:09:10 +04:00
|
|
|
from lib.core.settings import UNKNOWN_DBMS_VERSION
|
2011-01-31 23:36:01 +03:00
|
|
|
from lib.core.settings import URI_INJECTABLE_REGEX
|
2011-02-14 00:58:48 +03:00
|
|
|
from lib.core.settings import USER_AGENT_ALIASES
|
2014-04-30 23:25:45 +04:00
|
|
|
from lib.core.settings import XML_RECOGNITION_REGEX
|
2021-09-29 18:46:32 +03:00
|
|
|
from lib.core.threads import getCurrentThreadData
|
2011-09-26 00:36:32 +04:00
|
|
|
from lib.utils.hashdb import HashDB
|
2019-04-19 12:24:34 +03:00
|
|
|
from thirdparty import six
|
2019-03-11 16:36:01 +03:00
|
|
|
from thirdparty.odict import OrderedDict
|
2019-03-27 15:33:46 +03:00
|
|
|
from thirdparty.six.moves import urllib as _urllib
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _setRequestParams():
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
|
|
|
Check and set the parameters and perform checks on 'data' option for
|
|
|
|
HTTP method POST.
|
|
|
|
"""
|
|
|
|
|
2010-03-27 02:23:25 +03:00
|
|
|
if conf.direct:
|
|
|
|
conf.parameters[None] = "direct connection"
|
|
|
|
return
|
|
|
|
|
2018-06-12 23:45:16 +03:00
|
|
|
hintNames = []
|
2012-04-17 18:23:00 +04:00
|
|
|
testableParameters = False
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
# Perform checks on GET parameters
|
2012-07-14 13:01:30 +04:00
|
|
|
if conf.parameters.get(PLACE.GET):
|
2010-11-08 12:44:32 +03:00
|
|
|
parameters = conf.parameters[PLACE.GET]
|
2012-04-17 18:23:00 +04:00
|
|
|
paramDict = paramToDict(PLACE.GET, parameters)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-04-17 18:23:00 +04:00
|
|
|
if paramDict:
|
|
|
|
conf.paramDict[PLACE.GET] = paramDict
|
|
|
|
testableParameters = True
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
# Perform checks on POST parameters
|
2012-11-13 13:21:11 +04:00
|
|
|
if conf.method == HTTPMETHOD.POST and conf.data is None:
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning("detected empty POST body")
|
2015-08-31 15:43:41 +03:00
|
|
|
conf.data = ""
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-11-13 13:21:11 +04:00
|
|
|
if conf.data is not None:
|
2020-01-10 13:09:20 +03:00
|
|
|
conf.method = conf.method or HTTPMETHOD.POST
|
2012-10-04 13:25:44 +04:00
|
|
|
|
2013-02-14 18:32:16 +04:00
|
|
|
def process(match, repl):
|
2013-02-14 18:41:27 +04:00
|
|
|
retVal = match.group(0)
|
|
|
|
|
2020-08-13 17:22:09 +03:00
|
|
|
if not (conf.testParameter and match.group("name") not in (removePostHintPrefix(_) for _ in conf.testParameter)) and match.group("name") == match.group("name").strip('\\'):
|
2013-02-14 18:32:16 +04:00
|
|
|
retVal = repl
|
|
|
|
while True:
|
|
|
|
_ = re.search(r"\\g<([^>]+)>", retVal)
|
|
|
|
if _:
|
2022-09-25 17:02:48 +03:00
|
|
|
try:
|
|
|
|
retVal = retVal.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1)))
|
|
|
|
except IndexError:
|
|
|
|
break
|
2013-02-14 18:32:16 +04:00
|
|
|
else:
|
|
|
|
break
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.customInjectionMark in retVal:
|
2020-07-28 13:55:57 +03:00
|
|
|
hintNames.append((retVal.split(kb.customInjectionMark)[0], match.group("name").strip('"\'') if kb.postHint == POST_HINT.JSON_LIKE else match.group("name")))
|
2019-08-02 20:33:16 +03:00
|
|
|
|
2013-02-14 18:32:16 +04:00
|
|
|
return retVal
|
|
|
|
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.processUserMarks is None and kb.customInjectionMark in conf.data:
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "custom injection marker ('%s') found in %s " % (kb.customInjectionMark, conf.method)
|
2019-08-21 15:08:13 +03:00
|
|
|
message += "body. Do you want to process it? [Y/n/q] "
|
2017-07-26 01:54:29 +03:00
|
|
|
choice = readInput(message, default='Y').upper()
|
2017-04-18 16:48:05 +03:00
|
|
|
|
|
|
|
if choice == 'Q':
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapUserQuitException
|
2013-05-25 20:52:59 +04:00
|
|
|
else:
|
2017-04-18 16:48:05 +03:00
|
|
|
kb.processUserMarks = choice == 'Y'
|
2013-05-25 20:52:59 +04:00
|
|
|
|
2015-07-06 12:50:59 +03:00
|
|
|
if kb.processUserMarks:
|
2015-07-17 11:14:35 +03:00
|
|
|
kb.testOnlyCustom = True
|
2014-08-31 00:15:14 +04:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
if re.search(JSON_RECOGNITION_REGEX, conf.data):
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "JSON data found in %s body. " % conf.method
|
2017-06-08 00:19:19 +03:00
|
|
|
message += "Do you want to process it? [Y/n/q] "
|
2017-07-26 01:54:29 +03:00
|
|
|
choice = readInput(message, default='Y').upper()
|
2017-06-08 00:19:19 +03:00
|
|
|
|
|
|
|
if choice == 'Q':
|
|
|
|
raise SqlmapUserQuitException
|
|
|
|
elif choice == 'Y':
|
2020-07-28 13:55:57 +03:00
|
|
|
kb.postHint = POST_HINT.JSON
|
2017-07-20 03:41:47 +03:00
|
|
|
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
2015-08-18 23:48:55 +03:00
|
|
|
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
2017-07-20 03:41:47 +03:00
|
|
|
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
2023-03-24 16:29:02 +03:00
|
|
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*".*?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
2023-04-07 14:26:52 +03:00
|
|
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*")"', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
2017-09-11 11:17:02 +03:00
|
|
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
|
|
|
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
|
2019-09-12 16:29:15 +03:00
|
|
|
for match in re.finditer(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data):
|
|
|
|
if not (conf.testParameter and match.group("name") not in conf.testParameter):
|
|
|
|
_ = match.group(2)
|
|
|
|
if kb.customInjectionMark not in _: # Note: only for unprocessed (simple) forms - i.e. non-associative arrays (e.g. [1,2,3])
|
|
|
|
_ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _)
|
|
|
|
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', r'\g<0>%s' % kb.customInjectionMark, _)
|
|
|
|
conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _))
|
2013-05-25 20:52:59 +04:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data):
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "JSON-like data found in %s body. " % conf.method
|
2017-06-08 00:19:19 +03:00
|
|
|
message += "Do you want to process it? [Y/n/q] "
|
|
|
|
choice = readInput(message, default='Y').upper()
|
2017-04-18 16:48:05 +03:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
if choice == 'Q':
|
|
|
|
raise SqlmapUserQuitException
|
|
|
|
elif choice == 'Y':
|
2020-07-28 13:55:57 +03:00
|
|
|
kb.postHint = POST_HINT.JSON_LIKE
|
2017-07-20 03:41:47 +03:00
|
|
|
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
2015-08-18 23:48:55 +03:00
|
|
|
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
2017-07-20 03:41:47 +03:00
|
|
|
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
2020-07-28 13:55:57 +03:00
|
|
|
if '"' in conf.data:
|
|
|
|
conf.data = re.sub(r'((?P<name>"[^"]+"|\w+)\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
|
|
|
|
conf.data = re.sub(r'((?P<name>"[^"]+"|\w+)\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % kb.customInjectionMark), conf.data)
|
|
|
|
else:
|
|
|
|
conf.data = re.sub(r"((?P<name>'[^']+'|\w+)\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % kb.customInjectionMark), conf.data)
|
|
|
|
conf.data = re.sub(r"((?P<name>'[^']+'|\w+)\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % kb.customInjectionMark), conf.data)
|
2017-04-18 16:48:05 +03:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data):
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "Array-like data found in %s body. " % conf.method
|
2017-06-08 00:19:19 +03:00
|
|
|
message += "Do you want to process it? [Y/n/q] "
|
|
|
|
choice = readInput(message, default='Y').upper()
|
|
|
|
|
|
|
|
if choice == 'Q':
|
|
|
|
raise SqlmapUserQuitException
|
|
|
|
elif choice == 'Y':
|
2020-07-28 13:55:57 +03:00
|
|
|
kb.postHint = POST_HINT.ARRAY_LIKE
|
2017-07-20 03:41:47 +03:00
|
|
|
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
|
|
|
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
|
|
|
conf.data = re.sub(r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % kb.customInjectionMark, conf.data)
|
2014-10-09 17:21:26 +04:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
elif re.search(XML_RECOGNITION_REGEX, conf.data):
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "SOAP/XML data found in %s body. " % conf.method
|
2017-06-08 00:19:19 +03:00
|
|
|
message += "Do you want to process it? [Y/n/q] "
|
|
|
|
choice = readInput(message, default='Y').upper()
|
2017-04-18 16:48:05 +03:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
if choice == 'Q':
|
|
|
|
raise SqlmapUserQuitException
|
|
|
|
elif choice == 'Y':
|
2020-07-28 13:55:57 +03:00
|
|
|
kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML
|
2017-07-20 03:41:47 +03:00
|
|
|
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
2015-08-18 23:48:55 +03:00
|
|
|
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
2017-07-20 03:41:47 +03:00
|
|
|
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>" % kb.customInjectionMark), conf.data)
|
2013-05-25 20:52:59 +04:00
|
|
|
|
2017-06-08 00:19:19 +03:00
|
|
|
elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data):
|
2020-01-10 13:09:20 +03:00
|
|
|
message = "Multipart-like data found in %s body. " % conf.method
|
2017-06-08 00:19:19 +03:00
|
|
|
message += "Do you want to process it? [Y/n/q] "
|
|
|
|
choice = readInput(message, default='Y').upper()
|
|
|
|
|
|
|
|
if choice == 'Q':
|
|
|
|
raise SqlmapUserQuitException
|
|
|
|
elif choice == 'Y':
|
2020-07-28 13:55:57 +03:00
|
|
|
kb.postHint = POST_HINT.MULTIPART
|
2017-07-20 03:41:47 +03:00
|
|
|
if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
|
2015-08-18 23:48:55 +03:00
|
|
|
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
2017-07-20 03:41:47 +03:00
|
|
|
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
|
2024-01-09 11:36:17 +03:00
|
|
|
conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"']?(?P<name>[^\"'\r\n]+)[\"']?).+?)((%s)+--)" % ("\r\n" if "\r\n" in conf.data else '\n'), functools.partial(process, repl=r"\g<1>%s\g<4>" % kb.customInjectionMark), conf.data)
|
2017-06-08 00:19:19 +03:00
|
|
|
|
2013-03-26 18:07:14 +04:00
|
|
|
if not kb.postHint:
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.customInjectionMark in conf.data: # later processed
|
2013-03-26 18:07:14 +04:00
|
|
|
pass
|
|
|
|
else:
|
|
|
|
place = PLACE.POST
|
|
|
|
|
|
|
|
conf.parameters[place] = conf.data
|
|
|
|
paramDict = paramToDict(place, conf.data)
|
|
|
|
|
|
|
|
if paramDict:
|
|
|
|
conf.paramDict[place] = paramDict
|
|
|
|
testableParameters = True
|
2013-03-26 19:04:56 +04:00
|
|
|
else:
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.customInjectionMark not in conf.data: # in case that no usable parameter values has been found
|
2013-03-26 19:04:56 +04:00
|
|
|
conf.parameters[PLACE.POST] = conf.data
|
2010-01-02 05:02:12 +03:00
|
|
|
|
2018-04-26 19:56:17 +03:00
|
|
|
kb.processUserMarks = True if (kb.postHint and kb.customInjectionMark in (conf.data or "")) else kb.processUserMarks
|
2012-10-16 14:32:58 +04:00
|
|
|
|
2018-03-13 15:45:42 +03:00
|
|
|
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 kb.customInjectionMark not in (conf.data or "") and conf.url.startswith("http"):
|
2013-04-09 13:48:42 +04:00
|
|
|
warnMsg = "you've provided target URL without any GET "
|
2016-05-24 16:08:04 +03:00
|
|
|
warnMsg += "parameters (e.g. 'http://www.site.com/article.php?id=1') "
|
2011-05-08 10:28:58 +04:00
|
|
|
warnMsg += "and without providing any POST parameters "
|
2016-05-24 16:08:04 +03:00
|
|
|
warnMsg += "through option '--data'"
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2011-05-08 10:17:43 +04:00
|
|
|
|
|
|
|
message = "do you want to try URI injections "
|
2013-04-09 13:48:42 +04:00
|
|
|
message += "in the target URL itself? [Y/n/q] "
|
2017-04-19 15:46:27 +03:00
|
|
|
choice = readInput(message, default='Y').upper()
|
2011-05-08 10:17:43 +04:00
|
|
|
|
2017-04-18 16:48:05 +03:00
|
|
|
if choice == 'Q':
|
2015-08-31 10:51:35 +03:00
|
|
|
raise SqlmapUserQuitException
|
2017-04-18 16:48:05 +03:00
|
|
|
elif choice == 'Y':
|
2017-07-20 03:41:47 +03:00
|
|
|
conf.url = "%s%s" % (conf.url, kb.customInjectionMark)
|
2012-04-17 18:23:00 +04:00
|
|
|
kb.processUserMarks = True
|
2011-01-31 23:36:01 +03:00
|
|
|
|
2014-12-15 15:51:00 +03:00
|
|
|
for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))):
|
2019-11-06 16:53:33 +03:00
|
|
|
if place == PLACE.CUSTOM_HEADER and any((conf.forms, conf.crawlDepth)):
|
|
|
|
continue
|
|
|
|
|
2013-02-14 19:18:16 +04:00
|
|
|
_ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or ""
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.customInjectionMark in _:
|
2012-04-17 18:23:00 +04:00
|
|
|
if kb.processUserMarks is None:
|
2013-02-12 15:06:13 +04:00
|
|
|
lut = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie'}
|
2017-07-20 03:41:47 +03:00
|
|
|
message = "custom injection marker ('%s') found in option " % kb.customInjectionMark
|
2013-02-12 15:06:13 +04:00
|
|
|
message += "'%s'. Do you want to process it? [Y/n/q] " % lut[place]
|
2017-04-19 15:46:27 +03:00
|
|
|
choice = readInput(message, default='Y').upper()
|
2017-04-18 16:48:05 +03:00
|
|
|
|
|
|
|
if choice == 'Q':
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapUserQuitException
|
2012-04-17 18:23:00 +04:00
|
|
|
else:
|
2017-04-18 16:48:05 +03:00
|
|
|
kb.processUserMarks = choice == 'Y'
|
2011-04-22 01:15:23 +04:00
|
|
|
|
2015-07-06 12:50:59 +03:00
|
|
|
if kb.processUserMarks:
|
2015-07-17 11:14:35 +03:00
|
|
|
kb.testOnlyCustom = True
|
2015-07-06 12:50:59 +03:00
|
|
|
|
2017-07-20 03:41:47 +03:00
|
|
|
if "=%s" % kb.customInjectionMark in _:
|
2015-07-06 12:50:59 +03:00
|
|
|
warnMsg = "it seems that you've provided empty parameter value(s) "
|
|
|
|
warnMsg += "for testing. Please, always use only valid parameter values "
|
|
|
|
warnMsg += "so sqlmap could be able to run properly"
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2014-08-31 00:15:14 +04:00
|
|
|
|
2012-04-17 18:23:00 +04:00
|
|
|
if not kb.processUserMarks:
|
2012-11-05 18:58:54 +04:00
|
|
|
if place == PLACE.URI:
|
2019-03-27 15:33:46 +03:00
|
|
|
query = _urllib.parse.urlsplit(value).query
|
2012-11-05 18:58:54 +04:00
|
|
|
if query:
|
|
|
|
parameters = conf.parameters[PLACE.GET] = query
|
|
|
|
paramDict = paramToDict(PLACE.GET, parameters)
|
|
|
|
|
|
|
|
if paramDict:
|
2012-12-09 00:23:30 +04:00
|
|
|
conf.url = conf.url.split('?')[0]
|
2012-11-05 18:58:54 +04:00
|
|
|
conf.paramDict[PLACE.GET] = paramDict
|
|
|
|
testableParameters = True
|
2013-01-22 17:08:19 +04:00
|
|
|
elif place == PLACE.CUSTOM_POST:
|
|
|
|
conf.parameters[PLACE.POST] = conf.data
|
|
|
|
paramDict = paramToDict(PLACE.POST, conf.data)
|
|
|
|
|
|
|
|
if paramDict:
|
|
|
|
conf.paramDict[PLACE.POST] = paramDict
|
|
|
|
testableParameters = True
|
|
|
|
|
2013-01-13 19:22:43 +04:00
|
|
|
else:
|
2022-06-23 14:47:52 +03:00
|
|
|
if place == PLACE.URI:
|
|
|
|
value = conf.url = conf.url.replace('+', "%20") # NOTE: https://github.com/sqlmapproject/sqlmap/issues/5123
|
|
|
|
|
2013-01-13 19:22:43 +04:00
|
|
|
conf.parameters[place] = value
|
|
|
|
conf.paramDict[place] = OrderedDict()
|
|
|
|
|
|
|
|
if place == PLACE.CUSTOM_HEADER:
|
|
|
|
for index in xrange(len(conf.httpHeaders)):
|
|
|
|
header, value = conf.httpHeaders[index]
|
2017-07-20 03:41:47 +03:00
|
|
|
if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value):
|
|
|
|
parts = value.split(kb.customInjectionMark)
|
2013-02-12 15:06:13 +04:00
|
|
|
for i in xrange(len(parts) - 1):
|
2017-07-20 03:41:47 +03:00
|
|
|
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(kb.customInjectionMark, ""))
|
2013-01-13 19:22:43 +04:00
|
|
|
else:
|
2017-07-20 03:41:47 +03:00
|
|
|
parts = value.split(kb.customInjectionMark)
|
2011-04-22 01:15:23 +04:00
|
|
|
|
2013-01-13 19:22:43 +04:00
|
|
|
for i in xrange(len(parts) - 1):
|
2015-01-08 00:09:40 +03:00
|
|
|
name = None
|
|
|
|
if kb.postHint:
|
|
|
|
for ending, _ in hintNames:
|
|
|
|
if parts[i].endswith(ending):
|
|
|
|
name = "%s %s" % (kb.postHint, _)
|
|
|
|
break
|
|
|
|
if name is None:
|
2017-07-20 03:41:47 +03:00
|
|
|
name = "%s#%s%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, kb.customInjectionMark)
|
|
|
|
conf.paramDict[place][name] = "".join("%s%s" % (parts[j], kb.customInjectionMark if i == j else "") for j in xrange(len(parts)))
|
2011-04-22 01:15:23 +04:00
|
|
|
|
2013-01-13 19:22:43 +04:00
|
|
|
if place == PLACE.URI and PLACE.GET in conf.paramDict:
|
|
|
|
del conf.paramDict[PLACE.GET]
|
|
|
|
elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict:
|
|
|
|
del conf.paramDict[PLACE.POST]
|
2011-04-22 01:15:23 +04:00
|
|
|
|
2013-01-13 19:22:43 +04:00
|
|
|
testableParameters = True
|
2012-04-17 18:23:00 +04:00
|
|
|
|
|
|
|
if kb.processUserMarks:
|
2013-02-12 15:06:13 +04:00
|
|
|
for item in ("url", "data", "agent", "referer", "cookie"):
|
|
|
|
if conf.get(item):
|
2017-07-20 03:41:47 +03:00
|
|
|
conf[item] = conf[item].replace(kb.customInjectionMark, "")
|
2010-09-22 15:56:35 +04:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
# Perform checks on Cookie parameters
|
|
|
|
if conf.cookie:
|
|
|
|
conf.parameters[PLACE.COOKIE] = conf.cookie
|
|
|
|
paramDict = paramToDict(PLACE.COOKIE, conf.cookie)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
if paramDict:
|
|
|
|
conf.paramDict[PLACE.COOKIE] = paramDict
|
|
|
|
testableParameters = True
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
# Perform checks on header values
|
|
|
|
if conf.httpHeaders:
|
2015-11-09 16:05:53 +03:00
|
|
|
for httpHeader, headerValue in list(conf.httpHeaders):
|
2015-07-17 11:14:35 +03:00
|
|
|
# Url encoding of the header values should be avoided
|
|
|
|
# Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value
|
2012-03-16 15:18:18 +04:00
|
|
|
|
2018-11-28 02:29:17 +03:00
|
|
|
if httpHeader.upper() == HTTP_HEADER.USER_AGENT.upper():
|
2015-07-17 11:14:35 +03:00
|
|
|
conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2015-11-09 15:19:55 +03:00
|
|
|
condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True)))
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
if condition:
|
|
|
|
conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue}
|
|
|
|
testableParameters = True
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2018-11-28 02:29:17 +03:00
|
|
|
elif httpHeader.upper() == HTTP_HEADER.REFERER.upper():
|
2015-07-17 11:14:35 +03:00
|
|
|
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
2011-02-12 02:07:03 +03:00
|
|
|
|
2015-11-09 15:19:55 +03:00
|
|
|
condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True)))
|
2011-02-12 02:07:03 +03:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
if condition:
|
|
|
|
conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
|
|
|
|
testableParameters = True
|
2011-02-12 02:07:03 +03:00
|
|
|
|
2018-11-28 02:29:17 +03:00
|
|
|
elif httpHeader.upper() == HTTP_HEADER.HOST.upper():
|
2015-07-17 11:14:35 +03:00
|
|
|
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
2011-12-20 16:52:41 +04:00
|
|
|
|
2015-11-09 15:19:55 +03:00
|
|
|
condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True)))
|
2011-12-20 16:52:41 +04:00
|
|
|
|
2015-07-17 11:14:35 +03:00
|
|
|
if condition:
|
|
|
|
conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue}
|
|
|
|
testableParameters = True
|
2011-12-20 16:52:41 +04:00
|
|
|
|
2015-11-09 16:05:53 +03:00
|
|
|
else:
|
|
|
|
condition = intersect(conf.testParameter, [httpHeader], True)
|
|
|
|
|
|
|
|
if condition:
|
|
|
|
conf.parameters[PLACE.CUSTOM_HEADER] = str(conf.httpHeaders)
|
2017-07-20 03:41:47 +03:00
|
|
|
conf.paramDict[PLACE.CUSTOM_HEADER] = {httpHeader: "%s,%s%s" % (httpHeader, headerValue, kb.customInjectionMark)}
|
2018-03-13 15:45:42 +03:00
|
|
|
conf.httpHeaders = [(_[0], _[1].replace(kb.customInjectionMark, "")) for _ in conf.httpHeaders]
|
2015-11-09 16:05:53 +03:00
|
|
|
testableParameters = True
|
|
|
|
|
2008-10-15 19:38:22 +04:00
|
|
|
if not conf.parameters:
|
2011-04-30 17:20:05 +04:00
|
|
|
errMsg = "you did not provide any GET, POST and Cookie "
|
2011-12-20 16:52:41 +04:00
|
|
|
errMsg += "parameter, neither an User-Agent, Referer or Host header value"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapGenericException(errMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-04-17 18:23:00 +04:00
|
|
|
elif not testableParameters:
|
2011-04-30 17:20:05 +04:00
|
|
|
errMsg = "all testable parameters you provided are not present "
|
2013-02-14 18:34:03 +04:00
|
|
|
errMsg += "within the given request data"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapGenericException(errMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2014-10-23 13:23:53 +04:00
|
|
|
if conf.csrfToken:
|
2020-08-13 17:18:31 +03:00
|
|
|
if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}), conf.paramDict.get(PLACE.COOKIE, {}))) and not re.search(r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}) and not all(re.search(conf.csrfToken, _, re.I) for _ in conf.paramDict.get(PLACE.URI, {}).values()):
|
2018-12-10 16:53:11 +03:00
|
|
|
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
|
2014-10-24 11:37:51 +04:00
|
|
|
errMsg += "found in provided GET, POST, Cookie or header values"
|
2014-10-23 13:23:53 +04:00
|
|
|
raise SqlmapGenericException(errMsg)
|
2014-10-23 13:42:30 +04:00
|
|
|
else:
|
2014-10-24 11:37:51 +04:00
|
|
|
for place in (PLACE.GET, PLACE.POST, PLACE.COOKIE):
|
2017-12-04 15:41:02 +03:00
|
|
|
if conf.csrfToken:
|
|
|
|
break
|
|
|
|
|
2014-10-23 13:42:30 +04:00
|
|
|
for parameter in conf.paramDict.get(place, {}):
|
2014-10-23 16:03:44 +04:00
|
|
|
if any(parameter.lower().count(_) for _ in CSRF_TOKEN_PARAMETER_INFIXES):
|
2019-05-21 13:07:19 +03:00
|
|
|
message = "%sparameter '%s' appears to hold anti-CSRF token. " % ("%s " % place if place != parameter else "", parameter)
|
2014-10-23 13:42:30 +04:00
|
|
|
message += "Do you want sqlmap to automatically update it in further requests? [y/N] "
|
2017-04-18 16:48:05 +03:00
|
|
|
|
|
|
|
if readInput(message, default='N', boolean=True):
|
2019-04-19 12:24:34 +03:00
|
|
|
class _(six.text_type):
|
2018-12-11 15:28:51 +03:00
|
|
|
pass
|
|
|
|
conf.csrfToken = _(re.escape(getUnicode(parameter)))
|
|
|
|
conf.csrfToken._original = getUnicode(parameter)
|
2017-12-04 15:41:02 +03:00
|
|
|
break
|
2014-10-23 13:23:53 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _setHashDB():
|
2011-09-26 17:01:43 +04:00
|
|
|
"""
|
|
|
|
Check and set the HashDB SQLite file for query resume functionality.
|
|
|
|
"""
|
2011-11-22 12:39:13 +04:00
|
|
|
|
2011-09-26 17:01:43 +04:00
|
|
|
if not conf.hashDBFile:
|
2017-12-04 15:41:02 +03:00
|
|
|
conf.hashDBFile = conf.sessionFile or os.path.join(conf.outputPath, SESSION_SQLITE_FILE)
|
2011-09-26 17:01:43 +04:00
|
|
|
|
2021-12-27 13:19:49 +03:00
|
|
|
if conf.flushSession:
|
|
|
|
if os.path.exists(conf.hashDBFile):
|
2021-09-29 23:24:30 +03:00
|
|
|
if conf.hashDB:
|
2021-09-30 00:01:32 +03:00
|
|
|
conf.hashDB.closeAll()
|
2021-09-29 23:24:30 +03:00
|
|
|
|
2011-09-26 17:01:43 +04:00
|
|
|
try:
|
|
|
|
os.remove(conf.hashDBFile)
|
2012-07-07 21:02:46 +04:00
|
|
|
logger.info("flushing session file")
|
2019-01-22 04:08:02 +03:00
|
|
|
except OSError as ex:
|
|
|
|
errMsg = "unable to flush the session file ('%s')" % getSafeExString(ex)
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapFilePathException(errMsg)
|
2011-09-26 17:01:43 +04:00
|
|
|
|
|
|
|
conf.hashDB = HashDB(conf.hashDBFile)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _resumeHashDBValues():
|
2011-11-22 12:39:13 +04:00
|
|
|
"""
|
|
|
|
Resume stored data values from HashDB
|
|
|
|
"""
|
|
|
|
|
2012-03-13 02:55:57 +04:00
|
|
|
kb.absFilePaths = hashDBRetrieve(HASHDB_KEYS.KB_ABS_FILE_PATHS, True) or kb.absFilePaths
|
|
|
|
kb.brute.tables = hashDBRetrieve(HASHDB_KEYS.KB_BRUTE_TABLES, True) or kb.brute.tables
|
|
|
|
kb.brute.columns = hashDBRetrieve(HASHDB_KEYS.KB_BRUTE_COLUMNS, True) or kb.brute.columns
|
2015-08-26 16:26:16 +03:00
|
|
|
kb.chars = hashDBRetrieve(HASHDB_KEYS.KB_CHARS, True) or kb.chars
|
|
|
|
kb.dynamicMarkings = hashDBRetrieve(HASHDB_KEYS.KB_DYNAMIC_MARKINGS, True) or kb.dynamicMarkings
|
2012-03-13 02:55:57 +04:00
|
|
|
kb.xpCmdshellAvailable = hashDBRetrieve(HASHDB_KEYS.KB_XP_CMDSHELL_AVAILABLE) or kb.xpCmdshellAvailable
|
|
|
|
|
2015-08-26 16:26:16 +03:00
|
|
|
kb.errorChunkLength = hashDBRetrieve(HASHDB_KEYS.KB_ERROR_CHUNK_LENGTH)
|
2017-07-05 14:51:48 +03:00
|
|
|
if isNumPosStrValue(kb.errorChunkLength):
|
2015-08-26 16:26:16 +03:00
|
|
|
kb.errorChunkLength = int(kb.errorChunkLength)
|
|
|
|
else:
|
|
|
|
kb.errorChunkLength = None
|
|
|
|
|
2012-03-13 02:55:57 +04:00
|
|
|
conf.tmpPath = conf.tmpPath or hashDBRetrieve(HASHDB_KEYS.CONF_TMP_PATH)
|
|
|
|
|
|
|
|
for injection in hashDBRetrieve(HASHDB_KEYS.KB_INJECTIONS, True) or []:
|
2018-03-13 15:45:42 +03:00
|
|
|
if isinstance(injection, InjectionDict) and injection.place in conf.paramDict and injection.parameter in conf.paramDict[injection.place]:
|
2019-06-07 01:21:43 +03:00
|
|
|
if not conf.technique or intersect(conf.technique, injection.data.keys()):
|
|
|
|
if intersect(conf.technique, injection.data.keys()):
|
|
|
|
injection.data = dict(_ for _ in injection.data.items() if _[0] in conf.technique)
|
2012-03-13 02:55:57 +04:00
|
|
|
if injection not in kb.injections:
|
|
|
|
kb.injections.append(injection)
|
2019-06-07 11:37:13 +03:00
|
|
|
kb.vulnHosts.add(conf.hostname)
|
2012-02-27 17:44:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
_resumeDBMS()
|
|
|
|
_resumeOS()
|
2012-06-21 14:09:10 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _resumeDBMS():
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
2012-06-21 14:09:10 +04:00
|
|
|
Resume stored DBMS information from HashDB
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
value = hashDBRetrieve(HASHDB_KEYS.DBMS)
|
2010-04-12 13:35:20 +04:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
if not value:
|
2018-10-15 01:53:26 +03:00
|
|
|
if conf.offline:
|
|
|
|
errMsg = "unable to continue in offline mode "
|
|
|
|
errMsg += "because of lack of usable "
|
|
|
|
errMsg += "session data"
|
|
|
|
raise SqlmapNoneDataException(errMsg)
|
|
|
|
else:
|
|
|
|
return
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
dbms = value.lower()
|
|
|
|
dbmsVersion = [UNKNOWN_DBMS_VERSION]
|
2020-03-03 16:40:40 +03:00
|
|
|
_ = "(%s)" % ('|'.join(SUPPORTED_DBMS))
|
2016-03-10 17:42:01 +03:00
|
|
|
_ = re.search(r"\A%s (.*)" % _, dbms, re.I)
|
2012-06-21 14:09:10 +04:00
|
|
|
|
|
|
|
if _:
|
|
|
|
dbms = _.group(1).lower()
|
|
|
|
dbmsVersion = [_.group(2)]
|
|
|
|
|
|
|
|
if conf.dbms:
|
2012-10-23 16:37:45 +04:00
|
|
|
check = True
|
2013-04-15 12:33:25 +04:00
|
|
|
for aliases, _, _, _ in DBMS_DICT.values():
|
2012-10-23 16:37:45 +04:00
|
|
|
if conf.dbms.lower() in aliases and dbms not in aliases:
|
|
|
|
check = False
|
|
|
|
break
|
|
|
|
|
|
|
|
if not check:
|
|
|
|
message = "you provided '%s' as a back-end DBMS, " % conf.dbms
|
2012-06-21 14:09:10 +04:00
|
|
|
message += "but from a past scan information on the target URL "
|
2012-10-23 16:38:24 +04:00
|
|
|
message += "sqlmap assumes the back-end DBMS is '%s'. " % dbms
|
2012-06-21 14:09:10 +04:00
|
|
|
message += "Do you really want to force the back-end "
|
|
|
|
message += "DBMS value? [y/N] "
|
|
|
|
|
2017-04-18 16:48:05 +03:00
|
|
|
if not readInput(message, default='N', boolean=True):
|
2012-06-21 14:09:10 +04:00
|
|
|
conf.dbms = None
|
|
|
|
Backend.setDbms(dbms)
|
|
|
|
Backend.setVersionList(dbmsVersion)
|
|
|
|
else:
|
|
|
|
infoMsg = "resuming back-end DBMS '%s' " % dbms
|
|
|
|
logger.info(infoMsg)
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
Backend.setDbms(dbms)
|
|
|
|
Backend.setVersionList(dbmsVersion)
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _resumeOS():
|
2012-06-21 14:09:10 +04:00
|
|
|
"""
|
|
|
|
Resume stored OS information from HashDB
|
|
|
|
"""
|
2010-04-12 13:35:20 +04:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
value = hashDBRetrieve(HASHDB_KEYS.OS)
|
2010-04-12 13:35:20 +04:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
if not value:
|
|
|
|
return
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
os = value
|
2010-11-03 13:08:27 +03:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
if os and os != 'None':
|
|
|
|
infoMsg = "resuming back-end DBMS operating system '%s' " % os
|
|
|
|
logger.info(infoMsg)
|
2010-05-11 17:36:30 +04:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
if conf.os and conf.os.lower() != os.lower():
|
|
|
|
message = "you provided '%s' as back-end DBMS operating " % conf.os
|
|
|
|
message += "system, but from a past scan information on the "
|
|
|
|
message += "target URL sqlmap assumes the back-end DBMS "
|
|
|
|
message += "operating system is %s. " % os
|
|
|
|
message += "Do you really want to force the back-end DBMS "
|
|
|
|
message += "OS value? [y/N] "
|
2010-12-01 01:40:25 +03:00
|
|
|
|
2017-04-18 16:48:05 +03:00
|
|
|
if not readInput(message, default='N', boolean=True):
|
2012-06-21 14:09:10 +04:00
|
|
|
conf.os = os
|
2010-03-04 16:01:18 +03:00
|
|
|
else:
|
2012-06-21 14:09:10 +04:00
|
|
|
conf.os = os
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-06-21 14:09:10 +04:00
|
|
|
Backend.setOs(conf.os)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _setResultsFile():
|
2011-05-16 02:21:38 +04:00
|
|
|
"""
|
2012-02-22 14:40:11 +04:00
|
|
|
Create results file for storing results of running in a
|
2011-05-16 02:21:38 +04:00
|
|
|
multiple target mode.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if not conf.multipleTargets:
|
|
|
|
return
|
|
|
|
|
|
|
|
if not conf.resultsFP:
|
2019-11-01 19:27:30 +03:00
|
|
|
conf.resultsFile = conf.resultsFile or os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
|
|
|
|
found = os.path.exists(conf.resultsFile)
|
|
|
|
|
2014-12-24 00:04:23 +03:00
|
|
|
try:
|
2019-11-01 19:27:30 +03:00
|
|
|
conf.resultsFP = openFile(conf.resultsFile, "a", UNICODE_ENCODING, buffering=0)
|
2019-01-22 02:40:48 +03:00
|
|
|
except (OSError, IOError) as ex:
|
2014-12-24 00:04:23 +03:00
|
|
|
try:
|
2019-11-01 19:27:30 +03:00
|
|
|
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFile, getUnicode(ex))
|
|
|
|
handle, conf.resultsFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")
|
2017-04-14 14:08:51 +03:00
|
|
|
os.close(handle)
|
2019-11-01 19:27:30 +03:00
|
|
|
conf.resultsFP = openFile(conf.resultsFile, "w+", UNICODE_ENCODING, buffering=0)
|
|
|
|
warnMsg += "Using temporary file '%s' instead" % conf.resultsFile
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2019-01-22 04:08:02 +03:00
|
|
|
except IOError as _:
|
2014-12-24 00:04:23 +03:00
|
|
|
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
|
|
|
errMsg += "Please make sure that your disk is not full and "
|
|
|
|
errMsg += "that you have sufficient write permissions to "
|
|
|
|
errMsg += "create temporary files and/or directories"
|
|
|
|
raise SqlmapSystemException(errMsg)
|
|
|
|
|
2019-11-01 19:27:30 +03:00
|
|
|
if not found:
|
|
|
|
conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep)
|
2011-05-16 02:21:38 +04:00
|
|
|
|
2019-11-01 19:27:30 +03:00
|
|
|
logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFile)
|
2011-05-16 02:21:38 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _createFilesDir():
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
|
|
|
Create the file directory.
|
|
|
|
"""
|
|
|
|
|
2019-06-27 18:28:43 +03:00
|
|
|
if not any((conf.fileRead, conf.commonFiles)):
|
2008-10-15 19:38:22 +04:00
|
|
|
return
|
|
|
|
|
|
|
|
conf.filePath = paths.SQLMAP_FILES_PATH % conf.hostname
|
|
|
|
|
|
|
|
if not os.path.isdir(conf.filePath):
|
2014-04-12 19:22:33 +04:00
|
|
|
try:
|
2018-03-07 16:34:38 +03:00
|
|
|
os.makedirs(conf.filePath)
|
2019-01-22 02:40:48 +03:00
|
|
|
except OSError as ex:
|
2014-04-12 19:22:33 +04:00
|
|
|
tempDir = tempfile.mkdtemp(prefix="sqlmapfiles")
|
|
|
|
warnMsg = "unable to create files directory "
|
2014-12-15 09:18:47 +03:00
|
|
|
warnMsg += "'%s' (%s). " % (conf.filePath, getUnicode(ex))
|
2021-12-03 16:18:54 +03:00
|
|
|
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2014-04-12 19:22:33 +04:00
|
|
|
|
|
|
|
conf.filePath = tempDir
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _createDumpDir():
|
2008-10-15 19:38:22 +04:00
|
|
|
"""
|
|
|
|
Create the dump directory.
|
|
|
|
"""
|
|
|
|
|
2010-06-02 15:01:41 +04:00
|
|
|
if not conf.dumpTable and not conf.dumpAll and not conf.search:
|
2008-10-15 19:38:22 +04:00
|
|
|
return
|
|
|
|
|
2022-01-17 15:24:02 +03:00
|
|
|
conf.dumpPath = safeStringFormat(paths.SQLMAP_DUMP_PATH, conf.hostname)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
if not os.path.isdir(conf.dumpPath):
|
2013-10-11 23:16:48 +04:00
|
|
|
try:
|
2018-03-07 16:34:38 +03:00
|
|
|
os.makedirs(conf.dumpPath)
|
2023-08-16 13:43:55 +03:00
|
|
|
except Exception as ex:
|
2013-10-11 23:16:48 +04:00
|
|
|
tempDir = tempfile.mkdtemp(prefix="sqlmapdump")
|
|
|
|
warnMsg = "unable to create dump directory "
|
2014-12-15 09:18:47 +03:00
|
|
|
warnMsg += "'%s' (%s). " % (conf.dumpPath, getUnicode(ex))
|
2021-12-03 16:18:54 +03:00
|
|
|
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2013-10-11 23:16:48 +04:00
|
|
|
|
|
|
|
conf.dumpPath = tempDir
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _configureDumper():
|
2016-09-28 16:00:26 +03:00
|
|
|
conf.dumper = dumper
|
2010-05-28 20:43:04 +04:00
|
|
|
conf.dumper.setOutputFile()
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _createTargetDirs():
|
2009-09-26 03:03:45 +04:00
|
|
|
"""
|
|
|
|
Create the output directory.
|
|
|
|
"""
|
|
|
|
|
2014-11-03 01:38:52 +03:00
|
|
|
conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname)))
|
2009-09-26 03:03:45 +04:00
|
|
|
|
2017-08-07 12:27:22 +03:00
|
|
|
try:
|
|
|
|
if not os.path.isdir(conf.outputPath):
|
2018-03-07 16:34:38 +03:00
|
|
|
os.makedirs(conf.outputPath)
|
2019-01-22 02:40:48 +03:00
|
|
|
except (OSError, IOError, TypeError) as ex:
|
2019-05-09 11:52:33 +03:00
|
|
|
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
|
2017-08-07 12:27:22 +03:00
|
|
|
warnMsg = "unable to create output directory "
|
|
|
|
warnMsg += "'%s' (%s). " % (conf.outputPath, getUnicode(ex))
|
|
|
|
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2010-12-09 00:16:18 +03:00
|
|
|
|
2017-08-07 12:27:22 +03:00
|
|
|
conf.outputPath = tempDir
|
2009-09-26 03:03:45 +04:00
|
|
|
|
2018-07-18 16:34:38 +03:00
|
|
|
conf.outputPath = getUnicode(conf.outputPath)
|
|
|
|
|
2012-10-30 03:20:49 +04:00
|
|
|
try:
|
2018-08-10 15:16:27 +03:00
|
|
|
with openFile(os.path.join(conf.outputPath, "target.txt"), "w+") as f:
|
2021-01-27 16:01:20 +03:00
|
|
|
f.write(getUnicode(kb.originalUrls.get(conf.url) or conf.url or conf.hostname))
|
2013-01-17 17:17:39 +04:00
|
|
|
f.write(" (%s)" % (HTTPMETHOD.POST if conf.data else HTTPMETHOD.GET))
|
2017-06-29 16:29:54 +03:00
|
|
|
f.write(" # %s" % getUnicode(subprocess.list2cmdline(sys.argv), encoding=sys.stdin.encoding))
|
2013-01-17 17:17:39 +04:00
|
|
|
if conf.data:
|
2014-09-01 18:16:12 +04:00
|
|
|
f.write("\n\n%s" % getUnicode(conf.data))
|
2019-01-22 02:40:48 +03:00
|
|
|
except IOError as ex:
|
2014-12-15 15:36:08 +03:00
|
|
|
if "denied" in getUnicode(ex):
|
2012-10-30 03:20:49 +04:00
|
|
|
errMsg = "you don't have enough permissions "
|
|
|
|
else:
|
|
|
|
errMsg = "something went wrong while trying "
|
2016-01-12 12:27:04 +03:00
|
|
|
errMsg += "to write to the output directory '%s' (%s)" % (paths.SQLMAP_OUTPUT_PATH, getSafeExString(ex))
|
2012-10-30 03:20:49 +04:00
|
|
|
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapMissingPrivileges(errMsg)
|
2021-01-27 16:01:20 +03:00
|
|
|
except UnicodeError as ex:
|
|
|
|
warnMsg = "something went wrong while saving target data ('%s')" % getSafeExString(ex)
|
2022-06-22 13:04:34 +03:00
|
|
|
logger.warning(warnMsg)
|
2012-08-15 18:37:18 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
_createDumpDir()
|
|
|
|
_createFilesDir()
|
|
|
|
_configureDumper()
|
2009-09-26 03:03:45 +04:00
|
|
|
|
2018-09-22 00:06:45 +03:00
|
|
|
def _setAuxOptions():
|
|
|
|
"""
|
|
|
|
Setup auxiliary (host-dependent) options
|
|
|
|
"""
|
|
|
|
|
|
|
|
kb.aliasName = randomStr(seed=hash(conf.hostname or ""))
|
|
|
|
|
2013-04-10 21:33:31 +04:00
|
|
|
def _restoreMergedOptions():
|
2011-01-02 13:37:32 +03:00
|
|
|
"""
|
2013-04-10 21:33:31 +04:00
|
|
|
Restore merged options (command line, configuration file and default values)
|
|
|
|
that could be possibly changed during the testing of previous target.
|
2011-01-02 13:37:32 +03:00
|
|
|
"""
|
2013-04-07 23:32:03 +04:00
|
|
|
|
2013-04-10 21:33:31 +04:00
|
|
|
for option in RESTORE_MERGED_OPTIONS:
|
|
|
|
conf[option] = mergedOptions[option]
|
2011-01-02 13:37:32 +03:00
|
|
|
|
2008-10-15 19:38:22 +04:00
|
|
|
def initTargetEnv():
|
|
|
|
"""
|
|
|
|
Initialize target environment.
|
|
|
|
"""
|
|
|
|
|
2008-11-28 01:33:33 +03:00
|
|
|
if conf.multipleTargets:
|
2011-09-26 00:36:32 +04:00
|
|
|
if conf.hashDB:
|
|
|
|
conf.hashDB.close()
|
|
|
|
|
2010-04-06 14:15:19 +04:00
|
|
|
if conf.cj:
|
2012-03-08 14:19:34 +04:00
|
|
|
resetCookieJar(conf.cj)
|
2010-04-06 14:15:19 +04:00
|
|
|
|
2021-09-29 18:46:32 +03:00
|
|
|
threadData = getCurrentThreadData()
|
|
|
|
threadData.reset()
|
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
conf.paramDict = {}
|
|
|
|
conf.parameters = {}
|
2011-09-26 00:36:32 +04:00
|
|
|
conf.hashDBFile = None
|
2010-10-19 22:17:34 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
_setKnowledgeBaseAttributes(False)
|
2013-04-10 21:33:31 +04:00
|
|
|
_restoreMergedOptions()
|
2012-12-06 17:14:19 +04:00
|
|
|
_setDBMS()
|
2008-11-28 01:33:33 +03:00
|
|
|
|
2013-01-19 21:06:36 +04:00
|
|
|
if conf.data:
|
2019-04-19 12:24:34 +03:00
|
|
|
class _(six.text_type):
|
2013-01-19 21:40:44 +04:00
|
|
|
pass
|
|
|
|
|
2015-08-18 23:48:55 +03:00
|
|
|
kb.postUrlEncode = True
|
2015-08-12 23:09:31 +03:00
|
|
|
|
2014-03-21 23:28:16 +04:00
|
|
|
for key, value in conf.httpHeaders:
|
|
|
|
if key.upper() == HTTP_HEADER.CONTENT_TYPE.upper():
|
|
|
|
kb.postUrlEncode = "urlencoded" in value
|
|
|
|
break
|
2015-08-12 23:09:31 +03:00
|
|
|
|
2014-03-21 23:28:16 +04:00
|
|
|
if kb.postUrlEncode:
|
|
|
|
original = conf.data
|
|
|
|
conf.data = _(urldecode(conf.data))
|
|
|
|
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
|
|
|
kb.postSpaceToPlus = '+' in original
|
2013-01-19 21:06:36 +04:00
|
|
|
|
2022-02-11 00:30:17 +03:00
|
|
|
if conf.data and unArrayizeValue(conf.base64Parameter) == HTTPMETHOD.POST:
|
|
|
|
if '=' not in conf.data.strip('='):
|
|
|
|
try:
|
|
|
|
original = conf.data
|
|
|
|
conf.data = _(decodeBase64(conf.data, binary=False))
|
|
|
|
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2019-04-23 01:55:14 +03:00
|
|
|
match = re.search(INJECT_HERE_REGEX, "%s %s %s" % (conf.url, conf.data, conf.httpHeaders))
|
2018-10-27 00:38:37 +03:00
|
|
|
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
|
|
|
|
|
2010-03-15 14:33:34 +03:00
|
|
|
def setupTargetEnv():
|
2012-12-06 17:14:19 +04:00
|
|
|
_createTargetDirs()
|
|
|
|
_setRequestParams()
|
|
|
|
_setHashDB()
|
|
|
|
_resumeHashDBValues()
|
|
|
|
_setResultsFile()
|
|
|
|
_setAuthCred()
|
2019-01-22 03:20:27 +03:00
|
|
|
_setAuxOptions()
|