sqlmap/lib/core/option.py

2156 lines
72 KiB
Python
Raw Normal View History

2008-10-15 19:38:22 +04:00
#!/usr/bin/env python
"""
2012-07-12 21:38:03 +04:00
Copyright (c) 2006-2012 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 inspect
2008-10-15 19:38:22 +04:00
import logging
import os
import re
import socket
2012-10-18 13:11:20 +04:00
import string
2010-10-15 14:36:29 +04:00
import sys
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.core.common
import lib.core.threads
2012-07-31 13:03:44 +04:00
import lib.core.convert
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 dataToStdout
2011-04-07 14:00:47 +04:00
from lib.core.common import getPublicTypeMembers
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 randomRange
from lib.core.common import randomStr
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
2008-10-15 19:38:22 +04:00
from lib.core.common import sanitizeStr
from lib.core.common import setOptimize
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.common import urlencode
from lib.core.convert import base64pickle
from lib.core.convert import base64unpickle
from lib.core.convert import jsonize
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
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
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
2011-03-18 16:46:51 +03:00
from lib.core.enums import HTTPHEADER
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
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
from lib.core.exception import SqlmapMissingDependence
from lib.core.exception import SqlmapMissingMandatoryOptionException
from lib.core.exception import SqlmapMissingPrivileges
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapSyntaxException
from lib.core.exception import SqlmapUnsupportedDBMSException
from lib.core.exception import SqlmapUserQuitException
from lib.core.log import FORMATTER
2012-08-16 00:31:25 +04:00
from lib.core.log import LOGGER_HANDLER
2008-10-15 19:38:22 +04:00
from lib.core.optiondict import optDict
2012-04-23 18:24:23 +04:00
from lib.core.purge import purge
from lib.core.settings import ACCESS_ALIASES
from lib.core.settings import BURP_REQUEST_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 DB2_ALIASES
2011-11-22 01:31:08 +04:00
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
2011-11-24 01:39:53 +04:00
from lib.core.settings import DEFAULT_TOR_SOCKS_PORT
from lib.core.settings import FIREBIRD_ALIASES
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 LOCALHOST
from lib.core.settings import MAXDB_ALIASES
from lib.core.settings import MAX_NUMBER_OF_THREADS
from lib.core.settings import MSSQL_ALIASES
from lib.core.settings import MYSQL_ALIASES
2012-02-07 14:46:55 +04:00
from lib.core.settings import NULL
from lib.core.settings import ORACLE_ALIASES
from lib.core.settings import PARAMETER_SPLITTING_REGEX
from lib.core.settings import PGSQL_ALIASES
from lib.core.settings import PYVERSION
from lib.core.settings import SITE
from lib.core.settings import SQLITE_ALIASES
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 SYBASE_ALIASES
from lib.core.settings import TIME_DELAY_CANDIDATES
from lib.core.settings import UNENCODED_ORIGINAL_VALUE
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
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 loadPayloads
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
2008-10-15 19:38:22 +04:00
from lib.request.proxy import ProxyHTTPSHandler
from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler
2010-01-07 15:59:09 +03:00
from lib.request.certhandler import HTTPSCertAuthHandler
2012-06-04 23:46:28 +04:00
from lib.request.httpshandler import HTTPSHandler
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
2008-10-15 19:38:22 +04:00
from lib.utils.google import Google
2012-07-14 19:01:04 +04:00
from thirdparty.colorama.initialise import init as coloramainit
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()
2008-10-15 19:38:22 +04:00
proxyHandler = urllib2.BaseHandler()
redirectHandler = SmartRedirectHandler()
rangeHandler = HTTPRangeHandler()
2008-10-15 19:38:22 +04:00
2012-12-10 20:20:04 +04:00
def _urllib2Opener():
2008-10-15 19:38:22 +04:00
"""
This function creates the urllib2 OpenerDirector.
"""
debugMsg = "creating HTTP requests opener object"
logger.debug(debugMsg)
2012-06-04 23:46:28 +04:00
handlers = [proxyHandler, authHandler, redirectHandler, rangeHandler, httpsHandler]
2010-06-10 18:14:56 +04:00
2010-06-01 16:21:10 +04:00
if not conf.dropSetCookie:
2012-07-24 17:34:50 +04:00
if not conf.loadCookies:
2012-03-07 18:48:45 +04:00
conf.cj = cookielib.CookieJar()
else:
conf.cj = cookielib.MozillaCookieJar()
2012-03-08 14:19:34 +04:00
resetCookieJar(conf.cj)
2012-03-07 18:48:45 +04:00
2010-06-01 16:21:10 +04:00
handlers.append(urllib2.HTTPCookieProcessor(conf.cj))
2010-06-10 18:14:56 +04:00
# Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html
if conf.keepAlive:
2011-01-12 00:46:21 +03:00
warnMsg = "persistent HTTP(s) connections, Keep-Alive, has "
2012-03-14 02:03:23 +04:00
warnMsg += "been disabled because of its incompatibility "
2011-01-12 00:46:21 +03:00
if conf.proxy:
warnMsg += "with HTTP(s) proxy"
logger.warn(warnMsg)
elif conf.aType:
warnMsg += "with authentication methods"
logger.warn(warnMsg)
else:
handlers.append(keepAliveHandler)
2008-10-15 19:38:22 +04:00
2010-06-10 18:14:56 +04:00
opener = urllib2.build_opener(*handlers)
2008-10-15 19:38:22 +04:00
urllib2.install_opener(opener)
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
"""
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:
kb.targets.add((url, method, None, cookie))
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):
2011-10-27 21:31:34 +04:00
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)
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-01-10 18:02:28 +04:00
if not re.search(r"^[\n]*(GET|POST).*?\sHTTP\/", request, re.I | re.M):
continue
2012-04-11 02:26:42 +04:00
if re.search(r"^[\n]*(GET|POST).*?\.(%s)\sHTTP\/" % "|".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
lines = request.split("\n")
2011-01-20 18:55:50 +03:00
for line in lines:
if len(line) == 0 or line == "\n":
if method == HTTPMETHOD.POST and data is None:
data = ""
params = True
elif (line.startswith("GET ") or line.startswith("POST ")) and " HTTP/" in line:
2011-01-20 18:55:50 +03:00
if line.startswith("GET "):
index = 4
else:
index = 5
2011-01-20 18:55:50 +03:00
url = line[index:line.index(" HTTP/")]
2013-01-10 16:18:44 +04:00
method = line[:index - 1]
2011-01-20 18:55:50 +03:00
if "?" in line and "=" in line:
params = True
getPostReq = True
# POST parameters
elif data is not None and params:
2012-08-31 14:46:38 +04:00
data += "%s%s" % ("\n" if data else "", line)
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
2012-10-09 13:33:19 +04:00
elif re.search(r"\A\S+: ", line):
2011-01-20 18:55:50 +03:00
key, value = line.split(": ", 1)
2011-01-20 18:55:50 +03:00
# Cookie and Host headers
if key.lower() == "cookie":
cookie = value
elif key.lower() == "host":
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:
port = filterStringValue(splitValue[1], '[0-9]')
2011-01-20 18:55:50 +03:00
# Avoid to add a static content length header to
# conf.httpHeaders and consider the following lines as
# POSTed data
2011-11-29 23:17:07 +04:00
if key == HTTPHEADER.CONTENT_LENGTH:
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 (HTTPHEADER.PROXY_CONNECTION, HTTPHEADER.CONNECTION):
2012-07-13 12:28:03 +04:00
conf.httpHeaders.append((getUnicode(key), getUnicode(value)))
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"
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:
kb.targets.add((url, method, urldecode(data) if data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in data else data, cookie))
2012-01-16 14:28:21 +04:00
addedTargetUrls.add(url)
2010-03-05 17:06:03 +03:00
2011-01-20 18:55:50 +03:00
fp = openFile(reqFile, "rb")
2010-03-05 17:06:03 +03:00
2011-01-20 19:07:08 +03:00
content = fp.read()
content = content.replace("\r", "")
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)
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()
tree.parse(paths.QUERIES_XML)
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)
infoMsg += "testable requests from the targets list"
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):
_ = boldifyMessage(FORMATTER._format(record))
if kb.prependFlag:
_ = "\n%s" % _
kb.prependFlag = False
return _
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()
conf.requestFile = os.path.expanduser(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
2013-01-09 18:22:21 +04:00
crawl(conf.url)
def _setGoogleDorking():
"""
This function checks if the way to request testable hosts is through
Google dorking then requests to Google the search parameter, parses
the results and save the testable hosts into the knowledge base.
"""
if not conf.googleDork:
return
global keepAliveHandler
global proxyHandler
debugMsg = "initializing Google dorking requests"
logger.debug(debugMsg)
2011-04-30 19:29:59 +04:00
infoMsg = "first request to Google to get the session cookie"
logger.info(infoMsg)
2013-01-10 14:54:07 +04:00
handlers = [proxyHandler]
# Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html
if conf.keepAlive:
if conf.proxy:
warnMsg = "persistent HTTP(s) connections, Keep-Alive, has "
2012-03-14 02:03:23 +04:00
warnMsg += "been disabled because of its incompatibility "
warnMsg += "with HTTP(s) proxy"
logger.warn(warnMsg)
else:
handlers.append(keepAliveHandler)
googleObj = Google(handlers)
kb.data.onlyGETs = None
def retrieve():
links = googleObj.search(conf.googleDork)
if not links:
errMsg = "unable to find results for your "
errMsg += "Google dork expression"
raise SqlmapGenericException(errMsg)
for link in links:
link = urldecode(link)
if re.search(r"(.*?)\?(.+)", link):
kb.targets.add((link, conf.method, conf.data, conf.cookie))
elif re.search(URI_INJECTABLE_REGEX, link, re.I):
if kb.data.onlyGETs is None and conf.data is None:
message = "do you want to scan only results containing GET parameters? [Y/n] "
test = readInput(message, default="Y")
kb.data.onlyGETs = test.lower() != 'n'
if not kb.data.onlyGETs:
kb.targets.add((link, conf.method, conf.data, conf.cookie))
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 += "Google 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 Google 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
conf.bulkFile = os.path.expanduser(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)
2012-07-17 01:28:01 +04:00
for line in getFileItems(conf.bulkFile):
if re.search(r"[^ ]+\?(.+)", line, re.I):
kb.targets.add((line.strip(), None, None, None))
2011-06-08 20:08:20 +04:00
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)
2013-01-09 18:22:21 +04:00
if not conf.bulkFile:
page, _ = Request.queryPage(content=True)
findPageForms(page, conf.url, True, True)
else:
2013-01-09 19:10:26 +04:00
targets = getFileItems(conf.bulkFile)
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)
2013-01-09 18:58:13 +04:00
except Exception, ex:
errMsg = "problem occured while searching for forms at '%s' ('%s')" % (target, ex)
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:
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")):
2012-07-06 19:28:01 +04:00
if all(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("", "msfcli", "msfconsole", "msfencode", "msfpayload")):
2012-07-06 19:34:40 +04:00
msfEnvPathExists = True
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(";", "")
2012-07-06 19:28:01 +04:00
if all(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("", "msfcli", "msfconsole", "msfencode", "msfpayload")):
infoMsg = "Metasploit Framework has been found "
infoMsg += "installed in the '%s' path" % envPath
logger.info(infoMsg)
msfEnvPathExists = True
2011-04-30 17:20:05 +04:00
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 "
errMsg += "system. The supported DBMS are %s. " % ', '.join([d for d 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 aliases in (MSSQL_ALIASES, MYSQL_ALIASES, PGSQL_ALIASES, ORACLE_ALIASES, \
SQLITE_ALIASES, ACCESS_ALIASES, FIREBIRD_ALIASES, \
MAXDB_ALIASES, SYBASE_ALIASES, DB2_ALIASES):
if conf.dbms in aliases:
conf.dbms = aliases[0]
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:
module = __import__(filename[:-3])
except ImportError, msg:
raise SqlmapSyntaxException("cannot import tamper script '%s' (%s)" % (filename[:-3], msg))
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):
2012-12-03 17:27:01 +04:00
if name == "tamper":
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:
2011-04-30 17:20:05 +04:00
message = "it seems 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:
2012-07-27 02:11:07 +04:00
errMsg = "missing function 'tamper(payload, headers)' "
errMsg += "in tamper script '%s'" % tfile
raise SqlmapGenericException(errMsg)
2010-10-13 02:45:25 +04:00
if resolve_priorities and priorities:
priorities.sort(reverse=True)
kb.tamperFunctions = []
for _, function in priorities:
kb.tamperFunctions.append(function)
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]
2011-04-11 00:53:27 +04:00
if not hasattr(socket, '_getaddrinfo'):
2011-04-08 01:39:18 +04:00
socket._getaddrinfo = socket.getaddrinfo
socket.getaddrinfo = _getaddrinfo
def _setHTTPProxy():
2008-10-15 19:38:22 +04:00
"""
Check and set the HTTP proxy to pass by all HTTP requests.
"""
global proxyHandler
if not conf.proxy:
2010-02-26 13:01:23 +03:00
if conf.hostname in ('localhost', '127.0.0.1') or conf.ignoreProxy:
proxyHandler = urllib2.ProxyHandler({})
2008-10-15 19:38:22 +04:00
return
2012-07-16 14:24:54 +04:00
debugMsg = "setting the HTTP/SOCKS proxy to pass by all HTTP requests"
2008-10-15 19:38:22 +04:00
logger.debug(debugMsg)
2012-07-16 14:12:52 +04:00
proxySplit = urlparse.urlsplit(conf.proxy)
2013-01-10 18:41:07 +04:00
hostnamePort = proxySplit.netloc.split(":")
2008-10-15 19:38:22 +04:00
2013-01-10 18:41:07 +04:00
scheme = proxySplit.scheme.upper()
2012-07-16 14:12:52 +04:00
hostname = hostnamePort[0]
port = None
username = None
password = None
2008-10-15 19:38:22 +04:00
2012-07-16 14:12:52 +04:00
if len(hostnamePort) == 2:
try:
2012-07-16 14:12:52 +04:00
port = int(hostnamePort[1])
except:
2013-01-10 16:18:44 +04:00
pass # drops into the next check block
2008-10-15 19:38:22 +04:00
2012-11-28 13:59:15 +04:00
if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)):
errMsg = "proxy value must be in format '(%s)://url:port'" % "|".join(_[0].lower() for _ in getPublicTypeMembers(PROXY_TYPE))
raise SqlmapSyntaxException(errMsg)
2008-10-15 19:38:22 +04:00
if conf.pCred:
2012-07-16 14:12:52 +04:00
_ = re.search("^(.*?):(.*?)$", conf.pCred)
if not _:
2011-04-30 17:20:05 +04:00
errMsg = "Proxy authentication credentials "
errMsg += "value must be in format username:password"
raise SqlmapSyntaxException(errMsg)
2012-07-16 14:12:52 +04:00
else:
username = _.group(1)
password = _.group(2)
2012-11-28 13:59:15 +04:00
if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5):
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if scheme == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, hostname, port, username=username, password=password)
2012-07-16 14:12:52 +04:00
socks.wrapmodule(urllib2)
2008-10-15 19:38:22 +04:00
else:
2012-07-16 14:12:52 +04:00
if conf.pCred:
# Reference: http://stackoverflow.com/questions/34079/how-to-specify-an-authenticated-proxy-for-a-python-http-connection
proxyString = "%s@" % conf.pCred
else:
proxyString = ""
proxyString += "%s:%d" % (hostname, port)
# Workaround for http://bugs.python.org/issue1424152 (urllib/urllib2:
# HTTPS over (Squid) Proxy fails) as long as HTTP over SSL requests
# can't be tunneled over an HTTP proxy natively by Python (<= 2.5)
# urllib2 standard library
if PYVERSION >= "2.6":
proxyHandler = urllib2.ProxyHandler({"http": proxyString, "https": proxyString})
elif conf.scheme == "https":
proxyHandler = ProxyHTTPSHandler(proxyString)
else:
proxyHandler = urllib2.ProxyHandler({"http": proxyString})
2008-10-15 19:38:22 +04:00
def _setSafeUrl():
"""
Check and set the safe URL options.
"""
if not conf.safUrl:
return
if not re.search("^http[s]*://", conf.safUrl):
if ":443/" in conf.safUrl:
conf.safUrl = "https://" + conf.safUrl
else:
conf.safUrl = "http://" + conf.safUrl
if conf.saFreq <= 0:
errMsg = "please provide a valid value (>0) for safe frequency (--safe-freq) while using safe url feature"
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:
kb.passwordMgr.add_password(None, "%s://%s" % (conf.scheme, conf.hostname), conf.authUsername, conf.authPassword)
def _setHTTPAuthentication():
2008-10-15 19:38:22 +04:00
"""
2010-01-07 15:59:09 +03:00
Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or Certificate),
username and password for first three methods, or key file and certification file for
certificate authentication
2008-10-15 19:38:22 +04:00
"""
global authHandler
2010-01-07 15:59:09 +03:00
if not conf.aType and not conf.aCred and not conf.aCert:
2008-10-15 19:38:22 +04:00
return
elif conf.aType and not conf.aCred:
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
elif not conf.aType and conf.aCred:
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
2010-01-07 15:59:09 +03:00
if not conf.aCert:
debugMsg = "setting the HTTP authentication type and credentials"
logger.debug(debugMsg)
2010-01-07 15:59:09 +03:00
aTypeLower = conf.aType.lower()
if aTypeLower not in ("basic", "digest", "ntlm"):
2011-04-30 17:20:05 +04:00
errMsg = "HTTP authentication type value must be "
2010-01-07 15:59:09 +03:00
errMsg += "Basic, Digest or NTLM"
raise SqlmapSyntaxException(errMsg)
elif aTypeLower in ("basic", "digest"):
regExp = "^(.*?):(.*?)$"
2011-04-30 17:20:05 +04:00
errMsg = "HTTP %s authentication credentials " % aTypeLower
errMsg += "value must be in format username:password"
elif aTypeLower == "ntlm":
regExp = "^(.*\\\\.*):(.*?)$"
2011-04-30 17:20:05 +04:00
errMsg = "HTTP NTLM authentication credentials value must "
errMsg += "be in format DOMAIN\username:password"
aCredRegExp = re.search(regExp, conf.aCred)
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
2010-01-07 15:59:09 +03:00
if aTypeLower == "basic":
authHandler = SmartHTTPBasicAuthHandler(kb.passwordMgr)
2010-01-07 15:59:09 +03:00
elif aTypeLower == "digest":
authHandler = urllib2.HTTPDigestAuthHandler(kb.passwordMgr)
2010-01-07 15:59:09 +03:00
elif aTypeLower == "ntlm":
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 certificate"
logger.debug(debugMsg)
2010-01-07 15:59:09 +03:00
aCertRegExp = re.search("^(.+?),\s*(.+?)$", conf.aCert)
2010-01-07 15:59:09 +03:00
if not aCertRegExp:
2011-04-30 17:20:05 +04:00
errMsg = "HTTP authentication certificate option "
2010-01-07 15:59:09 +03:00
errMsg += "must be in format key_file,cert_file"
raise SqlmapSyntaxException(errMsg)
# os.path.expanduser for support of paths with ~
2010-01-07 15:59:09 +03:00
key_file = os.path.expanduser(aCertRegExp.group(1))
cert_file = os.path.expanduser(aCertRegExp.group(2))
2010-03-21 03:39:44 +03:00
for ifile in (key_file, cert_file):
if not os.path.exists(ifile):
2011-04-30 17:20:05 +04:00
errMsg = "File '%s' does not exist" % ifile
raise SqlmapSyntaxException(errMsg)
2010-01-07 15:59:09 +03:00
authHandler = HTTPSCertAuthHandler(key_file, cert_file)
2009-12-03 01:54:39 +03:00
def _setHTTPMethod():
2008-10-15 19:38:22 +04:00
"""
Check and set the HTTP method to perform HTTP requests through.
"""
2012-11-13 13:21:11 +04:00
conf.method = HTTPMETHOD.POST if conf.data is not None else HTTPMETHOD.GET
2008-10-15 19:38:22 +04:00
debugMsg = "setting the HTTP method to %s" % conf.method
logger.debug(debugMsg)
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:
2012-04-23 14:11:00 +04:00
if headerValue.count(':') == 1:
2012-01-07 19:26:54 +04:00
header, value = (_.lstrip() for _ in headerValue.split(":"))
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
elif not conf.httpHeaders or len(conf.httpHeaders) == 1:
2011-11-29 23:17:07 +04:00
conf.httpHeaders.append((HTTPHEADER.ACCEPT_LANGUAGE, "en-us,en;q=0.5"))
2011-10-26 02:06:47 +04:00
if not conf.charset:
2011-11-29 23:17:07 +04:00
conf.httpHeaders.append((HTTPHEADER.ACCEPT_CHARSET, "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
2011-10-26 02:06:47 +04:00
else:
2011-11-29 23:17:07 +04:00
conf.httpHeaders.append((HTTPHEADER.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
2011-11-29 23:17:07 +04:00
conf.httpHeaders.append((HTTPHEADER.CACHE_CONTROL, "no-cache,no-store"))
conf.httpHeaders.append((HTTPHEADER.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
2012-10-30 13:30:22 +04:00
conf.httpHeaders.append((HTTPHEADER.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)
2012-10-07 22:28:24 +04:00
conf.httpHeaders.append((HTTPHEADER.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:
2012-10-07 22:28:24 +04:00
if header == HTTPHEADER.USER_AGENT:
2012-06-28 15:55:30 +04:00
_ = False
break
2012-06-28 15:55:30 +04:00
if _:
conf.httpHeaders.append((HTTPHEADER.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((HTTPHEADER.USER_AGENT, _defaultHTTPUserAgent()))
2011-04-30 11:01:21 +04:00
return
2008-10-15 19:38:22 +04:00
2011-04-29 23:27:23 +04:00
count = len(kb.userAgents)
2008-10-15 19:38:22 +04:00
2011-04-29 23:27:23 +04:00
if count == 1:
userAgent = kb.userAgents[0]
else:
2013-01-10 18:02:28 +04:00
userAgent = kb.userAgents[randomRange(stop=count - 1)]
2008-10-15 19:38:22 +04:00
2011-04-29 23:27:23 +04:00
userAgent = sanitizeStr(userAgent)
conf.httpHeaders.append((HTTPHEADER.USER_AGENT, userAgent))
2011-04-30 19:29:59 +04:00
infoMsg = "fetched random HTTP User-Agent header from "
infoMsg += "file '%s': %s" % (paths.USER_AGENTS, userAgent)
logger.info(infoMsg)
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)
2011-03-18 16:46:51 +03:00
conf.httpHeaders.append((HTTPHEADER.REFERER, conf.referer))
2008-10-15 19:38:22 +04:00
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)
2011-03-18 16:46:51 +03:00
conf.httpHeaders.append((HTTPHEADER.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()
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
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 = []
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 = []
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 = []
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))
if conf.msfPath:
conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath))
if conf.tmpPath:
conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath))
2011-06-24 09:40:03 +04:00
if conf.googleDork or conf.logFile or conf.bulkFile or conf.forms or 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 re.search(r'%[0-9a-f]{2}', conf.data, re.I):
2013-01-10 16:18:44 +04:00
class _(unicode):
pass
original = conf.data
2012-10-15 18:23:41 +04:00
conf.data = _(urldecode(conf.data))
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
else:
2012-10-15 18:23:41 +04:00
conf.data = urldecode(conf.data)
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:
if not any([char in conf.testFilter for char in ('.', ')', '(', ']', '[')]):
conf.testFilter = conf.testFilter.replace('*', '.*')
if conf.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
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
2011-12-23 14:57:09 +04:00
if conf.torPort and conf.torPort.isdigit():
conf.torPort = int(conf.torPort)
2011-12-16 03:19:55 +04:00
if conf.torType:
conf.torType = conf.torType.upper()
2012-07-03 02:50:23 +04:00
if conf.oDir:
paths.SQLMAP_OUTPUT_PATH = conf.oDir
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()
2011-11-23 18:26:40 +04:00
threadData = getCurrentThreadData()
threadData.reset()
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.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-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 = {}
2012-07-06 19:34:40 +04:00
kb.chars = AttribDict()
kb.chars.delimiter = randomStr(length=6, lowercase=True)
kb.chars.start = ":%s:" % randomStr(length=3, lowercase=True)
kb.chars.stop = ":%s:" % randomStr(length=3, lowercase=True)
kb.chars.at, kb.chars.space, kb.chars.dollar, kb.chars.hash_ = (":%s:" % _ for _ in randomStr(length=4, lowercase=True))
2011-04-30 17:20:05 +04:00
kb.commonOutputs = 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
kb.dumpTable = None
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()
2011-04-30 17:20:05 +04:00
kb.errorIsNone = True
2012-07-06 16:24:44 +04:00
kb.fileReadMode = False
2011-09-26 01:10:45 +04:00
kb.forcedDbms = None
2011-04-30 17:20:05 +04:00
kb.headersFp = {}
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.lastParserStatus = None
2011-07-08 10:02:31 +04:00
kb.locks = AttribDict()
2012-12-20 14:06:52 +04:00
for _ in ("cache", "count", "index", "io", "limit", "log", "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
2012-09-11 16:58:52 +04:00
kb.pageCompress = True
2011-04-30 17:20:05 +04:00
kb.pageTemplate = None
kb.pageTemplates = dict()
2012-10-04 13:25:44 +04:00
kb.postHint = None
2011-09-09 15:36:09 +04:00
kb.previousMethod = None
kb.processUserMarks = None
kb.orderByColumns = None
kb.originalCode = None
2011-04-30 17:20:05 +04:00
kb.originalPage = 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
kb.pageEncoding = DEFAULT_PAGE_ENCODING
kb.pageStable = None
kb.partRun = None
2012-02-08 16:02:50 +04:00
kb.permissionFlag = False
kb.prependFlag = False
2011-11-22 16:18:24 +04:00
kb.processResponseCounter = 0
2011-04-30 17:20:05 +04:00
kb.proxyAuthHeader = None
kb.queryCounter = 0
kb.redirectChoice = None
2011-04-30 17:20:05 +04:00
kb.redirectSetCookie = 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}
2011-04-30 17:20:05 +04:00
kb.responseTimes = []
kb.resumeValues = True
kb.safeCharEncode = False
2011-04-30 17:20:05 +04:00
kb.singleLogFlags = set()
kb.skipOthersDbms = None
2012-07-12 17:24:40 +04:00
kb.stickyDBMS = False
2012-07-12 17:23:35 +04:00
kb.stickyLevel = None
2011-04-30 17:20:05 +04:00
kb.suppressResumeInfo = False
kb.technique = None
kb.testMode = False
kb.testQueryCount = 0
kb.threadContinue = True
kb.threadException = False
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
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()
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")
while True:
while not conf.url:
message = "Please enter full target URL (-u): "
conf.url = readInput(message, default=None)
message = "POST data (--data) [Enter for None]: "
conf.data = readInput(message, default=None)
2011-05-25 12:14:39 +04:00
if filter(lambda x: '=' in str(x), [conf.url, conf.data]) or '*' in conf.url:
break
else:
2011-11-15 15:17:39 +04:00
warnMsg = "no GET and/or POST parameter(s) found for testing "
warnMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')"
logger.critical(warnMsg)
2011-11-02 18:33:23 +04:00
if conf.crawlDepth or conf.forms:
break
else:
conf.url = conf.data = None
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] Smart\n[3] All"
choice = readInput(message, default='1')
2012-10-05 12:24:09 +04:00
if choice == '2':
map(lambda x: conf.__setitem__(x, True), WIZARD.SMART)
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 _saveCmdline():
2008-10-15 19:38:22 +04:00
"""
Saves the command line options on a sqlmap configuration INI file
Format.
2008-10-15 19:38:22 +04:00
"""
if not conf.saveCmdline:
return
debugMsg = "saving command line options on a sqlmap configuration INI file"
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 value is None:
2008-10-15 19:38:22 +04:00
if datatype == "boolean":
value = "False"
elif datatype in ("integer", "float"):
if option in ("threads", "verbose"):
value = "1"
elif option == "timeout":
value = "10"
else:
value = "0"
2008-10-15 19:38:22 +04:00
elif datatype == "string":
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(paths.SQLMAP_CONFIG, "wb")
config.write(confFP)
2008-10-15 19:38:22 +04:00
infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG
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
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:
inputOptions = base64unpickle(inputOptions.pickledOptions)
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
# Logger recorder object, which keeps the log structure
class LogRecorder(logging.StreamHandler):
"""
Logging handler class which only records CUSTOM_LOGGING.PAYLOAD entries
to a global list.
"""
loghist = []
def emit(self, record):
"""
Simply record the emitted events.
"""
self.loghist.append({'levelname': record.levelname,
'text': record.msg % record.args if record.args else record.msg,
2013-01-10 18:02:28 +04:00
'id': len(self.loghist) + 1})
if conf.fdLog:
2013-01-10 05:11:22 +04:00
# TODO: this is very heavy operation and slows down a lot the
# whole execution of the sqlmap engine, find an alternative
os.write(conf.fdLog, base64pickle(self.loghist))
def _setRestAPILog():
if hasattr(conf, "fdLog") and conf.fdLog:
logger.removeHandler(LOGGER_HANDLER)
LOGGER_RECORDER = LogRecorder()
logger.addHandler(LOGGER_RECORDER)
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)
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)
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
s.close()
if found:
conf.proxy = "http://%s:%d" % (LOCALHOST, found)
else:
errMsg = "can't establish connection with the Tor 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' "
if IS_WIN:
errMsg += "(e.g. https://www.torproject.org/projects/vidalia.html.en)"
else:
errMsg += "(e.g. http://www.coresec.org/2011/04/24/sqlmap-with-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 "
warnMsg += "your own convenience when using "
warnMsg += "HTTP proxy type (option '--tor-type') "
2012-05-10 22:25:12 +04:00
warnMsg += "for accessing 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 _checkTor():
if not conf.checkTor:
return
2011-10-25 22:07:33 +04:00
infoMsg = "checking Tor connection"
logger.info(infoMsg)
page, _, _ = Request.getPage(url="https://check.torproject.org/", raise404=False)
if not page or 'Congratulations' not in page:
2012-04-05 03:47:06 +04:00
errMsg = "it seems 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 > 0):
errMsg = "value for option '--level' must be an integer value greater than zero (>0)"
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 > 0):
errMsg = "value for option '--risk' must be an integer value greater than zero (>0)"
raise SqlmapSyntaxException(errMsg)
2010-10-15 14:28:06 +04:00
if conf.limitStart is not None and isinstance(conf.limitStart, int) and conf.limitStart > 0 and \
conf.limitStop is not None 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)
if conf.firstChar is not None and isinstance(conf.firstChar, int) and conf.firstChar > 0 and \
conf.lastChar is not None 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)
2010-10-15 14:28:06 +04:00
if conf.cpuThrottle is not None and isinstance(conf.cpuThrottle, int) and (conf.cpuThrottle > 100 or conf.cpuThrottle < 0):
2012-10-16 12:28:59 +04:00
errMsg = "value for option '--cpu-throttle' (cpuThrottle) must be in range [0,100]"
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
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
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.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
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
2011-02-02 13:10:28 +03:00
if conf.threads > MAX_NUMBER_OF_THREADS:
errMsg = "maximum number of used threads is %d avoiding possible connection issues" % MAX_NUMBER_OF_THREADS
raise SqlmapSyntaxException(errMsg)
2013-01-10 18:02:28 +04:00
if conf.forms and not any((conf.url, conf.bulkFile)):
2013-01-09 18:22:21 +04:00
errMsg = "switch '--forms' requires usage of option '-u' (--url) or '-m'"
raise SqlmapSyntaxException(errMsg)
if conf.requestFile and conf.url:
errMsg = "option '-r' is incompatible with option '-u' (--url)"
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
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)
2011-12-23 14:57:09 +04:00
if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort > 0):
2012-02-01 18:49:42 +04:00
errMsg = "value for option '--tor-port' must be a positive integer"
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)
2013-01-09 18:22:21 +04:00
if conf.forms and any([conf.logFile, conf.direct, conf.requestFile, conf.googleDork]):
errMsg = "switch '--forms' is compatible only with options '-u' (--url) and '-m'"
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.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
2011-07-08 10:02:31 +04:00
def init(inputOptions=AttribDict(), overrideOptions=False):
2008-10-15 19:38:22 +04:00
"""
Set attributes into both configuration and knowledge base singletons
based upon command line and configuration file options.
"""
2012-08-16 00:31:25 +04:00
if not inputOptions.disableColoring:
coloramainit()
_setConfAttributes()
_setKnowledgeBaseAttributes()
_mergeOptions(inputOptions, overrideOptions)
_useWizardInterface()
setVerbosity()
_setRestAPILog()
_saveCmdline()
_setRequestFromFile()
_cleanupOptions()
_purgeOutput()
_checkDependencies()
_basicOptionValidation()
_setTorProxySettings()
_setDNSServer()
_adjustLoggingFormatter()
_setMultipleTargets()
_setTamperingFunctions()
_setTrafficOutputFP()
_resolveCrossReferences()
parseTargetUrl()
parseTargetDirect()
if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.liveTest)):
_setHTTPTimeout()
_setHTTPExtraHeaders()
_setHTTPCookies()
_setHTTPReferer()
_setHTTPUserAgent()
_setHTTPMethod()
_setHTTPAuthentication()
_setHTTPProxy()
_setDNSCache()
_setSafeUrl()
_setGoogleDorking()
_setBulkMultipleTargets()
2012-12-10 20:20:04 +04:00
_urllib2Opener()
_checkTor()
_setCrawler()
_findPageForms()
_setDBMS()
_setTechnique()
_setThreads()
_setOS()
_setWriteFile()
_setMetasploit()
_setDBMSAuthentication()
loadPayloads()
_setPrefixSuffix()
2008-10-15 19:38:22 +04:00
update()
_loadQueries()