Compare commits

..

1 Commits

Author SHA1 Message Date
Miroslav Stampar
85f25c90bb Fixes #5216 2022-11-01 23:12:32 +01:00
12 changed files with 41 additions and 50 deletions

View File

@@ -10,6 +10,7 @@ import logging
import random import random
import re import re
import socket import socket
import subprocess
import time import time
from extra.beep.beep import beep from extra.beep.beep import beep
@@ -782,8 +783,22 @@ def checkSqlInjection(place, parameter, value):
injection.conf.regexp = conf.regexp injection.conf.regexp = conf.regexp
injection.conf.optimize = conf.optimize injection.conf.optimize = conf.optimize
if conf.beep: if not kb.alerted:
beep() if conf.beep:
beep()
if conf.alert:
infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
logger.info(infoMsg)
try:
process = subprocess.Popen(conf.alert, shell=True)
process.wait()
except Exception as ex:
errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
logger.error(errMsg)
kb.alerted = True
# There is no need to perform this test for other # There is no need to perform this test for other
# <where> tags # <where> tags
@@ -844,8 +859,10 @@ def checkSqlInjection(place, parameter, value):
if not checkFalsePositives(injection): if not checkFalsePositives(injection):
if conf.hostname in kb.vulnHosts: if conf.hostname in kb.vulnHosts:
kb.vulnHosts.remove(conf.hostname) kb.vulnHosts.remove(conf.hostname)
if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE not in injection.notes: if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE not in injection.notes:
injection.notes.append(NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE) injection.notes.append(NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE)
else: else:
injection = None injection = None

View File

@@ -9,7 +9,6 @@ from __future__ import division
import os import os
import re import re
import subprocess
import time import time
from lib.controller.action import action from lib.controller.action import action
@@ -599,19 +598,6 @@ def start():
kb.injections.append(injection) kb.injections.append(injection)
if not kb.alerted:
if conf.alert:
infoMsg = "executing alerting shell command(s) ('%s')" % conf.alert
logger.info(infoMsg)
try:
process = subprocess.Popen(conf.alert, shell=True)
process.wait()
except Exception as ex:
errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
logger.error(errMsg)
kb.alerted = True
# In case when user wants to end detection phase (Ctrl+C) # In case when user wants to end detection phase (Ctrl+C)
if not proceed: if not proceed:
break break

View File

@@ -449,7 +449,7 @@ class Dump(object):
dumpDbPath = tempDir dumpDbPath = tempDir
dumpFileName = conf.dumpFile or os.path.join(dumpDbPath, re.sub(r'[\\/]', UNSAFE_DUMP_FILEPATH_REPLACEMENT, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower()))) dumpFileName = os.path.join(dumpDbPath, re.sub(r'[\\/]', UNSAFE_DUMP_FILEPATH_REPLACEMENT, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower())))
if not checkFile(dumpFileName, False): if not checkFile(dumpFileName, False):
try: try:
openFile(dumpFileName, "w+b").close() openFile(dumpFileName, "w+b").close()

View File

@@ -416,9 +416,6 @@ def _doSearch():
conf.googlePage += 1 conf.googlePage += 1
def _setStdinPipeTargets(): def _setStdinPipeTargets():
if conf.url:
return
if isinstance(conf.stdinPipe, _collections.Iterable): if isinstance(conf.stdinPipe, _collections.Iterable):
infoMsg = "using 'STDIN' for parsing targets list" infoMsg = "using 'STDIN' for parsing targets list"
logger.info(infoMsg) logger.info(infoMsg)
@@ -2097,7 +2094,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.lastParserStatus = None kb.lastParserStatus = None
kb.locks = AttribDict() kb.locks = AttribDict()
for _ in ("cache", "connError", "count", "handlers", "hint", "identYwaf", "index", "io", "limit", "liveCookies", "log", "socket", "redirect", "request", "value"): for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "liveCookies", "log", "socket", "redirect", "request", "value"):
kb.locks[_] = threading.Lock() kb.locks[_] = threading.Lock()
kb.matchRatio = None kb.matchRatio = None

View File

