mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-07 21:21:33 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66d26f67bf | ||
|
|
101d1f0d49 | ||
|
|
843126702d | ||
|
|
65f227fe65 | ||
|
|
536d9a597e | ||
|
|
0ce2128a9b | ||
|
|
e7ed2bbcbb | ||
|
|
560ff4154b | ||
|
|
1d0d5f1675 | ||
|
|
f1a3c81aec | ||
|
|
277a4fa402 | ||
|
|
037db0f4a0 | ||
|
|
3f1bf742fc | ||
|
|
abb911d741 | ||
|
|
dc5edf1a86 | ||
|
|
e11febdcbc | ||
|
|
f2af8861f9 | ||
|
|
2895e5c20f | ||
|
|
b1e8c75672 | ||
|
|
6cc52cc12a | ||
|
|
ddf353b86e | ||
|
|
e6535d359d | ||
|
|
90e381a5a5 | ||
|
|
e99e9919cd | ||
|
|
dbdfbcc425 | ||
|
|
1d6832a84a |
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap) [](https://badge.fury.io/py/sqlmap)
|
||||
[](https://api.travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester and a broad range of switches lasting from database fingerprinting, over data fetching from the database, to accessing the underlying file system and executing commands on the operating system via out-of-band connections.
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ from lib.core.enums import PAYLOAD
|
||||
from lib.core.enums import PLACE
|
||||
from lib.core.enums import REDIRECTION
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapDataException
|
||||
from lib.core.exception import SqlmapNoneDataException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
from lib.core.exception import SqlmapSkipTargetException
|
||||
@@ -1534,6 +1535,10 @@ def checkConnection(suppressOutput=False):
|
||||
errMsg = "problem occurred while "
|
||||
errMsg += "resolving a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
except UnicodeError, ex:
|
||||
errMsg = "problem occurred while "
|
||||
errMsg += "handling a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
|
||||
raise SqlmapDataException(errMsg)
|
||||
|
||||
if not suppressOutput and not conf.dummy and not conf.offline:
|
||||
infoMsg = "testing connection to the target URL"
|
||||
|
||||
@@ -313,6 +313,7 @@ def start():
|
||||
conf.cookie = targetCookie
|
||||
conf.httpHeaders = list(initialHeaders)
|
||||
conf.httpHeaders.extend(targetHeaders or [])
|
||||
conf.httpHeaders = [conf.httpHeaders[i] for i in xrange(len(conf.httpHeaders)) if conf.httpHeaders[i][0].upper() not in (__[0].upper() for __ in conf.httpHeaders[i + 1:])]
|
||||
|
||||
initTargetEnv()
|
||||
parseTargetUrl()
|
||||
|
||||
@@ -10,6 +10,7 @@ from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.dicts import DBMS_DICT
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
@@ -94,29 +95,41 @@ def setHandler():
|
||||
conf.dbmsConnector = Connector()
|
||||
|
||||
if conf.direct:
|
||||
exception = None
|
||||
dialect = DBMS_DICT[dbms][3]
|
||||
|
||||
if dialect:
|
||||
sqlalchemy = SQLAlchemy(dialect=dialect)
|
||||
sqlalchemy.connect()
|
||||
try:
|
||||
sqlalchemy = SQLAlchemy(dialect=dialect)
|
||||
sqlalchemy.connect()
|
||||
|
||||
if sqlalchemy.connector:
|
||||
conf.dbmsConnector = sqlalchemy
|
||||
else:
|
||||
try:
|
||||
conf.dbmsConnector.connect()
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
conf.dbmsConnector.connect()
|
||||
if sqlalchemy.connector:
|
||||
conf.dbmsConnector = sqlalchemy
|
||||
except Exception, ex:
|
||||
exception = ex
|
||||
|
||||
if not dialect or exception:
|
||||
try:
|
||||
conf.dbmsConnector.connect()
|
||||
except Exception, ex:
|
||||
if exception:
|
||||
raise exception
|
||||
else:
|
||||
if not isinstance(ex, NameError):
|
||||
raise
|
||||
else:
|
||||
msg = "support for direct connection to '%s' is not available. " % dbms
|
||||
msg += "Please rerun with '--dependencies'"
|
||||
raise SqlmapConnectionException(msg)
|
||||
|
||||
if conf.forceDbms == dbms or handler.checkDbms():
|
||||
if kb.resolutionDbms:
|
||||
conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]()
|
||||
conf.dbmsHandler._dbms = kb.resolutionDbms
|
||||
else:
|
||||
conf.dbmsHandler = handler
|
||||
conf.dbmsHandler._dbms = dbms
|
||||
|
||||
conf.dbmsHandler._dbms = dbms
|
||||
break
|
||||
else:
|
||||
conf.dbmsConnector = None
|
||||
|
||||
@@ -920,7 +920,7 @@ class Agent(object):
|
||||
elif Backend.isDbms(DBMS.HSQLDB):
|
||||
match = re.search(r"ORDER BY [^ ]+", limitedQuery)
|
||||
if match:
|
||||
limitedQuery = re.sub(r"\s*%s\s*" % match.group(0), " ", limitedQuery).strip()
|
||||
limitedQuery = re.sub(r"\s*%s\s*" % re.escape(match.group(0)), " ", limitedQuery).strip()
|
||||
limitedQuery += " %s" % match.group(0)
|
||||
|
||||
if query.startswith("SELECT "):
|
||||
|
||||
@@ -645,7 +645,7 @@ def paramToDict(place, parameters=None):
|
||||
current[key] = "%s%s" % (getUnicode(value).lower(), BOUNDED_INJECTION_MARKER)
|
||||
else:
|
||||
current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER)
|
||||
candidates["%s (%s)" % (parameter, key)] = re.sub(r"\b(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized), parameters)
|
||||
candidates["%s (%s)" % (parameter, key)] = re.sub(r"\b(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized, separators=(',', ':') if ", " not in testableParameters[parameter] else None), parameters)
|
||||
current[key] = original
|
||||
|
||||
deserialized = json.loads(testableParameters[parameter])
|
||||
@@ -997,6 +997,11 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
retVal = None
|
||||
kb.stickyLevel = None
|
||||
|
||||
if kb.lastInputMessage == message:
|
||||
checkBatch = False
|
||||
else:
|
||||
kb.lastInputMessage = message
|
||||
|
||||
message = getUnicode(message)
|
||||
|
||||
if "\n" in message:
|
||||
@@ -1407,8 +1412,10 @@ def parseTargetDirect():
|
||||
__import__("pyodbc")
|
||||
elif dbmsName == DBMS.FIREBIRD:
|
||||
__import__("kinterbasdb")
|
||||
except (SqlmapSyntaxException, SqlmapMissingDependence):
|
||||
raise
|
||||
except:
|
||||
if _sqlalchemy and data[3] in _sqlalchemy.dialects.__all__:
|
||||
if _sqlalchemy and data[3] and any(_ in _sqlalchemy.dialects.__all__ for _ in (data[3], data[3].split('+')[0])):
|
||||
pass
|
||||
else:
|
||||
errMsg = "sqlmap requires '%s' third-party library " % data[1]
|
||||
|
||||
@@ -82,6 +82,7 @@ from lib.core.enums import PROXY_TYPE
|
||||
from lib.core.enums import REFLECTIVE_COUNTER
|
||||
from lib.core.enums import WIZARD
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapDataException
|
||||
from lib.core.exception import SqlmapFilePathException
|
||||
from lib.core.exception import SqlmapGenericException
|
||||
from lib.core.exception import SqlmapInstallationException
|
||||
@@ -102,6 +103,7 @@ from lib.core.settings import DBMS_ALIASES
|
||||
from lib.core.settings import DEFAULT_PAGE_ENCODING
|
||||
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
|
||||
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
|
||||
from lib.core.settings import DEFAULT_USER_AGENT
|
||||
from lib.core.settings import DUMMY_URL
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
|
||||
@@ -112,7 +114,6 @@ from lib.core.settings import MAX_NUMBER_OF_THREADS
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import PARAMETER_SPLITTING_REGEX
|
||||
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
|
||||
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
@@ -122,7 +123,6 @@ from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import UNION_CHAR_REGEX
|
||||
from lib.core.settings import UNKNOWN_DBMS_VERSION
|
||||
from lib.core.settings import URI_INJECTABLE_REGEX
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import setDaemon
|
||||
from lib.core.update import update
|
||||
@@ -1071,7 +1071,7 @@ def _setSafeVisit():
|
||||
key, value = line.split(':', 1)
|
||||
value = value.strip()
|
||||
kb.safeReq.headers[key] = value
|
||||
if key == HTTP_HEADER.HOST:
|
||||
if key.upper() == HTTP_HEADER.HOST.upper():
|
||||
if not value.startswith("http"):
|
||||
scheme = "http"
|
||||
if value.endswith(":443"):
|
||||
@@ -1256,14 +1256,6 @@ def _setHTTPExtraHeaders():
|
||||
# Reference: http://stackoverflow.com/a/1383359
|
||||
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache"))
|
||||
|
||||
def _defaultHTTPUserAgent():
|
||||
"""
|
||||
@return: default sqlmap HTTP User-Agent header
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
return "%s (%s)" % (VERSION_STRING, SITE)
|
||||
|
||||
def _setHTTPUserAgent():
|
||||
"""
|
||||
Set the HTTP User-Agent header.
|
||||
@@ -1303,12 +1295,12 @@ def _setHTTPUserAgent():
|
||||
_ = True
|
||||
|
||||
for header, _ in conf.httpHeaders:
|
||||
if header == HTTP_HEADER.USER_AGENT:
|
||||
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
_ = False
|
||||
break
|
||||
|
||||
if _:
|
||||
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent()))
|
||||
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
|
||||
|
||||
else:
|
||||
if not kb.userAgents:
|
||||
@@ -1323,10 +1315,10 @@ def _setHTTPUserAgent():
|
||||
warnMsg += "file '%s'" % paths.USER_AGENTS
|
||||
logger.warn(warnMsg)
|
||||
|
||||
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent()))
|
||||
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
|
||||
return
|
||||
|
||||
userAgent = random.sample(kb.userAgents or [_defaultHTTPUserAgent()], 1)[0]
|
||||
userAgent = random.sample(kb.userAgents or [DEFAULT_USER_AGENT], 1)[0]
|
||||
|
||||
infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent
|
||||
infoMsg += "file '%s'" % paths.USER_AGENTS
|
||||
@@ -1373,7 +1365,12 @@ def _setHostname():
|
||||
"""
|
||||
|
||||
if conf.url:
|
||||
conf.hostname = urlparse.urlsplit(conf.url).netloc.split(':')[0]
|
||||
try:
|
||||
conf.hostname = urlparse.urlsplit(conf.url).netloc.split(':')[0]
|
||||
except ValueError, ex:
|
||||
errMsg = "problem occurred while "
|
||||
errMsg += "parsing an URL '%s' ('%s')" % (conf.url, getSafeExString(ex))
|
||||
raise SqlmapDataException(errMsg)
|
||||
|
||||
def _setHTTPTimeout():
|
||||
"""
|
||||
@@ -1795,6 +1792,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.injection = InjectionDict()
|
||||
kb.injections = []
|
||||
kb.laggingChecked = False
|
||||
kb.lastInputMessage = None
|
||||
kb.lastParserStatus = None
|
||||
|
||||
kb.locks = AttribDict()
|
||||
|
||||
@@ -19,12 +19,13 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||
from lib.core.enums import OS
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.2.11.0"
|
||||
VERSION = "1.2.12.0"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
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)
|
||||
DESCRIPTION = "automatic SQL injection and database takeover tool"
|
||||
SITE = "http://sqlmap.org"
|
||||
DEFAULT_USER_AGENT = "%s (%s)" % (VERSION_STRING, SITE)
|
||||
DEV_EMAIL_ADDRESS = "dev@sqlmap.org"
|
||||
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
|
||||
GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
|
||||
@@ -174,6 +175,9 @@ PUSH_VALUE_EXCEPTION_RETRY_COUNT = 3
|
||||
# Minimum time response set needed for time-comparison based on standard deviation
|
||||
MIN_TIME_RESPONSES = 30
|
||||
|
||||
# Maximum time response set used during time-comparison based on standard deviation
|
||||
MAX_TIME_RESPONSES = 200
|
||||
|
||||
# Minimum comparison ratio set needed for searching valid union column number based on standard deviation
|
||||
MIN_UNION_RESPONSES = 5
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ def _setRequestParams():
|
||||
# Url encoding of the header values should be avoided
|
||||
# Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value
|
||||
|
||||
if httpHeader.title() == HTTP_HEADER.USER_AGENT:
|
||||
if httpHeader.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True)))
|
||||
@@ -355,7 +355,7 @@ def _setRequestParams():
|
||||
conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader.title() == HTTP_HEADER.REFERER:
|
||||
elif httpHeader.upper() == HTTP_HEADER.REFERER.upper():
|
||||
conf.parameters[PLACE.REFERER] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True)))
|
||||
@@ -364,7 +364,7 @@ def _setRequestParams():
|
||||
conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
|
||||
testableParameters = True
|
||||
|
||||
elif httpHeader.title() == HTTP_HEADER.HOST:
|
||||
elif httpHeader.upper() == HTTP_HEADER.HOST.upper():
|
||||
conf.parameters[PLACE.HOST] = urldecode(headerValue)
|
||||
|
||||
condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True)))
|
||||
|
||||
@@ -89,6 +89,7 @@ from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
|
||||
from lib.core.settings import DEFAULT_CONTENT_TYPE
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
from lib.core.settings import DEFAULT_USER_AGENT
|
||||
from lib.core.settings import EVALCODE_KEYWORD_SUFFIX
|
||||
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
|
||||
from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
|
||||
@@ -99,6 +100,7 @@ from lib.core.settings import MAX_CONSECUTIVE_CONNECTION_ERRORS
|
||||
from lib.core.settings import MAX_MURPHY_SLEEP_TIME
|
||||
from lib.core.settings import META_REFRESH_REGEX
|
||||
from lib.core.settings import MIN_TIME_RESPONSES
|
||||
from lib.core.settings import MAX_TIME_RESPONSES
|
||||
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import LARGE_CHUNK_TRIM_MARKER
|
||||
@@ -360,14 +362,21 @@ class Connect(object):
|
||||
if kb.proxyAuthHeader:
|
||||
headers[HTTP_HEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader
|
||||
|
||||
if not getHeader(headers, HTTP_HEADER.ACCEPT):
|
||||
headers[HTTP_HEADER.ACCEPT] = HTTP_ACCEPT_HEADER_VALUE
|
||||
if not conf.requestFile or not target:
|
||||
if not getHeader(headers, HTTP_HEADER.HOST):
|
||||
headers[HTTP_HEADER.HOST] = getHostHeader(url)
|
||||
|
||||
if not getHeader(headers, HTTP_HEADER.HOST) or not target:
|
||||
headers[HTTP_HEADER.HOST] = getHostHeader(url)
|
||||
if not getHeader(headers, HTTP_HEADER.ACCEPT):
|
||||
headers[HTTP_HEADER.ACCEPT] = HTTP_ACCEPT_HEADER_VALUE
|
||||
|
||||
if not getHeader(headers, HTTP_HEADER.ACCEPT_ENCODING):
|
||||
headers[HTTP_HEADER.ACCEPT_ENCODING] = HTTP_ACCEPT_ENCODING_HEADER_VALUE if kb.pageCompress else "identity"
|
||||
if not getHeader(headers, HTTP_HEADER.ACCEPT_ENCODING):
|
||||
headers[HTTP_HEADER.ACCEPT_ENCODING] = HTTP_ACCEPT_ENCODING_HEADER_VALUE if kb.pageCompress else "identity"
|
||||
|
||||
elif conf.requestFile and getHeader(headers, HTTP_HEADER.USER_AGENT) == DEFAULT_USER_AGENT:
|
||||
for header in headers:
|
||||
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
del headers[header]
|
||||
break
|
||||
|
||||
if post is not None and not multipart and not getHeader(headers, HTTP_HEADER.CONTENT_TYPE):
|
||||
headers[HTTP_HEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE)
|
||||
@@ -384,10 +393,6 @@ class Connect(object):
|
||||
if conf.keepAlive:
|
||||
headers[HTTP_HEADER.CONNECTION] = "keep-alive"
|
||||
|
||||
# Reset header values to original in case of provided request file
|
||||
if target and conf.requestFile:
|
||||
headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie})
|
||||
|
||||
if auxHeaders:
|
||||
headers = forgeHeaders(auxHeaders, headers)
|
||||
|
||||
@@ -591,7 +596,7 @@ class Connect(object):
|
||||
threadData.lastHTTPError = (threadData.lastRequestUID, code, status)
|
||||
kb.httpErrorCodes[code] = kb.httpErrorCodes.get(code, 0) + 1
|
||||
|
||||
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
|
||||
if responseHeaders:
|
||||
logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
|
||||
@@ -750,7 +755,7 @@ class Connect(object):
|
||||
|
||||
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, conn.code, status)
|
||||
else:
|
||||
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
|
||||
if responseHeaders:
|
||||
logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
|
||||
@@ -865,10 +870,10 @@ class Connect(object):
|
||||
value = agent.replacePayload(value, payload)
|
||||
else:
|
||||
# GET, POST, URI and Cookie payload needs to be thoroughly URL encoded
|
||||
if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and postUrlEncode:
|
||||
if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0].upper() == HTTP_HEADER.COOKIE.upper()) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and postUrlEncode:
|
||||
skip = False
|
||||
|
||||
if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE:
|
||||
if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0].upper() == HTTP_HEADER.COOKIE.upper():
|
||||
if kb.cookieEncodeChoice is None:
|
||||
msg = "do you want to URL encode cookie values (implementation specific)? %s" % ("[Y/n]" if not conf.url.endswith(".aspx") else "[y/N]") # Reference: https://support.microsoft.com/en-us/kb/313282
|
||||
kb.cookieEncodeChoice = readInput(msg, default='Y' if not conf.url.endswith(".aspx") else 'N', boolean=True)
|
||||
@@ -957,7 +962,7 @@ class Connect(object):
|
||||
retVal = paramString
|
||||
match = re.search(r"%s=[^&]*" % re.escape(parameter), paramString)
|
||||
if match:
|
||||
retVal = re.sub(re.escape(match.group(0)), "%s=%s" % (parameter, newValue), paramString)
|
||||
retVal = re.sub(re.escape(match.group(0)), ("%s=%s" % (parameter, newValue)).replace('\\', r'\\'), paramString)
|
||||
else:
|
||||
match = re.search(r"(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString)
|
||||
if match:
|
||||
@@ -1293,6 +1298,8 @@ class Connect(object):
|
||||
elif noteResponseTime:
|
||||
kb.responseTimes.setdefault(kb.responseTimeMode, [])
|
||||
kb.responseTimes[kb.responseTimeMode].append(threadData.lastQueryDuration)
|
||||
if len(kb.responseTimes) > MAX_TIME_RESPONSES:
|
||||
kb.responseTimes = kb.responseTimes[-MAX_TIME_RESPONSES:]
|
||||
|
||||
if not response and removeReflection:
|
||||
page = removeReflectiveValues(page, payload)
|
||||
|
||||
@@ -332,7 +332,7 @@ def errorUse(expression, dump=False):
|
||||
stopLimit = int(count)
|
||||
|
||||
infoMsg = "used SQL query returns "
|
||||
infoMsg += "%d entries" % stopLimit
|
||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif count and not count.isdigit():
|
||||
@@ -444,8 +444,11 @@ def errorUse(expression, dump=False):
|
||||
if not value and not abortedFlag:
|
||||
value = _errorFields(expression, expressionFields, expressionFieldsList)
|
||||
|
||||
if value and isListLike(value) and len(value) == 1 and isinstance(value[0], basestring):
|
||||
value = unArrayizeValue(value)
|
||||
if value and isListLike(value):
|
||||
if len(value) == 1 and isinstance(value[0], basestring):
|
||||
value = unArrayizeValue(value)
|
||||
elif len(value) > 1 and stopLimit == 1:
|
||||
value = [value]
|
||||
|
||||
duration = calculateDeltaSeconds(start)
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ def unionUse(expression, unpack=True, dump=False):
|
||||
stopLimit = int(count)
|
||||
|
||||
infoMsg = "used SQL query returns "
|
||||
infoMsg += "%d entries" % stopLimit
|
||||
infoMsg += "%d %s" % (stopLimit, "entries" if stopLimit > 1 else "entry")
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif count and (not isinstance(count, basestring) or not count.isdigit()):
|
||||
|
||||
@@ -58,7 +58,7 @@ from thirdparty.bottle.bottle import server_names
|
||||
|
||||
# Global data storage
|
||||
class DataStore(object):
|
||||
admin_id = ""
|
||||
admin_token = ""
|
||||
current_db = None
|
||||
tasks = dict()
|
||||
username = None
|
||||
@@ -275,8 +275,8 @@ def setRestAPILog():
|
||||
logger.addHandler(LOGGER_RECORDER)
|
||||
|
||||
# Generic functions
|
||||
def is_admin(taskid):
|
||||
return DataStore.admin_id == taskid
|
||||
def is_admin(token):
|
||||
return DataStore.admin_token == token
|
||||
|
||||
@hook('before_request')
|
||||
def check_authentication():
|
||||
@@ -358,7 +358,7 @@ def path_401():
|
||||
@get("/task/new")
|
||||
def task_new():
|
||||
"""
|
||||
Create new task ID
|
||||
Create a new task
|
||||
"""
|
||||
taskid = hexencode(os.urandom(8))
|
||||
remote_addr = request.remote_addr
|
||||
@@ -371,7 +371,7 @@ def task_new():
|
||||
@get("/task/<taskid>/delete")
|
||||
def task_delete(taskid):
|
||||
"""
|
||||
Delete own task ID
|
||||
Delete an existing task
|
||||
"""
|
||||
if taskid in DataStore.tasks:
|
||||
DataStore.tasks.pop(taskid)
|
||||
@@ -379,39 +379,42 @@ def task_delete(taskid):
|
||||
logger.debug("[%s] Deleted task" % taskid)
|
||||
return jsonize({"success": True})
|
||||
else:
|
||||
logger.warning("[%s] Invalid task ID provided to task_delete()" % taskid)
|
||||
return jsonize({"success": False, "message": "Invalid task ID"})
|
||||
response.status = 404
|
||||
logger.warning("[%s] Non-existing task ID provided to task_delete()" % taskid)
|
||||
return jsonize({"success": False, "message": "Non-existing task ID"})
|
||||
|
||||
###################
|
||||
# Admin functions #
|
||||
###################
|
||||
|
||||
@get("/admin/<taskid>/list")
|
||||
def task_list(taskid=None):
|
||||
@get("/admin/list")
|
||||
@get("/admin/<token>/list")
|
||||
def task_list(token=None):
|
||||
"""
|
||||
List task pull
|
||||
Pull task list
|
||||
"""
|
||||
tasks = {}
|
||||
|
||||
for key in DataStore.tasks:
|
||||
if is_admin(taskid) or DataStore.tasks[key].remote_addr == request.remote_addr:
|
||||
if is_admin(token) or DataStore.tasks[key].remote_addr == request.remote_addr:
|
||||
tasks[key] = dejsonize(scan_status(key))["status"]
|
||||
|
||||
logger.debug("[%s] Listed task pool (%s)" % (taskid, "admin" if is_admin(taskid) else request.remote_addr))
|
||||
logger.debug("[%s] Listed task pool (%s)" % (token, "admin" if is_admin(token) else request.remote_addr))
|
||||
return jsonize({"success": True, "tasks": tasks, "tasks_num": len(tasks)})
|
||||
|
||||
@get("/admin/<taskid>/flush")
|
||||
def task_flush(taskid):
|
||||
@get("/admin/flush")
|
||||
@get("/admin/<token>/flush")
|
||||
def task_flush(token=None):
|
||||
"""
|
||||
Flush task spool (delete all tasks)
|
||||
"""
|
||||
|
||||
for key in list(DataStore.tasks):
|
||||
if is_admin(taskid) or DataStore.tasks[key].remote_addr == request.remote_addr:
|
||||
if is_admin(token) or DataStore.tasks[key].remote_addr == request.remote_addr:
|
||||
DataStore.tasks[key].engine_kill()
|
||||
del DataStore.tasks[key]
|
||||
|
||||
logger.debug("[%s] Flushed task pool (%s)" % (taskid, "admin" if is_admin(taskid) else request.remote_addr))
|
||||
logger.debug("[%s] Flushed task pool (%s)" % (token, "admin" if is_admin(token) else request.remote_addr))
|
||||
return jsonize({"success": True})
|
||||
|
||||
##################################
|
||||
@@ -434,25 +437,30 @@ def option_list(taskid):
|
||||
@post("/option/<taskid>/get")
|
||||
def option_get(taskid):
|
||||
"""
|
||||
Get the value of an option (command line switch) for a certain task ID
|
||||
Get value of option(s) for a certain task ID
|
||||
"""
|
||||
if taskid not in DataStore.tasks:
|
||||
logger.warning("[%s] Invalid task ID provided to option_get()" % taskid)
|
||||
return jsonize({"success": False, "message": "Invalid task ID"})
|
||||
|
||||
option = request.json.get("option", "")
|
||||
options = request.json or []
|
||||
results = {}
|
||||
|
||||
if option in DataStore.tasks[taskid].options:
|
||||
logger.debug("[%s] Retrieved value for option %s" % (taskid, option))
|
||||
return jsonize({"success": True, option: DataStore.tasks[taskid].get_option(option)})
|
||||
else:
|
||||
logger.debug("[%s] Requested value for unknown option %s" % (taskid, option))
|
||||
return jsonize({"success": False, "message": "Unknown option", option: "not set"})
|
||||
for option in options:
|
||||
if option in DataStore.tasks[taskid].options:
|
||||
results[option] = DataStore.tasks[taskid].options[option]
|
||||
else:
|
||||
logger.debug("[%s] Requested value for unknown option '%s'" % (taskid, option))
|
||||
return jsonize({"success": False, "message": "Unknown option '%s'" % option})
|
||||
|
||||
logger.debug("[%s] Retrieved values for option(s) '%s'" % (taskid, ",".join(options)))
|
||||
|
||||
return jsonize({"success": True, "options": results})
|
||||
|
||||
@post("/option/<taskid>/set")
|
||||
def option_set(taskid):
|
||||
"""
|
||||
Set an option (command line switch) for a certain task ID
|
||||
Set value of option(s) for a certain task ID
|
||||
"""
|
||||
|
||||
if taskid not in DataStore.tasks:
|
||||
@@ -647,7 +655,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
||||
REST-JSON API server
|
||||
"""
|
||||
|
||||
DataStore.admin_id = hexencode(os.urandom(16))
|
||||
DataStore.admin_token = hexencode(os.urandom(16))
|
||||
DataStore.username = username
|
||||
DataStore.password = password
|
||||
|
||||
@@ -660,7 +668,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
||||
port = s.getsockname()[1]
|
||||
|
||||
logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port))
|
||||
logger.info("Admin ID: %s" % DataStore.admin_id)
|
||||
logger.info("Admin (secret) token: %s" % DataStore.admin_token)
|
||||
logger.debug("IPC database: '%s'" % Database.filepath)
|
||||
|
||||
# Initialize IPC database
|
||||
@@ -696,7 +704,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
||||
logger.critical(errMsg)
|
||||
|
||||
def _client(url, options=None):
|
||||
logger.debug("Calling %s" % url)
|
||||
logger.debug("Calling '%s'" % url)
|
||||
try:
|
||||
data = None
|
||||
if options is not None:
|
||||
@@ -772,11 +780,11 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
||||
logger.error("No task ID in use")
|
||||
continue
|
||||
try:
|
||||
command, option = command.split(" ")
|
||||
command, option = command.split(" ", 1)
|
||||
except ValueError:
|
||||
raw = _client("%s/option/%s/list" % (addr, taskid))
|
||||
else:
|
||||
options = {"option": option}
|
||||
options = re.split(r"\s*,\s*", option.strip())
|
||||
raw = _client("%s/option/%s/get" % (addr, taskid), options)
|
||||
res = dejsonize(raw)
|
||||
if not res["success"]:
|
||||
@@ -833,7 +841,7 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
||||
logger.info("Switching to task ID '%s' " % taskid)
|
||||
|
||||
elif command in ("list", "flush"):
|
||||
raw = _client("%s/admin/%s/%s" % (addr, taskid or 0, command))
|
||||
raw = _client("%s/admin/%s" % (addr, command))
|
||||
res = dejsonize(raw)
|
||||
if not res["success"]:
|
||||
logger.error("Failed to execute command %s" % command)
|
||||
|
||||
@@ -91,7 +91,7 @@ class HashDB(object):
|
||||
raise
|
||||
except sqlite3.DatabaseError, ex:
|
||||
errMsg = "error occurred while accessing session file '%s' ('%s'). " % (self.filepath, getSafeExString(ex))
|
||||
errMsg += "If the problem persists please rerun with `--flush-session`"
|
||||
errMsg += "If the problem persists please rerun with '--flush-session'"
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
else:
|
||||
break
|
||||
@@ -104,7 +104,7 @@ class HashDB(object):
|
||||
except:
|
||||
retVal = None
|
||||
warnMsg = "error occurred while unserializing value for session key '%s'. " % key
|
||||
warnMsg += "If the problem persists please rerun with `--flush-session`"
|
||||
warnMsg += "If the problem persists please rerun with '--flush-session'"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -41,7 +41,7 @@ class Connector(GenericConnector):
|
||||
|
||||
try:
|
||||
self.connector = pymssql.connect(host="%s:%d" % (self.hostname, self.port), user=self.user, password=self.password, database=self.db, login_timeout=conf.timeout, timeout=conf.timeout)
|
||||
except (pymssql.Error, _mssql.MssqlDatabaseException), msg:
|
||||
except (pymssql2.Error, _mssql.MssqlDatabaseException), msg:
|
||||
raise SqlmapConnectionException(msg)
|
||||
except ValueError:
|
||||
raise SqlmapConnectionException
|
||||
|
||||
@@ -20,6 +20,7 @@ class Connector:
|
||||
def __init__(self):
|
||||
self.connector = None
|
||||
self.cursor = None
|
||||
self.hostname = None
|
||||
|
||||
def initConnection(self):
|
||||
self.user = conf.dbmsUser or ""
|
||||
@@ -34,9 +35,10 @@ class Connector:
|
||||
logger.info(infoMsg)
|
||||
|
||||
def closed(self):
|
||||
infoMsg = "connection to %s server %s" % (conf.dbms, self.hostname)
|
||||
infoMsg += ":%d closed" % self.port
|
||||
logger.info(infoMsg)
|
||||
if self.hostname:
|
||||
infoMsg = "connection to %s server %s" % (conf.dbms, self.hostname)
|
||||
infoMsg += ":%d closed" % self.port
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.connector = None
|
||||
self.cursor = None
|
||||
|
||||
@@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission
|
||||
import os
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import isStackingAvailable
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import runningAsAdmin
|
||||
@@ -20,6 +21,7 @@ from lib.core.exception import SqlmapMissingDependence
|
||||
from lib.core.exception import SqlmapMissingMandatoryOptionException
|
||||
from lib.core.exception import SqlmapMissingPrivileges
|
||||
from lib.core.exception import SqlmapNotVulnerableException
|
||||
from lib.core.exception import SqlmapSystemException
|
||||
from lib.core.exception import SqlmapUndefinedMethod
|
||||
from lib.core.exception import SqlmapUnsupportedDBMSException
|
||||
from lib.takeover.abstraction import Abstraction
|
||||
@@ -132,12 +134,16 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||
errMsg += "http://code.google.com/p/impacket/downloads/list"
|
||||
raise SqlmapMissingDependence(errMsg)
|
||||
|
||||
sysIgnoreIcmp = "/proc/sys/net/ipv4/icmp_echo_ignore_all"
|
||||
filename = "/proc/sys/net/ipv4/icmp_echo_ignore_all"
|
||||
|
||||
if os.path.exists(sysIgnoreIcmp):
|
||||
fp = open(sysIgnoreIcmp, "wb")
|
||||
fp.write("1")
|
||||
fp.close()
|
||||
if os.path.exists(filename):
|
||||
try:
|
||||
with open(filename, "wb") as f:
|
||||
f.write("1")
|
||||
except IOError, ex:
|
||||
errMsg = "there has been a file opening/writing error "
|
||||
errMsg += "for filename '%s' ('%s')" % (filename, getSafeExString(ex))
|
||||
raise SqlmapSystemException(errMsg)
|
||||
else:
|
||||
errMsg = "you need to disable ICMP replies by your machine "
|
||||
errMsg += "system-wide. For example run on Linux/Unix:\n"
|
||||
|
||||
@@ -285,6 +285,8 @@ class Users:
|
||||
query = rootQuery.blind.query % (user, index, user)
|
||||
elif Backend.isDbms(DBMS.INFORMIX):
|
||||
query = rootQuery.blind.query % (user,)
|
||||
elif Backend.isDbms(DBMS.HSQLDB):
|
||||
query = rootQuery.blind.query % (index, user)
|
||||
else:
|
||||
query = rootQuery.blind.query % (user, index)
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ def main():
|
||||
|
||||
conf.showTime = True
|
||||
dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True)
|
||||
dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True)
|
||||
dataToStdout("[*] starting @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True)
|
||||
|
||||
init()
|
||||
|
||||
@@ -357,7 +357,7 @@ def main():
|
||||
kb.threadContinue = False
|
||||
|
||||
if conf.get("showTime"):
|
||||
dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True)
|
||||
dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True)
|
||||
|
||||
kb.threadException = True
|
||||
|
||||
|
||||
460
swagger.yaml
Normal file
460
swagger.yaml
Normal file
@@ -0,0 +1,460 @@
|
||||
# Note: written with Swagger Editor (https://editor.swagger.io/)
|
||||
swagger: "2.0"
|
||||
info:
|
||||
description: ""
|
||||
version: "1.2"
|
||||
title: "sqlmap API"
|
||||
contact:
|
||||
email: "dev@sqlmap.org"
|
||||
license:
|
||||
name: "GPL 2.0"
|
||||
url: "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html"
|
||||
host: "0.0.0.0:8775"
|
||||
basePath: "/"
|
||||
tags:
|
||||
- name: "task"
|
||||
description: "Task management functions"
|
||||
- name: "admin"
|
||||
description: "Task administration functions"
|
||||
- name: "option"
|
||||
description: "Task option handling functions"
|
||||
schemes:
|
||||
- "http"
|
||||
paths:
|
||||
/task/new:
|
||||
get:
|
||||
tags:
|
||||
- "task"
|
||||
summary: "Create a new task"
|
||||
description: ""
|
||||
operationId: "taskNew"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
description: "Task successfully created"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
taskid:
|
||||
type: string
|
||||
example: "7e605b5d5a892b74"
|
||||
/task/{taskid}/delete:
|
||||
get:
|
||||
tags:
|
||||
- "task"
|
||||
summary: "Delete an existing task"
|
||||
description: ""
|
||||
operationId: "taskDelete"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters:
|
||||
- name: "taskid"
|
||||
in: "path"
|
||||
description: "ID of an existing task to delete"
|
||||
required: true
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "Task successfully deleted"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
404:
|
||||
description: "Task ID not found"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [false]
|
||||
message:
|
||||
type: string
|
||||
enum: ["Non-existing task ID"]
|
||||
/admin/list:
|
||||
get:
|
||||
tags:
|
||||
- "admin"
|
||||
summary: "Pull task list (locally)"
|
||||
description: "Note: Use in cases when connecting to server from same IP (e.g. `localhost`)"
|
||||
operationId: "adminList"
|
||||
produces:
|
||||
- "application/json"
|
||||
responses:
|
||||
200:
|
||||
description: "Task list successfully pulled"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
tasks:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
16a7a898e8eaaf45: running
|
||||
644fc063408e4f12: not running
|
||||
8e2eb10770d913cd: not running
|
||||
d59d1c69bdc06933: not running
|
||||
tasks_num:
|
||||
type: integer
|
||||
example: 4
|
||||
/admin/{token}/list:
|
||||
get:
|
||||
tags:
|
||||
- "admin"
|
||||
summary: "Pull task list (remotely)"
|
||||
description: "Note: Use in cases when connecting to server from different IP"
|
||||
operationId: "adminListToken"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters:
|
||||
- name: "token"
|
||||
in: "path"
|
||||
description: "Secret token (Note: written to console during a server run - e.g. `2756d5b6e7d093ba49b5fd06a93aca7a`)"
|
||||
required: true
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "Task list successfully pulled"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
tasks:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
5c911efa476b55f4: not running
|
||||
5ee038e153ffc534: not running
|
||||
e58c7a4de6bf7f51: not running
|
||||
tasks_num:
|
||||
type: integer
|
||||
example: 4
|
||||
/admin/flush:
|
||||
get:
|
||||
tags:
|
||||
- "admin"
|
||||
summary: "Flush task pool (locally)"
|
||||
description: "Note: Use in cases when connecting to server from same IP (e.g. `localhost`)"
|
||||
operationId: "adminFlush"
|
||||
produces:
|
||||
- "application/json"
|
||||
responses:
|
||||
200:
|
||||
description: "Task pool successfully flushed"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
/admin/{token}/flush:
|
||||
get:
|
||||
tags:
|
||||
- "admin"
|
||||
summary: "Flush task pool (remotely)"
|
||||
description: "Note: Use in cases when connecting to server from different IP"
|
||||
operationId: "adminFlushToken"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters:
|
||||
- name: "token"
|
||||
in: "path"
|
||||
description: "Secret token (Note: written to console during a server run - e.g. `2756d5b6e7d093ba49b5fd06a93aca7a`)"
|
||||
required: true
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "Task pool successfully flushed"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
/option/{taskid}/list:
|
||||
get:
|
||||
tags:
|
||||
- "option"
|
||||
summary: "List task options"
|
||||
description: ""
|
||||
operationId: "optionList"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters:
|
||||
- name: "taskid"
|
||||
in: "path"
|
||||
description: "ID of an existing task to list it's options"
|
||||
required: true
|
||||
type: "string"
|
||||
responses:
|
||||
200:
|
||||
description: "Task options successfully listed"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
enum: [true]
|
||||
options:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
crawlDepth: null
|
||||
osShell: false
|
||||
getUsers: false
|
||||
getPasswordHashes: false
|
||||
excludeSysDbs: false
|
||||
ignoreTimeouts: false
|
||||
regData: null
|
||||
fileDest: null
|
||||
prefix: null
|
||||
code: null
|
||||
googlePage: 1
|
||||
skip: null
|
||||
query: null
|
||||
randomAgent: false
|
||||
osPwn: false
|
||||
authType: null
|
||||
safeUrl: null
|
||||
requestFile: null
|
||||
predictOutput: false
|
||||
wizard: false
|
||||
stopFail: false
|
||||
forms: false
|
||||
uChar: null
|
||||
secondReq: null
|
||||
taskid: d977b0e5f091370e
|
||||
pivotColumn: null
|
||||
dropSetCookie: false
|
||||
smart: false
|
||||
paramExclude: null
|
||||
risk: 1
|
||||
sqlFile: null
|
||||
rParam: null
|
||||
getCurrentUser: false
|
||||
notString: null
|
||||
getRoles: false
|
||||
getPrivileges: false
|
||||
testParameter: null
|
||||
tbl: null
|
||||
charset: null
|
||||
trafficFile: null
|
||||
osSmb: false
|
||||
level: 1
|
||||
dnsDomain: null
|
||||
outputDir: null
|
||||
encoding: null
|
||||
skipWaf: false
|
||||
timeout: 30
|
||||
firstChar: null
|
||||
torPort: null
|
||||
getComments: false
|
||||
binaryFields: null
|
||||
checkTor: false
|
||||
commonTables: false
|
||||
direct: null
|
||||
tmpPath: null
|
||||
titles: false
|
||||
getSchema: false
|
||||
identifyWaf: false
|
||||
paramDel: null
|
||||
safeReqFile: null
|
||||
regKey: null
|
||||
murphyRate: null
|
||||
limitStart: null
|
||||
crawlExclude: null
|
||||
flushSession: false
|
||||
loadCookies: null
|
||||
csvDel:
|
||||
offline: false
|
||||
method: null
|
||||
tmpDir: null
|
||||
fileWrite: null
|
||||
disablePrecon: false
|
||||
osBof: false
|
||||
testSkip: null
|
||||
invalidLogical: false
|
||||
getCurrentDb: false
|
||||
hexConvert: false
|
||||
proxyFile: null
|
||||
answers: null
|
||||
host: null
|
||||
dependencies: false
|
||||
cookie: null
|
||||
proxy: null
|
||||
regType: null
|
||||
optimize: false
|
||||
limitStop: null
|
||||
search: false
|
||||
uFrom: null
|
||||
noCast: false
|
||||
testFilter: null
|
||||
ignoreCode: null
|
||||
eta: false
|
||||
csrfToken: null
|
||||
threads: 1
|
||||
logFile: null
|
||||
os: null
|
||||
col: null
|
||||
skipStatic: false
|
||||
proxyCred: null
|
||||
verbose: 1
|
||||
isDba: false
|
||||
updateAll: false
|
||||
privEsc: false
|
||||
forceDns: false
|
||||
getAll: false
|
||||
api: true
|
||||
url: http://www.test.com/index.php?id=1
|
||||
invalidBignum: false
|
||||
regexp: null
|
||||
getDbs: false
|
||||
freshQueries: false
|
||||
uCols: null
|
||||
smokeTest: false
|
||||
udfInject: false
|
||||
invalidString: false
|
||||
tor: false
|
||||
forceSSL: false
|
||||
beep: false
|
||||
noEscape: false
|
||||
configFile: null
|
||||
scope: null
|
||||
authFile: null
|
||||
torType: SOCKS5
|
||||
regVal: null
|
||||
dummy: false
|
||||
checkInternet: false
|
||||
safePost: null
|
||||
safeFreq: null
|
||||
skipUrlEncode: false
|
||||
referer: null
|
||||
liveTest: false
|
||||
retries: 3
|
||||
extensiveFp: false
|
||||
dumpTable: false
|
||||
getColumns: false
|
||||
batch: true
|
||||
purge: false
|
||||
headers: null
|
||||
authCred: null
|
||||
osCmd: null
|
||||
suffix: null
|
||||
dbmsCred: null
|
||||
regDel: false
|
||||
shLib: null
|
||||
sitemapUrl: null
|
||||
timeSec: 5
|
||||
msfPath: null
|
||||
dumpAll: false
|
||||
fileRead: null
|
||||
getHostname: false
|
||||
sessionFile: null
|
||||
disableColoring: true
|
||||
getTables: false
|
||||
listTampers: false
|
||||
agent: null
|
||||
webRoot: null
|
||||
exclude: null
|
||||
lastChar: null
|
||||
string: null
|
||||
dbms: null
|
||||
dumpWhere: null
|
||||
tamper: null
|
||||
ignoreRedirects: false
|
||||
hpp: false
|
||||
runCase: null
|
||||
delay: 0
|
||||
evalCode: null
|
||||
cleanup: false
|
||||
csrfUrl: null
|
||||
secondUrl: null
|
||||
getBanner: true
|
||||
profile: false
|
||||
regRead: false
|
||||
bulkFile: null
|
||||
db: null
|
||||
dumpFormat: CSV
|
||||
alert: null
|
||||
harFile: null
|
||||
nullConnection: false
|
||||
user: null
|
||||
parseErrors: false
|
||||
getCount: false
|
||||
data: null
|
||||
regAdd: false
|
||||
ignoreProxy: false
|
||||
database: /tmp/sqlmapipc-jGw6ZY
|
||||
mobile: false
|
||||
googleDork: null
|
||||
saveConfig: null
|
||||
sqlShell: false
|
||||
tech: BEUSTQ
|
||||
textOnly: false
|
||||
cookieDel: null
|
||||
commonColumns: false
|
||||
keepAlive: false
|
||||
/option/{taskid}/get:
|
||||
post:
|
||||
tags:
|
||||
- "option"
|
||||
summary: "Get task option value(s)"
|
||||
description: ""
|
||||
operationId: "optionGet"
|
||||
consumes:
|
||||
- "application/json"
|
||||
produces:
|
||||
- "application/json"
|
||||
parameters:
|
||||
- name: "taskid"
|
||||
in: "path"
|
||||
description: "ID of an existing task"
|
||||
required: true
|
||||
type: "string"
|
||||
- in: body
|
||||
name: options
|
||||
description: ""
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: ["url", "timeout"]
|
||||
responses:
|
||||
200:
|
||||
description: "Task option value successfully retrieved"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
options:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
example:
|
||||
- success: true
|
||||
options:
|
||||
url: http://www.test.com/index.php?id=1
|
||||
timeout: 30
|
||||
externalDocs:
|
||||
description: "Find out more about sqlmap API (REST-JSON)"
|
||||
url: "https://github.com/sqlmapproject/sqlmap/wiki/Usage#api-rest-json"
|
||||
@@ -41,6 +41,9 @@ def tamper(payload, **kwargs):
|
||||
retVal = payload
|
||||
|
||||
if payload:
|
||||
prefix, suffix = '+' * len(re.search(r"\A(\+*)", payload).group(0)), '+' * len(re.search(r"(\+*)\Z", payload).group(0))
|
||||
retVal = retVal.strip('+')
|
||||
|
||||
while True:
|
||||
indexes = zeroDepthSearch(retVal, '+')
|
||||
|
||||
@@ -76,4 +79,6 @@ def tamper(payload, **kwargs):
|
||||
else:
|
||||
break
|
||||
|
||||
retVal = "%s%s%s" % (prefix, retVal, suffix)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -42,6 +42,9 @@ def tamper(payload, **kwargs):
|
||||
retVal = payload
|
||||
|
||||
if payload:
|
||||
prefix, suffix = '+' * len(re.search(r"\A(\+*)", payload).group(0)), '+' * len(re.search(r"(\+*)\Z", payload).group(0))
|
||||
retVal = retVal.strip('+')
|
||||
|
||||
while True:
|
||||
indexes = zeroDepthSearch(retVal, '+')
|
||||
|
||||
@@ -89,4 +92,6 @@ def tamper(payload, **kwargs):
|
||||
else:
|
||||
break
|
||||
|
||||
retVal = "%s%s%s" % (prefix, retVal, suffix)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -25,6 +25,7 @@ def tamper(payload, **kwargs):
|
||||
* MySQL 4, 5.0 and 5.5
|
||||
* Oracle 10g
|
||||
* PostgreSQL 8.3, 8.4, 9.0
|
||||
* SQLite 3
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak and bespoke web application firewalls
|
||||
@@ -43,7 +44,7 @@ def tamper(payload, **kwargs):
|
||||
for match in re.finditer(r"\b[A-Za-z_]+\b", retVal):
|
||||
word = match.group()
|
||||
|
||||
if word.upper() in kb.keywords:
|
||||
if word.upper() in kb.keywords or ("%s(" % word) in payload:
|
||||
while True:
|
||||
_ = ""
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ b3e60ea4e18a65c48515d04aab28ff68 extra/sqlharvest/sqlharvest.py
|
||||
c1bccc94522d3425a372dcd57f78418e extra/wafdetectify/wafdetectify.py
|
||||
3459c562a6abb9b4bdcc36925f751f3e lib/controller/action.py
|
||||
71334197c7ed28167cd66c17b2c21844 lib/controller/checks.py
|
||||
dd42ef140ffc0bd517128e6df369ab01 lib/controller/controller.py
|
||||
97a0f363bfc33a5ee4853cdf91515423 lib/controller/handler.py
|
||||
95cde6dc7efe2581a5936f0d4635cb3b lib/controller/controller.py
|
||||
988b548f6578adf9cec17afdeee8291c lib/controller/handler.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/controller/__init__.py
|
||||
cb865cf6eff60118bc97a0f106af5e4d lib/core/agent.py
|
||||
c347f085bd561adfa26d3a9512e5f3b9 lib/core/bigarray.py
|
||||
83cb02b7fbb979b8c27e7fc58c76e6f1 lib/core/common.py
|
||||
9ed51d3e770b5cec2f8c91e962011d52 lib/core/common.py
|
||||
0d082da16c388b3445e656e0760fb582 lib/core/convert.py
|
||||
9f87391b6a3395f7f50830b391264f27 lib/core/data.py
|
||||
72016ea5c994a711a262fd64572a0fcd lib/core/datatype.py
|
||||
@@ -42,17 +42,17 @@ cada93357a7321655927fc9625b3bfec lib/core/exception.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/core/__init__.py
|
||||
458a194764805cd8312c14ecd4be4d1e lib/core/log.py
|
||||
7d6edc552e08c30f4f4d49fa93b746f1 lib/core/optiondict.py
|
||||
d6dace6468ed5d2bbd500b0a244a9650 lib/core/option.py
|
||||
7dacc178910ab4d57de36c3602bde17d lib/core/option.py
|
||||
c8c386d644d57c659d74542f5f57f632 lib/core/patch.py
|
||||
6783160150b4711d02c56ee2beadffdb lib/core/profiling.py
|
||||
6f654e1715571eff68a0f8af3d62dcf8 lib/core/readlineng.py
|
||||
0c3eef46bdbf87e29a3f95f90240d192 lib/core/replication.py
|
||||
a7db43859b61569b601b97f187dd31c5 lib/core/revision.py
|
||||
fcb74fcc9577523524659ec49e2e964b lib/core/session.py
|
||||
9aa489d9226056b672d83786f2c606c9 lib/core/settings.py
|
||||
9f209388d9fed41480e57c8574d0111a lib/core/settings.py
|
||||
a971ce157d04de96ba6e710d3d38a9a8 lib/core/shell.py
|
||||
a7edc9250d13af36ac0108f259859c19 lib/core/subprocessng.py
|
||||
721198b5be72c8015a02acb116532a1f lib/core/target.py
|
||||
52642badbbca4c31a2fcdd754d67a983 lib/core/target.py
|
||||
72d499ca8d792e90a1ebfb2ad2341a51 lib/core/testing.py
|
||||
cd0067d1798e45f422ce44b98baf57db lib/core/threads.py
|
||||
c40758411bb0bd68764d78e0bb72bd0f lib/core/unescaper.py
|
||||
@@ -71,7 +71,7 @@ f6b5957bf2103c3999891e4f45180bce lib/parse/payloads.py
|
||||
30eed3a92a04ed2c29770e1b10d39dc0 lib/request/basicauthhandler.py
|
||||
2b81435f5a7519298c15c724e3194a0d lib/request/basic.py
|
||||
859b6ad583e0ffba154f17ee179b5b89 lib/request/comparison.py
|
||||
0363fb0b3e58467ff5c915d1d85dfd3e lib/request/connect.py
|
||||
77b24c30b1a2163add76652998e74127 lib/request/connect.py
|
||||
dd4598675027fae99f2e2475b05986da lib/request/direct.py
|
||||
2044fce3f4ffa268fcfaaf63241b1e64 lib/request/dns.py
|
||||
98535d0efca5551e712fcc4b34a3f772 lib/request/httpshandler.py
|
||||
@@ -101,13 +101,13 @@ db208ab47de010836c6bf044e2357861 lib/techniques/blind/inference.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/union/__init__.py
|
||||
f7813cdee00df8f98d6f811475e520a1 lib/techniques/union/test.py
|
||||
7361338240ecd9d01d1d10ec76bce069 lib/techniques/union/use.py
|
||||
77ff35587af9e3dfde63b8327e230f9a lib/utils/api.py
|
||||
038ec99105c59acc2b1c6cb90e9e4043 lib/utils/api.py
|
||||
37dfb641358669f62c2acedff241348b lib/utils/brute.py
|
||||
31b1e7eb489eac837db6a2bc1dcb7da7 lib/utils/crawler.py
|
||||
f9867bbfcd6d31916ca73e72e95fd881 lib/utils/deps.py
|
||||
f7af65aa47329d021e2b2cc8521b42a4 lib/utils/getch.py
|
||||
7af29f61302c8693cd6436d4b69e22d3 lib/utils/har.py
|
||||
062e4e8fc43ac54305a75ddd0d482f81 lib/utils/hashdb.py
|
||||
1205648d55649accafae2cc77d647aa0 lib/utils/hashdb.py
|
||||
d0f4d56c5d6a09a4635035e233d4a782 lib/utils/hash.py
|
||||
011d2dbf589e0faa0deca61a651239cc lib/utils/htmlentities.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/utils/__init__.py
|
||||
@@ -169,7 +169,7 @@ ffd26f64142226d0b1ed1d70f7f294c0 plugins/dbms/maxdb/filesystem.py
|
||||
4321d7018f5121343460ebfd83bb69be plugins/dbms/maxdb/__init__.py
|
||||
e7d44671ae26c0bcd5fe8448be070bbd plugins/dbms/maxdb/syntax.py
|
||||
bf7842bb291e2297c3c8d1023eb3e550 plugins/dbms/maxdb/takeover.py
|
||||
decc645344bb93aca504a71ba2e4cad4 plugins/dbms/mssqlserver/connector.py
|
||||
5e1c7e578d07f3670bba5d88d856715d plugins/dbms/mssqlserver/connector.py
|
||||
f1f1541a54faf67440179fa521f99849 plugins/dbms/mssqlserver/enumeration.py
|
||||
65911fdc86fa6322e72319e6488a0bb8 plugins/dbms/mssqlserver/filesystem.py
|
||||
6cf74341fc84588205e02b70b2f0f5b6 plugins/dbms/mssqlserver/fingerprint.py
|
||||
@@ -211,7 +211,7 @@ f639120d42b33b6ca67930bddbf2ac1f plugins/dbms/sqlite/__init__.py
|
||||
a3db8618eed5bb2807b6f77605cba9cc plugins/dbms/sybase/__init__.py
|
||||
36acb9a5966af21b32e8558b0d50653d plugins/dbms/sybase/syntax.py
|
||||
79f6c7017db4ded8f74a0117188836ff plugins/dbms/sybase/takeover.py
|
||||
34d181a7086d6dfc7e72ae5f8a4cfe0f plugins/generic/connector.py
|
||||
bdc159cc5afb28cadd980c01c43ba669 plugins/generic/connector.py
|
||||
ce6a6ff713852b5eca7b78316cc941c4 plugins/generic/custom.py
|
||||
3d75e831574c750ed58e24eaa562c056 plugins/generic/databases.py
|
||||
35546acab0eea406c23b84363df4d534 plugins/generic/entries.py
|
||||
@@ -222,8 +222,8 @@ f5d5419efddfe04648ea5e953c650793 plugins/generic/fingerprint.py
|
||||
f7874230e5661910d5fd21544c7d1022 plugins/generic/misc.py
|
||||
30b421f06dc98998ddc1923a9048b7fc plugins/generic/search.py
|
||||
a70cc0ada4b0cc9e7df23cb6d48a4a0c plugins/generic/syntax.py
|
||||
a37c21cc3fa5c0c220d33d450bf503ed plugins/generic/takeover.py
|
||||
e762c77ff79e4c138145501f6fbb10cb plugins/generic/users.py
|
||||
f990d799e578dfbc3cde5728655a7854 plugins/generic/takeover.py
|
||||
1265241e309da72bb82c3863a4c1b4bd plugins/generic/users.py
|
||||
1e5532ede194ac9c083891c2f02bca93 plugins/__init__.py
|
||||
5dc693e22f5d020c5c568d7325bd4226 shell/backdoors/backdoor.asp_
|
||||
158bfa168128393dde8d6ed11fe9a1b8 shell/backdoors/backdoor.aspx_
|
||||
@@ -234,7 +234,7 @@ ec2ba8c757ac96425dcd2b97970edd3a shell/stagers/stager.asp_
|
||||
0c48ddb1feb7e38a951ef05a0d48e032 shell/stagers/stager.jsp_
|
||||
2f9e459a4cf6a58680978cdce5ff7971 shell/stagers/stager.php_
|
||||
cd90da0474d7b1a67d7b40d208493375 sqlmapapi.py
|
||||
ad5f9980c9bdca753578292720a5afe0 sqlmap.py
|
||||
fa713ca1dc1983f3cb3d90e76a05819a sqlmap.py
|
||||
523dab9e1093eb59264c6beb366b255a tamper/0x2char.py
|
||||
3a1697585ae4e7bf315e9dda97d6f321 tamper/apostrophemask.py
|
||||
d7a119a74be9b385ee3884fb5e6af041 tamper/apostrophenullencode.py
|
||||
@@ -270,7 +270,7 @@ a3a3cef042b864c4226b63f89548f939 tamper/overlongutf8.py
|
||||
89f8753a0ef65d2bb860c8864e9e935a tamper/percentage.py
|
||||
a47aafcbc1de2deb85160e29de46f748 tamper/plus2concat.py
|
||||
759b86cf3bb1d7871dc6489538253f94 tamper/plus2fnconcat.py
|
||||
078494e1217400b485ef653108d32699 tamper/randomcase.py
|
||||
b9db4cc9fc4e0a586198340d1268fdaf tamper/randomcase.py
|
||||
28626e4b8c673228dcfe4f1627a9e08b tamper/randomcomments.py
|
||||
cac8a56f8cc6c14524ee392daa5ae2fd tamper/space2comment.py
|
||||
4e6da2aca962b6110652e5f83dce5cd7 tamper/space2dash.py
|
||||
|
||||
Reference in New Issue
Block a user