sqlmap/lib/core/option.py

2554 lines
88 KiB
Python
Raw Normal View History

#!/usr/bin/env python
2008-10-15 19:38:22 +04:00
"""
2019-01-05 23:38:52 +03:00
Copyright (c) 2006-2019 sqlmap developers (http://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
"""
import cookielib
import glob
import inspect
2008-10-15 19:38:22 +04:00
import logging
import os
import random
2008-10-15 19:38:22 +04:00
import re
import socket
2012-10-18 13:11:20 +04:00
import string
2010-10-15 14:36:29 +04:00
import sys
2015-01-13 12:33:51 +03:00
import tempfile
import threading
2013-01-09 19:10:26 +04:00
import time
2008-10-15 19:38:22 +04:00
import urllib2
import urlparse
import lib.controller.checks
import lib.core.common
import lib.core.threads
2012-07-31 13:03:44 +04:00
import lib.core.convert
import lib.request.connect
import lib.utils.search
2010-11-15 15:07:13 +03:00
from lib.controller.checks import checkConnection
from lib.core.common import Backend
from lib.core.common import boldifyMessage
from lib.core.common import checkFile
from lib.core.common import dataToStdout
2011-04-07 14:00:47 +04:00
from lib.core.common import getPublicTypeMembers
2015-09-10 16:55:49 +03:00
from lib.core.common import getSafeExString
2016-10-10 15:19:44 +03:00
from lib.core.common import findLocalPort
from lib.core.common import findPageForms
from lib.core.common import getConsoleWidth
from lib.core.common import getFileItems
from lib.core.common import getFileType
from lib.core.common import normalizePath
from lib.core.common import ntToPosixSlashes
from lib.core.common import openFile
2018-06-19 17:08:38 +03:00
from lib.core.common import parseRequestFile
from lib.core.common import parseTargetDirect
2008-10-15 19:38:22 +04:00
from lib.core.common import paths
from lib.core.common import randomStr
from lib.core.common import readCachedFileContent
from lib.core.common import readInput
2012-03-08 14:19:34 +04:00
from lib.core.common import resetCookieJar
2010-10-28 00:39:50 +04:00
from lib.core.common import runningAsAdmin
2015-01-21 11:26:30 +03:00
from lib.core.common import safeExpandUser
2017-04-10 15:50:17 +03:00
from lib.core.common import saveConfig
2018-07-31 03:18:33 +03:00
from lib.core.common import setColor
from lib.core.common import setOptimize
2013-01-17 15:03:02 +04:00
from lib.core.common import setPaths
2012-07-31 13:03:44 +04:00
from lib.core.common import singleTimeWarnMessage
from lib.core.common import urldecode
2008-10-15 19:38:22 +04:00
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
2013-04-10 21:33:31 +04:00
from lib.core.data import mergedOptions
from lib.core.data import queries
2011-07-08 10:02:31 +04:00
from lib.core.datatype import AttribDict
from lib.core.datatype import InjectionDict
from lib.core.defaults import defaults
2012-08-21 13:19:15 +04:00
from lib.core.dicts import DBMS_DICT
from lib.core.dicts import DUMP_REPLACEMENTS
2012-10-09 17:19:47 +04:00
from lib.core.enums import ADJUST_TIME_DELAY
from lib.core.enums import AUTH_TYPE
2011-12-26 16:24:39 +04:00
from lib.core.enums import CUSTOM_LOGGING
2012-11-28 13:58:18 +04:00
from lib.core.enums import DUMP_FORMAT
from lib.core.enums import HTTP_HEADER
2010-11-08 12:44:32 +03:00
from lib.core.enums import HTTPMETHOD
2011-04-29 23:27:23 +04:00
from lib.core.enums import MOBILES
2014-04-25 11:17:10 +04:00
from lib.core.enums import OPTION_TYPE
from lib.core.enums import PAYLOAD
from lib.core.enums import PRIORITY
2012-11-28 13:59:15 +04:00
from lib.core.enums import PROXY_TYPE
2011-05-30 13:46:32 +04:00
from lib.core.enums import REFLECTIVE_COUNTER
2012-10-05 12:24:09 +04:00
from lib.core.enums import WIZARD
from lib.core.exception import SqlmapConnectionException
2018-12-04 01:18:52 +03:00
from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapFilePathException
from lib.core.exception import SqlmapGenericException
2014-11-10 15:41:53 +03:00
from lib.core.exception import SqlmapInstallationException
from lib.core.exception import SqlmapMissingDependence
from lib.core.exception import SqlmapMissingMandatoryOptionException
from lib.core.exception import SqlmapMissingPrivileges
from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapSyntaxException
2014-11-24 12:13:56 +03:00
from lib.core.exception import SqlmapSystemException
from lib.core.exception import SqlmapUnsupportedDBMSException
from lib.core.exception import SqlmapUserQuitException
from lib.core.log import FORMATTER
2008-10-15 19:38:22 +04:00
from lib.core.optiondict import optDict
2011-05-18 03:03:31 +04:00
from lib.core.settings import CODECS_LIST_PAGE
2012-11-28 14:41:39 +04:00
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DBMS_ALIASES
2019-01-06 04:29:09 +03:00
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
2016-10-10 15:19:44 +03:00
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
2018-11-29 02:09:05 +03:00
from lib.core.settings import DEFAULT_USER_AGENT
2013-09-24 23:44:59 +04:00
from lib.core.settings import DUMMY_URL
from lib.core.settings import IS_WIN
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET
from lib.core.settings import LOCALHOST
2013-03-04 21:05:40 +04:00
from lib.core.settings import MAX_CONNECT_RETRIES
from lib.core.settings import MAX_NUMBER_OF_THREADS
2012-02-07 14:46:55 +04:00
from lib.core.settings import NULL
from lib.core.settings import PARAMETER_SPLITTING_REGEX
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
2014-04-25 11:17:10 +04:00
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
2008-10-15 19:38:22 +04:00
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import SUPPORTED_OS
from lib.core.settings import TIME_DELAY_CANDIDATES
2016-06-19 18:44:47 +03:00
from lib.core.settings import UNICODE_ENCODING
2011-10-10 01:21:41 +04:00
from lib.core.settings import UNION_CHAR_REGEX
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import URI_INJECTABLE_REGEX
2011-11-23 18:26:40 +04:00
from lib.core.threads import getCurrentThreadData
2016-05-16 16:37:49 +03:00
from lib.core.threads import setDaemon
2008-10-15 19:38:22 +04:00
from lib.core.update import update
from lib.parse.configfile import configFileParser
from lib.parse.payloads import loadBoundaries
from lib.parse.payloads import loadPayloads
2014-07-03 00:27:51 +04:00
from lib.parse.sitemap import parseSitemap
2012-09-25 12:17:25 +04:00
from lib.request.basic import checkCharEncoding
from lib.request.connect import Connect as Request
2012-04-04 16:27:24 +04:00
from lib.request.dns import DNSServer
from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler
2012-06-04 23:46:28 +04:00
from lib.request.httpshandler import HTTPSHandler
from lib.request.pkihandler import HTTPSPKIAuthHandler
from lib.request.rangehandler import HTTPRangeHandler
from lib.request.redirecthandler import SmartRedirectHandler
from lib.request.templates import getPageTemplate
2017-07-03 17:55:24 +03:00
from lib.utils.har import HTTPCollectorFactory
2013-01-09 18:22:21 +04:00
from lib.utils.crawler import crawl
2011-06-13 23:00:27 +04:00
from lib.utils.deps import checkDependencies
from lib.utils.search import search
from lib.utils.purge import purge
2012-07-14 19:01:04 +04:00
from thirdparty.keepalive import keepalive
2016-09-02 15:14:17 +03:00
from thirdparty.multipart import multipartpost
2012-07-14 19:01:04 +04:00
from thirdparty.oset.pyoset import oset
from thirdparty.socks import socks
2011-06-22 18:33:52 +04:00
from xml.etree.ElementTree import ElementTree
2008-10-15 19:38:22 +04:00
2010-06-01 16:21:10 +04:00
authHandler = urllib2.BaseHandler()
2012-06-04 23:46:28 +04:00
httpsHandler = HTTPSHandler()
2010-06-01 16:21:10 +04:00
keepAliveHandler = keepalive.HTTPHandler()
2013-08-12 16:25:51 +04:00
proxyHandler = urllib2.ProxyHandler()
redirectHandler = SmartRedirectHandler()
rangeHandler = HTTPRangeHandler()
2016-09-02 15:14:17 +03:00
multipartPostHandler = multipartpost.MultipartPostHandler()
2008-10-15 19:38:22 +04:00
2016-10-04 11:39:28 +03:00
# Reference: https://mail.python.org/pipermail/python-list/2009-November/558615.html
try:
WindowsError
except NameError:
WindowsError = None
def _loadQueries():
"""
Loads queries from 'xml/queries.xml' file.
"""
2010-10-22 18:23:14 +04:00
2011-06-22 18:33:52 +04:00
def iterate(node, retVal=None):
class DictObject(object):
def __init__(self):
self.__dict__ = {}
2013-01-10 18:02:28 +04:00
2011-06-22 18:33:52 +04:00
def __contains__(self, name):
return name in self.__dict__
if retVal is None:
retVal = DictObject()
2011-06-22 19:36:59 +04:00
for child in node.findall("*"):
2011-06-22 18:33:52 +04:00
instance = DictObject()
retVal.__dict__[child.tag] = instance
if child.attrib:
instance.__dict__.update(child.attrib)
2011-06-22 18:33:52 +04:00
else:
iterate(child, instance)
2011-06-22 18:33:52 +04:00
return retVal
tree = ElementTree()
2014-11-10 15:41:53 +03:00
try:
tree.parse(paths.QUERIES_XML)
except Exception, ex:
2016-05-22 22:44:17 +03:00
errMsg = "something appears to be wrong with "
2016-01-12 12:27:04 +03:00
errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex))
2014-11-10 15:41:53 +03:00
errMsg += "sure that you haven't made any changes to it"
2018-03-13 13:13:38 +03:00
raise SqlmapInstallationException(errMsg)
2011-06-22 18:33:52 +04:00
2011-06-22 19:36:59 +04:00
for node in tree.findall("*"):
2011-06-22 18:33:52 +04:00
queries[node.attrib['value']] = iterate(node)
def _setMultipleTargets():
"""
Define a configuration parameter if we are running in multiple target
mode.
"""
initialTargetsCount = len(kb.targets)
2018-06-19 17:08:38 +03:00
seen = set()
if not conf.logFile:
return
debugMsg = "parsing targets list from '%s'" % conf.logFile
logger.debug(debugMsg)
if not os.path.exists(conf.logFile):
errMsg = "the specified list of targets does not exist"
raise SqlmapFilePathException(errMsg)
if os.path.isfile(conf.logFile):
2018-06-19 17:08:38 +03:00
for target in parseRequestFile(conf.logFile):
2019-01-06 04:29:09 +03:00
url, _, data, _, _ = target
key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data))
if key not in seen:
2018-06-19 17:08:38 +03:00
kb.targets.add(target)
2019-01-06 04:29:09 +03:00
seen.add(key)
elif os.path.isdir(conf.logFile):
files = os.listdir(conf.logFile)
files.sort()
for reqFile in files:
2017-10-31 13:38:09 +03:00
if not re.search(r"([\d]+)\-request", reqFile):
continue
2018-06-19 17:08:38 +03:00
for target in parseRequestFile(os.path.join(conf.logFile, reqFile)):
2019-01-06 04:29:09 +03:00
url, _, data, _, _ = target
key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data))
if key not in seen:
2018-06-19 17:08:38 +03:00
kb.targets.add(target)
2019-01-06 04:29:09 +03:00
seen.add(key)
else:
2011-04-30 17:20:05 +04:00
errMsg = "the specified list of targets is not a file "
errMsg += "nor a directory"
raise SqlmapFilePathException(errMsg)
updatedTargetsCount = len(kb.targets)
if updatedTargetsCount > initialTargetsCount:
2011-04-30 17:20:05 +04:00
infoMsg = "sqlmap parsed %d " % (updatedTargetsCount - initialTargetsCount)
2013-11-08 12:23:38 +04:00
infoMsg += "(parameter unique) requests from the "
infoMsg += "targets list ready to be tested"
logger.info(infoMsg)
def _adjustLoggingFormatter():
"""
Solves problem of line deletition caused by overlapping logging messages
and retrieved data info in inference mode
"""
2012-02-24 14:53:28 +04:00
if hasattr(FORMATTER, '_format'):
return
def format(record):
2015-01-22 11:17:45 +03:00
message = FORMATTER._format(record)
message = boldifyMessage(message)
2015-01-28 02:54:39 +03:00
if kb.get("prependFlag"):
2015-01-22 11:17:45 +03:00
message = "\n%s" % message
kb.prependFlag = False
2015-01-22 11:17:45 +03:00
return message
2012-02-24 14:53:28 +04:00
FORMATTER._format = FORMATTER.format
FORMATTER.format = format
def _setRequestFromFile():
"""
This function checks if the way to make a HTTP request is through supplied
textual file, parses it and saves the information into the knowledge base.
"""
2018-06-19 17:39:10 +03:00
if conf.requestFile:
conf.requestFile = safeExpandUser(conf.requestFile)
seen = set()
2018-06-19 17:39:10 +03:00
if not os.path.isfile(conf.requestFile):
errMsg = "specified HTTP request file '%s' " % conf.requestFile
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
2018-06-19 17:39:10 +03:00
infoMsg = "parsing HTTP request from '%s'" % conf.requestFile
logger.info(infoMsg)
2018-06-19 17:39:10 +03:00
for target in parseRequestFile(conf.requestFile):
url = target[0]
if url not in seen:
kb.targets.add(target)
seen.add(url)
2018-06-19 17:39:10 +03:00
if conf.secondReq:
conf.secondReq = safeExpandUser(conf.secondReq)
if not os.path.isfile(conf.secondReq):
2018-06-21 00:21:55 +03:00
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
2018-06-19 17:39:10 +03:00
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
logger.info(infoMsg)
2017-04-11 10:47:27 +03:00
2018-06-20 01:08:55 +03:00
target = parseRequestFile(conf.secondReq, False).next()
2018-06-19 17:39:10 +03:00
kb.secondReq = target
def _setCrawler():
2011-06-24 09:40:03 +04:00
if not conf.crawlDepth:
return
2014-07-03 00:27:51 +04:00
if not any((conf.bulkFile, conf.sitemapUrl)):
2013-04-09 13:36:33 +04:00
crawl(conf.url)
else:
2014-07-03 00:27:51 +04:00
if conf.bulkFile:
targets = getFileItems(conf.bulkFile)
else:
targets = parseSitemap(conf.sitemapUrl)
2013-04-09 13:36:33 +04:00
for i in xrange(len(targets)):
try:
target = targets[i]
crawl(target)
if conf.verbose in (1, 2):
2014-04-06 15:42:15 +04:00
status = "%d/%d links visited (%d%%)" % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets)))
2013-04-09 13:36:33 +04:00
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True)
except Exception, ex:
2016-01-12 12:27:04 +03:00
errMsg = "problem occurred while crawling at '%s' ('%s')" % (target, getSafeExString(ex))
2013-04-09 13:36:33 +04:00
logger.error(errMsg)
def _doSearch():
"""
This function performs search dorking, parses results
and saves the testable hosts into the knowledge base.
"""
if not conf.googleDork:
return
kb.data.onlyGETs = None
def retrieve():
links = search(conf.googleDork)
if not links:
errMsg = "unable to find results for your "
errMsg += "search dork expression"
raise SqlmapGenericException(errMsg)
for link in links:
link = urldecode(link)
if re.search(r"(.*?)\?(.+)", link):
2014-10-22 16:54:49 +04:00
kb.targets.add((link, conf.method, conf.data, conf.cookie, None))
elif re.search(URI_INJECTABLE_REGEX, link, re.I):
2014-08-01 16:19:32 +04:00
if kb.data.onlyGETs is None and conf.data is None and not conf.googleDork:
message = "do you want to scan only results containing GET parameters? [Y/n] "
2017-04-18 16:48:05 +03:00
kb.data.onlyGETs = readInput(message, default='Y', boolean=True)
2014-08-01 16:19:32 +04:00
if not kb.data.onlyGETs or conf.googleDork:
2014-10-22 16:54:49 +04:00
kb.targets.add((link, conf.method, conf.data, conf.cookie, None))
return links
while True:
links = retrieve()
2011-06-08 20:08:20 +04:00
if kb.targets:
infoMsg = "sqlmap got %d results for your " % len(links)
infoMsg += "search dork expression, "
if len(links) == len(kb.targets):
infoMsg += "all "
else:
infoMsg += "%d " % len(kb.targets)
infoMsg += "of them are testable targets"
logger.info(infoMsg)
break
else:
message = "sqlmap got %d results " % len(links)
message += "for your search dork expression, but none of them "
message += "have GET parameters to test for SQL injection. "
2011-06-08 20:08:20 +04:00
message += "Do you want to skip to the next result page? [Y/n]"
2017-04-18 16:48:05 +03:00
if not readInput(message, default='Y', boolean=True):
raise SqlmapSilentQuitException
else:
conf.googlePage += 1
def _setBulkMultipleTargets():
if not conf.bulkFile:
return
2015-01-21 11:26:30 +03:00
conf.bulkFile = safeExpandUser(conf.bulkFile)
infoMsg = "parsing multiple targets list from '%s'" % conf.bulkFile
logger.info(infoMsg)
if not os.path.isfile(conf.bulkFile):
errMsg = "the specified bulk file "
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
2014-07-03 00:27:51 +04:00
found = False
2012-07-17 01:28:01 +04:00
for line in getFileItems(conf.bulkFile):
2017-07-20 03:41:47 +03:00
if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line:
2014-07-03 00:27:51 +04:00
found = True
2015-09-08 12:53:29 +03:00
kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None))
2011-06-08 20:08:20 +04:00
2014-07-03 00:27:51 +04:00
if not found and not conf.forms and not conf.crawlDepth:
warnMsg = "no usable links found (with GET parameters)"
logger.warn(warnMsg)
def _setSitemapTargets():
if not conf.sitemapUrl:
return
infoMsg = "parsing sitemap '%s'" % conf.sitemapUrl
logger.info(infoMsg)
found = False
for item in parseSitemap(conf.sitemapUrl):
if re.match(r"[^ ]+\?(.+)", item, re.I):
found = True
2014-10-22 16:54:49 +04:00
kb.targets.add((item.strip(), None, None, None, None))
2014-07-03 00:27:51 +04:00
if not found and not conf.forms and not conf.crawlDepth:
warnMsg = "no usable links found (with GET parameters)"
logger.warn(warnMsg)
def _findPageForms():
if not conf.forms or conf.crawlDepth:
2010-11-15 15:07:13 +03:00
return
2013-01-09 18:22:21 +04:00
if conf.url and not checkConnection():
2010-11-15 15:07:13 +03:00
return
infoMsg = "searching for forms"
logger.info(infoMsg)
2014-08-01 16:19:32 +04:00
if not any((conf.bulkFile, conf.googleDork, conf.sitemapUrl)):
2017-06-05 17:28:19 +03:00
page, _, _ = Request.queryPage(content=True)
2013-01-09 18:22:21 +04:00
findPageForms(page, conf.url, True, True)
else:
2014-07-03 00:27:51 +04:00
if conf.bulkFile:
targets = getFileItems(conf.bulkFile)
2014-08-01 16:19:32 +04:00
elif conf.sitemapUrl:
2014-07-03 00:27:51 +04:00
targets = parseSitemap(conf.sitemapUrl)
2014-08-01 16:19:32 +04:00
elif conf.googleDork:
targets = [_[0] for _ in kb.targets]
kb.targets.clear()
2013-01-09 19:10:26 +04:00
for i in xrange(len(targets)):
2013-01-09 18:58:13 +04:00
try:
2013-01-09 19:10:26 +04:00
target = targets[i]
2013-01-10 16:18:44 +04:00
page, _, _ = Request.getPage(url=target.strip(), crawling=True, raise404=False)
2013-01-09 18:58:13 +04:00
findPageForms(page, target, False, True)
2013-01-09 19:10:26 +04:00
if conf.verbose in (1, 2):
status = '%d/%d links visited (%d%%)' % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets)))
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True)
2014-08-01 16:19:32 +04:00
except KeyboardInterrupt:
break
2013-01-09 18:58:13 +04:00
except Exception, ex:
2016-01-08 17:33:14 +03:00
errMsg = "problem occurred while searching for forms at '%s' ('%s')" % (target, getSafeExString(ex))
2013-01-09 18:58:13 +04:00
logger.error(errMsg)
def _setDBMSAuthentication():
"""
Check and set the DBMS authentication credentials to run statements as
another user, not the session user
"""
2012-07-24 17:34:50 +04:00
if not conf.dbmsCred:
return
debugMsg = "setting the DBMS authentication credentials"
logger.debug(debugMsg)
2017-10-31 13:38:09 +03:00
match = re.search(r"^(.+?):(.*?)$", conf.dbmsCred)
2012-07-06 19:28:01 +04:00
if not match:
errMsg = "DBMS authentication credentials value must be in format "
errMsg += "username:password"
raise SqlmapSyntaxException(errMsg)
2012-07-06 19:28:01 +04:00
conf.dbmsUsername = match.group(1)
conf.dbmsPassword = match.group(2)
def _setMetasploit():
if not conf.osPwn and not conf.osSmb and not conf.osBof:
return
debugMsg = "setting the takeover out-of-band functionality"
logger.debug(debugMsg)
msfEnvPathExists = False
if IS_WIN:
2013-12-29 19:16:50 +04:00
try:
__import__("win32file")
2013-12-29 19:16:50 +04:00
except ImportError:
errMsg = "sqlmap requires third-party module 'pywin32' "
errMsg += "in order to use Metasploit functionalities on "
errMsg += "Windows. You can download it from "
2017-12-12 15:39:58 +03:00
errMsg += "'https://sourceforge.net/projects/pywin32/files/pywin32/'"
2013-12-29 19:16:50 +04:00
raise SqlmapMissingDependence(errMsg)
2012-07-27 18:29:33 +04:00
if not conf.msfPath:
def _(key, value):
retVal = None
2012-12-17 17:29:19 +04:00
2012-07-27 18:29:33 +04:00
try:
from _winreg import ConnectRegistry, OpenKey, QueryValueEx, HKEY_LOCAL_MACHINE
2012-07-27 18:29:33 +04:00
_ = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
_ = OpenKey(_, key)
2012-07-27 19:05:21 +04:00
retVal = QueryValueEx(_, value)[0]
except:
2012-12-17 17:29:19 +04:00
logger.debug("unable to identify Metasploit installation path via registry key")
2012-07-27 18:29:33 +04:00
return retVal
conf.msfPath = _(r"SOFTWARE\Rapid7\Metasploit", "Location")
2012-07-27 19:05:21 +04:00
if conf.msfPath:
conf.msfPath = os.path.join(conf.msfPath, "msf3")
if conf.osSmb:
2010-10-28 00:39:50 +04:00
isAdmin = runningAsAdmin()
if not isAdmin:
2011-04-30 17:20:05 +04:00
errMsg = "you need to run sqlmap as an administrator "
2010-10-28 00:39:50 +04:00
errMsg += "if you want to perform a SMB relay attack because "
errMsg += "it will need to listen on a user-specified SMB "
errMsg += "TCP port for incoming connection attempts"
raise SqlmapMissingPrivileges(errMsg)
if conf.msfPath:
2012-07-27 18:29:33 +04:00
for path in (conf.msfPath, os.path.join(conf.msfPath, "bin")):
2015-07-23 11:07:21 +03:00
if any(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfcli", "msfconsole")):
2012-07-06 19:34:40 +04:00
msfEnvPathExists = True
2015-06-29 11:05:16 +03:00
if all(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfvenom",)):
2015-07-23 11:07:21 +03:00
kb.oldMsf = False
2015-06-29 11:05:16 +03:00
elif all(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfencode", "msfpayload")):
2015-07-23 11:07:21 +03:00
kb.oldMsf = True
2015-06-29 11:05:16 +03:00
else:
msfEnvPathExists = False
2015-10-07 10:43:25 +03:00
conf.msfPath = path
break
2012-07-06 19:34:40 +04:00
if msfEnvPathExists:
debugMsg = "provided Metasploit Framework path "
debugMsg += "'%s' is valid" % conf.msfPath
logger.debug(debugMsg)
else:
warnMsg = "the provided Metasploit Framework path "
warnMsg += "'%s' is not valid. The cause could " % conf.msfPath
warnMsg += "be that the path does not exists or that one "
warnMsg += "or more of the needed Metasploit executables "
warnMsg += "within msfcli, msfconsole, msfencode and "
warnMsg += "msfpayload do not exist"
logger.warn(warnMsg)
else:
2011-04-30 17:20:05 +04:00
warnMsg = "you did not provide the local path where Metasploit "
warnMsg += "Framework is installed"
logger.warn(warnMsg)
if not msfEnvPathExists:
warnMsg = "sqlmap is going to look for Metasploit Framework "
2013-01-03 01:11:59 +04:00
warnMsg += "installation inside the environment path(s)"
logger.warn(warnMsg)
2012-07-06 19:28:01 +04:00
envPaths = os.environ.get("PATH", "").split(";" if IS_WIN else ":")
for envPath in envPaths:
2011-04-30 17:20:05 +04:00
envPath = envPath.replace(";", "")
2015-10-07 10:43:25 +03:00
if any(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfcli", "msfconsole")):
msfEnvPathExists = True
2015-06-29 11:05:16 +03:00
if all(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfvenom",)):
2015-07-23 11:07:21 +03:00
kb.oldMsf = False
2015-06-29 11:05:16 +03:00
elif all(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfencode", "msfpayload")):
2015-07-23 11:07:21 +03:00
kb.oldMsf = True
2015-06-29 11:05:16 +03:00
else:
msfEnvPathExists = False
2015-06-29 11:05:16 +03:00
if msfEnvPathExists:
infoMsg = "Metasploit Framework has been found "
infoMsg += "installed in the '%s' path" % envPath
logger.info(infoMsg)
conf.msfPath = envPath
break
if not msfEnvPathExists:
errMsg = "unable to locate Metasploit Framework installation. "
2017-12-12 15:39:58 +03:00
errMsg += "You can get it at 'https://www.metasploit.com/download/'"
raise SqlmapFilePathException(errMsg)
def _setWriteFile():
2018-08-28 15:31:20 +03:00
if not conf.fileWrite:
return
debugMsg = "setting the write file functionality"
logger.debug(debugMsg)
2018-08-28 15:31:20 +03:00
if not os.path.exists(conf.fileWrite):
errMsg = "the provided local file '%s' does not exist" % conf.fileWrite
raise SqlmapFilePathException(errMsg)
2018-08-28 15:31:20 +03:00
if not conf.fileDest:
2011-04-30 17:20:05 +04:00
errMsg = "you did not provide the back-end DBMS absolute path "
2018-08-28 15:31:20 +03:00
errMsg += "where you want to write the local file '%s'" % conf.fileWrite
raise SqlmapMissingMandatoryOptionException(errMsg)
2018-08-28 15:31:20 +03:00
conf.fileWriteType = getFileType(conf.fileWrite)
def _setOS():
"""
Force the back-end DBMS operating system option.
"""
if not conf.os:
return
if conf.os.lower() not in SUPPORTED_OS:
errMsg = "you provided an unsupported back-end DBMS operating "
errMsg += "system. The supported DBMS operating systems for OS "
errMsg += "and file system access are %s. " % ', '.join([o.capitalize() for o in SUPPORTED_OS])
errMsg += "If you do not know the back-end DBMS underlying OS, "
errMsg += "do not provide it and sqlmap will fingerprint it for "
errMsg += "you."
raise SqlmapUnsupportedDBMSException(errMsg)
debugMsg = "forcing back-end DBMS operating system to user defined "
debugMsg += "value '%s'" % conf.os
logger.debug(debugMsg)
Backend.setOs(conf.os)
def _setTechnique():
2011-04-07 14:27:22 +04:00
validTechniques = sorted(getPublicTypeMembers(PAYLOAD.TECHNIQUE), key=lambda x: x[1])
2013-01-11 14:13:55 +04:00
validLetters = [_[0][0].upper() for _ in validTechniques]
2011-04-07 14:00:47 +04:00
if conf.tech and isinstance(conf.tech, basestring):
2011-12-02 18:11:43 +04:00
_ = []
2011-04-07 14:07:52 +04:00
2011-04-07 14:37:48 +04:00
for letter in conf.tech.upper():
if letter not in validLetters:
errMsg = "value for --technique must be a string composed "
2011-04-07 14:40:58 +04:00
errMsg += "by the letters %s. Refer to the " % ", ".join(validLetters)
2011-04-07 14:37:48 +04:00
errMsg += "user's manual for details"
raise SqlmapSyntaxException(errMsg)
2011-04-07 14:37:48 +04:00
for validTech, validInt in validTechniques:
if letter == validTech[0]:
2011-12-02 18:11:43 +04:00
_.append(validInt)
2011-04-07 14:37:48 +04:00
break
2011-04-07 14:07:52 +04:00
2011-12-02 18:11:43 +04:00
conf.tech = _
def _setDBMS():
2008-10-15 19:38:22 +04:00
"""
Force the back-end DBMS option.
2008-10-15 19:38:22 +04:00
"""
if not conf.dbms:
return
debugMsg = "forcing back-end DBMS to user defined value"
logger.debug(debugMsg)
conf.dbms = conf.dbms.lower()
2017-10-31 13:38:09 +03:00
regex = re.search(r"%s ([\d\.]+)" % ("(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])), conf.dbms, re.I)
2011-05-10 20:24:09 +04:00
if regex:
conf.dbms = regex.group(1)
Backend.setVersion(regex.group(2))
2008-10-15 19:38:22 +04:00
if conf.dbms not in SUPPORTED_DBMS:
errMsg = "you provided an unsupported back-end database management "
2014-09-04 01:13:57 +04:00
errMsg += "system. Supported DBMSes are as follows: %s. " % ', '.join(sorted(_ for _ in DBMS_DICT))
errMsg += "If you do not know the back-end DBMS, do not provide "
errMsg += "it and sqlmap will fingerprint it for you."
raise SqlmapUnsupportedDBMSException(errMsg)
2008-10-15 19:38:22 +04:00
for dbms, aliases in DBMS_ALIASES:
if conf.dbms in aliases:
conf.dbms = dbms
break
2018-07-31 03:18:33 +03:00
def _listTamperingFunctions():
"""
Lists available tamper functions
"""
if conf.listTampers:
infoMsg = "listing available tamper scripts\n"
logger.info(infoMsg)
for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))):
content = openFile(script, "rb").read()
match = re.search(r'(?s)__priority__.+"""(.+)"""', content)
if match:
comment = match.group(1).strip()
dataToStdout("* %s - %s\n" % (setColor(os.path.basename(script), "yellow"), re.sub(r" *\n *", " ", comment.split("\n\n")[0].strip())))
def _setTamperingFunctions():
2010-10-13 02:45:25 +04:00
"""
Loads tampering functions from given script(s)
2010-10-13 02:45:25 +04:00
"""
2010-10-15 14:36:29 +04:00
if conf.tamper:
last_priority = PRIORITY.HIGHEST
check_priority = True
resolve_priorities = False
priorities = []
2016-09-06 15:25:29 +03:00
for script in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper):
found = False
2010-10-15 14:36:29 +04:00
2017-01-24 20:07:06 +03:00
path = paths.SQLMAP_TAMPER_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
2016-09-06 15:25:29 +03:00
script = script.strip().encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
2010-10-17 01:55:34 +04:00
2017-01-22 01:09:15 +03:00
try:
if not script:
continue
2010-10-15 14:36:29 +04:00
2017-01-24 20:07:06 +03:00
elif os.path.exists(os.path.join(path, script if script.endswith(".py") else "%s.py" % script)):
script = os.path.join(path, script if script.endswith(".py") else "%s.py" % script)
2017-01-22 01:09:15 +03:00
elif not os.path.exists(script):
errMsg = "tamper script '%s' does not exist" % script
raise SqlmapFilePathException(errMsg)
2010-10-15 14:36:29 +04:00
2017-01-22 01:09:15 +03:00
elif not script.endswith(".py"):
errMsg = "tamper script '%s' should have an extension '.py'" % script
raise SqlmapSyntaxException(errMsg)
except UnicodeDecodeError:
errMsg = "invalid character provided in option '--tamper'"
raise SqlmapSyntaxException(errMsg)
2010-10-14 10:00:10 +04:00
2016-09-06 15:25:29 +03:00
dirname, filename = os.path.split(script)
2010-10-13 02:45:25 +04:00
dirname = os.path.abspath(dirname)
2010-10-14 10:00:10 +04:00
2018-04-09 13:14:46 +03:00
infoMsg = "loading tamper module '%s'" % filename[:-3]
2010-10-14 10:00:10 +04:00
logger.info(infoMsg)
2016-09-06 15:25:29 +03:00
if not os.path.exists(os.path.join(dirname, "__init__.py")):
2011-04-30 17:20:05 +04:00
errMsg = "make sure that there is an empty file '__init__.py' "
errMsg += "inside of tamper scripts directory '%s'" % dirname
raise SqlmapGenericException(errMsg)
2010-10-14 10:00:10 +04:00
2010-10-13 02:45:25 +04:00
if dirname not in sys.path:
sys.path.insert(0, dirname)
2010-10-15 14:36:29 +04:00
2010-10-13 02:45:25 +04:00
try:
2017-01-24 20:07:06 +03:00
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
2018-02-06 11:50:36 +03:00
except Exception, ex:
2018-04-09 13:14:46 +03:00
raise SqlmapSyntaxException("cannot import tamper module '%s' (%s)" % (filename[:-3], getSafeExString(ex)))
2010-10-15 14:36:29 +04:00
2016-09-06 15:25:29 +03:00
priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__
2010-10-13 02:45:25 +04:00
for name, function in inspect.getmembers(module, inspect.isfunction):
2014-10-28 15:10:07 +03:00
if name == "tamper" and inspect.getargspec(function).args and inspect.getargspec(function).keywords == "kwargs":
2010-10-13 02:45:25 +04:00
found = True
kb.tamperFunctions.append(function)
2012-11-10 14:01:29 +04:00
function.func_name = module.__name__
if check_priority and priority > last_priority:
2016-05-22 22:44:17 +03:00
message = "it appears that you might have mixed "
2012-11-08 14:09:34 +04:00
message += "the order of tamper scripts. "
message += "Do you want to auto resolve this? [Y/n/q] "
2017-04-19 15:46:27 +03:00
choice = readInput(message, default='Y').upper()
2017-04-18 16:48:05 +03:00
if choice == 'N':
resolve_priorities = False
2017-04-18 16:48:05 +03:00
elif choice == 'Q':
raise SqlmapUserQuitException
2017-04-18 16:48:05 +03:00
else:
resolve_priorities = True
check_priority = False
priorities.append((priority, function))
last_priority = priority
2010-10-15 14:36:29 +04:00
break
elif name == "dependencies":
2018-04-09 13:14:46 +03:00
try:
function()
except Exception, ex:
errMsg = "error occurred while checking dependencies "
errMsg += "for tamper module '%s' ('%s')" % (filename[:-3], getSafeExString(ex))
raise SqlmapGenericException(errMsg)
2010-10-15 14:36:29 +04:00
2010-10-13 02:45:25 +04:00
if not found:
2013-08-30 11:55:57 +04:00
errMsg = "missing function 'tamper(payload, **kwargs)' "
2016-09-06 15:25:29 +03:00
errMsg += "in tamper script '%s'" % script
raise SqlmapGenericException(errMsg)
2010-10-13 02:45:25 +04:00
if kb.tamperFunctions and len(kb.tamperFunctions) > 3:
warnMsg = "using too many tamper scripts is usually not "
warnMsg += "a good idea"
logger.warning(warnMsg)
if resolve_priorities and priorities:
priorities.sort(reverse=True)
kb.tamperFunctions = []
for _, function in priorities:
kb.tamperFunctions.append(function)
def _setWafFunctions():
"""
2018-09-14 11:01:31 +03:00
Loads WAF/IPS detecting functions from script(s)
"""
if conf.identifyWaf:
for found in glob.glob(os.path.join(paths.SQLMAP_WAF_PATH, "*.py")):
dirname, filename = os.path.split(found)
dirname = os.path.abspath(dirname)
if filename == "__init__.py":
continue
debugMsg = "loading WAF script '%s'" % filename[:-3]
logger.debug(debugMsg)
if dirname not in sys.path:
sys.path.insert(0, dirname)
try:
if filename[:-3] in sys.modules:
del sys.modules[filename[:-3]]
2017-01-24 20:07:06 +03:00
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except ImportError, msg:
raise SqlmapSyntaxException("cannot import WAF script '%s' (%s)" % (filename[:-3], msg))
_ = dict(inspect.getmembers(module))
if "detect" not in _:
2014-09-29 16:07:59 +04:00
errMsg = "missing function 'detect(get_page)' "
errMsg += "in WAF script '%s'" % found
raise SqlmapGenericException(errMsg)
else:
2013-02-21 17:39:22 +04:00
kb.wafFunctions.append((_["detect"], _.get("__product__", filename[:-3])))
kb.wafFunctions = sorted(kb.wafFunctions, key=lambda _: "generic" in _[1].lower())
def _setThreads():
if not isinstance(conf.threads, int) or conf.threads <= 0:
2008-10-15 19:38:22 +04:00
conf.threads = 1
def _setDNSCache():
2011-04-08 01:39:18 +04:00
"""
Makes a cached version of socket._getaddrinfo to avoid subsequent DNS requests.
"""
def _getaddrinfo(*args, **kwargs):
2016-09-09 12:06:38 +03:00
if args in kb.cache.addrinfo:
return kb.cache.addrinfo[args]
2011-06-17 19:23:58 +04:00
2011-04-08 01:39:18 +04:00
else:
2016-09-09 12:06:38 +03:00
kb.cache.addrinfo[args] = socket._getaddrinfo(*args, **kwargs)
return kb.cache.addrinfo[args]
2011-04-08 01:39:18 +04:00
2015-11-17 01:46:10 +03:00
if not hasattr(socket, "_getaddrinfo"):
2011-04-08 01:39:18 +04:00
socket._getaddrinfo = socket.getaddrinfo
socket.getaddrinfo = _getaddrinfo
2015-11-17 01:46:10 +03:00
def _setSocketPreConnect():
"""
Makes a pre-connect version of socket.connect
"""
if conf.disablePrecon:
return
2018-01-31 13:13:08 +03:00
def _thread():
2016-10-17 13:33:07 +03:00
while kb.get("threadContinue") and not conf.get("disablePrecon"):
2015-11-17 03:38:43 +03:00
try:
2015-11-20 18:52:59 +03:00
for key in socket._ready:
if len(socket._ready[key]) < SOCKET_PRE_CONNECT_QUEUE_SIZE:
family, type, proto, address = key
s = socket.socket(family, type, proto)
2015-11-17 03:38:43 +03:00
s._connect(address)
2018-12-17 16:19:59 +03:00
try:
if type == socket.SOCK_STREAM:
# Reference: https://www.techrepublic.com/article/tcp-ip-options-for-high-performance-data-transmission/
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except:
pass
2015-11-17 04:35:53 +03:00
with kb.locks.socket:
socket._ready[key].append((s._sock, time.time()))
2016-01-11 02:08:38 +03:00
except KeyboardInterrupt:
break
2016-01-25 00:05:08 +03:00
except:
pass
2015-11-17 03:38:43 +03:00
finally:
time.sleep(0.01)
2015-11-17 01:46:10 +03:00
def connect(self, address):
found = False
2016-01-11 02:34:03 +03:00
2015-11-20 18:52:59 +03:00
key = (self.family, self.type, self.proto, address)
2015-11-17 01:46:10 +03:00
with kb.locks.socket:
2015-11-20 18:52:59 +03:00
if key not in socket._ready:
socket._ready[key] = []
while len(socket._ready[key]) > 0:
candidate, created = socket._ready[key].pop(0)
if (time.time() - created) < PRECONNECT_CANDIDATE_TIMEOUT:
self._sock = candidate
found = True
break
else:
try:
2018-01-31 13:13:08 +03:00
candidate.shutdown(socket.SHUT_RDWR)
candidate.close()
except socket.error:
pass
2016-01-11 02:34:03 +03:00
2015-11-17 01:46:10 +03:00
if not found:
self._connect(address)
2015-11-22 17:33:00 +03:00
if not hasattr(socket.socket, "_connect"):
2015-11-17 01:46:10 +03:00
socket._ready = {}
socket.socket._connect = socket.socket.connect
socket.socket.connect = connect
2018-01-31 13:13:08 +03:00
thread = threading.Thread(target=_thread)
2016-05-16 16:37:49 +03:00
setDaemon(thread)
2015-11-17 01:46:10 +03:00
thread.start()
def _setHTTPHandlers():
2008-10-15 19:38:22 +04:00
"""
2013-01-29 19:04:20 +04:00
Check and set the HTTP/SOCKS proxy for all HTTP requests.
2008-10-15 19:38:22 +04:00
"""
2013-11-13 18:34:19 +04:00
global proxyHandler
2008-10-15 19:38:22 +04:00
2014-03-18 19:41:05 +04:00
for _ in ("http", "https"):
if hasattr(proxyHandler, "%s_open" % _):
delattr(proxyHandler, "%s_open" % _)
if conf.proxyList is not None:
if not conf.proxyList:
2015-09-26 00:41:47 +03:00
errMsg = "list of usable proxies is exhausted"
raise SqlmapNoneDataException(errMsg)
conf.proxy = conf.proxyList[0]
conf.proxyList = conf.proxyList[1:]
infoMsg = "loading proxy '%s' from a supplied proxy list file" % conf.proxy
logger.info(infoMsg)
elif not conf.proxy:
if conf.hostname in ("localhost", "127.0.0.1") or conf.ignoreProxy:
proxyHandler.proxies = {}
if conf.proxy:
debugMsg = "setting the HTTP/SOCKS proxy for all HTTP requests"
logger.debug(debugMsg)
2014-12-30 11:48:50 +03:00
try:
_ = urlparse.urlsplit(conf.proxy)
except Exception, ex:
2016-01-12 12:27:04 +03:00
errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex))
2018-03-13 13:13:38 +03:00
raise SqlmapSyntaxException(errMsg)
2008-10-15 19:38:22 +04:00
hostnamePort = _.netloc.split(":")
2008-10-15 19:38:22 +04:00
scheme = _.scheme.upper()
hostname = hostnamePort[0]
port = None
username = None
password = None
2008-10-15 19:38:22 +04:00
if len(hostnamePort) == 2:
try:
port = int(hostnamePort[1])
except:
pass # drops into the next check block
2008-10-15 19:38:22 +04:00
if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)):
errMsg = "proxy value must be in format '(%s)://address:port'" % "|".join(_[0].lower() for _ in getPublicTypeMembers(PROXY_TYPE))
raise SqlmapSyntaxException(errMsg)
if conf.proxyCred:
2017-10-31 13:38:09 +03:00
_ = re.search(r"\A(.*?):(.*?)\Z", conf.proxyCred)
if not _:
errMsg = "proxy authentication credentials "
errMsg += "value must be in format username:password"
raise SqlmapSyntaxException(errMsg)
else:
username = _.group(1)
password = _.group(2)
2013-08-12 16:25:51 +04:00
if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5):
proxyHandler.proxies = {}
2013-08-12 16:25:51 +04:00
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if scheme == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, hostname, port, username=username, password=password)
socks.wrapmodule(urllib2)
2012-07-16 14:12:52 +04:00
else:
socks.unwrapmodule(urllib2)
if conf.proxyCred:
# Reference: http://stackoverflow.com/questions/34079/how-to-specify-an-authenticated-proxy-for-a-python-http-connection
proxyString = "%s@" % conf.proxyCred
else:
proxyString = ""
2012-07-16 14:12:52 +04:00
proxyString += "%s:%d" % (hostname, port)
proxyHandler.proxies = {"http": proxyString, "https": proxyString}
2013-08-12 16:25:51 +04:00
proxyHandler.__init__(proxyHandler.proxies)
2008-10-15 19:38:22 +04:00
debugMsg = "creating HTTP requests opener object"
logger.debug(debugMsg)
2016-09-02 15:14:17 +03:00
handlers = filter(None, [multipartPostHandler, proxyHandler if proxyHandler.proxies else None, authHandler, redirectHandler, rangeHandler, httpsHandler])
if not conf.dropSetCookie:
if not conf.loadCookies:
conf.cj = cookielib.CookieJar()
else:
conf.cj = cookielib.MozillaCookieJar()
resetCookieJar(conf.cj)
handlers.append(urllib2.HTTPCookieProcessor(conf.cj))
# Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html
if conf.keepAlive:
warnMsg = "persistent HTTP(s) connections, Keep-Alive, has "
warnMsg += "been disabled because of its incompatibility "
if conf.proxy:
warnMsg += "with HTTP(s) proxy"
logger.warn(warnMsg)
elif conf.authType:
warnMsg += "with authentication methods"
logger.warn(warnMsg)
else:
handlers.append(keepAliveHandler)
opener = urllib2.build_opener(*handlers)
urllib2.install_opener(opener)
2015-04-22 17:28:54 +03:00
def _setSafeVisit():
"""
2015-04-22 17:28:54 +03:00
Check and set the safe visit options.
"""
2016-10-17 13:36:42 +03:00
if not any((conf.safeUrl, conf.safeReqFile)):
return
2015-04-22 17:28:54 +03:00
if conf.safeReqFile:
checkFile(conf.safeReqFile)
raw = readCachedFileContent(conf.safeReqFile)
match = re.search(r"\A([A-Z]+) ([^ ]+) HTTP/[0-9.]+\Z", raw[:raw.find('\n')])
if match:
kb.safeReq.method = match.group(1)
kb.safeReq.url = match.group(2)
kb.safeReq.headers = {}
for line in raw[raw.find('\n') + 1:].split('\n'):
line = line.strip()
if line and ':' in line:
key, value = line.split(':', 1)
value = value.strip()
kb.safeReq.headers[key] = value
2018-11-28 02:29:17 +03:00
if key.upper() == HTTP_HEADER.HOST.upper():
2015-04-22 17:28:54 +03:00
if not value.startswith("http"):
scheme = "http"
if value.endswith(":443"):
scheme = "https"
value = "%s://%s" % (scheme, value)
kb.safeReq.url = urlparse.urljoin(value, kb.safeReq.url)
else:
break
post = None
if '\r\n\r\n' in raw:
post = raw[raw.find('\r\n\r\n') + 4:]
elif '\n\n' in raw:
post = raw[raw.find('\n\n') + 2:]
if post and post.strip():
kb.safeReq.post = post
else:
kb.safeReq.post = None
else:
2015-04-22 17:28:54 +03:00
errMsg = "invalid format of a safe request file"
2018-03-13 13:13:38 +03:00
raise SqlmapSyntaxException(errMsg)
2015-04-22 17:28:54 +03:00
else:
2017-10-31 13:38:09 +03:00
if not re.search(r"\Ahttp[s]*://", conf.safeUrl):
2015-04-22 17:28:54 +03:00
if ":443/" in conf.safeUrl:
conf.safeUrl = "https://" + conf.safeUrl
else:
conf.safeUrl = "http://" + conf.safeUrl
2015-04-21 01:02:47 +03:00
if conf.safeFreq <= 0:
2015-04-22 17:28:54 +03:00
errMsg = "please provide a valid value (>0) for safe frequency (--safe-freq) while using safe visit features"
raise SqlmapSyntaxException(errMsg)
def _setPrefixSuffix():
if conf.prefix is not None and conf.suffix is not None:
# Create a custom boundary object for user's supplied prefix
# and suffix
2011-07-08 10:02:31 +04:00
boundary = AttribDict()
boundary.level = 1
2013-01-10 14:54:07 +04:00
boundary.clause = [0]
boundary.where = [1, 2, 3]
boundary.prefix = conf.prefix
boundary.suffix = conf.suffix
if " like" in boundary.suffix.lower():
if "'" in boundary.suffix.lower():
boundary.ptype = 3
elif '"' in boundary.suffix.lower():
boundary.ptype = 5
elif "'" in boundary.suffix:
boundary.ptype = 2
elif '"' in boundary.suffix:
boundary.ptype = 4
else:
boundary.ptype = 1
# user who provides --prefix/--suffix does not want other boundaries
# to be tested for
2013-01-10 14:54:07 +04:00
conf.boundaries = [boundary]
def _setAuthCred():
2012-07-31 15:06:45 +04:00
"""
Adds authentication credentials (if any) for current target to the password manager
(used by connection handler)
"""
if kb.passwordMgr and all(_ is not None for _ in (conf.scheme, conf.hostname, conf.port, conf.authUsername, conf.authPassword)):
2014-03-15 01:20:20 +04:00
kb.passwordMgr.add_password(None, "%s://%s:%d" % (conf.scheme, conf.hostname, conf.port), conf.authUsername, conf.authPassword)
2012-07-31 15:06:45 +04:00
def _setHTTPAuthentication():
2008-10-15 19:38:22 +04:00
"""
Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or PKI),
username and password for first three methods, or PEM private key file for
PKI authentication
2008-10-15 19:38:22 +04:00
"""
global authHandler
2015-09-27 16:59:17 +03:00
if not conf.authType and not conf.authCred and not conf.authFile:
2008-10-15 19:38:22 +04:00
return
2015-09-27 16:59:17 +03:00
if conf.authFile and not conf.authType:
2014-12-13 15:48:50 +03:00
conf.authType = AUTH_TYPE.PKI
2015-09-27 16:59:17 +03:00
elif conf.authType and not conf.authCred and not conf.authFile:
2011-04-30 17:20:05 +04:00
errMsg = "you specified the HTTP authentication type, but "
2008-10-15 19:38:22 +04:00
errMsg += "did not provide the credentials"
raise SqlmapSyntaxException(errMsg)
2008-10-15 19:38:22 +04:00
2013-08-09 16:13:48 +04:00
elif not conf.authType and conf.authCred:
2011-04-30 17:20:05 +04:00
errMsg = "you specified the HTTP authentication credentials, "
2008-10-15 19:38:22 +04:00
errMsg += "but did not provide the type"
raise SqlmapSyntaxException(errMsg)
2008-10-15 19:38:22 +04:00
2014-12-13 15:48:50 +03:00
elif (conf.authType or "").lower() not in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST, AUTH_TYPE.NTLM, AUTH_TYPE.PKI):
2013-09-12 01:22:10 +04:00
errMsg = "HTTP authentication type value must be "
errMsg += "Basic, Digest, NTLM or PKI"
raise SqlmapSyntaxException(errMsg)
2015-09-27 16:59:17 +03:00
if not conf.authFile:
2010-01-07 15:59:09 +03:00
debugMsg = "setting the HTTP authentication type and credentials"
logger.debug(debugMsg)
2016-12-20 01:47:39 +03:00
authType = conf.authType.lower()
2016-12-20 01:47:39 +03:00
if authType in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST):
regExp = "^(.*?):(.*?)$"
2016-12-20 01:47:39 +03:00
errMsg = "HTTP %s authentication credentials " % authType
2013-05-20 01:00:40 +04:00
errMsg += "value must be in format 'username:password'"
2016-12-20 01:47:39 +03:00
elif authType == AUTH_TYPE.NTLM:
regExp = "^(.*\\\\.*):(.*?)$"
2011-04-30 17:20:05 +04:00
errMsg = "HTTP NTLM authentication credentials value must "
2013-05-20 01:00:40 +04:00
errMsg += "be in format 'DOMAIN\username:password'"
2016-12-20 01:47:39 +03:00
elif authType == AUTH_TYPE.PKI:
errMsg = "HTTP PKI authentication require "
errMsg += "usage of option `--auth-pki`"
2013-05-20 01:00:40 +04:00
raise SqlmapSyntaxException(errMsg)
2013-08-09 16:13:48 +04:00
aCredRegExp = re.search(regExp, conf.authCred)
2010-01-07 15:59:09 +03:00
if not aCredRegExp:
raise SqlmapSyntaxException(errMsg)
conf.authUsername = aCredRegExp.group(1)
conf.authPassword = aCredRegExp.group(2)
kb.passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
_setAuthCred()
2012-07-31 15:06:45 +04:00
2016-12-20 01:47:39 +03:00
if authType == AUTH_TYPE.BASIC:
authHandler = SmartHTTPBasicAuthHandler(kb.passwordMgr)
2016-12-20 01:47:39 +03:00
elif authType == AUTH_TYPE.DIGEST:
authHandler = urllib2.HTTPDigestAuthHandler(kb.passwordMgr)
2016-12-20 01:47:39 +03:00
elif authType == AUTH_TYPE.NTLM:
2010-01-07 15:59:09 +03:00
try:
from ntlm import HTTPNtlmAuthHandler
2012-02-22 14:45:10 +04:00
except ImportError:
2011-04-30 17:20:05 +04:00
errMsg = "sqlmap requires Python NTLM third-party library "
2010-01-07 15:59:09 +03:00
errMsg += "in order to authenticate via NTLM, "
2017-12-12 15:39:58 +03:00
errMsg += "https://github.com/mullender/python-ntlm"
raise SqlmapMissingDependence(errMsg)
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr)
2010-01-07 15:59:09 +03:00
else:
debugMsg = "setting the HTTP(s) authentication PEM private key"
2010-01-07 15:59:09 +03:00
logger.debug(debugMsg)
2015-09-27 16:59:17 +03:00
_ = safeExpandUser(conf.authFile)
2015-01-21 11:12:12 +03:00
checkFile(_)
authHandler = HTTPSPKIAuthHandler(_)
2009-12-03 01:54:39 +03:00
def _setHTTPExtraHeaders():
if conf.headers:
debugMsg = "setting extra HTTP headers"
logger.debug(debugMsg)
2012-01-07 19:26:54 +04:00
conf.headers = conf.headers.split("\n") if "\n" in conf.headers else conf.headers.split("\\n")
for headerValue in conf.headers:
2015-07-07 10:24:16 +03:00
if not headerValue.strip():
continue
2013-05-30 13:42:27 +04:00
if headerValue.count(':') >= 1:
header, value = (_.lstrip() for _ in headerValue.split(":", 1))
2012-01-07 18:54:56 +04:00
if header and value:
conf.httpHeaders.append((header, value))
2012-04-23 14:11:00 +04:00
else:
2012-04-23 14:15:04 +04:00
errMsg = "invalid header value: %s. Valid header format is 'name:value'" % repr(headerValue).lstrip('u')
raise SqlmapSyntaxException(errMsg)
2011-04-17 12:33:46 +04:00
2015-12-03 03:43:37 +03:00
elif not conf.requestFile and len(conf.httpHeaders or []) < 2:
if conf.encoding:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.encoding))
2011-04-17 12:48:13 +04:00
# Invalidating any caching mechanism in between
# Reference: http://stackoverflow.com/a/1383359
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache"))
2011-04-17 12:33:46 +04:00
def _setHTTPUserAgent():
2008-10-15 19:38:22 +04:00
"""
Set the HTTP User-Agent header.
Depending on the user options it can be:
* The default sqlmap string
* A default value read as user option
* A random value read from a list of User-Agent headers from a
file choosed as user option
"""
2010-11-07 11:13:20 +03:00
2011-04-29 23:27:23 +04:00
if conf.mobile:
message = "which smartphone do you want sqlmap to imitate "
message += "through HTTP User-Agent header?\n"
2011-04-29 23:27:23 +04:00
items = sorted(getPublicTypeMembers(MOBILES, True))
for count in xrange(len(items)):
item = items[count]
2012-10-30 13:30:22 +04:00
message += "[%d] %s%s\n" % (count + 1, item[0], " (default)" if item == MOBILES.IPHONE else "")
2011-04-29 23:27:23 +04:00
test = readInput(message.rstrip('\n'), default=items.index(MOBILES.IPHONE) + 1)
2011-04-29 23:27:23 +04:00
try:
item = items[int(test) - 1]
except:
item = MOBILES.IPHONE
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, item[1]))
2011-04-29 23:27:23 +04:00
elif conf.agent:
2008-10-15 19:38:22 +04:00
debugMsg = "setting the HTTP User-Agent header"
logger.debug(debugMsg)
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, conf.agent))
2008-10-15 19:38:22 +04:00
2011-04-29 23:27:23 +04:00
elif not conf.randomAgent:
2012-06-28 15:55:30 +04:00
_ = True
for header, _ in conf.httpHeaders:
2018-11-28 02:29:17 +03:00
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
2012-06-28 15:55:30 +04:00
_ = False
break
2012-06-28 15:55:30 +04:00
if _:
2018-11-29 02:09:05 +03:00
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
else:
2011-04-30 11:01:21 +04:00
if not kb.userAgents:
2011-04-30 17:20:05 +04:00
debugMsg = "loading random HTTP User-Agent header(s) from "
2011-04-30 11:01:21 +04:00
debugMsg += "file '%s'" % paths.USER_AGENTS
logger.debug(debugMsg)
2008-10-15 19:38:22 +04:00
2011-04-30 11:01:21 +04:00
try:
kb.userAgents = getFileItems(paths.USER_AGENTS)
except IOError:
2011-04-30 17:20:05 +04:00
warnMsg = "unable to read HTTP User-Agent header "
2011-04-30 11:01:21 +04:00
warnMsg += "file '%s'" % paths.USER_AGENTS
logger.warn(warnMsg)
2018-11-29 02:09:05 +03:00
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
2011-04-30 11:01:21 +04:00
return
2008-10-15 19:38:22 +04:00
2018-11-29 02:09:05 +03:00
userAgent = random.sample(kb.userAgents or [DEFAULT_USER_AGENT], 1)[0]
2011-04-29 23:27:23 +04:00
2017-12-04 16:22:51 +03:00
infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent
infoMsg += "file '%s'" % paths.USER_AGENTS
2011-04-30 19:29:59 +04:00
logger.info(infoMsg)
2014-08-20 23:07:19 +04:00
2014-06-30 21:27:14 +04:00
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, userAgent))
2008-10-15 19:38:22 +04:00
def _setHTTPReferer():
2008-10-15 19:38:22 +04:00
"""
Set the HTTP Referer
"""
if conf.referer:
debugMsg = "setting the HTTP Referer header"
logger.debug(debugMsg)
conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.referer))
2008-10-15 19:38:22 +04:00
2015-03-20 02:56:36 +03:00
def _setHTTPHost():
"""
Set the HTTP Host
"""
if conf.host:
debugMsg = "setting the HTTP Host header"
logger.debug(debugMsg)
conf.httpHeaders.append((HTTP_HEADER.HOST, conf.host))
def _setHTTPCookies():
2008-10-15 19:38:22 +04:00
"""
Set the HTTP Cookie header
"""
if conf.cookie:
debugMsg = "setting the HTTP Cookie header"
logger.debug(debugMsg)
conf.httpHeaders.append((HTTP_HEADER.COOKIE, conf.cookie))
2008-10-15 19:38:22 +04:00
2018-10-27 15:30:28 +03:00
def _setHostname():
"""
Set value conf.hostname
"""
if conf.url:
2018-12-04 01:18:52 +03:00
try:
conf.hostname = urlparse.urlsplit(conf.url).netloc.split(':')[0]
except ValueError, ex:
errMsg = "problem occurred while "
errMsg += "parsing an URL '%s' ('%s')" % (conf.url, getSafeExString(ex))
raise SqlmapDataException(errMsg)
2018-10-27 15:30:28 +03:00
def _setHTTPTimeout():
"""
Set the HTTP timeout
"""
if conf.timeout:
debugMsg = "setting the HTTP timeout"
logger.debug(debugMsg)
conf.timeout = float(conf.timeout)
if conf.timeout < 3.0:
2011-04-30 17:20:05 +04:00
warnMsg = "the minimum HTTP timeout is 3 seconds, sqlmap "
warnMsg += "will going to reset it"
logger.warn(warnMsg)
conf.timeout = 3.0
else:
conf.timeout = 30.0
socket.setdefaulttimeout(conf.timeout)
def _checkDependencies():
"""
Checks for missing dependencies.
"""
if conf.dependencies:
checkDependencies()
2015-01-13 12:33:51 +03:00
def _createTemporaryDirectory():
"""
Creates temporary directory for this run.
"""
2016-05-31 15:55:56 +03:00
if conf.tmpDir:
try:
if not os.path.isdir(conf.tmpDir):
os.makedirs(conf.tmpDir)
_ = os.path.join(conf.tmpDir, randomStr())
2016-09-23 16:41:12 +03:00
2016-05-31 15:55:56 +03:00
open(_, "w+b").close()
os.remove(_)
tempfile.tempdir = conf.tmpDir
warnMsg = "using '%s' as the temporary directory" % conf.tmpDir
logger.warn(warnMsg)
except (OSError, IOError), ex:
errMsg = "there has been a problem while accessing "
errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex)
2018-03-13 13:13:38 +03:00
raise SqlmapSystemException(errMsg)
2016-05-31 15:55:56 +03:00
else:
try:
if not os.path.isdir(tempfile.gettempdir()):
os.makedirs(tempfile.gettempdir())
2018-06-29 17:33:17 +03:00
except Exception, ex:
2016-09-23 16:41:12 +03:00
warnMsg = "there has been a problem while accessing "
warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex)
warnMsg += "make sure that there is enough disk space left. If problem persists, "
warnMsg += "try to set environment variable 'TEMP' to a location "
warnMsg += "writeable by the current user"
logger.warn(warnMsg)
2016-05-31 15:55:56 +03:00
if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir:
2016-09-23 16:41:12 +03:00
try:
tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid()))
2018-06-29 17:34:16 +03:00
except:
2016-09-23 16:41:12 +03:00
tempfile.tempdir = os.path.join(paths.SQLMAP_HOME_PATH, "tmp", "sqlmap%s%d" % (randomStr(6), os.getpid()))
2015-01-28 02:52:40 +03:00
kb.tempDir = tempfile.tempdir
2015-01-13 12:33:51 +03:00
if not os.path.isdir(tempfile.tempdir):
2016-10-01 22:02:40 +03:00
try:
os.makedirs(tempfile.tempdir)
2018-06-29 17:34:16 +03:00
except Exception, ex:
2016-10-01 22:02:40 +03:00
errMsg = "there has been a problem while setting "
errMsg += "temporary directory location ('%s')" % getSafeExString(ex)
2018-03-13 13:13:38 +03:00
raise SqlmapSystemException(errMsg)
2015-01-13 12:33:51 +03:00
def _cleanupOptions():
2008-10-15 19:38:22 +04:00
"""
Cleanup configuration attributes.
"""
debugMsg = "cleaning up configuration parameters"
logger.debug(debugMsg)
2010-05-28 19:57:43 +04:00
width = getConsoleWidth()
if conf.eta:
2012-12-10 20:20:04 +04:00
conf.progressWidth = width - 26
2010-05-28 19:57:43 +04:00
else:
2012-12-10 20:20:04 +04:00
conf.progressWidth = width - 46
2010-05-28 19:57:43 +04:00
2013-07-29 22:42:29 +04:00
for key, value in conf.items():
2015-12-05 02:52:58 +03:00
if value and any(key.endswith(_) for _ in ("Path", "File", "Dir")):
2015-01-21 11:26:30 +03:00
conf[key] = safeExpandUser(value)
2013-07-29 22:42:29 +04:00
2008-10-15 19:38:22 +04:00
if conf.testParameter:
conf.testParameter = urldecode(conf.testParameter)
2008-10-15 19:38:22 +04:00
conf.testParameter = conf.testParameter.replace(" ", "")
2011-08-29 17:08:25 +04:00
conf.testParameter = re.split(PARAMETER_SPLITTING_REGEX, conf.testParameter)
2008-10-15 19:38:22 +04:00
else:
conf.testParameter = []
2016-05-25 16:43:39 +03:00
if conf.agent:
2016-06-03 03:02:11 +03:00
conf.agent = re.sub(r"[\r\n]", "", conf.agent)
2016-05-25 16:43:39 +03:00
2008-10-15 19:38:22 +04:00
if conf.user:
conf.user = conf.user.replace(" ", "")
2011-08-29 17:08:25 +04:00
if conf.rParam:
conf.rParam = conf.rParam.replace(" ", "")
conf.rParam = re.split(PARAMETER_SPLITTING_REGEX, conf.rParam)
else:
conf.rParam = []
2014-04-06 18:48:46 +04:00
if conf.paramDel and '\\' in conf.paramDel:
2018-02-21 13:47:01 +03:00
try:
conf.paramDel = conf.paramDel.decode("string_escape")
except ValueError:
pass
2013-05-30 14:01:13 +04:00
2011-08-29 17:29:42 +04:00
if conf.skip:
conf.skip = conf.skip.replace(" ", "")
conf.skip = re.split(PARAMETER_SPLITTING_REGEX, conf.skip)
else:
conf.skip = []
2015-08-28 16:30:28 +03:00
if conf.cookie:
conf.cookie = re.sub(r"[\r\n]", "", conf.cookie)
if conf.delay:
conf.delay = float(conf.delay)
2017-12-04 16:22:51 +03:00
if conf.url:
conf.url = conf.url.strip()
if not re.search(r"\A\w+://", conf.url):
conf.url = "http://%s" % conf.url
2017-12-04 16:22:51 +03:00
2018-08-28 15:31:20 +03:00
if conf.fileRead:
conf.fileRead = ntToPosixSlashes(normalizePath(conf.fileRead))
2018-08-28 15:31:20 +03:00
if conf.fileWrite:
conf.fileWrite = ntToPosixSlashes(normalizePath(conf.fileWrite))
2018-08-28 15:31:20 +03:00
if conf.fileDest:
conf.fileDest = ntToPosixSlashes(normalizePath(conf.fileDest))
2014-07-03 00:27:51 +04:00
if conf.sitemapUrl and not conf.sitemapUrl.lower().startswith("http"):
conf.sitemapUrl = "http%s://%s" % ('s' if conf.forceSSL else '', conf.sitemapUrl)
if conf.msfPath:
conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath))
if conf.tmpPath:
conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath))
2014-07-03 00:27:51 +04:00
if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.forms, conf.crawlDepth)):
conf.multipleTargets = True
2010-10-12 23:41:29 +04:00
if conf.optimize:
setOptimize()
2010-10-12 23:41:29 +04:00
if conf.os:
conf.os = conf.os.capitalize()
if conf.forceDbms:
conf.dbms = conf.forceDbms
if conf.dbms:
2017-08-28 14:02:08 +03:00
kb.dbmsFilter = []
for _ in conf.dbms.split(','):
for dbms, aliases in DBMS_ALIASES:
if _.strip().lower() in aliases:
kb.dbmsFilter.append(dbms)
conf.dbms = dbms if conf.dbms and ',' not in conf.dbms else None
break
2012-07-24 17:43:29 +04:00
if conf.testFilter:
2014-09-01 17:48:00 +04:00
conf.testFilter = conf.testFilter.strip('*+')
2018-06-10 00:38:00 +03:00
conf.testFilter = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testFilter)
2016-05-04 14:23:59 +03:00
try:
re.compile(conf.testFilter)
except re.error:
conf.testFilter = re.escape(conf.testFilter)
2018-12-10 16:53:11 +03:00
if conf.csrfToken:
original = conf.csrfToken
try:
re.compile(conf.csrfToken)
if re.escape(conf.csrfToken) != conf.csrfToken:
message = "provided value for option '--csrf-token' is a regular expression? [Y/n] "
if not readInput(message, default='Y', boolean=True):
conf.csrfToken = re.escape(conf.csrfToken)
except re.error:
conf.csrfToken = re.escape(conf.csrfToken)
finally:
class _(unicode):
pass
conf.csrfToken = _(conf.csrfToken)
conf.csrfToken._original = original
2015-10-01 12:57:33 +03:00
if conf.testSkip:
conf.testSkip = conf.testSkip.strip('*+')
2018-06-10 00:38:00 +03:00
conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip)
2015-10-01 12:57:33 +03:00
2016-05-04 14:23:59 +03:00
try:
re.compile(conf.testSkip)
except re.error:
conf.testSkip = re.escape(conf.testSkip)
2013-01-29 18:55:50 +04:00
if "timeSec" not in kb.explicitSettings:
if conf.tor:
conf.timeSec = 2 * conf.timeSec
2012-10-09 17:19:47 +04:00
kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE
2011-04-30 17:20:05 +04:00
warnMsg = "increasing default value for "
2012-07-13 17:00:39 +04:00
warnMsg += "option '--time-sec' to %d because " % conf.timeSec
2012-02-01 18:49:42 +04:00
warnMsg += "switch '--tor' was provided"
logger.warn(warnMsg)
2011-04-18 18:46:18 +04:00
else:
2012-10-09 17:19:47 +04:00
kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE
2013-03-04 21:05:40 +04:00
if conf.retries:
conf.retries = min(conf.retries, MAX_CONNECT_RETRIES)
if conf.code:
conf.code = int(conf.code)
2011-11-30 23:26:03 +04:00
if conf.csvDel:
2013-01-10 16:18:44 +04:00
conf.csvDel = conf.csvDel.decode("string_escape") # e.g. '\\t' -> '\t'
2011-11-30 23:26:03 +04:00
2013-07-11 12:11:43 +04:00
if conf.torPort and isinstance(conf.torPort, basestring) and conf.torPort.isdigit():
2011-12-23 14:57:09 +04:00
conf.torPort = int(conf.torPort)
2011-12-16 03:19:55 +04:00
if conf.torType:
conf.torType = conf.torType.upper()
2014-04-06 18:54:46 +04:00
if conf.outputDir:
2016-01-14 01:05:28 +03:00
paths.SQLMAP_OUTPUT_PATH = os.path.realpath(os.path.expanduser(conf.outputDir))
2016-08-02 01:17:59 +03:00
setPaths(paths.SQLMAP_ROOT_PATH)
2012-07-03 02:50:23 +04:00
if conf.string:
2012-10-18 13:11:20 +04:00
try:
conf.string = conf.string.decode("unicode_escape")
except:
charset = string.whitespace.replace(" ", "")
for _ in charset:
conf.string = conf.string.replace(_.encode("string_escape"), _)
2012-10-05 12:24:09 +04:00
if conf.getAll:
2017-10-29 00:27:19 +03:00
map(lambda _: conf.__setitem__(_, True), WIZARD.ALL)
2012-10-05 12:24:09 +04:00
if conf.noCast:
for _ in DUMP_REPLACEMENTS.keys():
del DUMP_REPLACEMENTS[_]
2012-11-28 13:58:18 +04:00
if conf.dumpFormat:
conf.dumpFormat = conf.dumpFormat.upper()
if conf.torType:
conf.torType = conf.torType.upper()
if conf.col:
2017-04-18 16:56:24 +03:00
conf.col = re.sub(r"\s*,\s*", ',', conf.col)
2018-02-13 17:53:50 +03:00
if conf.exclude:
conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude)
if conf.binaryFields:
2017-04-18 16:56:24 +03:00
conf.binaryFields = re.sub(r"\s*,\s*", ',', conf.binaryFields)
if any((conf.proxy, conf.proxyFile, conf.tor)):
conf.disablePrecon = True
2018-06-21 00:21:55 +03:00
if conf.dummy:
conf.batch = True
2011-11-23 18:26:40 +04:00
threadData = getCurrentThreadData()
threadData.reset()
2016-10-17 13:33:07 +03:00
def _cleanupEnvironment():
"""
Cleanup environment (e.g. from leftovers after --sqlmap-shell).
"""
if issubclass(urllib2.socket.socket, socks.socksocket):
socks.unwrapmodule(urllib2)
if hasattr(socket, "_ready"):
socket._ready.clear()
def _purge():
2012-04-23 18:24:23 +04:00
"""
Safely removes (purges) sqlmap data directory.
2012-04-23 18:24:23 +04:00
"""
if conf.purge:
purge(paths.SQLMAP_HOME_PATH)
2012-04-23 18:24:23 +04:00
def _setConfAttributes():
2008-10-15 19:38:22 +04:00
"""
This function set some needed attributes into the configuration
singleton.
"""
debugMsg = "initializing the configuration"
logger.debug(debugMsg)
conf.authUsername = None
conf.authPassword = None
2011-04-30 17:20:05 +04:00
conf.boundaries = []
conf.cj = None
conf.dbmsConnector = None
conf.dbmsHandler = None
conf.dnsServer = None
2011-04-30 17:20:05 +04:00
conf.dumpPath = None
conf.hashDB = None
conf.hashDBFile = None
2017-07-03 17:55:24 +03:00
conf.httpCollector = None
2011-04-30 17:20:05 +04:00
conf.httpHeaders = []
conf.hostname = None
2012-05-25 02:07:50 +04:00
conf.ipv6 = False
2011-04-30 17:20:05 +04:00
conf.multipleTargets = False
conf.outputPath = None
conf.paramDict = {}
conf.parameters = {}
conf.path = None
conf.port = None
conf.proxyList = None
conf.resultsFilename = None
conf.resultsFP = None
2011-04-30 17:20:05 +04:00
conf.scheme = None
conf.tests = []
conf.trafficFP = None
2017-07-03 17:55:24 +03:00
conf.HARCollectorFactory = None
2018-08-28 15:31:20 +03:00
conf.fileWriteType = None
2008-10-15 19:38:22 +04:00
def _setKnowledgeBaseAttributes(flushAll=True):
2008-10-15 19:38:22 +04:00
"""
This function set some needed attributes into the knowledge base
singleton.
"""
debugMsg = "initializing the knowledge base"
logger.debug(debugMsg)
2011-04-30 17:20:05 +04:00
kb.absFilePaths = set()
2012-10-09 17:19:47 +04:00
kb.adjustTimeDelay = None
kb.alerted = False
kb.aliasName = randomStr()
kb.alwaysRefresh = None
2011-04-30 17:20:05 +04:00
kb.arch = None
kb.authHeader = None
2011-07-08 10:02:31 +04:00
kb.bannerFp = AttribDict()
2013-12-27 01:27:04 +04:00
kb.binaryField = False
2017-06-07 13:55:14 +03:00
kb.browserVerification = None
2013-01-10 16:18:44 +04:00
kb.brute = AttribDict({"tables": [], "columns": []})
2011-04-30 17:20:05 +04:00
kb.bruteMode = False
2011-07-08 10:02:31 +04:00
kb.cache = AttribDict()
2016-09-09 12:06:38 +03:00
kb.cache.addrinfo = {}
2011-04-30 17:20:05 +04:00
kb.cache.content = {}
2016-09-09 12:06:38 +03:00
kb.cache.encoding = {}
2017-12-29 15:04:52 +03:00
kb.cache.alphaBoundaries = None
2016-09-20 11:03:00 +03:00
kb.cache.intBoundaries = None
2016-09-09 12:06:38 +03:00
kb.cache.parsedDbms = {}
2011-04-30 17:20:05 +04:00
kb.cache.regex = {}
kb.cache.stdev = {}
2016-06-01 16:48:04 +03:00
kb.captchaDetected = None
2012-07-06 19:34:40 +04:00
kb.chars = AttribDict()
kb.chars.delimiter = randomStr(length=6, lowercase=True)
kb.chars.start = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR)
kb.chars.stop = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR)
kb.chars.at, kb.chars.space, kb.chars.dollar, kb.chars.hash_ = ("%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, _, KB_CHARS_BOUNDARY_CHAR) for _ in randomStr(length=4, lowercase=True))
2012-07-06 19:34:40 +04:00
2014-05-13 02:50:36 +04:00
kb.columnExistsChoice = None
2011-04-30 17:20:05 +04:00
kb.commonOutputs = None
2016-10-02 12:13:40 +03:00
kb.connErrorChoice = None
kb.connErrorCounter = 0
kb.cookieEncodeChoice = None
2011-12-21 15:50:49 +04:00
kb.counters = {}
2017-07-20 03:41:47 +03:00
kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR
2011-07-08 10:02:31 +04:00
kb.data = AttribDict()
2011-05-11 00:44:36 +04:00
kb.dataOutputFlag = False
# Active back-end DBMS fingerprint
2011-04-30 17:20:05 +04:00
kb.dbms = None
2017-08-28 14:02:08 +03:00
kb.dbmsFilter = []
2013-01-10 14:54:07 +04:00
kb.dbmsVersion = [UNKNOWN_DBMS_VERSION]
2011-04-30 17:20:05 +04:00
kb.delayCandidates = TIME_DELAY_CANDIDATES * [0]
kb.dep = None
kb.dnsMode = False
kb.dnsTest = None
2011-04-30 17:20:05 +04:00
kb.docRoot = None
2017-05-26 15:14:35 +03:00
kb.droppingRequests = False
2016-07-15 00:18:28 +03:00
kb.dumpColumns = None
kb.dumpTable = None
2016-03-23 12:33:32 +03:00
kb.dumpKeyboardInterrupt = False
2011-04-30 17:20:05 +04:00
kb.dynamicMarkings = []
2012-08-20 13:40:49 +04:00
kb.dynamicParameter = False
2011-04-30 17:20:05 +04:00
kb.endDetection = False
kb.explicitSettings = set()
2013-02-01 20:24:04 +04:00
kb.extendTests = None
2015-08-26 16:26:16 +03:00
kb.errorChunkLength = None
2011-04-30 17:20:05 +04:00
kb.errorIsNone = True
2016-05-06 14:06:59 +03:00
kb.falsePositives = []
2012-07-06 16:24:44 +04:00
kb.fileReadMode = False
2014-07-03 00:27:51 +04:00
kb.followSitemapRecursion = None
2011-09-26 01:10:45 +04:00
kb.forcedDbms = None
2013-07-31 23:15:03 +04:00
kb.forcePartialUnion = False
2015-07-26 18:02:46 +03:00
kb.forceWhere = None
kb.futileUnion = None
kb.heavilyDynamic = False
2011-04-30 17:20:05 +04:00
kb.headersFp = {}
2013-01-25 15:34:57 +04:00
kb.heuristicDbms = None
2017-06-05 17:48:14 +03:00
kb.heuristicExtendedDbms = None
kb.heuristicMode = False
kb.heuristicPage = False
kb.heuristicTest = None
2011-04-30 17:20:05 +04:00
kb.hintValue = None
kb.htmlFp = []
2011-11-21 20:41:02 +04:00
kb.httpErrorCodes = {}
kb.inferenceMode = False
kb.ignoreCasted = None
2011-12-05 13:25:56 +04:00
kb.ignoreNotFound = False
kb.ignoreTimeout = False
2011-07-08 10:02:31 +04:00
kb.injection = InjectionDict()
2011-04-30 17:20:05 +04:00
kb.injections = []
kb.laggingChecked = False
kb.lastParserStatus = None
2011-07-08 10:02:31 +04:00
kb.locks = AttribDict()
2016-10-02 12:13:40 +03:00
for _ in ("cache", "connError", "count", "index", "io", "limit", "log", "socket", "redirect", "request", "value"):
2011-12-28 20:27:17 +04:00
kb.locks[_] = threading.Lock()
2011-04-30 17:20:05 +04:00
kb.matchRatio = None
kb.maxConnectionsFlag = False
kb.mergeCookies = None
kb.multiThreadMode = False
kb.negativeLogic = False
2011-04-30 17:20:05 +04:00
kb.nullConnection = None
2015-07-23 11:07:21 +03:00
kb.oldMsf = None
kb.orderByColumns = None
kb.originalCode = None
2011-04-30 17:20:05 +04:00
kb.originalPage = None
2015-07-10 10:24:14 +03:00
kb.originalPageTime = None
kb.originalTimeDelay = None
2012-08-15 18:37:18 +04:00
kb.originalUrls = dict()
# Back-end DBMS underlying operating system fingerprint via banner (-b)
# parsing
2011-04-30 17:20:05 +04:00
kb.os = None
kb.osVersion = None
kb.osSP = None
2013-02-01 20:24:04 +04:00
kb.pageCompress = True
kb.pageTemplate = None
kb.pageTemplates = dict()
2011-04-30 17:20:05 +04:00
kb.pageEncoding = DEFAULT_PAGE_ENCODING
kb.pageStable = None
kb.partRun = None
2012-02-08 16:02:50 +04:00
kb.permissionFlag = False
2013-02-01 20:24:04 +04:00
kb.postHint = None
kb.postSpaceToPlus = False
kb.postUrlEncode = True
kb.prependFlag = False
2011-11-22 16:18:24 +04:00
kb.processResponseCounter = 0
2013-02-01 20:24:04 +04:00
kb.previousMethod = None
kb.processUserMarks = None
2011-04-30 17:20:05 +04:00
kb.proxyAuthHeader = None
kb.queryCounter = 0
kb.redirectChoice = None
2011-05-30 13:46:32 +04:00
kb.reflectiveMechanism = True
2013-01-10 16:18:44 +04:00
kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS: 0, REFLECTIVE_COUNTER.HIT: 0}
kb.requestCounter = 0
kb.resendPostOnRedirect = None
kb.resolutionDbms = None
2016-01-09 19:32:19 +03:00
kb.responseTimes = {}
kb.responseTimeMode = None
kb.responseTimePayload = None
kb.resumeValues = True
2016-07-15 00:18:28 +03:00
kb.rowXmlMode = False
kb.safeCharEncode = False
2015-04-22 17:28:54 +03:00
kb.safeReq = AttribDict()
2018-06-19 17:39:10 +03:00
kb.secondReq = None
kb.serverHeader = None
2011-04-30 17:20:05 +04:00
kb.singleLogFlags = set()
kb.skipSeqMatcher = False
2013-02-01 20:24:04 +04:00
kb.reduceTests = None
2015-12-07 01:49:22 +03:00
kb.tlsSNI = {}
2012-07-12 17:24:40 +04:00
kb.stickyDBMS = False
2012-07-12 17:23:35 +04:00
kb.stickyLevel = None
kb.storeCrawlingChoice = None
kb.storeHashesChoice = None
2011-04-30 17:20:05 +04:00
kb.suppressResumeInfo = False
kb.tableFrom = None
2011-04-30 17:20:05 +04:00
kb.technique = None
2015-01-14 07:16:32 +03:00
kb.tempDir = None
2011-04-30 17:20:05 +04:00
kb.testMode = False
2015-07-17 11:14:35 +03:00
kb.testOnlyCustom = False
2011-04-30 17:20:05 +04:00
kb.testQueryCount = 0
kb.testType = None
2011-04-30 17:20:05 +04:00
kb.threadContinue = True
kb.threadException = False
2014-05-13 02:50:36 +04:00
kb.tableExistsChoice = None
2012-02-07 14:46:55 +04:00
kb.uChar = NULL
kb.unionDuplicates = False
2017-07-26 01:24:13 +03:00
kb.wafSpecificResponse = None
2018-02-27 14:37:45 +03:00
kb.wizardMode = False
kb.xpCmdshellAvailable = False
2010-12-18 13:02:01 +03:00
if flushAll:
2011-12-22 02:09:21 +04:00
kb.headerPaths = {}
2011-04-30 17:20:05 +04:00
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
kb.passwordMgr = None
2014-08-28 02:13:27 +04:00
kb.skipVulnHost = None
2010-12-18 13:02:01 +03:00
kb.tamperFunctions = []
kb.targets = oset()
2011-04-30 17:20:05 +04:00
kb.testedParams = set()
kb.userAgents = None
2011-05-24 21:15:25 +04:00
kb.vainRun = True
2012-08-22 18:50:01 +04:00
kb.vulnHosts = set()
kb.wafFunctions = []
2012-07-18 15:32:34 +04:00
kb.wordlists = None
2010-12-18 13:02:01 +03:00
def _useWizardInterface():
"""
Presents simple wizard interface for beginner users
"""
if not conf.wizard:
return
logger.info("starting wizard interface")
2014-06-09 01:55:15 +04:00
while not conf.url:
message = "Please enter full target URL (-u): "
conf.url = readInput(message, default=None)
2014-11-21 13:20:54 +03:00
message = "%s data (--data) [Enter for None]: " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST)
2014-06-09 01:55:15 +04:00
conf.data = readInput(message, default=None)
if not (filter(lambda _: '=' in unicode(_), (conf.url, conf.data)) or '*' in conf.url):
2014-11-21 13:20:54 +03:00
warnMsg = "no GET and/or %s parameter(s) found for testing " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST)
2014-06-09 01:55:15 +04:00
warnMsg += "(e.g. GET parameter 'id' in 'http://www.site.com/vuln.php?id=1'). "
if not conf.crawlDepth and not conf.forms:
warnMsg += "Will search for forms"
conf.forms = True
logger.warn(warnMsg)
2011-11-02 18:33:23 +04:00
choice = None
while choice is None or choice not in ("", "1", "2", "3"):
message = "Injection difficulty (--level/--risk). Please choose:\n"
message += "[1] Normal (default)\n[2] Medium\n[3] Hard"
choice = readInput(message, default='1')
if choice == '2':
conf.risk = 2
conf.level = 3
elif choice == '3':
conf.risk = 3
conf.level = 5
else:
conf.risk = 1
conf.level = 1
2012-10-05 12:24:09 +04:00
if not conf.getAll:
choice = None
2012-10-05 12:24:09 +04:00
while choice is None or choice not in ("", "1", "2", "3"):
message = "Enumeration (--banner/--current-user/etc). Please choose:\n"
message += "[1] Basic (default)\n[2] Intermediate\n[3] All"
2012-10-05 12:24:09 +04:00
choice = readInput(message, default='1')
2012-10-05 12:24:09 +04:00
if choice == '2':
2017-11-10 15:03:24 +03:00
map(lambda _: conf.__setitem__(_, True), WIZARD.INTERMEDIATE)
2012-10-05 12:24:09 +04:00
elif choice == '3':
2017-11-10 15:03:24 +03:00
map(lambda _: conf.__setitem__(_, True), WIZARD.ALL)
2012-10-05 12:24:09 +04:00
else:
2017-11-10 15:03:24 +03:00
map(lambda _: conf.__setitem__(_, True), WIZARD.BASIC)
logger.debug("muting sqlmap.. it will do the magic for you")
conf.verbose = 0
2011-11-02 18:33:23 +04:00
conf.batch = True
conf.threads = 4
dataToStdout("\nsqlmap is running, please wait..\n\n")
2018-02-27 14:37:45 +03:00
kb.wizardMode = True
def _saveConfig():
2008-10-15 19:38:22 +04:00
"""
Saves the command line options to a sqlmap configuration INI file
Format.
2008-10-15 19:38:22 +04:00
"""
if not conf.saveConfig:
2008-10-15 19:38:22 +04:00
return
debugMsg = "saving command line options to a sqlmap configuration INI file"
2008-10-15 19:38:22 +04:00
logger.debug(debugMsg)
2017-04-10 15:50:17 +03:00
saveConfig(conf, conf.saveConfig)
2008-10-15 19:38:22 +04:00
infoMsg = "saved command line options to the configuration file '%s'" % conf.saveConfig
2008-10-15 19:38:22 +04:00
logger.info(infoMsg)
def setVerbosity():
2008-10-15 19:38:22 +04:00
"""
This function set the verbosity of sqlmap output messages.
"""
if conf.verbose is None:
conf.verbose = 1
2008-10-15 19:38:22 +04:00
conf.verbose = int(conf.verbose)
2010-09-26 18:02:13 +04:00
if conf.verbose == 0:
logger.setLevel(logging.ERROR)
2010-09-26 18:02:13 +04:00
elif conf.verbose == 1:
2008-10-15 19:38:22 +04:00
logger.setLevel(logging.INFO)
2010-03-11 01:08:11 +03:00
elif conf.verbose > 2 and conf.eta:
conf.verbose = 2
logger.setLevel(logging.DEBUG)
2008-10-15 19:38:22 +04:00
elif conf.verbose == 2:
logger.setLevel(logging.DEBUG)
elif conf.verbose == 3:
2011-12-26 16:24:39 +04:00
logger.setLevel(CUSTOM_LOGGING.PAYLOAD)
elif conf.verbose == 4:
2011-12-26 16:24:39 +04:00
logger.setLevel(CUSTOM_LOGGING.TRAFFIC_OUT)
elif conf.verbose >= 5:
2011-12-26 16:24:39 +04:00
logger.setLevel(CUSTOM_LOGGING.TRAFFIC_IN)
2008-10-15 19:38:22 +04:00
2016-02-16 11:56:53 +03:00
def _normalizeOptions(inputOptions):
"""
Sets proper option types
"""
types_ = {}
for group in optDict.keys():
types_.update(optDict[group])
for key in inputOptions:
if key in types_:
value = inputOptions[key]
if value is None:
continue
type_ = types_[key]
if type_ and isinstance(type_, tuple):
type_ = type_[0]
if type_ == OPTION_TYPE.BOOLEAN:
try:
value = bool(value)
except (TypeError, ValueError):
value = False
elif type_ == OPTION_TYPE.INTEGER:
try:
value = int(value)
except (TypeError, ValueError):
value = 0
elif type_ == OPTION_TYPE.FLOAT:
try:
value = float(value)
except (TypeError, ValueError):
value = 0.0
inputOptions[key] = value
def _mergeOptions(inputOptions, overrideOptions):
2008-10-15 19:38:22 +04:00
"""
Merge command line options with configuration file and default options.
2008-10-15 19:38:22 +04:00
@param inputOptions: optparse object with command line options.
@type inputOptions: C{instance}
"""
if inputOptions.configFile:
configFileParser(inputOptions.configFile)
if hasattr(inputOptions, "items"):
inputOptionsItems = inputOptions.items()
else:
inputOptionsItems = inputOptions.__dict__.items()
for key, value in inputOptionsItems:
if key not in conf or value not in (None, False) or overrideOptions:
conf[key] = value
2017-04-10 20:21:22 +03:00
if not conf.api:
2016-10-18 21:17:51 +03:00
for key, value in conf.items():
if value is not None:
kb.explicitSettings.add(key)
for key, value in defaults.items():
2012-12-20 20:53:43 +04:00
if hasattr(conf, key) and conf[key] is None:
2008-10-15 19:38:22 +04:00
conf[key] = value
2016-02-16 11:56:53 +03:00
lut = {}
2014-04-25 11:17:10 +04:00
for group in optDict.keys():
2016-02-16 11:56:53 +03:00
lut.update((_.upper(), _) for _ in optDict[group])
2014-04-25 11:17:10 +04:00
2016-02-16 11:56:53 +03:00
envOptions = {}
for key, value in os.environ.items():
if key.upper().startswith(SQLMAP_ENVIRONMENT_PREFIX):
_ = key[len(SQLMAP_ENVIRONMENT_PREFIX):].upper()
if _ in lut:
envOptions[lut[_]] = value
2014-04-25 11:17:10 +04:00
2016-02-16 11:56:53 +03:00
if envOptions:
_normalizeOptions(envOptions)
for key, value in envOptions.items():
2014-04-25 11:17:10 +04:00
conf[key] = value
2013-04-10 21:33:31 +04:00
mergedOptions.update(conf)
def _setTrafficOutputFP():
2010-11-08 14:22:47 +03:00
if conf.trafficFile:
infoMsg = "setting file for logging HTTP traffic"
logger.info(infoMsg)
conf.trafficFP = openFile(conf.trafficFile, "w+")
2010-11-08 14:22:47 +03:00
2017-07-03 17:55:24 +03:00
def _setupHTTPCollector():
if not conf.harFile:
return
conf.httpCollector = HTTPCollectorFactory(conf.harFile).create()
def _setDNSServer():
2016-10-22 22:52:18 +03:00
if not conf.dnsDomain:
return
2012-04-04 16:27:24 +04:00
infoMsg = "setting up DNS server instance"
logger.info(infoMsg)
isAdmin = runningAsAdmin()
if isAdmin:
2012-05-27 13:11:19 +04:00
try:
conf.dnsServer = DNSServer()
conf.dnsServer.run()
except socket.error, msg:
errMsg = "there was an error while setting up "
errMsg += "DNS server instance ('%s')" % msg
raise SqlmapGenericException(errMsg)
else:
errMsg = "you need to run sqlmap as an administrator "
errMsg += "if you want to perform a DNS data exfiltration attack "
2012-04-04 16:27:24 +04:00
errMsg += "as it will need to listen on privileged UDP port 53 "
errMsg += "for incoming address resolution attempts"
raise SqlmapMissingPrivileges(errMsg)
2013-08-12 16:25:51 +04:00
def _setProxyList():
if not conf.proxyFile:
return
conf.proxyList = []
for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w\-.]+):(\d+)", readCachedFileContent(conf.proxyFile)):
_, type_, address, port = match.groups()
conf.proxyList.append("%s://%s:%s" % (type_ or "http", address, port))
2013-08-12 16:25:51 +04:00
def _setTorProxySettings():
2011-12-16 03:19:55 +04:00
if not conf.tor:
return
2012-11-28 13:59:15 +04:00
if conf.torType == PROXY_TYPE.HTTP:
_setTorHttpProxySettings()
2011-12-16 03:19:55 +04:00
else:
_setTorSocksProxySettings()
2011-12-16 03:19:55 +04:00
def _setTorHttpProxySettings():
infoMsg = "setting Tor HTTP proxy settings"
logger.info(infoMsg)
2016-10-10 15:19:44 +03:00
port = findLocalPort(DEFAULT_TOR_HTTP_PORTS if not conf.torPort else (conf.torPort,))
2016-10-10 15:19:44 +03:00
if port:
conf.proxy = "http://%s:%d" % (LOCALHOST, port)
else:
errMsg = "can't establish connection with the Tor HTTP proxy. "
2016-10-10 15:19:44 +03:00
errMsg += "Please make sure that you have Tor (bundle) installed and setup "
errMsg += "so you could be able to successfully use switch '--tor' "
raise SqlmapConnectionException(errMsg)
2012-05-10 22:17:32 +04:00
if not conf.checkTor:
2012-05-10 22:30:25 +04:00
warnMsg = "use switch '--check-tor' at "
2013-03-26 17:27:51 +04:00
warnMsg += "your own convenience when accessing "
warnMsg += "Tor anonymizing network because of "
2012-05-10 22:30:25 +04:00
warnMsg += "known issues with default settings of various 'bundles' "
2012-07-13 17:02:11 +04:00
warnMsg += "(e.g. Vidalia)"
2012-05-10 22:17:32 +04:00
logger.warn(warnMsg)
def _setTorSocksProxySettings():
infoMsg = "setting Tor SOCKS proxy settings"
logger.info(infoMsg)
2016-10-10 15:19:44 +03:00
port = findLocalPort(DEFAULT_TOR_SOCKS_PORTS if not conf.torPort else (conf.torPort,))
if not port:
errMsg = "can't establish connection with the Tor SOCKS proxy. "
errMsg += "Please make sure that you have Tor service installed and setup "
errMsg += "so you could be able to successfully use switch '--tor' "
raise SqlmapConnectionException(errMsg)
# SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29)
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if conf.torType == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, LOCALHOST, port)
socks.wrapmodule(urllib2)
def _checkWebSocket():
if conf.url and (conf.url.startswith("ws:/") or conf.url.startswith("wss:/")):
try:
from websocket import ABNF
except ImportError:
2015-05-11 12:01:21 +03:00
errMsg = "sqlmap requires third-party module 'websocket-client' "
errMsg += "in order to use WebSocket functionality"
raise SqlmapMissingDependence(errMsg)
def _checkTor():
if not conf.checkTor:
return
2011-10-25 22:07:33 +04:00
infoMsg = "checking Tor connection"
logger.info(infoMsg)
try:
2018-03-26 16:39:48 +03:00
page, _, _ = Request.getPage(url="https://check.torproject.org/", raise404=False)
except SqlmapConnectionException:
page = None
if not page or 'Congratulations' not in page:
2016-05-22 22:44:17 +03:00
errMsg = "it appears that Tor is not properly set. Please try using options '--tor-type' and/or '--tor-port'"
raise SqlmapConnectionException(errMsg)
else:
infoMsg = "Tor is properly being used"
logger.info(infoMsg)
2011-10-25 21:37:43 +04:00
def _basicOptionValidation():
if conf.limitStart is not None and not (isinstance(conf.limitStart, int) and conf.limitStart > 0):
2012-10-16 12:28:59 +04:00
errMsg = "value for option '--start' (limitStart) must be an integer value greater than zero (>0)"
raise SqlmapSyntaxException(errMsg)
if conf.limitStop is not None and not (isinstance(conf.limitStop, int) and conf.limitStop > 0):
2012-10-16 12:28:59 +04:00
errMsg = "value for option '--stop' (limitStop) must be an integer value greater than zero (>0)"
raise SqlmapSyntaxException(errMsg)
2012-10-16 12:28:59 +04:00
if conf.level is not None and not (isinstance(conf.level, int) and conf.level >= 1 and conf.level <= 5):
errMsg = "value for option '--level' must be an integer value from range [1, 5]"
raise SqlmapSyntaxException(errMsg)
2012-10-16 12:28:59 +04:00
if conf.risk is not None and not (isinstance(conf.risk, int) and conf.risk >= 1 and conf.risk <= 3):
errMsg = "value for option '--risk' must be an integer value from range [1, 3]"
raise SqlmapSyntaxException(errMsg)
2014-04-06 20:09:54 +04:00
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and \
isinstance(conf.limitStop, int) and conf.limitStop < conf.limitStart:
2017-08-11 11:47:32 +03:00
warnMsg = "usage of option '--start' (limitStart) which is bigger than value for --stop (limitStop) option is considered unstable"
logger.warn(warnMsg)
2014-04-06 20:09:54 +04:00
if isinstance(conf.firstChar, int) and conf.firstChar > 0 and \
isinstance(conf.lastChar, int) and conf.lastChar < conf.firstChar:
2012-10-16 12:28:59 +04:00
errMsg = "value for option '--first' (firstChar) must be smaller than or equal to value for --last (lastChar) option"
raise SqlmapSyntaxException(errMsg)
if conf.textOnly and conf.nullConnection:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--text-only' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2010-11-07 11:58:24 +03:00
2016-10-06 23:27:29 +03:00
if conf.eta and conf.verbose > defaults.verbose:
errMsg = "switch '--eta' is incompatible with option '-v'"
raise SqlmapSyntaxException(errMsg)
2018-06-20 01:08:55 +03:00
if conf.secondUrl and conf.secondReq:
errMsg = "option '--second-url' is incompatible with option '--second-req')"
raise SqlmapSyntaxException(errMsg)
if conf.direct and conf.url:
errMsg = "option '-d' is incompatible with option '-u' ('--url')"
raise SqlmapSyntaxException(errMsg)
2018-12-31 03:20:43 +03:00
if conf.direct and conf.dbms:
errMsg = "option '-d' is incompatible with option '--dbms'"
raise SqlmapSyntaxException(errMsg)
2015-09-21 15:57:44 +03:00
if conf.identifyWaf and conf.skipWaf:
errMsg = "switch '--identify-waf' is incompatible with switch '--skip-waf'"
raise SqlmapSyntaxException(errMsg)
2011-06-11 12:33:36 +04:00
if conf.titles and conf.nullConnection:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--titles' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2011-06-11 12:33:36 +04:00
2014-07-20 01:23:55 +04:00
if conf.dumpTable and conf.search:
errMsg = "switch '--dump' is incompatible with switch '--search'"
raise SqlmapSyntaxException(errMsg)
2017-04-10 15:50:17 +03:00
if conf.api and not conf.configFile:
errMsg = "switch '--api' requires usage of option '-c'"
raise SqlmapSyntaxException(errMsg)
if conf.data and conf.nullConnection:
2012-02-01 18:49:42 +04:00
errMsg = "option '--data' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2010-10-15 15:05:50 +04:00
2011-06-22 18:39:31 +04:00
if conf.string and conf.nullConnection:
2012-02-01 18:49:42 +04:00
errMsg = "option '--string' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2011-06-22 18:39:31 +04:00
2012-07-26 14:06:02 +04:00
if conf.notString and conf.nullConnection:
errMsg = "option '--not-string' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2012-07-26 14:06:02 +04:00
2017-09-12 11:32:22 +03:00
if conf.notString and conf.nullConnection:
errMsg = "option '--tor' is incompatible with switch '--os-pwn'"
raise SqlmapSyntaxException(errMsg)
if conf.noCast and conf.hexConvert:
errMsg = "switch '--no-cast' is incompatible with switch '--hex'"
raise SqlmapSyntaxException(errMsg)
2014-06-23 14:24:08 +04:00
if conf.dumpAll and conf.search:
errMsg = "switch '--dump-all' is incompatible with switch '--search'"
raise SqlmapSyntaxException(errMsg)
2012-07-26 14:06:02 +04:00
if conf.string and conf.notString:
errMsg = "option '--string' is incompatible with switch '--not-string'"
raise SqlmapSyntaxException(errMsg)
2012-07-26 14:06:02 +04:00
2011-06-22 18:39:31 +04:00
if conf.regexp and conf.nullConnection:
2012-02-01 18:49:42 +04:00
errMsg = "option '--regexp' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg)
2011-06-22 18:39:31 +04:00
2014-12-30 17:14:47 +03:00
if conf.regexp:
try:
re.compile(conf.regexp)
2016-12-31 15:39:22 +03:00
except Exception, ex:
2016-01-12 12:27:04 +03:00
errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex))
2014-12-30 17:14:47 +03:00
raise SqlmapSyntaxException(errMsg)
2015-04-06 23:07:22 +03:00
if conf.crawlExclude:
try:
re.compile(conf.crawlExclude)
2016-12-31 15:39:22 +03:00
except Exception, ex:
2016-01-12 12:27:04 +03:00
errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex))
2015-04-06 23:07:22 +03:00
raise SqlmapSyntaxException(errMsg)
2011-12-22 03:04:36 +04:00
if conf.dumpTable and conf.dumpAll:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--dump' is incompatible with switch '--dump-all'"
raise SqlmapSyntaxException(errMsg)
2011-12-22 03:04:36 +04:00
2011-07-08 17:12:53 +04:00
if conf.predictOutput and (conf.threads > 1 or conf.optimize):
2012-02-01 18:49:42 +04:00
errMsg = "switch '--predict-output' is incompatible with option '--threads' and switch '-o'"
raise SqlmapSyntaxException(errMsg)
2010-10-25 16:33:49 +04:00
if conf.threads > MAX_NUMBER_OF_THREADS and not conf.get("skipThreadCheck"):
2013-01-16 19:07:12 +04:00
errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS
raise SqlmapSyntaxException(errMsg)
2014-08-01 16:19:32 +04:00
if conf.forms and not any((conf.url, conf.googleDork, conf.bulkFile, conf.sitemapUrl)):
errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-g', '-m' or '-x'"
raise SqlmapSyntaxException(errMsg)
2015-04-06 23:07:22 +03:00
if conf.crawlExclude and not conf.crawlDepth:
errMsg = "option '--crawl-exclude' requires usage of switch '--crawl'"
raise SqlmapSyntaxException(errMsg)
if conf.safePost and not conf.safeUrl:
errMsg = "option '--safe-post' requires usage of option '--safe-url'"
raise SqlmapSyntaxException(errMsg)
2015-04-22 17:28:54 +03:00
if conf.safeFreq and not any((conf.safeUrl, conf.safeReqFile)):
errMsg = "option '--safe-freq' requires usage of option '--safe-url' or '--safe-req'"
raise SqlmapSyntaxException(errMsg)
if conf.safeReqFile and any((conf.safeUrl, conf.safePost)):
errMsg = "option '--safe-req' is incompatible with option '--safe-url' and option '--safe-post'"
raise SqlmapSyntaxException(errMsg)
2014-10-23 13:54:29 +04:00
if conf.csrfUrl and not conf.csrfToken:
errMsg = "option '--csrf-url' requires usage of option '--csrf-token'"
raise SqlmapSyntaxException(errMsg)
2014-10-23 16:23:01 +04:00
if conf.csrfToken and conf.threads > 1:
2014-10-23 13:54:29 +04:00
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
raise SqlmapSyntaxException(errMsg)
2013-09-24 23:44:59 +04:00
if conf.requestFile and conf.url and conf.url != DUMMY_URL:
errMsg = "option '-r' is incompatible with option '-u' ('--url')"
raise SqlmapSyntaxException(errMsg)
if conf.direct and conf.proxy:
errMsg = "option '-d' is incompatible with option '--proxy'"
raise SqlmapSyntaxException(errMsg)
if conf.direct and conf.tor:
errMsg = "option '-d' is incompatible with switch '--tor'"
raise SqlmapSyntaxException(errMsg)
2013-04-21 23:42:23 +04:00
if not conf.tech:
errMsg = "option '--technique' can't be empty"
raise SqlmapSyntaxException(errMsg)
if conf.tor and conf.ignoreProxy:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--tor' is incompatible with switch '--ignore-proxy'"
raise SqlmapSyntaxException(errMsg)
2011-04-29 23:27:23 +04:00
if conf.tor and conf.proxy:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--tor' is incompatible with option '--proxy'"
raise SqlmapSyntaxException(errMsg)
2011-08-29 17:29:42 +04:00
if conf.proxy and conf.proxyFile:
errMsg = "switch '--proxy' is incompatible with option '--proxy-file'"
raise SqlmapSyntaxException(errMsg)
2012-11-29 18:44:14 +04:00
if conf.checkTor and not any((conf.tor, conf.proxy)):
2018-03-16 16:30:47 +03:00
errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address of Tor service)"
raise SqlmapSyntaxException(errMsg)
2015-01-24 01:00:28 +03:00
if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort >= 0 and conf.torPort <= 65535):
2018-03-16 16:30:47 +03:00
errMsg = "value for option '--tor-port' must be in range [0, 65535]"
raise SqlmapSyntaxException(errMsg)
2011-12-23 14:57:09 +04:00
2012-11-28 13:59:15 +04:00
if conf.torType not in getPublicTypeMembers(PROXY_TYPE, True):
errMsg = "option '--tor-type' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(PROXY_TYPE, True))
raise SqlmapSyntaxException(errMsg)
2011-10-25 21:37:43 +04:00
2012-11-28 13:58:18 +04:00
if conf.dumpFormat not in getPublicTypeMembers(DUMP_FORMAT, True):
errMsg = "option '--dump-format' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(DUMP_FORMAT, True))
raise SqlmapSyntaxException(errMsg)
2012-11-28 13:58:18 +04:00
2011-08-29 17:29:42 +04:00
if conf.skip and conf.testParameter:
2012-02-01 18:49:42 +04:00
errMsg = "option '--skip' is incompatible with option '-p'"
raise SqlmapSyntaxException(errMsg)
2011-04-29 23:27:23 +04:00
if conf.mobile and conf.agent:
2012-02-01 18:49:42 +04:00
errMsg = "switch '--mobile' is incompatible with option '--user-agent'"
raise SqlmapSyntaxException(errMsg)
if conf.proxy and conf.ignoreProxy:
2012-02-01 18:49:42 +04:00
errMsg = "option '--proxy' is incompatible with switch '--ignore-proxy'"
raise SqlmapSyntaxException(errMsg)
if conf.timeSec < 1:
2012-02-01 18:49:42 +04:00
errMsg = "value for option '--time-sec' must be a positive integer"
raise SqlmapSyntaxException(errMsg)
2011-10-10 01:21:41 +04:00
if conf.uChar and not re.match(UNION_CHAR_REGEX, conf.uChar):
2012-02-01 18:49:42 +04:00
errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)"
raise SqlmapSyntaxException(errMsg)
2011-10-10 01:21:41 +04:00
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.liveTest, conf.wizard, conf.dependencies, conf.purge, conf.sitemapUrl, conf.listTampers)):
2018-12-17 19:48:22 +03:00
errMsg = "option '--crack' should be used as a standalone"
raise SqlmapSyntaxException(errMsg)
if isinstance(conf.uCols, basestring):
if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2):
2012-02-01 18:49:42 +04:00
errMsg = "value for option '--union-cols' must be a range with hyphon "
errMsg += "(e.g. 1-10) or integer value (e.g. 5)"
raise SqlmapSyntaxException(errMsg)
if conf.dbmsCred and ':' not in conf.dbmsCred:
errMsg = "value for option '--dbms-cred' must be in "
errMsg += "format <username>:<password> (e.g. \"root:pass\")"
raise SqlmapSyntaxException(errMsg)
if conf.encoding:
_ = checkCharEncoding(conf.encoding, False)
2012-09-25 12:17:25 +04:00
if _ is None:
2018-01-15 15:53:46 +03:00
errMsg = "unknown encoding '%s'. Please visit " % conf.encoding
2011-06-08 20:08:20 +04:00
errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE
2018-01-15 15:53:46 +03:00
errMsg += "supported encodings"
raise SqlmapSyntaxException(errMsg)
2012-09-25 12:17:25 +04:00
else:
conf.encoding = _
2012-07-24 17:34:50 +04:00
if conf.loadCookies:
if not os.path.exists(conf.loadCookies):
errMsg = "cookies file '%s' does not exist" % conf.loadCookies
raise SqlmapFilePathException(errMsg)
2012-03-08 14:03:59 +04:00
def _resolveCrossReferences():
lib.core.threads.readInput = readInput
lib.core.common.getPageTemplate = getPageTemplate
2012-07-31 13:03:44 +04:00
lib.core.convert.singleTimeWarnMessage = singleTimeWarnMessage
lib.request.connect.setHTTPHandlers = _setHTTPHandlers
lib.utils.search.setHTTPHandlers = _setHTTPHandlers
lib.controller.checks.setVerbosity = setVerbosity
lib.controller.checks.setWafFunctions = _setWafFunctions
def initOptions(inputOptions=AttribDict(), overrideOptions=False):
_setConfAttributes()
_setKnowledgeBaseAttributes()
_mergeOptions(inputOptions, overrideOptions)
def init():
"""
Set attributes into both configuration and knowledge base singletons
based upon command line and configuration file options.
"""
_useWizardInterface()
setVerbosity()
_saveConfig()
_setRequestFromFile()
_cleanupOptions()
2016-10-17 13:33:07 +03:00
_cleanupEnvironment()
_purge()
_checkDependencies()
2015-01-13 12:33:51 +03:00
_createTemporaryDirectory()
_basicOptionValidation()
2013-08-12 16:25:51 +04:00
_setProxyList()
_setTorProxySettings()
_setDNSServer()
_adjustLoggingFormatter()
_setMultipleTargets()
2018-07-31 03:18:33 +03:00
_listTamperingFunctions()
_setTamperingFunctions()
_setWafFunctions()
_setTrafficOutputFP()
2017-07-03 17:55:24 +03:00
_setupHTTPCollector()
_resolveCrossReferences()
_checkWebSocket()
parseTargetDirect()
2014-07-03 00:27:51 +04:00
if any((conf.url, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.requestFile, conf.googleDork, conf.liveTest)):
2018-10-27 15:30:28 +03:00
_setHostname()
_setHTTPTimeout()
_setHTTPExtraHeaders()
_setHTTPCookies()
_setHTTPReferer()
2015-03-20 02:56:36 +03:00
_setHTTPHost()
_setHTTPUserAgent()
_setHTTPAuthentication()
_setHTTPHandlers()
_setDNSCache()
2015-11-17 01:46:10 +03:00
_setSocketPreConnect()
2015-04-22 17:28:54 +03:00
_setSafeVisit()
_doSearch()
_setBulkMultipleTargets()
2014-07-03 00:27:51 +04:00
_setSitemapTargets()
_checkTor()
_setCrawler()
_findPageForms()
_setDBMS()
_setTechnique()
_setThreads()
_setOS()
_setWriteFile()
_setMetasploit()
_setDBMSAuthentication()
loadBoundaries()
loadPayloads()
_setPrefixSuffix()
2008-10-15 19:38:22 +04:00
update()
_loadQueries()