@@ -215,7 +215,6 @@ optDict = {
"crawlDepth": "integer", "crawlDepth": "integer",
"crawlExclude": "string", "crawlExclude": "string",
"csvDel": "string", "csvDel": "string",
"dumpFile": "string",
"dumpFormat": "string", "dumpFormat": "string",
"encoding": "string", "encoding": "string",
"eta": "boolean", "eta": "boolean",

View File

@@ -20,7 +20,7 @@ from thirdparty import six
from thirdparty.six import unichr as _unichr from thirdparty.six import unichr as _unichr
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.6.12.0" VERSION = "1.6.11.0"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -363,7 +363,6 @@ BASIC_HELP_ITEMS = (
"getCurrentUser", "getCurrentUser",
"getCurrentDb", "getCurrentDb",
"getPasswordHashes", "getPasswordHashes",
"getDbs",
"getTables", "getTables",
"getColumns", "getColumns",
"getSchema", "getSchema",

View File

@@ -661,9 +661,6 @@ def cmdLineParser(argv=None):
general.add_argument("--charset", dest="charset", general.add_argument("--charset", dest="charset",
help="Blind SQL injection charset (e.g. \"0123456789abcdef\")") help="Blind SQL injection charset (e.g. \"0123456789abcdef\")")
general.add_argument("--dump-file", dest="dumpFile",
help="Store dumped data to a custom file")
general.add_argument("--dump-format", dest="dumpFormat", general.add_argument("--dump-format", dest="dumpFormat",
help="Format of dumped data (CSV (default), HTML or SQLITE)") help="Format of dumped data (CSV (default), HTML or SQLITE)")
@@ -839,9 +836,6 @@ def cmdLineParser(argv=None):
parser.add_argument("--vuln-test", dest="vulnTest", action="store_true", parser.add_argument("--vuln-test", dest="vulnTest", action="store_true",
help=SUPPRESS) help=SUPPRESS)
parser.add_argument("--disable-json", dest="disableJson", action="store_true",
help=SUPPRESS)
# API options # API options
parser.add_argument("--api", dest="api", action="store_true", parser.add_argument("--api", dest="api", action="store_true",
help=SUPPRESS) help=SUPPRESS)

View File

@@ -275,8 +275,6 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
>>> getText(decodePage(b"<html>foo&amp;bar</html>", None, "text/html; charset=utf-8")) >>> getText(decodePage(b"<html>foo&amp;bar</html>", None, "text/html; charset=utf-8"))
'<html>foo&bar</html>' '<html>foo&bar</html>'
>>> getText(decodePage(b"&#x9;", None, "text/html; charset=utf-8"))
'\\t'
""" """
if not page or (conf.nullConnection and len(page) < 2): if not page or (conf.nullConnection and len(page) < 2):
@@ -341,7 +339,7 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
if not kb.disableHtmlDecoding: if not kb.disableHtmlDecoding:
# e.g. &#x9;&#195;&#235;&#224;&#226;&#224; # e.g. &#x9;&#195;&#235;&#224;&#226;&#224;
if b"&#" in page: if b"&#" in page:
page = re.sub(b"&#x([0-9a-f]{1,2});", lambda _: decodeHex(_.group(1) if len(_.group(1)) == 2 else b"0%s" % _.group(1)), page) page = re.sub(b"&#x([0-9a-f]{1,2});", lambda _: decodeHex(_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)), page)
page = re.sub(b"&#(\\d{1,3});", lambda _: six.int2byte(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page) page = re.sub(b"&#(\\d{1,3});", lambda _: six.int2byte(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
# e.g. %20%28%29 # e.g. %20%28%29
@@ -401,14 +399,13 @@ def processResponse(page, responseHeaders, code=None, status=None):
if not conf.skipWaf and kb.processResponseCounter < IDENTYWAF_PARSE_LIMIT: if not conf.skipWaf and kb.processResponseCounter < IDENTYWAF_PARSE_LIMIT:
rawResponse = "%s %s %s\n%s\n%s" % (_http_client.HTTPConnection._http_vsn_str, code or "", status or "", "".join(getUnicode(responseHeaders.headers if responseHeaders else [])), page[:HEURISTIC_PAGE_SIZE_THRESHOLD]) rawResponse = "%s %s %s\n%s\n%s" % (_http_client.HTTPConnection._http_vsn_str, code or "", status or "", "".join(getUnicode(responseHeaders.headers if responseHeaders else [])), page[:HEURISTIC_PAGE_SIZE_THRESHOLD])
with kb.locks.identYwaf: identYwaf.non_blind.clear()
identYwaf.non_blind.clear() if identYwaf.non_blind_check(rawResponse, silent=True):
if identYwaf.non_blind_check(rawResponse, silent=True): for waf in identYwaf.non_blind:
for waf in set(identYwaf.non_blind): if waf not in kb.identifiedWafs:
if waf not in kb.identifiedWafs: kb.identifiedWafs.add(waf)
kb.identifiedWafs.add(waf) errMsg = "WAF/IPS identified as '%s'" % identYwaf.format_name(waf)
errMsg = "WAF/IPS identified as '%s'" % identYwaf.format_name(waf) singleTimeLogMessage(errMsg, logging.CRITICAL)
singleTimeLogMessage(errMsg, logging.CRITICAL)
if kb.originalPage is None: if kb.originalPage is None:
for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX):

View File

@@ -587,9 +587,14 @@ class Connect(object):
if not getRequestHeader(req, HTTP_HEADER.COOKIE) and conf.cj: if not getRequestHeader(req, HTTP_HEADER.COOKIE) and conf.cj:
conf.cj._policy._now = conf.cj._now = int(time.time()) conf.cj._policy._now = conf.cj._now = int(time.time())
with conf.cj._cookies_lock: while True:
cookies = conf.cj._cookies_for_request(req) try:
requestHeaders += "\r\n%s" % ("Cookie: %s" % ";".join("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value)) for cookie in cookies)) cookies = conf.cj._cookies_for_request(req)
except RuntimeError: # NOTE: https://github.com/sqlmapproject/sqlmap/issues/5187
time.sleep(1)
else:
requestHeaders += "\r\n%s" % ("Cookie: %s" % ";".join("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value)) for cookie in cookies))
break
if post is not None: if post is not None:
if not getRequestHeader(req, HTTP_HEADER.CONTENT_LENGTH) and not chunked: if not getRequestHeader(req, HTTP_HEADER.CONTENT_LENGTH) and not chunked:

View File

@@ -69,7 +69,7 @@ class HTTPSConnection(_http_client.HTTPSConnection):
sock = create_sock() sock = create_sock()
if protocol not in _contexts: if protocol not in _contexts:
_contexts[protocol] = ssl.SSLContext(protocol) _contexts[protocol] = ssl.SSLContext(protocol)
if getattr(self, "cert_file", None) and getattr(self, "key_file", None): if self.cert_file and self.key_file:
_contexts[protocol].load_cert_chain(certfile=self.cert_file, keyfile=self.key_file) _contexts[protocol].load_cert_chain(certfile=self.cert_file, keyfile=self.key_file)
try: try:
# Reference(s): https://askubuntu.com/a/1263098 # Reference(s): https://askubuntu.com/a/1263098
@@ -94,7 +94,7 @@ class HTTPSConnection(_http_client.HTTPSConnection):
for protocol in _protocols: for protocol in _protocols:
try: try:
sock = create_sock() sock = create_sock()
_ = ssl.wrap_socket(sock, keyfile=getattr(self, "key_file"), certfile=getattr(self, "cert_file"), ssl_version=protocol) _ = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=protocol)
if _: if _:
success = True success = True
self.sock = _ self.sock = _

View File

@@ -252,7 +252,7 @@ def unionUse(expression, unpack=True, dump=False):
debugMsg += "it does not play well with UNION query SQL injection" debugMsg += "it does not play well with UNION query SQL injection"
singleTimeDebugMessage(debugMsg) singleTimeDebugMessage(debugMsg)
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL, DBMS.MSSQL, DBMS.SQLITE) and expressionFields and not any((conf.binaryFields, conf.limitStart, conf.limitStop, conf.forcePartial, conf.disableJson)): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ORACLE, DBMS.PGSQL, DBMS.MSSQL, DBMS.SQLITE) and expressionFields and not any((conf.binaryFields, conf.limitStart, conf.limitStop, conf.forcePartial)):
match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I) match = re.search(r"SELECT\s*(.+?)\bFROM", expression, re.I)
if match and not (Backend.isDbms(DBMS.ORACLE) and FROM_DUMMY_TABLE[DBMS.ORACLE] in expression) and not re.search(r"\b(MIN|MAX|COUNT)\(", expression): if match and not (Backend.isDbms(DBMS.ORACLE) and FROM_DUMMY_TABLE[DBMS.ORACLE] in expression) and not re.search(r"\b(MIN|MAX|COUNT)\(", expression):
kb.jsonAggMode = True kb.jsonAggMode = True

View File

@@ -738,9 +738,6 @@ crawlExclude =
# Default: , # Default: ,
csvDel = , csvDel = ,
# Store dumped data to a custom file.
dumpFile =
# Format of dumped data # Format of dumped data
# Valid: CSV, HTML or SQLITE # Valid: CSV, HTML or SQLITE
dumpFormat = CSV dumpFormat = CSV