sqlmap/lib/core/option.py

2659 lines
91 KiB
Python
Raw Normal View History

#!/usr/bin/env python
2008-10-15 19:38:22 +04:00
"""
2016-01-06 02:06:12 +03:00
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
2010-10-15 03:18:29 +04:00
See the file 'doc/COPYING' 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
2015-07-26 17:19:44 +03:00
import httplib
2008-10-15 19:38:22 +04:00
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
2011-01-20 18:55:50 +03:00
from lib.core.common import extractRegexResult
from lib.core.common import filterStringValue
from lib.core.common import findPageForms
from lib.core.common import getConsoleWidth
from lib.core.common import getFileItems
from lib.core.common import getFileType
2012-07-13 12:28:03 +04:00
from lib.core.common import getUnicode
2012-06-14 17:38:53 +04:00
from lib.core.common import isListLike
from lib.core.common import normalizePath
from lib.core.common import ntToPosixSlashes
from lib.core.common import openFile
from lib.core.common import parseTargetDirect
2008-10-15 19:38:22 +04:00
from lib.core.common import parseTargetUrl
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
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
2010-05-28 19:57:43 +04:00
from lib.core.common import UnicodeRawConfigParser
2012-07-31 13:03:44 +04:00
from lib.core.common import urldecode
from lib.core.convert import base64unpickle
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
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
from lib.core.settings import BURP_REQUEST_REGEX
2013-11-08 12:23:38 +04:00
from lib.core.settings import BURP_XML_HISTORY_REGEX
2011-05-18 03:03:31 +04:00
from lib.core.settings import CODECS_LIST_PAGE
2012-04-11 02:26:42 +04:00
from lib.core.settings import CRAWL_EXCLUDE_EXTENSIONS
2012-11-28 14:41:39 +04:00
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DBMS_ALIASES
from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
2011-11-24 01:39:53 +04:00
from lib.core.settings import DEFAULT_TOR_SOCKS_PORT
2013-09-24 23:44:59 +04:00
from lib.core.settings import DUMMY_URL
from lib.core.settings import IGNORE_SAVE_OPTIONS
2012-11-28 14:41:39 +04:00
from lib.core.settings import INJECT_HERE_MARK
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
2013-02-26 15:50:43 +04:00
from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
from lib.core.settings import SITE
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
from lib.core.settings import VERSION_STRING
2011-01-20 19:07:08 +03:00
from lib.core.settings import WEBSCARAB_SPLITTER
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
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
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()
2008-10-15 19:38:22 +04:00
def _feedTargetsDict(reqFile, addedTargetUrls):
2011-01-20 18:55:50 +03:00
"""
Parses web scarab and burp logs and adds results to the target URL list
2011-01-20 18:55:50 +03:00
"""
def _parseWebScarabLog(content):
2011-01-20 18:55:50 +03:00
"""
Parses web scarab logs (POST method not supported)
"""
2011-01-20 19:07:08 +03:00
reqResList = content.split(WEBSCARAB_SPLITTER)
2011-01-20 18:55:50 +03:00
for request in reqResList:
2011-04-30 17:20:05 +04:00
url = extractRegexResult(r"URL: (?P<result>.+?)\n", request, re.I)
2011-01-20 18:55:50 +03:00
method = extractRegexResult(r"METHOD: (?P<result>.+?)\n", request, re.I)
cookie = extractRegexResult(r"COOKIE: (?P<result>.+?)\n", request, re.I)
2011-01-20 18:55:50 +03:00
if not method or not url:
2011-04-18 02:25:25 +04:00
logger.debug("not a valid WebScarab log data")
2011-01-20 18:55:50 +03:00
continue
2012-10-07 22:28:24 +04:00
if method.upper() == HTTPMETHOD.POST:
2011-01-20 19:17:38 +03:00
warnMsg = "POST requests from WebScarab logs aren't supported "
warnMsg += "as their body content is stored in separate files. "
warnMsg += "Nevertheless you can use -r to load them individually."
2011-01-20 18:55:50 +03:00
logger.warning(warnMsg)
continue
2010-03-05 17:06:03 +03:00
2012-01-16 14:28:21 +04:00
if not(conf.scope and not re.search(conf.scope, url, re.I)):
if not kb.targets or url not in addedTargetUrls:
2014-10-22 16:54:49 +04:00
kb.targets.add((url, method, None, cookie, None))
addedTargetUrls.add(url)
def _parseBurpLog(content):
2011-01-20 18:55:50 +03:00
"""
Parses burp logs
"""
2012-10-09 13:27:19 +04:00
if not re.search(BURP_REQUEST_REGEX, content, re.I | re.S):
2013-11-08 12:23:38 +04:00
if re.search(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
reqResList = []
for match in re.finditer(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
port, request = match.groups()
request = request.decode("base64")
_ = re.search(r"%s:.+" % re.escape(HTTP_HEADER.HOST), request)
if _:
host = _.group(0).strip()
if not re.search(r":\d+\Z", host):
request = request.replace(host, "%s:%d" % (host, int(port)))
reqResList.append(request)
2013-11-08 12:23:38 +04:00
else:
reqResList = [content]
2012-10-09 13:27:19 +04:00
else:
reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S)
2012-10-09 13:27:19 +04:00
for match in reqResList:
request = match if isinstance(match, basestring) else match.group(0)
2014-03-26 00:26:22 +04:00
request = re.sub(r"\A[^\w]+", "", request)
2012-10-09 13:27:19 +04:00
schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S)
2012-10-09 13:27:19 +04:00
if schemePort:
scheme = schemePort.group(1)
port = schemePort.group(2)
else:
scheme, port = None, None
2013-04-10 18:43:57 +04:00
if not re.search(r"^[\n]*(%s).*?\sHTTP\/" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), request, re.I | re.M):
continue
2013-04-17 12:48:17 +04:00
if re.search(r"^[\n]*%s.*?\.(%s)\sHTTP\/" % (HTTPMETHOD.GET, "|".join(CRAWL_EXCLUDE_EXTENSIONS)), request, re.I | re.M):
2011-01-20 18:55:50 +03:00
continue
getPostReq = False
2011-04-30 17:20:05 +04:00
url = None
host = None
method = None
data = None
cookie = None
params = False
2013-01-23 16:36:17 +04:00
newline = None
lines = request.split('\n')
headers = []
2011-01-20 18:55:50 +03:00
2013-05-25 20:52:59 +04:00
for index in xrange(len(lines)):
line = lines[index]
if not line.strip() and index == len(lines) - 1:
break
2013-01-23 16:36:17 +04:00
newline = "\r\n" if line.endswith('\r') else '\n'
line = line.strip('\r')
2013-04-10 18:43:57 +04:00
match = re.search(r"\A(%s) (.+) HTTP/[\d.]+\Z" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), line) if not method else None
2015-06-29 02:12:14 +03:00
if len(line.strip()) == 0 and method and method != HTTPMETHOD.GET and data is None:
2013-05-25 20:52:59 +04:00
data = ""
params = True
2013-04-10 18:43:57 +04:00
elif match:
method = match.group(1)
url = match.group(2)
2011-01-20 18:55:50 +03:00
if any(_ in line for _ in ('?', '=', CUSTOM_INJECTION_MARK_CHAR)):
2011-01-20 18:55:50 +03:00
params = True
getPostReq = True
# POST parameters
elif data is not None and params:
2013-01-23 16:36:17 +04:00
data += "%s%s" % (line, newline)
2011-01-20 18:55:50 +03:00
# GET parameters
elif "?" in line and "=" in line and ": " not in line:
params = True
2011-01-20 18:55:50 +03:00
# Headers
2015-08-31 00:15:50 +03:00
elif re.search(r"\A\S+:", line):
key, value = line.split(":", 1)
value = value.strip().replace("\r", "").replace("\n", "")
2011-01-20 18:55:50 +03:00
# Cookie and Host headers
if key.upper() == HTTP_HEADER.COOKIE.upper():
2011-01-20 18:55:50 +03:00
cookie = value
elif key.upper() == HTTP_HEADER.HOST.upper():
if '://' in value:
scheme, value = value.split('://')[:2]
2011-01-20 18:55:50 +03:00
splitValue = value.split(":")
host = splitValue[0]
2011-01-20 18:55:50 +03:00
if len(splitValue) > 1:
2013-01-23 16:36:17 +04:00
port = filterStringValue(splitValue[1], "[0-9]")
2011-01-20 18:55:50 +03:00
# Avoid to add a static content length header to
# headers and consider the following lines as
2011-01-20 18:55:50 +03:00
# POSTed data
if key.upper() == HTTP_HEADER.CONTENT_LENGTH.upper():
2011-01-20 18:55:50 +03:00
params = True
2011-01-20 18:55:50 +03:00
# Avoid proxy and connection type related headers
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION):
headers.append((getUnicode(key), getUnicode(value)))
2013-02-26 15:50:43 +04:00
if CUSTOM_INJECTION_MARK_CHAR in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""):
params = True
data = data.rstrip("\r\n") if data else data
if getPostReq and (params or cookie):
2011-04-14 14:14:46 +04:00
if not port and isinstance(scheme, basestring) and scheme.lower() == "https":
port = "443"
2011-04-14 14:14:46 +04:00
elif not scheme and port == "443":
scheme = "https"
2012-04-18 14:01:04 +04:00
if conf.forceSSL:
scheme = "https"
port = port or "443"
if not host:
errMsg = "invalid format of a request file"
raise SqlmapSyntaxException, errMsg
2011-01-20 18:55:50 +03:00
if not url.startswith("http"):
2011-04-30 17:20:05 +04:00
url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url)
2011-01-20 18:55:50 +03:00
scheme = None
2011-04-30 17:20:05 +04:00
port = None
2012-01-16 14:28:21 +04:00
if not(conf.scope and not re.search(conf.scope, url, re.I)):
if not kb.targets or url not in addedTargetUrls:
2016-02-18 13:13:51 +03:00
kb.targets.add((url, conf.method or method, data, cookie, tuple(headers)))
2012-01-16 14:28:21 +04:00
addedTargetUrls.add(url)
2010-03-05 17:06:03 +03:00
2014-11-24 12:13:56 +03:00
checkFile(reqFile)
try:
with openFile(reqFile, "rb") as f:
content = f.read()
except (IOError, OSError, MemoryError), ex:
errMsg = "something went wrong while trying "
2016-01-12 12:27:04 +03:00
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
2014-11-24 12:13:56 +03:00
raise SqlmapSystemException(errMsg)
2011-01-20 18:55:50 +03:00
if conf.scope:
logger.info("using regular expression '%s' for filtering targets" % conf.scope)
_parseBurpLog(content)
_parseWebScarabLog(content)
2013-02-26 15:54:54 +04:00
if not addedTargetUrls:
errMsg = "unable to find usable request(s) "
errMsg += "in provided file ('%s')" % reqFile
raise SqlmapGenericException(errMsg)
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"
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)
addedTargetUrls = 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):
_feedTargetsDict(conf.logFile, addedTargetUrls)
elif os.path.isdir(conf.logFile):
files = os.listdir(conf.logFile)
files.sort()
for reqFile in files:
if not re.search("([\d]+)\-request", reqFile):
continue
_feedTargetsDict(os.path.join(conf.logFile, reqFile), addedTargetUrls)
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.
"""
if not conf.requestFile:
return
addedTargetUrls = set()
2015-01-21 11:26:30 +03:00
conf.requestFile = safeExpandUser(conf.requestFile)
infoMsg = "parsing HTTP request from '%s'" % conf.requestFile
logger.info(infoMsg)
if not os.path.isfile(conf.requestFile):
2011-04-30 17:20:05 +04:00
errMsg = "the specified HTTP request file "
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
_feedTargetsDict(conf.requestFile, addedTargetUrls)
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] "
test = readInput(message, default="Y")
kb.data.onlyGETs = test.lower() != 'n'
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]"
test = readInput(message, default="Y")
if test[0] in ("n", "N"):
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):
if re.match(r"[^ ]+\?(.+)", line, re.I) or CUSTOM_INJECTION_MARK_CHAR 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)):
2013-01-09 18:22:21 +04:00
page, _ = Request.queryPage(content=True)
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)
2012-07-24 17:34:50 +04:00
match = re.search("^(.+?):(.*?)$", 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
except ImportError:
errMsg = "sqlmap requires third-party module 'pywin32' "
errMsg += "in order to use Metasploit functionalities on "
errMsg += "Windows. You can download it from "
errMsg += "'http://sourceforge.net/projects/pywin32/files/pywin32/'"
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
_ = 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. "
2013-01-07 20:59:59 +04:00
errMsg += "You can get it at 'http://www.metasploit.com/download/'"
raise SqlmapFilePathException(errMsg)
def _setWriteFile():
if not conf.wFile:
return
debugMsg = "setting the write file functionality"
logger.debug(debugMsg)
if not os.path.exists(conf.wFile):
errMsg = "the provided local file '%s' does not exist" % conf.wFile
raise SqlmapFilePathException(errMsg)
if not conf.dFile:
2011-04-30 17:20:05 +04:00
errMsg = "you did not provide the back-end DBMS absolute path "
errMsg += "where you want to write the local file '%s'" % conf.wFile
raise SqlmapMissingMandatoryOptionException(errMsg)
conf.wFileType = getFileType(conf.wFile)
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()
regex = re.search("%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
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 = []
2011-08-29 17:08:25 +04:00
for tfile in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper):
found = False
2010-10-15 14:36:29 +04:00
2010-10-17 01:55:34 +04:00
tfile = tfile.strip()
if not tfile:
2010-10-13 02:45:25 +04:00
continue
2010-10-15 14:36:29 +04:00
elif os.path.exists(os.path.join(paths.SQLMAP_TAMPER_PATH, tfile if tfile.endswith('.py') else "%s.py" % tfile)):
tfile = os.path.join(paths.SQLMAP_TAMPER_PATH, tfile if tfile.endswith('.py') else "%s.py" % tfile)
elif not os.path.exists(tfile):
errMsg = "tamper script '%s' does not exist" % tfile
raise SqlmapFilePathException(errMsg)
2010-10-15 14:36:29 +04:00
elif not tfile.endswith('.py'):
errMsg = "tamper script '%s' should have an extension '.py'" % tfile
raise SqlmapSyntaxException(errMsg)
2010-10-14 10:00:10 +04:00
dirname, filename = os.path.split(tfile)
2010-10-13 02:45:25 +04:00
dirname = os.path.abspath(dirname)
2010-10-14 10:00:10 +04:00
2011-04-30 17:20:05 +04:00
infoMsg = "loading tamper script '%s'" % filename[:-3]
2010-10-14 10:00:10 +04:00
logger.info(infoMsg)
2010-10-13 02:45:25 +04: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:
2016-06-19 18:44:47 +03:00
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
2016-06-17 17:54:23 +03:00
except (ImportError, SyntaxError), ex:
raise SqlmapSyntaxException("cannot import tamper script '%s' (%s)" % (filename[:-3], getSafeExString(ex)))
2010-10-15 14:36:29 +04: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] "
test = readInput(message, default="Y")
if not test or test[0] in ("y", "Y"):
resolve_priorities = True
elif test[0] in ("n", "N"):
resolve_priorities = False
elif test[0] in ("q", "Q"):
raise SqlmapUserQuitException
check_priority = False
priorities.append((priority, function))
last_priority = priority
2010-10-15 14:36:29 +04:00
break
elif name == "dependencies":
function()
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)' "
2012-07-27 02:11:07 +04:00
errMsg += "in tamper script '%s'" % tfile
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():
"""
Loads WAF/IDS/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]]
module = __import__(filename[:-3])
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):
2011-06-24 22:19:33 +04:00
if args in kb.cache:
2011-04-08 01:39:18 +04:00
return kb.cache[args]
2011-06-17 19:23:58 +04:00
2011-04-08 01:39:18 +04:00
else:
kb.cache[args] = socket._getaddrinfo(*args, **kwargs)
return kb.cache[args]
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
2015-11-17 01:46:10 +03:00
def _():
2016-01-11 02:34:03 +03:00
while kb.threadContinue and not conf.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)
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:
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
thread = threading.Thread(target=_)
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))
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:
_ = re.search("^(.*?):(.*?)$", 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)
handlers = filter(None, [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.
"""
2015-04-22 17:28:54 +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
if key == HTTP_HEADER.HOST:
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"
raise SqlmapSyntaxException, errMsg
else:
if not re.search("^http[s]*://", conf.safeUrl):
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)
2013-08-09 16:13:48 +04:00
aTypeLower = conf.authType.lower()
2013-09-12 01:22:10 +04:00
if aTypeLower in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST):
regExp = "^(.*?):(.*?)$"
2011-04-30 17:20:05 +04:00
errMsg = "HTTP %s authentication credentials " % aTypeLower
2013-05-20 01:00:40 +04:00
errMsg += "value must be in format 'username:password'"
elif aTypeLower == 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'"
elif aTypeLower == 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
if aTypeLower == AUTH_TYPE.BASIC:
authHandler = SmartHTTPBasicAuthHandler(kb.passwordMgr)
elif aTypeLower == AUTH_TYPE.DIGEST:
authHandler = urllib2.HTTPDigestAuthHandler(kb.passwordMgr)
elif aTypeLower == 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, "
errMsg += "http://code.google.com/p/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:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_LANGUAGE, "en-us,en;q=0.5"))
2011-10-26 02:06:47 +04:00
if not conf.charset:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
2011-10-26 02:06:47 +04:00
else:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.charset))
2011-04-17 12:48:13 +04:00
# Invalidating any caching mechanism in between
2011-04-17 12:33:46 +04:00
# Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache,no-store"))
conf.httpHeaders.append((HTTP_HEADER.PRAGMA, "no-cache"))
2011-04-17 12:33:46 +04:00
def _defaultHTTPUserAgent():
2008-10-15 19:38:22 +04:00
"""
@return: default sqlmap HTTP User-Agent header
@rtype: C{str}
"""
return "%s (%s)" % (VERSION_STRING, SITE)
# Firefox 3 running on Ubuntu 9.04 updated at April 2009
#return "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.9) Gecko/2009042113 Ubuntu/9.04 (jaunty) Firefox/3.0.9"
2009-04-25 00:13:21 +04:00
# Internet Explorer 7.0 running on Windows 2003 Service Pack 2 english
# updated at March 2009
#return "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
2008-10-15 19:38:22 +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:
if header == HTTP_HEADER.USER_AGENT:
2012-06-28 15:55:30 +04:00
_ = False
break
2012-06-28 15:55:30 +04:00
if _:
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent()))
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)
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent()))
2011-04-30 11:01:21 +04:00
return
2008-10-15 19:38:22 +04:00
userAgent = random.sample(kb.userAgents or [_defaultHTTPUserAgent()], 1)[0]
2011-04-29 23:27:23 +04:00
2011-04-30 19:29:59 +04:00
infoMsg = "fetched random HTTP User-Agent header from "
2014-08-20 15:32:32 +04:00
infoMsg += "file '%s': '%s'" % (paths.USER_AGENTS, userAgent)
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
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())
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)
raise SqlmapSystemException, errMsg
else:
try:
if not os.path.isdir(tempfile.gettempdir()):
os.makedirs(tempfile.gettempdir())
except IOError, ex:
errMsg = "there has been a problem while accessing "
errMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex)
errMsg += "make sure that there is enough disk space left. If problem persists, "
errMsg += "try to set environment variable 'TEMP' to a location "
errMsg += "writeable by the current user"
raise SqlmapSystemException, errMsg
if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir:
2015-01-28 02:52:40 +03:00
tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid()))
kb.tempDir = tempfile.tempdir
2015-01-13 12:33:51 +03:00
if not os.path.isdir(tempfile.tempdir):
os.makedirs(tempfile.tempdir)
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:
conf.paramDel = conf.paramDel.decode("string_escape")
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)
if conf.rFile:
conf.rFile = ntToPosixSlashes(normalizePath(conf.rFile))
if conf.wFile:
conf.wFile = ntToPosixSlashes(normalizePath(conf.wFile))
if conf.dFile:
conf.dFile = ntToPosixSlashes(normalizePath(conf.dFile))
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.data:
2012-11-28 14:45:33 +04:00
conf.data = re.sub(INJECT_HERE_MARK.replace(" ", r"[^A-Za-z]*"), CUSTOM_INJECTION_MARK_CHAR, conf.data, re.I)
2012-11-28 14:41:39 +04:00
if conf.url:
2012-11-28 14:45:33 +04:00
conf.url = re.sub(INJECT_HERE_MARK.replace(" ", r"[^A-Za-z]*"), CUSTOM_INJECTION_MARK_CHAR, conf.url, re.I)
2012-11-28 14:41:39 +04:00
if conf.os:
conf.os = conf.os.capitalize()
if conf.dbms:
conf.dbms = conf.dbms.capitalize()
2012-07-24 17:43:29 +04:00
if conf.testFilter:
2014-09-01 17:48:00 +04:00
conf.testFilter = conf.testFilter.strip('*+')
conf.testFilter = re.sub(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)
2015-10-01 12:57:33 +03:00
if conf.testSkip:
conf.testSkip = conf.testSkip.strip('*+')
conf.testSkip = re.sub(r"([^.])([*+])", "\g<1>.\g<2>", conf.testSkip)
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:
map(lambda x: conf.__setitem__(x, True), WIZARD.ALL)
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:
conf.col = re.sub(r"\s*,\s*", ",", conf.col)
if conf.excludeCol:
conf.excludeCol = re.sub(r"\s*,\s*", ",", conf.excludeCol)
if conf.binaryFields:
conf.binaryFields = re.sub(r"\s*,\s*", ",", conf.binaryFields)
2011-11-23 18:26:40 +04:00
threadData = getCurrentThreadData()
threadData.reset()
2015-07-26 17:18:41 +03:00
def _dirtyPatches():
"""
Place for "dirty" Python related patches
"""
httplib._MAXLINE = 1 * 1024 * 1024 # to accept overly long result lines (e.g. SQLi results in HTTP header responses)
def _purgeOutput():
2012-04-23 18:24:23 +04:00
"""
Safely removes (purges) output directory.
"""
2012-04-23 18:43:59 +04:00
if conf.purgeOutput:
2012-04-23 18:24:23 +04:00
purge(paths.SQLMAP_OUTPUT_PATH)
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
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
conf.wFileType = 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.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
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()
2011-04-30 17:20:05 +04:00
kb.cache.content = {}
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
kb.cookieEncodeChoice = None
2011-12-21 15:50:49 +04:00
kb.counters = {}
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
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
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
2011-04-30 17:20:05 +04:00
kb.headersFp = {}
2013-01-25 15:34:57 +04:00
kb.heuristicDbms = 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()
2015-11-17 01:46:10 +03:00
for _ in ("cache", "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()
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
kb.timeValidCharsRun = 0
2012-02-07 14:46:55 +04:00
kb.uChar = NULL
kb.unionDuplicates = 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':
map(lambda x: conf.__setitem__(x, True), WIZARD.INTERMEDIATE)
2012-10-05 12:24:09 +04:00
elif choice == '3':
map(lambda x: conf.__setitem__(x, True), WIZARD.ALL)
else:
map(lambda x: conf.__setitem__(x, 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")
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)
2010-05-28 19:57:43 +04:00
config = UnicodeRawConfigParser()
2008-10-15 19:38:22 +04:00
userOpts = {}
for family in optDict.keys():
userOpts[family] = []
for option, value in conf.items():
for family, optionData in optDict.items():
if option in optionData:
userOpts[family].append((option, value, optionData[option]))
for family, optionData in userOpts.items():
config.add_section(family)
2008-10-15 19:38:22 +04:00
optionData.sort()
for option, value, datatype in optionData:
2012-06-14 17:38:53 +04:00
if datatype and isListLike(datatype):
2010-05-28 19:57:43 +04:00
datatype = datatype[0]
if option in IGNORE_SAVE_OPTIONS:
continue
if value is None:
2014-04-25 11:17:10 +04:00
if datatype == OPTION_TYPE.BOOLEAN:
2008-10-15 19:38:22 +04:00
value = "False"
2014-04-25 11:17:10 +04:00
elif datatype in (OPTION_TYPE.INTEGER, OPTION_TYPE.FLOAT):
if option in defaults:
value = str(defaults[option])
else:
value = "0"
2014-04-25 11:17:10 +04:00
elif datatype == OPTION_TYPE.STRING:
2008-10-15 19:38:22 +04:00
value = ""
if isinstance(value, basestring):
value = value.replace("\n", "\n ")
config.set(family, option, value)
2008-10-15 19:38:22 +04:00
confFP = openFile(conf.saveConfig, "wb")
2014-12-13 02:08:18 +03:00
try:
config.write(confFP)
except IOError, ex:
errMsg = "something went wrong while trying "
2016-01-12 12:27:04 +03:00
errMsg += "to write to the configuration file '%s' ('%s')" % (conf.saveConfig, getSafeExString(ex))
2014-12-13 02:08:18 +03:00
raise SqlmapSystemException(errMsg)
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.pickledOptions:
2015-08-18 23:03:42 +03:00
try:
inputOptions = base64unpickle(inputOptions.pickledOptions)
2016-07-28 18:02:27 +03:00
if type(inputOptions) == dict:
inputOptions = AttribDict(inputOptions)
2016-07-28 18:04:15 +03:00
_normalizeOptions(inputOptions)
2015-08-18 23:03:42 +03:00
except Exception, ex:
errMsg = "provided invalid value '%s' for option '--pickled-options'" % inputOptions.pickledOptions
errMsg += " ('%s')" % ex if ex.message else ""
2015-08-18 23:03:42 +03:00
raise SqlmapSyntaxException(errMsg)
2008-10-15 19:38:22 +04:00
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
for key, value in conf.items():
2012-07-17 12:36:22 +04:00
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
def _setDNSServer():
2012-07-24 17:34:50 +04:00
if not conf.dnsName:
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)
s = None
found = None
for port in (DEFAULT_TOR_HTTP_PORTS if not conf.torPort else (conf.torPort,)):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((LOCALHOST, port))
found = port
break
except socket.error:
pass
if s:
s.close()
if found:
conf.proxy = "http://%s:%d" % (LOCALHOST, found)
else:
errMsg = "can't establish connection with the Tor HTTP proxy. "
errMsg += "Please make sure that you have Vidalia, Privoxy or "
errMsg += "Polipo bundle installed for you to be able to "
2012-02-01 18:49:42 +04:00
errMsg += "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)
2011-12-04 20:37:18 +04:00
# Has to be SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29)
2012-11-28 13:59:15 +04:00
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if conf.torType == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, LOCALHOST, conf.torPort or DEFAULT_TOR_SOCKS_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 funcionality"
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:
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:
2012-10-16 12:28:59 +04:00
errMsg = "value for option '--start' (limitStart) must be smaller or equal than value for --stop (limitStop) option"
raise SqlmapSyntaxException(errMsg)
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
if conf.direct and conf.url:
errMsg = "option '-d' is incompatible with option '-u' ('--url')"
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)
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
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)
except re.error, 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)
except re.error, 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)):
2012-02-01 18:49:42 +04:00
errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address using Tor)"
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):
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 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.charset:
2012-09-25 12:17:25 +04:00
_ = checkCharEncoding(conf.charset, False)
if _ is None:
2011-06-08 20:08:20 +04:00
errMsg = "unknown charset '%s'. Please visit " % conf.charset
errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE
errMsg += "supported charsets"
raise SqlmapSyntaxException(errMsg)
2012-09-25 12:17:25 +04:00
else:
conf.charset = _
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()
2015-07-26 17:18:41 +03:00
_dirtyPatches()
_purgeOutput()
_checkDependencies()
2015-01-13 12:33:51 +03:00
_createTemporaryDirectory()
_basicOptionValidation()
2013-08-12 16:25:51 +04:00
_setProxyList()
_setTorProxySettings()
_setDNSServer()
_adjustLoggingFormatter()
_setMultipleTargets()
_setTamperingFunctions()
_setWafFunctions()
_setTrafficOutputFP()
_resolveCrossReferences()
_checkWebSocket()
parseTargetUrl()
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)):
_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()