1#!/usr/bin/env python 2 3""" 4Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/) 5See the file 'LICENSE' for copying permission 6""" 7 8from __future__ import division 9 10import codecs 11import functools 12import glob 13import inspect 14import logging 15import os 16import random 17import re 18import socket 19import sys 20import tempfile 21import threading 22import time 23 24from lib.controller.checks import checkConnection 25from lib.core.common import Backend 26from lib.core.common import boldifyMessage 27from lib.core.common import checkFile 28from lib.core.common import dataToStdout 29from lib.core.common import decodeStringEscape 30from lib.core.common import fetchRandomAgent 31from lib.core.common import filterNone 32from lib.core.common import findLocalPort 33from lib.core.common import findPageForms 34from lib.core.common import getConsoleWidth 35from lib.core.common import getFileItems 36from lib.core.common import getFileType 37from lib.core.common import getPublicTypeMembers 38from lib.core.common import getSafeExString 39from lib.core.common import intersect 40from lib.core.common import normalizePath 41from lib.core.common import ntToPosixSlashes 42from lib.core.common import openFile 43from lib.core.common import parseRequestFile 44from lib.core.common import parseTargetDirect 45from lib.core.common import paths 46from lib.core.common import randomStr 47from lib.core.common import readCachedFileContent 48from lib.core.common import readInput 49from lib.core.common import resetCookieJar 50from lib.core.common import runningAsAdmin 51from lib.core.common import safeExpandUser 52from lib.core.common import safeFilepathEncode 53from lib.core.common import saveConfig 54from lib.core.common import setColor 55from lib.core.common import setOptimize 56from lib.core.common import setPaths 57from lib.core.common import singleTimeWarnMessage 58from lib.core.common import urldecode 59from lib.core.compat import cmp 60from lib.core.compat import round 61from lib.core.compat import xrange 62from lib.core.convert import getUnicode 63from lib.core.data import conf 64from lib.core.data import kb 65from lib.core.data import logger 66from lib.core.data import mergedOptions 67from lib.core.data import queries 68from lib.core.datatype import AttribDict 69from lib.core.datatype import InjectionDict 70from lib.core.datatype import OrderedSet 71from lib.core.defaults import defaults 72from lib.core.dicts import DBMS_DICT 73from lib.core.dicts import DUMP_REPLACEMENTS 74from lib.core.enums import ADJUST_TIME_DELAY 75from lib.core.enums import AUTH_TYPE 76from lib.core.enums import CUSTOM_LOGGING 77from lib.core.enums import DUMP_FORMAT 78from lib.core.enums import HTTP_HEADER 79from lib.core.enums import HTTPMETHOD 80from lib.core.enums import MKSTEMP_PREFIX 81from lib.core.enums import MOBILES 82from lib.core.enums import OPTION_TYPE 83from lib.core.enums import PAYLOAD 84from lib.core.enums import PRIORITY 85from lib.core.enums import PROXY_TYPE 86from lib.core.enums import REFLECTIVE_COUNTER 87from lib.core.enums import WIZARD 88from lib.core.exception import SqlmapConnectionException 89from lib.core.exception import SqlmapDataException 90from lib.core.exception import SqlmapFilePathException 91from lib.core.exception import SqlmapGenericException 92from lib.core.exception import SqlmapInstallationException 93from lib.core.exception import SqlmapMissingDependence 94from lib.core.exception import SqlmapMissingMandatoryOptionException 95from lib.core.exception import SqlmapMissingPrivileges 96from lib.core.exception import SqlmapNoneDataException 97from lib.core.exception import SqlmapSilentQuitException 98from lib.core.exception import SqlmapSyntaxException 99from lib.core.exception import SqlmapSystemException 100from lib.core.exception import SqlmapUnsupportedDBMSException 101from lib.core.exception import SqlmapUserQuitException 102from lib.core.exception import SqlmapValueException 103from lib.core.log import FORMATTER 104from lib.core.optiondict import optDict 105from lib.core.settings import CODECS_LIST_PAGE 106from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR 107from lib.core.settings import DBMS_ALIASES 108from lib.core.settings import DEFAULT_GET_POST_DELIMITER 109from lib.core.settings import DEFAULT_PAGE_ENCODING 110from lib.core.settings import DEFAULT_TOR_HTTP_PORTS 111from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS 112from lib.core.settings import DEFAULT_USER_AGENT 113from lib.core.settings import DUMMY_URL 114from lib.core.settings import IGNORE_CODE_WILDCARD 115from lib.core.settings import IS_WIN 116from lib.core.settings import KB_CHARS_BOUNDARY_CHAR 117from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET 118from lib.core.settings import LOCALHOST 119from lib.core.settings import MAX_CONNECT_RETRIES 120from lib.core.settings import MAX_NUMBER_OF_THREADS 121from lib.core.settings import NULL 122from lib.core.settings import PARAMETER_SPLITTING_REGEX 123from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT 124from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE 125from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX 126from lib.core.settings import SUPPORTED_DBMS 127from lib.core.settings import SUPPORTED_OS 128from lib.core.settings import TIME_DELAY_CANDIDATES 129from lib.core.settings import UNION_CHAR_REGEX 130from lib.core.settings import UNKNOWN_DBMS_VERSION 131from lib.core.settings import URI_INJECTABLE_REGEX 132from lib.core.threads import getCurrentThreadData 133from lib.core.threads import setDaemon 134from lib.core.update import update 135from lib.parse.configfile import configFileParser 136from lib.parse.payloads import loadBoundaries 137from lib.parse.payloads import loadPayloads 138from lib.request.basic import checkCharEncoding 139from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler 140from lib.request.chunkedhandler import ChunkedHandler 141from lib.request.connect import Connect as Request 142from lib.request.dns import DNSServer 143from lib.request.httpshandler import HTTPSHandler 144from lib.request.pkihandler import HTTPSPKIAuthHandler 145from lib.request.rangehandler import HTTPRangeHandler 146from lib.request.redirecthandler import SmartRedirectHandler 147from lib.utils.crawler import crawl 148from lib.utils.deps import checkDependencies 149from lib.utils.har import HTTPCollectorFactory 150from lib.utils.purge import purge 151from lib.utils.search import search 152from thirdparty import six 153from thirdparty.keepalive import keepalive 154from thirdparty.multipart import multipartpost 155from thirdparty.six.moves import http_client as _http_client 156from thirdparty.six.moves import http_cookiejar as _http_cookiejar 157from thirdparty.six.moves import urllib as _urllib 158from thirdparty.socks import socks 159from xml.etree.ElementTree import ElementTree 160 161authHandler = _urllib.request.BaseHandler() 162chunkedHandler = ChunkedHandler() 163httpsHandler = HTTPSHandler() 164keepAliveHandler = keepalive.HTTPHandler() 165proxyHandler = _urllib.request.ProxyHandler() 166redirectHandler = SmartRedirectHandler() 167rangeHandler = HTTPRangeHandler() 168multipartPostHandler = multipartpost.MultipartPostHandler() 169 170# Reference: https://mail.python.org/pipermail/python-list/2009-November/558615.html 171try: 172 WindowsError 173except NameError: 174 WindowsError = None 175 176def _loadQueries(): 177 """ 178 Loads queries from 'xml/queries.xml' file. 179 """ 180 181 def iterate(node, retVal=None): 182 class DictObject(object): 183 def __init__(self): 184 self.__dict__ = {} 185 186 def __contains__(self, name): 187 return name in self.__dict__ 188 189 if retVal is None: 190 retVal = DictObject() 191 192 for child in node.findall("*"): 193 instance = DictObject() 194 retVal.__dict__[child.tag] = instance 195 if child.attrib: 196 instance.__dict__.update(child.attrib) 197 else: 198 iterate(child, instance) 199 200 return retVal 201 202 tree = ElementTree() 203 try: 204 tree.parse(paths.QUERIES_XML) 205 except Exception as ex: 206 errMsg = "something appears to be wrong with " 207 errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex)) 208 errMsg += "sure that you haven't made any changes to it" 209 raise SqlmapInstallationException(errMsg) 210 211 for node in tree.findall("*"): 212 queries[node.attrib['value']] = iterate(node) 213 214def _setMultipleTargets(): 215 """ 216 Define a configuration parameter if we are running in multiple target 217 mode. 218 """ 219 220 initialTargetsCount = len(kb.targets) 221 seen = set() 222 223 if not conf.logFile: 224 return 225 226 debugMsg = "parsing targets list from '%s'" % conf.logFile 227 logger.debug(debugMsg) 228 229 if not os.path.exists(conf.logFile): 230 errMsg = "the specified list of targets does not exist" 231 raise SqlmapFilePathException(errMsg) 232 233 if checkFile(conf.logFile, False): 234 for target in parseRequestFile(conf.logFile): 235 url, _, data, _, _ = target 236 key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data)) 237 if key not in seen: 238 kb.targets.add(target) 239 seen.add(key) 240 241 elif os.path.isdir(conf.logFile): 242 files = os.listdir(conf.logFile) 243 files.sort() 244 245 for reqFile in files: 246 if not re.search(r"([\d]+)\-request", reqFile): 247 continue 248 249 for target in parseRequestFile(os.path.join(conf.logFile, reqFile)): 250 url, _, data, _, _ = target 251 key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data)) 252 if key not in seen: 253 kb.targets.add(target) 254 seen.add(key) 255 256 else: 257 errMsg = "the specified list of targets is not a file " 258 errMsg += "nor a directory" 259 raise SqlmapFilePathException(errMsg) 260 261 updatedTargetsCount = len(kb.targets) 262 263 if updatedTargetsCount > initialTargetsCount: 264 infoMsg = "sqlmap parsed %d " % (updatedTargetsCount - initialTargetsCount) 265 infoMsg += "(parameter unique) requests from the " 266 infoMsg += "targets list ready to be tested" 267 logger.info(infoMsg) 268 269def _adjustLoggingFormatter(): 270 """ 271 Solves problem of line deletition caused by overlapping logging messages 272 and retrieved data info in inference mode 273 """ 274 275 if hasattr(FORMATTER, '_format'): 276 return 277 278 def format(record): 279 message = FORMATTER._format(record) 280 message = boldifyMessage(message) 281 if kb.get("prependFlag"): 282 message = "\n%s" % message 283 kb.prependFlag = False 284 return message 285 286 FORMATTER._format = FORMATTER.format 287 FORMATTER.format = format 288 289def _setRequestFromFile(): 290 """ 291 This function checks if the way to make a HTTP request is through supplied 292 textual file, parses it and saves the information into the knowledge base. 293 """ 294 295 if conf.requestFile: 296 for requestFile in re.split(PARAMETER_SPLITTING_REGEX, conf.requestFile): 297 requestFile = safeExpandUser(requestFile) 298 url = None 299 seen = set() 300 301 if not checkFile(requestFile, False): 302 errMsg = "specified HTTP request file '%s' " % requestFile 303 errMsg += "does not exist" 304 raise SqlmapFilePathException(errMsg) 305 306 infoMsg = "parsing HTTP request from '%s'" % requestFile 307 logger.info(infoMsg) 308 309 for target in parseRequestFile(requestFile): 310 url = target[0] 311 if url not in seen: 312 kb.targets.add(target) 313 if len(kb.targets) > 1: 314 conf.multipleTargets = True 315 seen.add(url) 316 317 if url is None: 318 errMsg = "specified file '%s' " % requestFile 319 errMsg += "does not contain a usable HTTP request (with parameters)" 320 raise SqlmapDataException(errMsg) 321 322 if conf.secondReq: 323 conf.secondReq = safeExpandUser(conf.secondReq) 324 325 if not checkFile(conf.secondReq, False): 326 errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq 327 errMsg += "does not exist" 328 raise SqlmapFilePathException(errMsg) 329 330 infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq 331 logger.info(infoMsg) 332 333 target = next(parseRequestFile(conf.secondReq, False)) 334 kb.secondReq = target 335 336def _setCrawler(): 337 if not conf.crawlDepth: 338 return 339 340 if not conf.bulkFile: 341 if conf.url: 342 crawl(conf.url) 343 elif conf.requestFile and kb.targets: 344 target = list(kb.targets)[0] 345 crawl(target[0], target[2], target[3]) 346 347def _doSearch(): 348 """ 349 This function performs search dorking, parses results 350 and saves the testable hosts into the knowledge base. 351 """ 352 353 if not conf.googleDork: 354 return 355 356 kb.data.onlyGETs = None 357 358 def retrieve(): 359 links = search(conf.googleDork) 360 361 if not links: 362 errMsg = "unable to find results for your " 363 errMsg += "search dork expression" 364 raise SqlmapGenericException(errMsg) 365 366 for link in links: 367 link = urldecode(link) 368 if re.search(r"(.*?)\?(.+)", link): 369 kb.targets.add((link, conf.method, conf.data, conf.cookie, None)) 370 elif re.search(URI_INJECTABLE_REGEX, link, re.I): 371 if kb.data.onlyGETs is None and conf.data is None and not conf.googleDork: 372 message = "do you want to scan only results containing GET parameters? [Y/n] " 373 kb.data.onlyGETs = readInput(message, default='Y', boolean=True) 374 if not kb.data.onlyGETs or conf.googleDork: 375 kb.targets.add((link, conf.method, conf.data, conf.cookie, None)) 376 377 return links 378 379 while True: 380 links = retrieve() 381 382 if kb.targets: 383 infoMsg = "found %d results for your " % len(links) 384 infoMsg += "search dork expression, " 385 386 if len(links) == len(kb.targets): 387 infoMsg += "all " 388 else: 389 infoMsg += "%d " % len(kb.targets) 390 391 infoMsg += "of them are testable targets" 392 logger.info(infoMsg) 393 break 394 395 else: 396 message = "found %d results " % len(links) 397 message += "for your search dork expression, but none of them " 398 message += "have GET parameters to test for SQL injection. " 399 message += "Do you want to skip to the next result page? [Y/n]" 400 401 if not readInput(message, default='Y', boolean=True): 402 raise SqlmapSilentQuitException 403 else: 404 conf.googlePage += 1 405 406def _setBulkMultipleTargets(): 407 if not conf.bulkFile: 408 return 409 410 conf.bulkFile = safeExpandUser(conf.bulkFile) 411 412 infoMsg = "parsing multiple targets list from '%s'" % conf.bulkFile 413 logger.info(infoMsg) 414 415 if not checkFile(conf.bulkFile, False): 416 errMsg = "the specified bulk file " 417 errMsg += "does not exist" 418 raise SqlmapFilePathException(errMsg) 419 420 found = False 421 for line in getFileItems(conf.bulkFile): 422 if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line: 423 found = True 424 kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None)) 425 426 if not found and not conf.forms and not conf.crawlDepth: 427 warnMsg = "no usable links found (with GET parameters)" 428 logger.warn(warnMsg) 429 430def _findPageForms(): 431 if not conf.forms or conf.crawlDepth: 432 return 433 434 if conf.url and not checkConnection(): 435 return 436 437 found = False 438 infoMsg = "searching for forms" 439 logger.info(infoMsg) 440 441 if not any((conf.bulkFile, conf.googleDork)): 442 page, _, _ = Request.queryPage(content=True, ignoreSecondOrder=True) 443 if findPageForms(page, conf.url, True, True): 444 found = True 445 else: 446 if conf.bulkFile: 447 targets = getFileItems(conf.bulkFile) 448 elif conf.googleDork: 449 targets = [_[0] for _ in kb.targets] 450 kb.targets.clear() 451 else: 452 targets = [] 453 454 for i in xrange(len(targets)): 455 try: 456 target = targets[i].strip() 457 458 if not re.search(r"(?i)\Ahttp[s]*://", target): 459 target = "http://%s" % target 460 461 page, _, _ = Request.getPage(url=target.strip(), cookie=conf.cookie, crawling=True, raise404=False) 462 if findPageForms(page, target, False, True): 463 found = True 464 465 if conf.verbose in (1, 2): 466 status = '%d/%d links visited (%d%%)' % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets))) 467 dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True) 468 except KeyboardInterrupt: 469 break 470 except Exception as ex: 471 errMsg = "problem occurred while searching for forms at '%s' ('%s')" % (target, getSafeExString(ex)) 472 logger.error(errMsg) 473 474 if not found: 475 warnMsg = "no forms found" 476 logger.warn(warnMsg) 477 478def _setDBMSAuthentication(): 479 """ 480 Check and set the DBMS authentication credentials to run statements as 481 another user, not the session user 482 """ 483 484 if not conf.dbmsCred: 485 return 486 487 debugMsg = "setting the DBMS authentication credentials" 488 logger.debug(debugMsg) 489 490 match = re.search(r"^(.+?):(.*?)$", conf.dbmsCred) 491 492 if not match: 493 errMsg = "DBMS authentication credentials value must be in format " 494 errMsg += "username:password" 495 raise SqlmapSyntaxException(errMsg) 496 497 conf.dbmsUsername = match.group(1) 498 conf.dbmsPassword = match.group(2) 499 500def _setMetasploit(): 501 if not conf.osPwn and not conf.osSmb and not conf.osBof: 502 return 503 504 debugMsg = "setting the takeover out-of-band functionality" 505 logger.debug(debugMsg) 506 507 msfEnvPathExists = False 508 509 if IS_WIN: 510 try: 511 __import__("win32file") 512 except ImportError: 513 errMsg = "sqlmap requires third-party module 'pywin32' " 514 errMsg += "in order to use Metasploit functionalities on " 515 errMsg += "Windows. You can download it from " 516 errMsg += "'https://github.com/mhammond/pywin32'" 517 raise SqlmapMissingDependence(errMsg) 518 519 if not conf.msfPath: 520 for candidate in os.environ.get("PATH", "").split(';'): 521 if all(_ in candidate for _ in ("metasploit", "bin")): 522 conf.msfPath = os.path.dirname(candidate.rstrip('\\')) 523 break 524 525 if conf.osSmb: 526 isAdmin = runningAsAdmin() 527 528 if not isAdmin: 529 errMsg = "you need to run sqlmap as an administrator " 530 errMsg += "if you want to perform a SMB relay attack because " 531 errMsg += "it will need to listen on a user-specified SMB " 532 errMsg += "TCP port for incoming connection attempts" 533 raise SqlmapMissingPrivileges(errMsg) 534 535 if conf.msfPath: 536 for path in (conf.msfPath, os.path.join(conf.msfPath, "bin")): 537 if any(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")): 538 msfEnvPathExists = True 539 if all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)): 540 kb.oldMsf = False 541 elif all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")): 542 kb.oldMsf = True 543 else: 544 msfEnvPathExists = False 545 546 conf.msfPath = path 547 break 548 549 if msfEnvPathExists: 550 debugMsg = "provided Metasploit Framework path " 551 debugMsg += "'%s' is valid" % conf.msfPath 552 logger.debug(debugMsg) 553 else: 554 warnMsg = "the provided Metasploit Framework path " 555 warnMsg += "'%s' is not valid. The cause could " % conf.msfPath 556 warnMsg += "be that the path does not exists or that one " 557 warnMsg += "or more of the needed Metasploit executables " 558 warnMsg += "within msfcli, msfconsole, msfencode and " 559 warnMsg += "msfpayload do not exist" 560 logger.warn(warnMsg) 561 else: 562 warnMsg = "you did not provide the local path where Metasploit " 563 warnMsg += "Framework is installed" 564 logger.warn(warnMsg) 565 566 if not msfEnvPathExists: 567 warnMsg = "sqlmap is going to look for Metasploit Framework " 568 warnMsg += "installation inside the environment path(s)" 569 logger.warn(warnMsg) 570 571 envPaths = os.environ.get("PATH", "").split(";" if IS_WIN else ":") 572 573 for envPath in envPaths: 574 envPath = envPath.replace(";", "") 575 576 if any(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")): 577 msfEnvPathExists = True 578 if all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)): 579 kb.oldMsf = False 580 elif all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")): 581 kb.oldMsf = True 582 else: 583 msfEnvPathExists = False 584 585 if msfEnvPathExists: 586 infoMsg = "Metasploit Framework has been found " 587 infoMsg += "installed in the '%s' path" % envPath 588 logger.info(infoMsg) 589 590 conf.msfPath = envPath 591 592 break 593 594 if not msfEnvPathExists: 595 errMsg = "unable to locate Metasploit Framework installation. " 596 errMsg += "You can get it at 'https://www.metasploit.com/download/'" 597 raise SqlmapFilePathException(errMsg) 598 599def _setWriteFile(): 600 if not conf.fileWrite: 601 return 602 603 debugMsg = "setting the write file functionality" 604 logger.debug(debugMsg) 605 606 if not os.path.exists(conf.fileWrite): 607 errMsg = "the provided local file '%s' does not exist" % conf.fileWrite 608 raise SqlmapFilePathException(errMsg) 609 610 if not conf.fileDest: 611 errMsg = "you did not provide the back-end DBMS absolute path " 612 errMsg += "where you want to write the local file '%s'" % conf.fileWrite 613 raise SqlmapMissingMandatoryOptionException(errMsg) 614 615 conf.fileWriteType = getFileType(conf.fileWrite) 616 617def _setOS(): 618 """ 619 Force the back-end DBMS operating system option. 620 """ 621 622 if not conf.os: 623 return 624 625 if conf.os.lower() not in SUPPORTED_OS: 626 errMsg = "you provided an unsupported back-end DBMS operating " 627 errMsg += "system. The supported DBMS operating systems for OS " 628 errMsg += "and file system access are %s. " % ', '.join([o.capitalize() for o in SUPPORTED_OS]) 629 errMsg += "If you do not know the back-end DBMS underlying OS, " 630 errMsg += "do not provide it and sqlmap will fingerprint it for " 631 errMsg += "you." 632 raise SqlmapUnsupportedDBMSException(errMsg) 633 634 debugMsg = "forcing back-end DBMS operating system to user defined " 635 debugMsg += "value '%s'" % conf.os 636 logger.debug(debugMsg) 637 638 Backend.setOs(conf.os) 639 640def _setTechnique(): 641 validTechniques = sorted(getPublicTypeMembers(PAYLOAD.TECHNIQUE), key=lambda x: x[1]) 642 validLetters = [_[0][0].upper() for _ in validTechniques] 643 644 if conf.technique and isinstance(conf.technique, six.string_types): 645 _ = [] 646 647 for letter in conf.technique.upper(): 648 if letter not in validLetters: 649 errMsg = "value for --technique must be a string composed " 650 errMsg += "by the letters %s. Refer to the " % ", ".join(validLetters) 651 errMsg += "user's manual for details" 652 raise SqlmapSyntaxException(errMsg) 653 654 for validTech, validInt in validTechniques: 655 if letter == validTech[0]: 656 _.append(validInt) 657 break 658 659 conf.technique = _ 660 661def _setDBMS(): 662 """ 663 Force the back-end DBMS option. 664 """ 665 666 if not conf.dbms: 667 return 668 669 debugMsg = "forcing back-end DBMS to user defined value" 670 logger.debug(debugMsg) 671 672 conf.dbms = conf.dbms.lower() 673 regex = re.search(r"%s ([\d\.]+)" % ("(%s)" % "|".join([alias for alias in SUPPORTED_DBMS])), conf.dbms, re.I) 674 675 if regex: 676 conf.dbms = regex.group(1) 677 Backend.setVersion(regex.group(2)) 678 679 if conf.dbms not in SUPPORTED_DBMS: 680 errMsg = "you provided an unsupported back-end database management " 681 errMsg += "system. Supported DBMSes are as follows: %s. " % ', '.join(sorted(_ for _ in DBMS_DICT)) 682 errMsg += "If you do not know the back-end DBMS, do not provide " 683 errMsg += "it and sqlmap will fingerprint it for you." 684 raise SqlmapUnsupportedDBMSException(errMsg) 685 686 for dbms, aliases in DBMS_ALIASES: 687 if conf.dbms in aliases: 688 conf.dbms = dbms 689 690 break 691 692def _listTamperingFunctions(): 693 """ 694 Lists available tamper functions 695 """ 696 697 if conf.listTampers: 698 infoMsg = "listing available tamper scripts\n" 699 logger.info(infoMsg) 700 701 for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))): 702 content = openFile(script, "rb").read() 703 match = re.search(r'(?s)__priority__.+"""(.+)"""', content) 704 if match: 705 comment = match.group(1).strip() 706 dataToStdout("* %s - %s\n" % (setColor(os.path.basename(script), "yellow"), re.sub(r" *\n *", " ", comment.split("\n\n")[0].strip()))) 707 708def _setTamperingFunctions(): 709 """ 710 Loads tampering functions from given script(s) 711 """ 712 713 if conf.tamper: 714 last_priority = PRIORITY.HIGHEST 715 check_priority = True 716 resolve_priorities = False 717 priorities = [] 718 719 for script in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper): 720 found = False 721 722 path = safeFilepathEncode(paths.SQLMAP_TAMPER_PATH) 723 script = safeFilepathEncode(script.strip()) 724 725 try: 726 if not script: 727 continue 728 729 elif os.path.exists(os.path.join(path, script if script.endswith(".py") else "%s.py" % script)): 730 script = os.path.join(path, script if script.endswith(".py") else "%s.py" % script) 731 732 elif not os.path.exists(script): 733 errMsg = "tamper script '%s' does not exist" % script 734 raise SqlmapFilePathException(errMsg) 735 736 elif not script.endswith(".py"): 737 errMsg = "tamper script '%s' should have an extension '.py'" % script 738 raise SqlmapSyntaxException(errMsg) 739 except UnicodeDecodeError: 740 errMsg = "invalid character provided in option '--tamper'" 741 raise SqlmapSyntaxException(errMsg) 742 743 dirname, filename = os.path.split(script) 744 dirname = os.path.abspath(dirname) 745 746 infoMsg = "loading tamper module '%s'" % filename[:-3] 747 logger.info(infoMsg) 748 749 if not os.path.exists(os.path.join(dirname, "__init__.py")): 750 errMsg = "make sure that there is an empty file '__init__.py' " 751 errMsg += "inside of tamper scripts directory '%s'" % dirname 752 raise SqlmapGenericException(errMsg) 753 754 if dirname not in sys.path: 755 sys.path.insert(0, dirname) 756 757 try: 758 module = __import__(safeFilepathEncode(filename[:-3])) 759 except Exception as ex: 760 raise SqlmapSyntaxException("cannot import tamper module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex))) 761 762 priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__ 763 764 for name, function in inspect.getmembers(module, inspect.isfunction): 765 if name == "tamper" and inspect.getargspec(function).args and inspect.getargspec(function).keywords == "kwargs": 766 found = True 767 kb.tamperFunctions.append(function) 768 function.__name__ = module.__name__ 769 770 if check_priority and priority > last_priority: 771 message = "it appears that you might have mixed " 772 message += "the order of tamper scripts. " 773 message += "Do you want to auto resolve this? [Y/n/q] " 774 choice = readInput(message, default='Y').upper() 775 776 if choice == 'N': 777 resolve_priorities = False 778 elif choice == 'Q': 779 raise SqlmapUserQuitException 780 else: 781 resolve_priorities = True 782 783 check_priority = False 784 785 priorities.append((priority, function)) 786 last_priority = priority 787 788 break 789 elif name == "dependencies": 790 try: 791 function() 792 except Exception as ex: 793 errMsg = "error occurred while checking dependencies " 794 errMsg += "for tamper module '%s' ('%s')" % (getUnicode(filename[:-3]), getSafeExString(ex)) 795 raise SqlmapGenericException(errMsg) 796 797 if not found: 798 errMsg = "missing function 'tamper(payload, **kwargs)' " 799 errMsg += "in tamper script '%s'" % script 800 raise SqlmapGenericException(errMsg) 801 802 if kb.tamperFunctions and len(kb.tamperFunctions) > 3: 803 warnMsg = "using too many tamper scripts is usually not " 804 warnMsg += "a good idea" 805 logger.warning(warnMsg) 806 807 if resolve_priorities and priorities: 808 priorities.sort(key=functools.cmp_to_key(lambda a, b: cmp(a[0], b[0])), reverse=True) 809 kb.tamperFunctions = [] 810 811 for _, function in priorities: 812 kb.tamperFunctions.append(function) 813 814def _setPreprocessFunctions(): 815 """ 816 Loads preprocess functions from given script(s) 817 """ 818 819 if conf.preprocess: 820 for script in re.split(PARAMETER_SPLITTING_REGEX, conf.preprocess): 821 found = False 822 function = None 823 824 script = safeFilepathEncode(script.strip()) 825 826 try: 827 if not script: 828 continue 829 830 if not os.path.exists(script): 831 errMsg = "preprocess script '%s' does not exist" % script 832 raise SqlmapFilePathException(errMsg) 833 834 elif not script.endswith(".py"): 835 errMsg = "preprocess script '%s' should have an extension '.py'" % script 836 raise SqlmapSyntaxException(errMsg) 837 except UnicodeDecodeError: 838 errMsg = "invalid character provided in option '--preprocess'" 839 raise SqlmapSyntaxException(errMsg) 840 841 dirname, filename = os.path.split(script) 842 dirname = os.path.abspath(dirname) 843 844 infoMsg = "loading preprocess module '%s'" % filename[:-3] 845 logger.info(infoMsg) 846 847 if not os.path.exists(os.path.join(dirname, "__init__.py")): 848 errMsg = "make sure that there is an empty file '__init__.py' " 849 errMsg += "inside of preprocess scripts directory '%s'" % dirname 850 raise SqlmapGenericException(errMsg) 851 852 if dirname not in sys.path: 853 sys.path.insert(0, dirname) 854 855 try: 856 module = __import__(safeFilepathEncode(filename[:-3])) 857 except Exception as ex: 858 raise SqlmapSyntaxException("cannot import preprocess module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex))) 859 860 for name, function in inspect.getmembers(module, inspect.isfunction): 861 if name == "preprocess" and inspect.getargspec(function).args and all(_ in inspect.getargspec(function).args for _ in ("page", "headers", "code")): 862 found = True 863 864 kb.preprocessFunctions.append(function) 865 function.__name__ = module.__name__ 866 867 break 868 869 if not found: 870 errMsg = "missing function 'preprocess(page, headers=None, code=None)' " 871 errMsg += "in preprocess script '%s'" % script 872 raise SqlmapGenericException(errMsg) 873 else: 874 try: 875 _, _, _ = function("", {}, None) 876 except: 877 handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.PREPROCESS, suffix=".py") 878 os.close(handle) 879 880 open(filename, "w+b").write("#!/usr/bin/env\n\ndef preprocess(page, headers=None, code=None):\n return page, headers, code\n") 881 open(os.path.join(os.path.dirname(filename), "__init__.py"), "w+b").write("pass") 882 883 errMsg = "function 'preprocess(page, headers=None, code=None)' " 884 errMsg += "in preprocess script '%s' " % script 885 errMsg += "should return a tuple '(page, headers, code)' " 886 errMsg += "(Note: find template script at '%s')" % filename 887 raise SqlmapGenericException(errMsg) 888 889def _setThreads(): 890 if not isinstance(conf.threads, int) or conf.threads <= 0: 891 conf.threads = 1 892 893def _setDNSCache(): 894 """ 895 Makes a cached version of socket._getaddrinfo to avoid subsequent DNS requests. 896 """ 897 898 def _getaddrinfo(*args, **kwargs): 899 if args in kb.cache.addrinfo: 900 return kb.cache.addrinfo[args] 901 902 else: 903 kb.cache.addrinfo[args] = socket._getaddrinfo(*args, **kwargs) 904 return kb.cache.addrinfo[args] 905 906 if not hasattr(socket, "_getaddrinfo"): 907 socket._getaddrinfo = socket.getaddrinfo 908 socket.getaddrinfo = _getaddrinfo 909 910def _setSocketPreConnect(): 911 """ 912 Makes a pre-connect version of socket.create_connection 913 """ 914 915 if conf.disablePrecon: 916 return 917 918 def _thread(): 919 while kb.get("threadContinue") and not conf.get("disablePrecon"): 920 try: 921 for key in socket._ready: 922 if len(socket._ready[key]) < SOCKET_PRE_CONNECT_QUEUE_SIZE: 923 s = socket.create_connection(*key[0], **dict(key[1])) 924 with kb.locks.socket: 925 socket._ready[key].append((s, time.time())) 926 except KeyboardInterrupt: 927 break 928 except: 929 pass 930 finally: 931 time.sleep(0.01) 932 933 def create_connection(*args, **kwargs): 934 retVal = None 935 936 key = (tuple(args), frozenset(kwargs.items())) 937 with kb.locks.socket: 938 if key not in socket._ready: 939 socket._ready[key] = [] 940 941 while len(socket._ready[key]) > 0: 942 candidate, created = socket._ready[key].pop(0) 943 if (time.time() - created) < PRECONNECT_CANDIDATE_TIMEOUT: 944 retVal = candidate 945 break 946 else: 947 try: 948 candidate.shutdown(socket.SHUT_RDWR) 949 candidate.close() 950 except socket.error: 951 pass 952 953 if not retVal: 954 retVal = socket._create_connection(*args, **kwargs) 955 956 return retVal 957 958 if not hasattr(socket, "_create_connection"): 959 socket._ready = {} 960 socket._create_connection = socket.create_connection 961 socket.create_connection = create_connection 962 963 thread = threading.Thread(target=_thread) 964 setDaemon(thread) 965 thread.start() 966 967def _setHTTPHandlers(): 968 """ 969 Check and set the HTTP/SOCKS proxy for all HTTP requests. 970 """ 971 972 with kb.locks.handlers: 973 if conf.proxyList is not None: 974 if not conf.proxyList: 975 errMsg = "list of usable proxies is exhausted" 976 raise SqlmapNoneDataException(errMsg) 977 978 conf.proxy = conf.proxyList[0] 979 conf.proxyList = conf.proxyList[1:] 980 981 infoMsg = "loading proxy '%s' from a supplied proxy list file" % conf.proxy 982 logger.info(infoMsg) 983 984 elif not conf.proxy: 985 if conf.hostname in ("localhost", "127.0.0.1") or conf.ignoreProxy: 986 proxyHandler.proxies = {} 987 988 if conf.proxy: 989 debugMsg = "setting the HTTP/SOCKS proxy for all HTTP requests" 990 logger.debug(debugMsg) 991 992 try: 993 _ = _urllib.parse.urlsplit(conf.proxy) 994 except Exception as ex: 995 errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex)) 996 raise SqlmapSyntaxException(errMsg) 997 998 hostnamePort = _.netloc.split(":") 999 1000 scheme = _.scheme.upper() 1001 hostname = hostnamePort[0] 1002 port = None 1003 username = None 1004 password = None 1005 1006 if len(hostnamePort) == 2: 1007 try: 1008 port = int(hostnamePort[1]) 1009 except: 1010 pass # drops into the next check block 1011 1012 if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)): 1013 errMsg = "proxy value must be in format '(%s)://address:port'" % "|".join(_[0].lower() for _ in getPublicTypeMembers(PROXY_TYPE)) 1014 raise SqlmapSyntaxException(errMsg) 1015 1016 if conf.proxyCred: 1017 _ = re.search(r"\A(.*?):(.*?)\Z", conf.proxyCred) 1018 if not _: 1019 errMsg = "proxy authentication credentials " 1020 errMsg += "value must be in format username:password" 1021 raise SqlmapSyntaxException(errMsg) 1022 else: 1023 username = _.group(1) 1024 password = _.group(2) 1025 1026 if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5): 1027 proxyHandler.proxies = {} 1028 1029 if scheme == PROXY_TYPE.SOCKS4: 1030 warnMsg = "SOCKS4 does not support resolving (DNS) names (i.e. causing DNS leakage)" 1031 singleTimeWarnMessage(warnMsg) 1032 1033 socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if scheme == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, hostname, port, username=username, password=password) 1034 socks.wrapmodule(_http_client) 1035 else: 1036 socks.unwrapmodule(_http_client) 1037 1038 if conf.proxyCred: 1039 # Reference: http://stackoverflow.com/questions/34079/how-to-specify-an-authenticated-proxy-for-a-python-http-connection 1040 proxyString = "%s@" % conf.proxyCred 1041 else: 1042 proxyString = "" 1043 1044 proxyString += "%s:%d" % (hostname, port) 1045 proxyHandler.proxies = {"http": proxyString, "https": proxyString} 1046 1047 proxyHandler.__init__(proxyHandler.proxies) 1048 1049 if not proxyHandler.proxies: 1050 for _ in ("http", "https"): 1051 if hasattr(proxyHandler, "%s_open" % _): 1052 delattr(proxyHandler, "%s_open" % _) 1053 1054 debugMsg = "creating HTTP requests opener object" 1055 logger.debug(debugMsg) 1056 1057 handlers = filterNone([multipartPostHandler, proxyHandler if proxyHandler.proxies else None, authHandler, redirectHandler, rangeHandler, chunkedHandler if conf.chunked else None, httpsHandler]) 1058 1059 if not conf.dropSetCookie: 1060 if not conf.loadCookies: 1061 conf.cj = _http_cookiejar.CookieJar() 1062 else: 1063 conf.cj = _http_cookiejar.MozillaCookieJar() 1064 resetCookieJar(conf.cj) 1065 1066 handlers.append(_urllib.request.HTTPCookieProcessor(conf.cj)) 1067 1068 # Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html 1069 if conf.keepAlive: 1070 warnMsg = "persistent HTTP(s) connections, Keep-Alive, has " 1071 warnMsg += "been disabled because of its incompatibility " 1072 1073 if conf.proxy: 1074 warnMsg += "with HTTP(s) proxy" 1075 logger.warn(warnMsg) 1076 elif conf.authType: 1077 warnMsg += "with authentication methods" 1078 logger.warn(warnMsg) 1079 else: 1080 handlers.append(keepAliveHandler) 1081 1082 opener = _urllib.request.build_opener(*handlers) 1083 opener.addheaders = [] # Note: clearing default "User-Agent: Python-urllib/X.Y" 1084 _urllib.request.install_opener(opener) 1085 1086def _setSafeVisit(): 1087 """ 1088 Check and set the safe visit options. 1089 """ 1090 if not any((conf.safeUrl, conf.safeReqFile)): 1091 return 1092 1093 if conf.safeReqFile: 1094 checkFile(conf.safeReqFile) 1095 1096 raw = readCachedFileContent(conf.safeReqFile) 1097 match = re.search(r"\A([A-Z]+) ([^ ]+) HTTP/[0-9.]+\Z", raw.split('\n')[0].strip()) 1098 1099 if match: 1100 kb.safeReq.method = match.group(1) 1101 kb.safeReq.url = match.group(2) 1102 kb.safeReq.headers = {} 1103 1104 for line in raw.split('\n')[1:]: 1105 line = line.strip() 1106 if line and ':' in line: 1107 key, value = line.split(':', 1) 1108 value = value.strip() 1109 kb.safeReq.headers[key] = value 1110 if key.upper() == HTTP_HEADER.HOST.upper(): 1111 if not value.startswith("http"): 1112 scheme = "http" 1113 if value.endswith(":443"): 1114 scheme = "https" 1115 value = "%s://%s" % (scheme, value) 1116 kb.safeReq.url = _urllib.parse.urljoin(value, kb.safeReq.url) 1117 else: 1118 break 1119 1120 post = None 1121 1122 if '\r\n\r\n' in raw: 1123 post = raw[raw.find('\r\n\r\n') + 4:] 1124 elif '\n\n' in raw: 1125 post = raw[raw.find('\n\n') + 2:] 1126 1127 if post and post.strip(): 1128 kb.safeReq.post = post 1129 else: 1130 kb.safeReq.post = None 1131 else: 1132 errMsg = "invalid format of a safe request file" 1133 raise SqlmapSyntaxException(errMsg) 1134 else: 1135 if not re.search(r"(?i)\Ahttp[s]*://", conf.safeUrl): 1136 if ":443/" in conf.safeUrl: 1137 conf.safeUrl = "https://%s" % conf.safeUrl 1138 else: 1139 conf.safeUrl = "http://%s" % conf.safeUrl 1140 1141 if (conf.safeFreq or 0) <= 0: 1142 errMsg = "please provide a valid value (>0) for safe frequency (--safe-freq) while using safe visit features" 1143 raise SqlmapSyntaxException(errMsg) 1144 1145def _setPrefixSuffix(): 1146 if conf.prefix is not None and conf.suffix is not None: 1147 # Create a custom boundary object for user's supplied prefix 1148 # and suffix 1149 boundary = AttribDict() 1150 1151 boundary.level = 1 1152 boundary.clause = [0] 1153 boundary.where = [1, 2, 3] 1154 boundary.prefix = conf.prefix 1155 boundary.suffix = conf.suffix 1156 1157 if " like" in boundary.suffix.lower(): 1158 if "'" in boundary.suffix.lower(): 1159 boundary.ptype = 3 1160 elif '"' in boundary.suffix.lower(): 1161 boundary.ptype = 5 1162 elif "'" in boundary.suffix: 1163 boundary.ptype = 2 1164 elif '"' in boundary.suffix: 1165 boundary.ptype = 4 1166 else: 1167 boundary.ptype = 1 1168 1169 # user who provides --prefix/--suffix does not want other boundaries 1170 # to be tested for 1171 conf.boundaries = [boundary] 1172 1173def _setAuthCred(): 1174 """ 1175 Adds authentication credentials (if any) for current target to the password manager 1176 (used by connection handler) 1177 """ 1178 1179 if kb.passwordMgr and all(_ is not None for _ in (conf.scheme, conf.hostname, conf.port, conf.authUsername, conf.authPassword)): 1180 kb.passwordMgr.add_password(None, "%s://%s:%d" % (conf.scheme, conf.hostname, conf.port), conf.authUsername, conf.authPassword) 1181 1182def _setHTTPAuthentication(): 1183 """ 1184 Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or PKI), 1185 username and password for first three methods, or PEM private key file for 1186 PKI authentication 1187 """ 1188 1189 global authHandler 1190 1191 if not conf.authType and not conf.authCred and not conf.authFile: 1192 return 1193 1194 if conf.authFile and not conf.authType: 1195 conf.authType = AUTH_TYPE.PKI 1196 1197 elif conf.authType and not conf.authCred and not conf.authFile: 1198 errMsg = "you specified the HTTP authentication type, but " 1199 errMsg += "did not provide the credentials" 1200 raise SqlmapSyntaxException(errMsg) 1201 1202 elif not conf.authType and conf.authCred: 1203 errMsg = "you specified the HTTP authentication credentials, " 1204 errMsg += "but did not provide the type (e.g. --auth-type=\"basic\")" 1205 raise SqlmapSyntaxException(errMsg) 1206 1207 elif (conf.authType or "").lower() not in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST, AUTH_TYPE.NTLM, AUTH_TYPE.PKI): 1208 errMsg = "HTTP authentication type value must be " 1209 errMsg += "Basic, Digest, NTLM or PKI" 1210 raise SqlmapSyntaxException(errMsg) 1211 1212 if not conf.authFile: 1213 debugMsg = "setting the HTTP authentication type and credentials" 1214 logger.debug(debugMsg) 1215 1216 authType = conf.authType.lower() 1217 1218 if authType in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST): 1219 regExp = "^(.*?):(.*?)$" 1220 errMsg = "HTTP %s authentication credentials " % authType 1221 errMsg += "value must be in format 'username:password'" 1222 elif authType == AUTH_TYPE.NTLM: 1223 regExp = "^(.*\\\\.*):(.*?)$" 1224 errMsg = "HTTP NTLM authentication credentials value must " 1225 errMsg += "be in format 'DOMAIN\\username:password'" 1226 elif authType == AUTH_TYPE.PKI: 1227 errMsg = "HTTP PKI authentication require " 1228 errMsg += "usage of option `--auth-pki`" 1229 raise SqlmapSyntaxException(errMsg) 1230 1231 aCredRegExp = re.search(regExp, conf.authCred) 1232 1233 if not aCredRegExp: 1234 raise SqlmapSyntaxException(errMsg) 1235 1236 conf.authUsername = aCredRegExp.group(1) 1237 conf.authPassword = aCredRegExp.group(2) 1238 1239 kb.passwordMgr = _urllib.request.HTTPPasswordMgrWithDefaultRealm() 1240 1241 _setAuthCred() 1242 1243 if authType == AUTH_TYPE.BASIC: 1244 authHandler = SmartHTTPBasicAuthHandler(kb.passwordMgr) 1245 1246 elif authType == AUTH_TYPE.DIGEST: 1247 authHandler = _urllib.request.HTTPDigestAuthHandler(kb.passwordMgr) 1248 1249 elif authType == AUTH_TYPE.NTLM: 1250 try: 1251 from ntlm import HTTPNtlmAuthHandler 1252 except ImportError: 1253 errMsg = "sqlmap requires Python NTLM third-party library " 1254 errMsg += "in order to authenticate via NTLM. Download from " 1255 errMsg += "'https://github.com/mullender/python-ntlm'" 1256 raise SqlmapMissingDependence(errMsg) 1257 1258 authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr) 1259 else: 1260 debugMsg = "setting the HTTP(s) authentication PEM private key" 1261 logger.debug(debugMsg) 1262 1263 _ = safeExpandUser(conf.authFile) 1264 checkFile(_) 1265 authHandler = HTTPSPKIAuthHandler(_) 1266 1267def _setHTTPExtraHeaders(): 1268 if conf.headers: 1269 debugMsg = "setting extra HTTP headers" 1270 logger.debug(debugMsg) 1271 1272 conf.headers = conf.headers.split("\n") if "\n" in conf.headers else conf.headers.split("\\n") 1273 1274 for headerValue in conf.headers: 1275 if not headerValue.strip(): 1276 continue 1277 1278 if headerValue.count(':') >= 1: 1279 header, value = (_.lstrip() for _ in headerValue.split(":", 1)) 1280 1281 if header and value: 1282 conf.httpHeaders.append((header, value)) 1283 elif headerValue.startswith('@'): 1284 checkFile(headerValue[1:]) 1285 kb.headersFile = headerValue[1:] 1286 else: 1287 errMsg = "invalid header value: %s. Valid header format is 'name:value'" % repr(headerValue).lstrip('u') 1288 raise SqlmapSyntaxException(errMsg) 1289 1290 elif not conf.requestFile and len(conf.httpHeaders or []) < 2: 1291 if conf.encoding: 1292 conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.encoding)) 1293 1294 # Invalidating any caching mechanism in between 1295 # Reference: http://stackoverflow.com/a/1383359 1296 conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache")) 1297 1298def _setHTTPUserAgent(): 1299 """ 1300 Set the HTTP User-Agent header. 1301 Depending on the user options it can be: 1302 1303 * The default sqlmap string 1304 * A default value read as user option 1305 * A random value read from a list of User-Agent headers from a 1306 file choosed as user option 1307 """ 1308 1309 debugMsg = "setting the HTTP User-Agent header" 1310 logger.debug(debugMsg) 1311 1312 if conf.mobile: 1313 if conf.randomAgent: 1314 _ = random.sample([_[1] for _ in getPublicTypeMembers(MOBILES, True)], 1)[0] 1315 conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _)) 1316 else: 1317 message = "which smartphone do you want sqlmap to imitate " 1318 message += "through HTTP User-Agent header?\n" 1319 items = sorted(getPublicTypeMembers(MOBILES, True)) 1320 1321 for count in xrange(len(items)): 1322 item = items[count] 1323 message += "[%d] %s%s\n" % (count + 1, item[0], " (default)" if item == MOBILES.IPHONE else "") 1324 1325 test = readInput(message.rstrip('\n'), default=items.index(MOBILES.IPHONE) + 1) 1326 1327 try: 1328 item = items[int(test) - 1] 1329 except: 1330 item = MOBILES.IPHONE 1331 1332 conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, item[1])) 1333 1334 elif conf.agent: 1335 conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, conf.agent)) 1336 1337 elif not conf.randomAgent: 1338 _ = True 1339 1340 for header, _ in conf.httpHeaders: 1341 if header.upper() == HTTP_HEADER.USER_AGENT.upper(): 1342 _ = False 1343 break 1344 1345 if _: 1346 conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT)) 1347 1348 else: 1349 userAgent = fetchRandomAgent() 1350 1351 infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent 1352 infoMsg += "file '%s'" % paths.USER_AGENTS 1353 logger.info(infoMsg) 1354 1355 conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, userAgent)) 1356 1357def _setHTTPReferer(): 1358 """ 1359 Set the HTTP Referer 1360 """ 1361 1362 if conf.referer: 1363 debugMsg = "setting the HTTP Referer header" 1364 logger.debug(debugMsg) 1365 1366 conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.referer)) 1367 1368def _setHTTPHost(): 1369 """ 1370 Set the HTTP Host 1371 """ 1372 1373 if conf.host: 1374 debugMsg = "setting the HTTP Host header" 1375 logger.debug(debugMsg) 1376 1377 conf.httpHeaders.append((HTTP_HEADER.HOST, conf.host)) 1378 1379def _setHTTPCookies(): 1380 """ 1381 Set the HTTP Cookie header 1382 """ 1383 1384 if conf.cookie: 1385 debugMsg = "setting the HTTP Cookie header" 1386 logger.debug(debugMsg) 1387 1388 conf.httpHeaders.append((HTTP_HEADER.COOKIE, conf.cookie)) 1389 1390def _setHostname(): 1391 """ 1392 Set value conf.hostname 1393 """ 1394 1395 if conf.url: 1396 try: 1397 conf.hostname = _urllib.parse.urlsplit(conf.url).netloc.split(':')[0] 1398 except ValueError as ex: 1399 errMsg = "problem occurred while " 1400 errMsg += "parsing an URL '%s' ('%s')" % (conf.url, getSafeExString(ex)) 1401 raise SqlmapDataException(errMsg) 1402 1403def _setHTTPTimeout(): 1404 """ 1405 Set the HTTP timeout 1406 """ 1407 1408 if conf.timeout: 1409 debugMsg = "setting the HTTP timeout" 1410 logger.debug(debugMsg) 1411 1412 conf.timeout = float(conf.timeout) 1413 1414 if conf.timeout < 3.0: 1415 warnMsg = "the minimum HTTP timeout is 3 seconds, sqlmap " 1416 warnMsg += "will going to reset it" 1417 logger.warn(warnMsg) 1418 1419 conf.timeout = 3.0 1420 else: 1421 conf.timeout = 30.0 1422 1423 try: 1424 socket.setdefaulttimeout(conf.timeout) 1425 except OverflowError as ex: 1426 raise SqlmapValueException("invalid value used for option '--timeout' ('%s')" % getSafeExString(ex)) 1427 1428def _checkDependencies(): 1429 """ 1430 Checks for missing dependencies. 1431 """ 1432 1433 if conf.dependencies: 1434 checkDependencies() 1435 1436def _createHomeDirectories(): 1437 """ 1438 Creates directories inside sqlmap's home directory 1439 """ 1440 1441 if conf.get("purge"): 1442 return 1443 1444 for context in "output", "history": 1445 directory = paths["SQLMAP_%s_PATH" % context.upper()] 1446 try: 1447 if not os.path.isdir(directory): 1448 os.makedirs(directory) 1449 1450 _ = os.path.join(directory, randomStr()) 1451 open(_, "w+b").close() 1452 os.remove(_) 1453 1454 if conf.get("outputDir") and context == "output": 1455 warnMsg = "using '%s' as the %s directory" % (directory, context) 1456 logger.warn(warnMsg) 1457 except (OSError, IOError) as ex: 1458 tempDir = tempfile.mkdtemp(prefix="sqlmap%s" % context) 1459 warnMsg = "unable to %s %s directory " % ("create" if not os.path.isdir(directory) else "write to the", context) 1460 warnMsg += "'%s' (%s). " % (directory, getUnicode(ex)) 1461 warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir) 1462 logger.warn(warnMsg) 1463 1464 paths["SQLMAP_%s_PATH" % context.upper()] = tempDir 1465 1466def _pympTempLeakPatch(tempDir): # Cross-referenced function 1467 raise NotImplementedError 1468 1469def _createTemporaryDirectory(): 1470 """ 1471 Creates temporary directory for this run. 1472 """ 1473 1474 if conf.tmpDir: 1475 try: 1476 if not os.path.isdir(conf.tmpDir): 1477 os.makedirs(conf.tmpDir) 1478 1479 _ = os.path.join(conf.tmpDir, randomStr()) 1480 1481 open(_, "w+b").close() 1482 os.remove(_) 1483 1484 tempfile.tempdir = conf.tmpDir 1485 1486 warnMsg = "using '%s' as the temporary directory" % conf.tmpDir 1487 logger.warn(warnMsg) 1488 except (OSError, IOError) as ex: 1489 errMsg = "there has been a problem while accessing " 1490 errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex) 1491 raise SqlmapSystemException(errMsg) 1492 else: 1493 try: 1494 if not os.path.isdir(tempfile.gettempdir()): 1495 os.makedirs(tempfile.gettempdir()) 1496 except Exception as ex: 1497 warnMsg = "there has been a problem while accessing " 1498 warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex) 1499 warnMsg += "make sure that there is enough disk space left. If problem persists, " 1500 warnMsg += "try to set environment variable 'TEMP' to a location " 1501 warnMsg += "writeable by the current user" 1502 logger.warn(warnMsg) 1503 1504 if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir: 1505 try: 1506 tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid())) 1507 except: 1508 tempfile.tempdir = os.path.join(paths.SQLMAP_HOME_PATH, "tmp", "sqlmap%s%d" % (randomStr(6), os.getpid())) 1509 1510 kb.tempDir = tempfile.tempdir 1511 1512 if not os.path.isdir(tempfile.tempdir): 1513 try: 1514 os.makedirs(tempfile.tempdir) 1515 except Exception as ex: 1516 errMsg = "there has been a problem while setting " 1517 errMsg += "temporary directory location ('%s')" % getSafeExString(ex) 1518 raise SqlmapSystemException(errMsg) 1519 1520 if six.PY3: 1521 _pympTempLeakPatch(kb.tempDir) 1522 1523def _cleanupOptions(): 1524 """ 1525 Cleanup configuration attributes. 1526 """ 1527 1528 if conf.encoding: 1529 try: 1530 codecs.lookup(conf.encoding) 1531 except LookupError: 1532 errMsg = "unknown encoding '%s'" % conf.encoding 1533 raise SqlmapValueException(errMsg) 1534 1535 debugMsg = "cleaning up configuration parameters" 1536 logger.debug(debugMsg) 1537 1538 width = getConsoleWidth() 1539 1540 if conf.eta: 1541 conf.progressWidth = width - 26 1542 else: 1543 conf.progressWidth = width - 46 1544 1545 for key, value in conf.items(): 1546 if value and any(key.endswith(_) for _ in ("Path", "File", "Dir")): 1547 conf[key] = safeExpandUser(value) 1548 1549 if conf.testParameter: 1550 conf.testParameter = urldecode(conf.testParameter) 1551 conf.testParameter = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.testParameter)] 1552 else: 1553 conf.testParameter = [] 1554 1555 if conf.ignoreCode: 1556 if conf.ignoreCode == IGNORE_CODE_WILDCARD: 1557 conf.ignoreCode = xrange(0, 1000) 1558 else: 1559 try: 1560 conf.ignoreCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.ignoreCode)] 1561 except ValueError: 1562 errMsg = "options '--ignore-code' should contain a list of integer values or a wildcard value '%s'" % IGNORE_CODE_WILDCARD 1563 raise SqlmapSyntaxException(errMsg) 1564 else: 1565 conf.ignoreCode = [] 1566 1567 if conf.paramFilter: 1568 conf.paramFilter = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.paramFilter.upper())] 1569 else: 1570 conf.paramFilter = [] 1571 1572 if conf.base64Parameter: 1573 conf.base64Parameter = urldecode(conf.base64Parameter) 1574 conf.base64Parameter = conf.base64Parameter.replace(" ", "") 1575 conf.base64Parameter = re.split(PARAMETER_SPLITTING_REGEX, conf.base64Parameter) 1576 else: 1577 conf.base64Parameter = [] 1578 1579 if conf.agent: 1580 conf.agent = re.sub(r"[\r\n]", "", conf.agent) 1581 1582 if conf.user: 1583 conf.user = conf.user.replace(" ", "") 1584 1585 if conf.rParam: 1586 if all(_ in conf.rParam for _ in ('=', ',')): 1587 original = conf.rParam 1588 conf.rParam = [] 1589 for part in original.split(';'): 1590 if '=' in part: 1591 left, right = part.split('=', 1) 1592 conf.rParam.append(left) 1593 kb.randomPool[left] = filterNone(_.strip() for _ in right.split(',')) 1594 else: 1595 conf.rParam.append(part) 1596 else: 1597 conf.rParam = conf.rParam.replace(" ", "") 1598 conf.rParam = re.split(PARAMETER_SPLITTING_REGEX, conf.rParam) 1599 else: 1600 conf.rParam = [] 1601 1602 if conf.paramDel: 1603 conf.paramDel = decodeStringEscape(conf.paramDel) 1604 1605 if conf.skip: 1606 conf.skip = conf.skip.replace(" ", "") 1607 conf.skip = re.split(PARAMETER_SPLITTING_REGEX, conf.skip) 1608 else: 1609 conf.skip = [] 1610 1611 if conf.cookie: 1612 conf.cookie = re.sub(r"[\r\n]", "", conf.cookie) 1613 1614 if conf.delay: 1615 conf.delay = float(conf.delay) 1616 1617 if conf.url: 1618 conf.url = conf.url.strip().lstrip('/') 1619 if not re.search(r"\A\w+://", conf.url): 1620 conf.url = "http://%s" % conf.url 1621 1622 if conf.fileRead: 1623 conf.fileRead = ntToPosixSlashes(normalizePath(conf.fileRead)) 1624 1625 if conf.fileWrite: 1626 conf.fileWrite = ntToPosixSlashes(normalizePath(conf.fileWrite)) 1627 1628 if conf.fileDest: 1629 conf.fileDest = ntToPosixSlashes(normalizePath(conf.fileDest)) 1630 1631 if conf.msfPath: 1632 conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath)) 1633 1634 if conf.tmpPath: 1635 conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath)) 1636 1637 if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.forms, conf.crawlDepth)): 1638 conf.multipleTargets = True 1639 1640 if conf.optimize: 1641 setOptimize() 1642 1643 if conf.os: 1644 conf.os = conf.os.capitalize() 1645 1646 if conf.forceDbms: 1647 conf.dbms = conf.forceDbms 1648 1649 if conf.dbms: 1650 kb.dbmsFilter = [] 1651 for _ in conf.dbms.split(','): 1652 for dbms, aliases in DBMS_ALIASES: 1653 if _.strip().lower() in aliases: 1654 kb.dbmsFilter.append(dbms) 1655 conf.dbms = dbms if conf.dbms and ',' not in conf.dbms else None 1656 break 1657 1658 if conf.testFilter: 1659 conf.testFilter = conf.testFilter.strip('*+') 1660 conf.testFilter = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testFilter) 1661 1662 try: 1663 re.compile(conf.testFilter) 1664 except re.error: 1665 conf.testFilter = re.escape(conf.testFilter) 1666 1667 if conf.csrfToken: 1668 original = conf.csrfToken 1669 try: 1670 re.compile(conf.csrfToken) 1671 1672 if re.escape(conf.csrfToken) != conf.csrfToken: 1673 message = "provided value for option '--csrf-token' is a regular expression? [y/N] " 1674 if not readInput(message, default='N', boolean=True): 1675 conf.csrfToken = re.escape(conf.csrfToken) 1676 except re.error: 1677 conf.csrfToken = re.escape(conf.csrfToken) 1678 finally: 1679 class _(six.text_type): 1680 pass 1681 conf.csrfToken = _(conf.csrfToken) 1682 conf.csrfToken._original = original 1683 1684 if conf.testSkip: 1685 conf.testSkip = conf.testSkip.strip('*+') 1686 conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip) 1687 1688 try: 1689 re.compile(conf.testSkip) 1690 except re.error: 1691 conf.testSkip = re.escape(conf.testSkip) 1692 1693 if "timeSec" not in kb.explicitSettings: 1694 if conf.tor: 1695 conf.timeSec = 2 * conf.timeSec 1696 kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE 1697 1698 warnMsg = "increasing default value for " 1699 warnMsg += "option '--time-sec' to %d because " % conf.timeSec 1700 warnMsg += "switch '--tor' was provided" 1701 logger.warn(warnMsg) 1702 else: 1703 kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE 1704 1705 if conf.retries: 1706 conf.retries = min(conf.retries, MAX_CONNECT_RETRIES) 1707 1708 if conf.code: 1709 conf.code = int(conf.code) 1710 1711 if conf.csvDel: 1712 conf.csvDel = decodeStringEscape(conf.csvDel) 1713 1714 if conf.torPort and hasattr(conf.torPort, "isdigit") and conf.torPort.isdigit(): 1715 conf.torPort = int(conf.torPort) 1716 1717 if conf.torType: 1718 conf.torType = conf.torType.upper() 1719 1720 if conf.outputDir: 1721 paths.SQLMAP_OUTPUT_PATH = os.path.realpath(os.path.expanduser(conf.outputDir)) 1722 setPaths(paths.SQLMAP_ROOT_PATH) 1723 1724 if conf.string: 1725 conf.string = decodeStringEscape(conf.string) 1726 1727 if conf.getAll: 1728 for _ in WIZARD.ALL: 1729 conf.__setitem__(_, True) 1730 1731 if conf.noCast: 1732 for _ in list(DUMP_REPLACEMENTS.keys()): 1733 del DUMP_REPLACEMENTS[_] 1734 1735 if conf.dumpFormat: 1736 conf.dumpFormat = conf.dumpFormat.upper() 1737 1738 if conf.torType: 1739 conf.torType = conf.torType.upper() 1740 1741 if conf.col: 1742 conf.col = re.sub(r"\s*,\s*", ',', conf.col) 1743 1744 if conf.exclude: 1745 regex = False 1746 if any(_ in conf.exclude for _ in ('+', '*')): 1747 try: 1748 re.compile(conf.exclude) 1749 except re.error: 1750 pass 1751 else: 1752 regex = True 1753 1754 if not regex: 1755 conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude) 1756 conf.exclude = r"\A%s\Z" % '|'.join(re.escape(_) for _ in conf.exclude.split(',')) 1757 1758 if conf.binaryFields: 1759 conf.binaryFields = conf.binaryFields.replace(" ", "") 1760 conf.binaryFields = re.split(PARAMETER_SPLITTING_REGEX, conf.binaryFields) 1761 1762 if any((conf.proxy, conf.proxyFile, conf.tor)): 1763 conf.disablePrecon = True 1764 1765 if conf.dummy: 1766 conf.batch = True 1767 1768 threadData = getCurrentThreadData() 1769 threadData.reset() 1770 1771def _cleanupEnvironment(): 1772 """ 1773 Cleanup environment (e.g. from leftovers after --sqlmap-shell). 1774 """ 1775 1776 if issubclass(_http_client.socket.socket, socks.socksocket): 1777 socks.unwrapmodule(_http_client) 1778 1779 if hasattr(socket, "_ready"): 1780 socket._ready.clear() 1781 1782def _purge(): 1783 """ 1784 Safely removes (purges) sqlmap data directory. 1785 """ 1786 1787 if conf.purge: 1788 purge(paths.SQLMAP_HOME_PATH) 1789 1790def _setConfAttributes(): 1791 """ 1792 This function set some needed attributes into the configuration 1793 singleton. 1794 """ 1795 1796 debugMsg = "initializing the configuration" 1797 logger.debug(debugMsg) 1798 1799 conf.authUsername = None 1800 conf.authPassword = None 1801 conf.boundaries = [] 1802 conf.cj = None 1803 conf.dbmsConnector = None 1804 conf.dbmsHandler = None 1805 conf.dnsServer = None 1806 conf.dumpPath = None 1807 conf.hashDB = None 1808 conf.hashDBFile = None 1809 conf.httpCollector = None 1810 conf.httpHeaders = [] 1811 conf.hostname = None 1812 conf.ipv6 = False 1813 conf.multipleTargets = False 1814 conf.outputPath = None 1815 conf.paramDict = {} 1816 conf.parameters = {} 1817 conf.path = None 1818 conf.port = None 1819 conf.proxyList = None 1820 conf.resultsFP = None 1821 conf.scheme = None 1822 conf.tests = [] 1823 conf.trafficFP = None 1824 conf.HARCollectorFactory = None 1825 conf.fileWriteType = None 1826 1827def _setKnowledgeBaseAttributes(flushAll=True): 1828 """ 1829 This function set some needed attributes into the knowledge base 1830 singleton. 1831 """ 1832 1833 debugMsg = "initializing the knowledge base" 1834 logger.debug(debugMsg) 1835 1836 kb.absFilePaths = set() 1837 kb.adjustTimeDelay = None 1838 kb.alerted = False 1839 kb.aliasName = randomStr() 1840 kb.alwaysRefresh = None 1841 kb.arch = None 1842 kb.authHeader = None 1843 kb.bannerFp = AttribDict() 1844 kb.binaryField = False 1845 kb.browserVerification = None 1846 1847 kb.brute = AttribDict({"tables": [], "columns": []}) 1848 kb.bruteMode = False 1849 1850 kb.cache = AttribDict() 1851 kb.cache.addrinfo = {} 1852 kb.cache.content = {} 1853 kb.cache.encoding = {} 1854 kb.cache.alphaBoundaries = None 1855 kb.cache.intBoundaries = None 1856 kb.cache.parsedDbms = {} 1857 kb.cache.regex = {} 1858 kb.cache.stdev = {} 1859 1860 kb.captchaDetected = None 1861 1862 kb.chars = AttribDict() 1863 kb.chars.delimiter = randomStr(length=6, lowercase=True) 1864 kb.chars.start = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR) 1865 kb.chars.stop = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR) 1866 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)) 1867 1868 kb.codePage = None 1869 kb.columnExistsChoice = None 1870 kb.commonOutputs = None 1871 kb.connErrorChoice = None 1872 kb.connErrorCounter = 0 1873 kb.cookieEncodeChoice = None 1874 kb.copyExecTest = None 1875 kb.counters = {} 1876 kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR 1877 kb.data = AttribDict() 1878 kb.dataOutputFlag = False 1879 1880 # Active back-end DBMS fingerprint 1881 kb.dbms = None 1882 kb.dbmsFilter = [] 1883 kb.dbmsVersion = [UNKNOWN_DBMS_VERSION] 1884 1885 kb.delayCandidates = TIME_DELAY_CANDIDATES * [0] 1886 kb.dep = None 1887 kb.disableHtmlDecoding = False 1888 kb.dnsMode = False 1889 kb.dnsTest = None 1890 kb.docRoot = None 1891 kb.droppingRequests = False 1892 kb.dumpColumns = None 1893 kb.dumpTable = None 1894 kb.dumpKeyboardInterrupt = False 1895 kb.dynamicMarkings = [] 1896 kb.dynamicParameter = False 1897 kb.endDetection = False 1898 kb.explicitSettings = set() 1899 kb.extendTests = None 1900 kb.errorChunkLength = None 1901 kb.errorIsNone = True 1902 kb.falsePositives = [] 1903 kb.fileReadMode = False 1904 kb.followSitemapRecursion = None 1905 kb.forcedDbms = None 1906 kb.forcePartialUnion = False 1907 kb.forceThreads = None 1908 kb.forceWhere = None 1909 kb.futileUnion = None 1910 kb.heavilyDynamic = False 1911 kb.headersFile = None 1912 kb.headersFp = {} 1913 kb.heuristicDbms = None 1914 kb.heuristicExtendedDbms = None 1915 kb.heuristicMode = False 1916 kb.heuristicPage = False 1917 kb.heuristicTest = None 1918 kb.hintValue = "" 1919 kb.htmlFp = [] 1920 kb.httpErrorCodes = {} 1921 kb.inferenceMode = False 1922 kb.ignoreCasted = None 1923 kb.ignoreNotFound = False 1924 kb.ignoreTimeout = False 1925 kb.identifiedWafs = set() 1926 kb.injection = InjectionDict() 1927 kb.injections = [] 1928 kb.laggingChecked = False 1929 kb.lastParserStatus = None 1930 kb.lastCtrlCTime = None 1931 1932 kb.locks = AttribDict() 1933 for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "log", "socket", "redirect", "request", "value"): 1934 kb.locks[_] = threading.Lock() 1935 1936 kb.matchRatio = None 1937 kb.maxConnectionsFlag = False 1938 kb.mergeCookies = None 1939 kb.multipleCtrlC = False 1940 kb.negativeLogic = False 1941 kb.nullConnection = None 1942 kb.oldMsf = None 1943 kb.orderByColumns = None 1944 kb.originalCode = None 1945 kb.originalPage = None 1946 kb.originalPageTime = None 1947 kb.originalTimeDelay = None 1948 kb.originalUrls = dict() 1949 1950 # Back-end DBMS underlying operating system fingerprint via banner (-b) 1951 # parsing 1952 kb.os = None 1953 kb.osVersion = None 1954 kb.osSP = None 1955 1956 kb.pageCompress = True 1957 kb.pageTemplate = None 1958 kb.pageTemplates = dict() 1959 kb.pageEncoding = DEFAULT_PAGE_ENCODING 1960 kb.pageStable = None 1961 kb.partRun = None 1962 kb.permissionFlag = False 1963 kb.postHint = None 1964 kb.postSpaceToPlus = False 1965 kb.postUrlEncode = True 1966 kb.prependFlag = False 1967 kb.processResponseCounter = 0 1968 kb.previousMethod = None 1969 kb.processUserMarks = None 1970 kb.proxyAuthHeader = None 1971 kb.queryCounter = 0 1972 kb.randomPool = {} 1973 kb.redirectChoice = None 1974 kb.reflectiveMechanism = True 1975 kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS: 0, REFLECTIVE_COUNTER.HIT: 0} 1976 kb.requestCounter = 0 1977 kb.resendPostOnRedirect = None 1978 kb.resolutionDbms = None 1979 kb.responseTimes = {} 1980 kb.responseTimeMode = None 1981 kb.responseTimePayload = None 1982 kb.resumeValues = True 1983 kb.rowXmlMode = False 1984 kb.safeCharEncode = False 1985 kb.safeReq = AttribDict() 1986 kb.secondReq = None 1987 kb.serverHeader = None 1988 kb.singleLogFlags = set() 1989 kb.skipSeqMatcher = False 1990 kb.smokeMode = False 1991 kb.reduceTests = None 1992 kb.tlsSNI = {} 1993 kb.stickyDBMS = False 1994 kb.storeHashesChoice = None 1995 kb.suppressResumeInfo = False 1996 kb.tableFrom = None 1997 kb.technique = None 1998 kb.tempDir = None 1999 kb.testMode = False 2000 kb.testOnlyCustom = False 2001 kb.testQueryCount = 0 2002 kb.testType = None 2003 kb.threadContinue = True 2004 kb.threadException = False 2005 kb.tableExistsChoice = None 2006 kb.uChar = NULL 2007 kb.udfFail = False 2008 kb.unionDuplicates = False 2009 kb.webSocketRecvCount = None 2010 kb.wizardMode = False 2011 kb.xpCmdshellAvailable = False 2012 2013 if flushAll: 2014 kb.checkSitemap = None 2015 kb.headerPaths = {} 2016 kb.keywords = set(getFileItems(paths.SQL_KEYWORDS)) 2017 kb.normalizeCrawlingChoice = None 2018 kb.passwordMgr = None 2019 kb.preprocessFunctions = [] 2020 kb.skipVulnHost = None 2021 kb.storeCrawlingChoice = None 2022 kb.tamperFunctions = [] 2023 kb.targets = OrderedSet() 2024 kb.testedParams = set() 2025 kb.userAgents = None 2026 kb.vainRun = True 2027 kb.vulnHosts = set() 2028 kb.wafFunctions = [] 2029 kb.wordlists = None 2030 2031def _useWizardInterface(): 2032 """ 2033 Presents simple wizard interface for beginner users 2034 """ 2035 2036 if not conf.wizard: 2037 return 2038 2039 logger.info("starting wizard interface") 2040 2041 while not conf.url: 2042 message = "Please enter full target URL (-u): " 2043 conf.url = readInput(message, default=None) 2044 2045 message = "%s data (--data) [Enter for None]: " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST) 2046 conf.data = readInput(message, default=None) 2047 2048 if not (any('=' in _ for _ in (conf.url, conf.data)) or '*' in conf.url): 2049 warnMsg = "no GET and/or %s parameter(s) found for testing " % ((conf.method if conf.method != HTTPMETHOD.GET else conf.method) or HTTPMETHOD.POST) 2050 warnMsg += "(e.g. GET parameter 'id' in 'http://www.site.com/vuln.php?id=1'). " 2051 if not conf.crawlDepth and not conf.forms: 2052 warnMsg += "Will search for forms" 2053 conf.forms = True 2054 logger.warn(warnMsg) 2055 2056 choice = None 2057 2058 while choice is None or choice not in ("", "1", "2", "3"): 2059 message = "Injection difficulty (--level/--risk). Please choose:\n" 2060 message += "[1] Normal (default)\n[2] Medium\n[3] Hard" 2061 choice = readInput(message, default='1') 2062 2063 if choice == '2': 2064 conf.risk = 2 2065 conf.level = 3 2066 elif choice == '3': 2067 conf.risk = 3 2068 conf.level = 5 2069 else: 2070 conf.risk = 1 2071 conf.level = 1 2072 2073 if not conf.getAll: 2074 choice = None 2075 2076 while choice is None or choice not in ("", "1", "2", "3"): 2077 message = "Enumeration (--banner/--current-user/etc). Please choose:\n" 2078 message += "[1] Basic (default)\n[2] Intermediate\n[3] All" 2079 choice = readInput(message, default='1') 2080 2081 if choice == '2': 2082 options = WIZARD.INTERMEDIATE 2083 elif choice == '3': 2084 options = WIZARD.ALL 2085 else: 2086 options = WIZARD.BASIC 2087 2088 for _ in options: 2089 conf.__setitem__(_, True) 2090 2091 logger.debug("muting sqlmap.. it will do the magic for you") 2092 conf.verbose = 0 2093 2094 conf.batch = True 2095 conf.threads = 4 2096 2097 dataToStdout("\nsqlmap is running, please wait..\n\n") 2098 2099 kb.wizardMode = True 2100 2101def _saveConfig(): 2102 """ 2103 Saves the command line options to a sqlmap configuration INI file 2104 Format. 2105 """ 2106 2107 if not conf.saveConfig: 2108 return 2109 2110 debugMsg = "saving command line options to a sqlmap configuration INI file" 2111 logger.debug(debugMsg) 2112 2113 saveConfig(conf, conf.saveConfig) 2114 2115 infoMsg = "saved command line options to the configuration file '%s'" % conf.saveConfig 2116 logger.info(infoMsg) 2117 2118def setVerbosity(): 2119 """ 2120 This function set the verbosity of sqlmap output messages. 2121 """ 2122 2123 if conf.verbose is None: 2124 conf.verbose = 1 2125 2126 conf.verbose = int(conf.verbose) 2127 2128 if conf.verbose == 0: 2129 logger.setLevel(logging.ERROR) 2130 elif conf.verbose == 1: 2131 logger.setLevel(logging.INFO) 2132 elif conf.verbose > 2 and conf.eta: 2133 conf.verbose = 2 2134 logger.setLevel(logging.DEBUG) 2135 elif conf.verbose == 2: 2136 logger.setLevel(logging.DEBUG) 2137 elif conf.verbose == 3: 2138 logger.setLevel(CUSTOM_LOGGING.PAYLOAD) 2139 elif conf.verbose == 4: 2140 logger.setLevel(CUSTOM_LOGGING.TRAFFIC_OUT) 2141 elif conf.verbose >= 5: 2142 logger.setLevel(CUSTOM_LOGGING.TRAFFIC_IN) 2143 2144def _normalizeOptions(inputOptions): 2145 """ 2146 Sets proper option types 2147 """ 2148 2149 types_ = {} 2150 for group in optDict.keys(): 2151 types_.update(optDict[group]) 2152 2153 for key in inputOptions: 2154 if key in types_: 2155 value = inputOptions[key] 2156 if value is None: 2157 continue 2158 2159 type_ = types_[key] 2160 if type_ and isinstance(type_, tuple): 2161 type_ = type_[0] 2162 2163 if type_ == OPTION_TYPE.BOOLEAN: 2164 try: 2165 value = bool(value) 2166 except (TypeError, ValueError): 2167 value = False 2168 elif type_ == OPTION_TYPE.INTEGER: 2169 try: 2170 value = int(value) 2171 except (TypeError, ValueError): 2172 value = 0 2173 elif type_ == OPTION_TYPE.FLOAT: 2174 try: 2175 value = float(value) 2176 except (TypeError, ValueError): 2177 value = 0.0 2178 2179 inputOptions[key] = value 2180 2181def _mergeOptions(inputOptions, overrideOptions): 2182 """ 2183 Merge command line options with configuration file and default options. 2184 2185 @param inputOptions: optparse object with command line options. 2186 @type inputOptions: C{instance} 2187 """ 2188 2189 if inputOptions.configFile: 2190 configFileParser(inputOptions.configFile) 2191 2192 if hasattr(inputOptions, "items"): 2193 inputOptionsItems = inputOptions.items() 2194 else: 2195 inputOptionsItems = inputOptions.__dict__.items() 2196 2197 for key, value in inputOptionsItems: 2198 if key not in conf or value not in (None, False) or overrideOptions: 2199 conf[key] = value 2200 2201 if not conf.api: 2202 for key, value in conf.items(): 2203 if value is not None: 2204 kb.explicitSettings.add(key) 2205 2206 for key, value in defaults.items(): 2207 if hasattr(conf, key) and conf[key] is None: 2208 conf[key] = value 2209 2210 if conf.unstable: 2211 if key in ("timeSec", "retries", "timeout"): 2212 conf[key] *= 2 2213 2214 if conf.unstable: 2215 conf.forcePartial = True 2216 2217 lut = {} 2218 for group in optDict.keys(): 2219 lut.update((_.upper(), _) for _ in optDict[group]) 2220 2221 envOptions = {} 2222 for key, value in os.environ.items(): 2223 if key.upper().startswith(SQLMAP_ENVIRONMENT_PREFIX): 2224 _ = key[len(SQLMAP_ENVIRONMENT_PREFIX):].upper() 2225 if _ in lut: 2226 envOptions[lut[_]] = value 2227 2228 if envOptions: 2229 _normalizeOptions(envOptions) 2230 for key, value in envOptions.items(): 2231 conf[key] = value 2232 2233 mergedOptions.update(conf) 2234 2235def _setTrafficOutputFP(): 2236 if conf.trafficFile: 2237 infoMsg = "setting file for logging HTTP traffic" 2238 logger.info(infoMsg) 2239 2240 conf.trafficFP = openFile(conf.trafficFile, "w+") 2241 2242def _setupHTTPCollector(): 2243 if not conf.harFile: 2244 return 2245 2246 conf.httpCollector = HTTPCollectorFactory(conf.harFile).create() 2247 2248def _setDNSServer(): 2249 if not conf.dnsDomain: 2250 return 2251 2252 infoMsg = "setting up DNS server instance" 2253 logger.info(infoMsg) 2254 2255 isAdmin = runningAsAdmin() 2256 2257 if isAdmin: 2258 try: 2259 conf.dnsServer = DNSServer() 2260 conf.dnsServer.run() 2261 except socket.error as ex: 2262 errMsg = "there was an error while setting up " 2263 errMsg += "DNS server instance ('%s')" % getSafeExString(ex) 2264 raise SqlmapGenericException(errMsg) 2265 else: 2266 errMsg = "you need to run sqlmap as an administrator " 2267 errMsg += "if you want to perform a DNS data exfiltration attack " 2268 errMsg += "as it will need to listen on privileged UDP port 53 " 2269 errMsg += "for incoming address resolution attempts" 2270 raise SqlmapMissingPrivileges(errMsg) 2271 2272def _setProxyList(): 2273 if not conf.proxyFile: 2274 return 2275 2276 conf.proxyList = [] 2277 for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w\-.]+):(\d+)", readCachedFileContent(conf.proxyFile)): 2278 _, type_, address, port = match.groups() 2279 conf.proxyList.append("%s://%s:%s" % (type_ or "http", address, port)) 2280 2281def _setTorProxySettings(): 2282 if not conf.tor: 2283 return 2284 2285 if conf.torType == PROXY_TYPE.HTTP: 2286 _setTorHttpProxySettings() 2287 else: 2288 _setTorSocksProxySettings() 2289 2290def _setTorHttpProxySettings(): 2291 infoMsg = "setting Tor HTTP proxy settings" 2292 logger.info(infoMsg) 2293 2294 port = findLocalPort(DEFAULT_TOR_HTTP_PORTS if not conf.torPort else (conf.torPort,)) 2295 2296 if port: 2297 conf.proxy = "http://%s:%d" % (LOCALHOST, port) 2298 else: 2299 errMsg = "can't establish connection with the Tor HTTP proxy. " 2300 errMsg += "Please make sure that you have Tor (bundle) installed and setup " 2301 errMsg += "so you could be able to successfully use switch '--tor' " 2302 raise SqlmapConnectionException(errMsg) 2303 2304 if not conf.checkTor: 2305 warnMsg = "use switch '--check-tor' at " 2306 warnMsg += "your own convenience when accessing " 2307 warnMsg += "Tor anonymizing network because of " 2308 warnMsg += "known issues with default settings of various 'bundles' " 2309 warnMsg += "(e.g. Vidalia)" 2310 logger.warn(warnMsg) 2311 2312def _setTorSocksProxySettings(): 2313 infoMsg = "setting Tor SOCKS proxy settings" 2314 logger.info(infoMsg) 2315 2316 port = findLocalPort(DEFAULT_TOR_SOCKS_PORTS if not conf.torPort else (conf.torPort,)) 2317 2318 if not port: 2319 errMsg = "can't establish connection with the Tor SOCKS proxy. " 2320 errMsg += "Please make sure that you have Tor service installed and setup " 2321 errMsg += "so you could be able to successfully use switch '--tor' " 2322 raise SqlmapConnectionException(errMsg) 2323 2324 # SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29) 2325 socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if conf.torType == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, LOCALHOST, port) 2326 socks.wrapmodule(_http_client) 2327 2328def _setHttpChunked(): 2329 if conf.chunked and conf.data: 2330 _http_client.HTTPConnection._set_content_length = lambda self, a, b: None 2331 2332def _checkWebSocket(): 2333 if conf.url and (conf.url.startswith("ws:/") or conf.url.startswith("wss:/")): 2334 try: 2335 from websocket import ABNF 2336 except ImportError: 2337 errMsg = "sqlmap requires third-party module 'websocket-client' " 2338 errMsg += "in order to use WebSocket functionality" 2339 raise SqlmapMissingDependence(errMsg) 2340 2341def _checkTor(): 2342 if not conf.checkTor: 2343 return 2344 2345 infoMsg = "checking Tor connection" 2346 logger.info(infoMsg) 2347 2348 try: 2349 page, _, _ = Request.getPage(url="https://check.torproject.org/", raise404=False) 2350 except SqlmapConnectionException: 2351 page = None 2352 2353 if not page or "Congratulations" not in page: 2354 errMsg = "it appears that Tor is not properly set. Please try using options '--tor-type' and/or '--tor-port'" 2355 raise SqlmapConnectionException(errMsg) 2356 else: 2357 infoMsg = "Tor is properly being used" 2358 logger.info(infoMsg) 2359 2360def _basicOptionValidation(): 2361 if conf.limitStart is not None and not (isinstance(conf.limitStart, int) and conf.limitStart > 0): 2362 errMsg = "value for option '--start' (limitStart) must be an integer value greater than zero (>0)" 2363 raise SqlmapSyntaxException(errMsg) 2364 2365 if conf.limitStop is not None and not (isinstance(conf.limitStop, int) and conf.limitStop > 0): 2366 errMsg = "value for option '--stop' (limitStop) must be an integer value greater than zero (>0)" 2367 raise SqlmapSyntaxException(errMsg) 2368 2369 if conf.level is not None and not (isinstance(conf.level, int) and conf.level >= 1 and conf.level <= 5): 2370 errMsg = "value for option '--level' must be an integer value from range [1, 5]" 2371 raise SqlmapSyntaxException(errMsg) 2372 2373 if conf.risk is not None and not (isinstance(conf.risk, int) and conf.risk >= 1 and conf.risk <= 3): 2374 errMsg = "value for option '--risk' must be an integer value from range [1, 3]" 2375 raise SqlmapSyntaxException(errMsg) 2376 2377 if isinstance(conf.limitStart, int) and conf.limitStart > 0 and \ 2378 isinstance(conf.limitStop, int) and conf.limitStop < conf.limitStart: 2379 warnMsg = "usage of option '--start' (limitStart) which is bigger than value for --stop (limitStop) option is considered unstable" 2380 logger.warn(warnMsg) 2381 2382 if isinstance(conf.firstChar, int) and conf.firstChar > 0 and \ 2383 isinstance(conf.lastChar, int) and conf.lastChar < conf.firstChar: 2384 errMsg = "value for option '--first' (firstChar) must be smaller than or equal to value for --last (lastChar) option" 2385 raise SqlmapSyntaxException(errMsg) 2386 2387 if conf.textOnly and conf.nullConnection: 2388 errMsg = "switch '--text-only' is incompatible with switch '--null-connection'" 2389 raise SqlmapSyntaxException(errMsg) 2390 2391 if conf.eta and conf.verbose > defaults.verbose: 2392 errMsg = "switch '--eta' is incompatible with option '-v'" 2393 raise SqlmapSyntaxException(errMsg) 2394 2395 if conf.secondUrl and conf.secondReq: 2396 errMsg = "option '--second-url' is incompatible with option '--second-req')" 2397 raise SqlmapSyntaxException(errMsg) 2398 2399 if conf.direct and conf.url: 2400 errMsg = "option '-d' is incompatible with option '-u' ('--url')" 2401 raise SqlmapSyntaxException(errMsg) 2402 2403 if conf.direct and conf.dbms: 2404 errMsg = "option '-d' is incompatible with option '--dbms'" 2405 raise SqlmapSyntaxException(errMsg) 2406 2407 if conf.titles and conf.nullConnection: 2408 errMsg = "switch '--titles' is incompatible with switch '--null-connection'" 2409 raise SqlmapSyntaxException(errMsg) 2410 2411 if conf.dumpTable and conf.search: 2412 errMsg = "switch '--dump' is incompatible with switch '--search'" 2413 raise SqlmapSyntaxException(errMsg) 2414 2415 if conf.chunked and not any((conf.data, conf.requestFile, conf.forms)): 2416 errMsg = "switch '--chunked' requires usage of (POST) options/switches '--data', '-r' or '--forms'" 2417 raise SqlmapSyntaxException(errMsg) 2418 2419 if conf.api and not conf.configFile: 2420 errMsg = "switch '--api' requires usage of option '-c'" 2421 raise SqlmapSyntaxException(errMsg) 2422 2423 if conf.data and conf.nullConnection: 2424 errMsg = "option '--data' is incompatible with switch '--null-connection'" 2425 raise SqlmapSyntaxException(errMsg) 2426 2427 if conf.string and conf.nullConnection: 2428 errMsg = "option '--string' is incompatible with switch '--null-connection'" 2429 raise SqlmapSyntaxException(errMsg) 2430 2431 if conf.notString and conf.nullConnection: 2432 errMsg = "option '--not-string' is incompatible with switch '--null-connection'" 2433 raise SqlmapSyntaxException(errMsg) 2434 2435 if conf.tor and conf.osPwn: 2436 errMsg = "option '--tor' is incompatible with switch '--os-pwn'" 2437 raise SqlmapSyntaxException(errMsg) 2438 2439 if conf.noCast and conf.hexConvert: 2440 errMsg = "switch '--no-cast' is incompatible with switch '--hex'" 2441 raise SqlmapSyntaxException(errMsg) 2442 2443 if conf.dumpAll and conf.search: 2444 errMsg = "switch '--dump-all' is incompatible with switch '--search'" 2445 raise SqlmapSyntaxException(errMsg) 2446 2447 if conf.string and conf.notString: 2448 errMsg = "option '--string' is incompatible with switch '--not-string'" 2449 raise SqlmapSyntaxException(errMsg) 2450 2451 if conf.regexp and conf.nullConnection: 2452 errMsg = "option '--regexp' is incompatible with switch '--null-connection'" 2453 raise SqlmapSyntaxException(errMsg) 2454 2455 if conf.regexp: 2456 try: 2457 re.compile(conf.regexp) 2458 except Exception as ex: 2459 errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex)) 2460 raise SqlmapSyntaxException(errMsg) 2461 2462 if conf.paramExclude: 2463 try: 2464 re.compile(conf.paramExclude) 2465 except Exception as ex: 2466 errMsg = "invalid regular expression '%s' ('%s')" % (conf.paramExclude, getSafeExString(ex)) 2467 raise SqlmapSyntaxException(errMsg) 2468 2469 if conf.crawlExclude: 2470 try: 2471 re.compile(conf.crawlExclude) 2472 except Exception as ex: 2473 errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex)) 2474 raise SqlmapSyntaxException(errMsg) 2475 2476 if conf.dumpTable and conf.dumpAll: 2477 errMsg = "switch '--dump' is incompatible with switch '--dump-all'" 2478 raise SqlmapSyntaxException(errMsg) 2479 2480 if conf.predictOutput and (conf.threads > 1 or conf.optimize): 2481 errMsg = "switch '--predict-output' is incompatible with option '--threads' and switch '-o'" 2482 raise SqlmapSyntaxException(errMsg) 2483 2484 if conf.threads > MAX_NUMBER_OF_THREADS and not conf.get("skipThreadCheck"): 2485 errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS 2486 raise SqlmapSyntaxException(errMsg) 2487 2488 if conf.forms and not any((conf.url, conf.googleDork, conf.bulkFile)): 2489 errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-g' or '-m'" 2490 raise SqlmapSyntaxException(errMsg) 2491 2492 if conf.crawlExclude and not conf.crawlDepth: 2493 errMsg = "option '--crawl-exclude' requires usage of switch '--crawl'" 2494 raise SqlmapSyntaxException(errMsg) 2495 2496 if conf.safePost and not conf.safeUrl: 2497 errMsg = "option '--safe-post' requires usage of option '--safe-url'" 2498 raise SqlmapSyntaxException(errMsg) 2499 2500 if conf.safeFreq and not any((conf.safeUrl, conf.safeReqFile)): 2501 errMsg = "option '--safe-freq' requires usage of option '--safe-url' or '--safe-req'" 2502 raise SqlmapSyntaxException(errMsg) 2503 2504 if conf.safeReqFile and any((conf.safeUrl, conf.safePost)): 2505 errMsg = "option '--safe-req' is incompatible with option '--safe-url' and option '--safe-post'" 2506 raise SqlmapSyntaxException(errMsg) 2507 2508 if conf.csrfUrl and not conf.csrfToken: 2509 errMsg = "option '--csrf-url' requires usage of option '--csrf-token'" 2510 raise SqlmapSyntaxException(errMsg) 2511 2512 if conf.csrfMethod and not conf.csrfToken: 2513 errMsg = "option '--csrf-method' requires usage of option '--csrf-token'" 2514 raise SqlmapSyntaxException(errMsg) 2515 2516 if conf.csrfToken and conf.threads > 1: 2517 errMsg = "option '--csrf-url' is incompatible with option '--threads'" 2518 raise SqlmapSyntaxException(errMsg) 2519 2520 if conf.requestFile and conf.url and conf.url != DUMMY_URL: 2521 errMsg = "option '-r' is incompatible with option '-u' ('--url')" 2522 raise SqlmapSyntaxException(errMsg) 2523 2524 if conf.direct and conf.proxy: 2525 errMsg = "option '-d' is incompatible with option '--proxy'" 2526 raise SqlmapSyntaxException(errMsg) 2527 2528 if conf.direct and conf.tor: 2529 errMsg = "option '-d' is incompatible with switch '--tor'" 2530 raise SqlmapSyntaxException(errMsg) 2531 2532 if not conf.technique: 2533 errMsg = "option '--technique' can't be empty" 2534 raise SqlmapSyntaxException(errMsg) 2535 2536 if conf.tor and conf.ignoreProxy: 2537 errMsg = "switch '--tor' is incompatible with switch '--ignore-proxy'" 2538 raise SqlmapSyntaxException(errMsg) 2539 2540 if conf.tor and conf.proxy: 2541 errMsg = "switch '--tor' is incompatible with option '--proxy'" 2542 raise SqlmapSyntaxException(errMsg) 2543 2544 if conf.proxy and conf.proxyFile: 2545 errMsg = "switch '--proxy' is incompatible with option '--proxy-file'" 2546 raise SqlmapSyntaxException(errMsg) 2547 2548 if conf.checkTor and not any((conf.tor, conf.proxy)): 2549 errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address of Tor service)" 2550 raise SqlmapSyntaxException(errMsg) 2551 2552 if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort >= 0 and conf.torPort <= 65535): 2553 errMsg = "value for option '--tor-port' must be in range [0, 65535]" 2554 raise SqlmapSyntaxException(errMsg) 2555 2556 if conf.torType not in getPublicTypeMembers(PROXY_TYPE, True): 2557 errMsg = "option '--tor-type' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(PROXY_TYPE, True)) 2558 raise SqlmapSyntaxException(errMsg) 2559 2560 if conf.dumpFormat not in getPublicTypeMembers(DUMP_FORMAT, True): 2561 errMsg = "option '--dump-format' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(DUMP_FORMAT, True)) 2562 raise SqlmapSyntaxException(errMsg) 2563 2564 if conf.skip and conf.testParameter: 2565 if intersect(conf.skip, conf.testParameter): 2566 errMsg = "option '--skip' is incompatible with option '-p'" 2567 raise SqlmapSyntaxException(errMsg) 2568 2569 if conf.rParam and conf.testParameter: 2570 if intersect(conf.rParam, conf.testParameter): 2571 errMsg = "option '--randomize' is incompatible with option '-p'" 2572 raise SqlmapSyntaxException(errMsg) 2573 2574 if conf.mobile and conf.agent: 2575 errMsg = "switch '--mobile' is incompatible with option '--user-agent'" 2576 raise SqlmapSyntaxException(errMsg) 2577 2578 if conf.proxy and conf.ignoreProxy: 2579 errMsg = "option '--proxy' is incompatible with switch '--ignore-proxy'" 2580 raise SqlmapSyntaxException(errMsg) 2581 2582 if conf.alert and conf.alert.startswith('-'): 2583 errMsg = "value for option '--alert' must be valid operating system command(s)" 2584 raise SqlmapSyntaxException(errMsg) 2585 2586 if conf.timeSec < 1: 2587 errMsg = "value for option '--time-sec' must be a positive integer" 2588 raise SqlmapSyntaxException(errMsg) 2589 2590 if conf.uChar and not re.match(UNION_CHAR_REGEX, conf.uChar): 2591 errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)" 2592 raise SqlmapSyntaxException(errMsg) 2593 2594 if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.liveTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)): 2595 errMsg = "option '--crack' should be used as a standalone" 2596 raise SqlmapSyntaxException(errMsg) 2597 2598 if isinstance(conf.uCols, six.string_types): 2599 if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2): 2600 errMsg = "value for option '--union-cols' must be a range with hyphon " 2601 errMsg += "(e.g. 1-10) or integer value (e.g. 5)" 2602 raise SqlmapSyntaxException(errMsg) 2603 2604 if conf.dbmsCred and ':' not in conf.dbmsCred: 2605 errMsg = "value for option '--dbms-cred' must be in " 2606 errMsg += "format <username>:<password> (e.g. \"root:pass\")" 2607 raise SqlmapSyntaxException(errMsg) 2608 2609 if conf.encoding: 2610 _ = checkCharEncoding(conf.encoding, False) 2611 if _ is None: 2612 errMsg = "unknown encoding '%s'. Please visit " % conf.encoding 2613 errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE 2614 errMsg += "supported encodings" 2615 raise SqlmapSyntaxException(errMsg) 2616 else: 2617 conf.encoding = _ 2618 2619 if conf.loadCookies: 2620 if not os.path.exists(conf.loadCookies): 2621 errMsg = "cookies file '%s' does not exist" % conf.loadCookies 2622 raise SqlmapFilePathException(errMsg) 2623 2624def initOptions(inputOptions=AttribDict(), overrideOptions=False): 2625 _setConfAttributes() 2626 _setKnowledgeBaseAttributes() 2627 _mergeOptions(inputOptions, overrideOptions) 2628 2629def init(): 2630 """ 2631 Set attributes into both configuration and knowledge base singletons 2632 based upon command line and configuration file options. 2633 """ 2634 2635 _useWizardInterface() 2636 setVerbosity() 2637 _saveConfig() 2638 _setRequestFromFile() 2639 _cleanupOptions() 2640 _cleanupEnvironment() 2641 _purge() 2642 _checkDependencies() 2643 _createHomeDirectories() 2644 _createTemporaryDirectory() 2645 _basicOptionValidation() 2646 _setProxyList() 2647 _setTorProxySettings() 2648 _setDNSServer() 2649 _adjustLoggingFormatter() 2650 _setMultipleTargets() 2651 _listTamperingFunctions() 2652 _setTamperingFunctions() 2653 _setPreprocessFunctions() 2654 _setTrafficOutputFP() 2655 _setupHTTPCollector() 2656 _setHttpChunked() 2657 _checkWebSocket() 2658 2659 parseTargetDirect() 2660 2661 if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.liveTest)): 2662 _setHostname() 2663 _setHTTPTimeout() 2664 _setHTTPExtraHeaders() 2665 _setHTTPCookies() 2666 _setHTTPReferer() 2667 _setHTTPHost() 2668 _setHTTPUserAgent() 2669 _setHTTPAuthentication() 2670 _setHTTPHandlers() 2671 _setDNSCache() 2672 _setSocketPreConnect() 2673 _setSafeVisit() 2674 _doSearch() 2675 _setBulkMultipleTargets() 2676 _checkTor() 2677 _setCrawler() 2678 _findPageForms() 2679 _setDBMS() 2680 _setTechnique() 2681 2682 _setThreads() 2683 _setOS() 2684 _setWriteFile() 2685 _setMetasploit() 2686 _setDBMSAuthentication() 2687 loadBoundaries() 2688 loadPayloads() 2689 _setPrefixSuffix() 2690 update() 2691 _loadQueries() 2692