mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-11 02:09:04 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e968584f6 | ||
|
|
cc5ba4753c | ||
|
|
afa4d2c514 | ||
|
|
d63401632c | ||
|
|
45553f0efc | ||
|
|
f1dbe9e388 | ||
|
|
3977be9c9e | ||
|
|
9da558f041 | ||
|
|
b3bc401f2e | ||
|
|
06cd97f097 | ||
|
|
293772348c | ||
|
|
2679c650aa | ||
|
|
179a6edf92 | ||
|
|
8af87c7ea6 | ||
|
|
3a1dd163ec | ||
|
|
f8a9288953 | ||
|
|
8895b7d09d | ||
|
|
fa05878712 | ||
|
|
795b9e6521 | ||
|
|
1f3a1410f2 | ||
|
|
69c679cf06 | ||
|
|
5ea08b397a | ||
|
|
7c41967865 | ||
|
|
255dce8c49 | ||
|
|
7c7c338705 | ||
|
|
63073a1873 |
@@ -127,8 +127,8 @@
|
|||||||
<blind query="SELECT DISTINCT(schemaname) FROM pg_tables ORDER BY schemaname OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(schemaname)) FROM pg_tables"/>
|
<blind query="SELECT DISTINCT(schemaname) FROM pg_tables ORDER BY schemaname OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(schemaname)) FROM pg_tables"/>
|
||||||
</dbs>
|
</dbs>
|
||||||
<tables>
|
<tables>
|
||||||
<inband query="SELECT schemaname,tablename FROM pg_tables" condition="schemaname"/>
|
<inband query="SELECT schemaname,tablename FROM pg_tables" condition="schemaname" query2="SELECT table_schema,table_name FROM information_schema.tables" condition2="table_schema"/>
|
||||||
<blind query="SELECT tablename FROM pg_tables WHERE schemaname='%s' ORDER BY tablename OFFSET %d LIMIT 1" count="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'"/>
|
<blind query="SELECT tablename FROM pg_tables WHERE schemaname='%s' ORDER BY tablename OFFSET %d LIMIT 1" count="SELECT COUNT(tablename) FROM pg_tables WHERE schemaname='%s'" query2="SELECT table_name FROM information_schema.tables WHERE table_schema='%s' OFFSET %d LIMIT 1" count2="SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema='%s'"/>
|
||||||
</tables>
|
</tables>
|
||||||
<columns>
|
<columns>
|
||||||
<inband query="SELECT attname,typname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" condition="attname"/>
|
<inband query="SELECT attname,typname FROM pg_attribute b JOIN pg_class a ON a.oid=b.attrelid JOIN pg_type c ON c.oid=b.atttypid JOIN pg_namespace d ON a.relnamespace=d.oid WHERE b.attnum>0 AND a.relname='%s' AND nspname='%s' ORDER BY attname" condition="attname"/>
|
||||||
@@ -1209,7 +1209,7 @@
|
|||||||
</users>
|
</users>
|
||||||
<passwords>
|
<passwords>
|
||||||
<inband query="SELECT USER_NAME,PASSWORD FROM SYSTEM_.SYS_USERS_" condition="USER_NAME"/>
|
<inband query="SELECT USER_NAME,PASSWORD FROM SYSTEM_.SYS_USERS_" condition="USER_NAME"/>
|
||||||
<blind query="SELECT PASSWORD FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s'" count="SELECT COUNT(PASSWORD) FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s'"/>
|
<blind query="SELECT PASSWORD FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s' LIMIT %d,1" count="SELECT COUNT(PASSWORD) FROM SYSTEM_.SYS_USERS_ WHERE USER_NAME='%s'"/>
|
||||||
</passwords>
|
</passwords>
|
||||||
<privileges>
|
<privileges>
|
||||||
<inband query="SELECT USER_NAME,PRIV_NAME FROM SYSTEM_.SYS_GRANT_OBJECT_ JOIN SYSTEM_.SYS_PRIVILEGES_ ON SYSTEM_.SYS_GRANT_OBJECT_.PRIV_ID=SYSTEM_.SYS_PRIVILEGES_.PRIV_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_GRANT_OBJECT_.GRANTEE_ID" condition="USER_NAME"/>
|
<inband query="SELECT USER_NAME,PRIV_NAME FROM SYSTEM_.SYS_GRANT_OBJECT_ JOIN SYSTEM_.SYS_PRIVILEGES_ ON SYSTEM_.SYS_GRANT_OBJECT_.PRIV_ID=SYSTEM_.SYS_PRIVILEGES_.PRIV_ID JOIN SYSTEM_.SYS_USERS_ ON SYSTEM_.SYS_USERS_.USER_ID=SYSTEM_.SYS_GRANT_OBJECT_.GRANTEE_ID" condition="USER_NAME"/>
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
origValue = origValue.split(kb.customInjectionMark)[0]
|
origValue = origValue.split(kb.customInjectionMark)[0]
|
||||||
origValue = re.search(r"(\w*)\Z", origValue).group(1)
|
origValue = re.search(r"(\w*)\Z", origValue).group(1)
|
||||||
|
|
||||||
# Threat the parameter original value according to the
|
# Treat the parameter original value according to the
|
||||||
# test's <where> tag
|
# test's <where> tag
|
||||||
if where == PAYLOAD.WHERE.ORIGINAL or conf.prefix:
|
if where == PAYLOAD.WHERE.ORIGINAL or conf.prefix:
|
||||||
if kb.tamperFunctions:
|
if kb.tamperFunctions:
|
||||||
|
|||||||
@@ -295,10 +295,12 @@ def start():
|
|||||||
infoMsg = "found a total of %d targets" % len(kb.targets)
|
infoMsg = "found a total of %d targets" % len(kb.targets)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
hostCount = 0
|
targetCount = 0
|
||||||
initialHeaders = list(conf.httpHeaders)
|
initialHeaders = list(conf.httpHeaders)
|
||||||
|
|
||||||
for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
|
for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
|
||||||
|
targetCount += 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if conf.checkInternet:
|
if conf.checkInternet:
|
||||||
infoMsg = "checking for Internet connection"
|
infoMsg = "checking for Internet connection"
|
||||||
@@ -375,12 +377,10 @@ def start():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if conf.multipleTargets:
|
if conf.multipleTargets:
|
||||||
hostCount += 1
|
|
||||||
|
|
||||||
if conf.forms and conf.method:
|
if conf.forms and conf.method:
|
||||||
message = "[#%d] form:\n%s %s" % (hostCount, conf.method, targetUrl)
|
message = "[%d/%s] Form:\n%s %s" % (targetCount, len(kb.targets) if isListLike(kb.targets) else '?', conf.method, targetUrl)
|
||||||
else:
|
else:
|
||||||
message = "URL %d:\n%s %s" % (hostCount, HTTPMETHOD.GET, targetUrl)
|
message = "[%d/%s] URL:\n%s %s" % (targetCount, len(kb.targets) if isListLike(kb.targets) else '?', HTTPMETHOD.GET, targetUrl)
|
||||||
|
|
||||||
if conf.cookie:
|
if conf.cookie:
|
||||||
message += "\nCookie: %s" % conf.cookie
|
message += "\nCookie: %s" % conf.cookie
|
||||||
@@ -738,7 +738,7 @@ def start():
|
|||||||
if conf.multipleTargets:
|
if conf.multipleTargets:
|
||||||
_saveToResultsFile()
|
_saveToResultsFile()
|
||||||
|
|
||||||
errMsg += ", skipping to the next %s" % ("form" if conf.forms else "URL")
|
errMsg += ", skipping to the next target"
|
||||||
logger.error(errMsg.lstrip(", "))
|
logger.error(errMsg.lstrip(", "))
|
||||||
else:
|
else:
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from lib.core.common import openFile
|
|||||||
from lib.core.common import prioritySortColumns
|
from lib.core.common import prioritySortColumns
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import safeCSValue
|
from lib.core.common import safeCSValue
|
||||||
|
from lib.core.common import unArrayizeValue
|
||||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import getBytes
|
from lib.core.convert import getBytes
|
||||||
@@ -116,6 +117,9 @@ class Dump(object):
|
|||||||
if conf.api:
|
if conf.api:
|
||||||
self._write(data, content_type=content_type)
|
self._write(data, content_type=content_type)
|
||||||
|
|
||||||
|
if isListLike(data) and len(data) == 1:
|
||||||
|
data = unArrayizeValue(data)
|
||||||
|
|
||||||
if isListLike(data):
|
if isListLike(data):
|
||||||
self.lister(header, data, content_type, sort)
|
self.lister(header, data, content_type, sort)
|
||||||
elif data is not None:
|
elif data is not None:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class Replication(object):
|
|||||||
self.cursor = self.connection.cursor()
|
self.cursor = self.connection.cursor()
|
||||||
except sqlite3.OperationalError as ex:
|
except sqlite3.OperationalError as ex:
|
||||||
errMsg = "error occurred while opening a replication "
|
errMsg = "error occurred while opening a replication "
|
||||||
errMsg += "file '%s' ('%s')" % (self.filepath, getSafeExString(ex))
|
errMsg += "file '%s' ('%s')" % (dbpath, getSafeExString(ex))
|
||||||
raise SqlmapConnectionException(errMsg)
|
raise SqlmapConnectionException(errMsg)
|
||||||
|
|
||||||
class DataType(object):
|
class DataType(object):
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ import time
|
|||||||
from lib.core.enums import DBMS
|
from lib.core.enums import DBMS
|
||||||
from lib.core.enums import DBMS_DIRECTORY_NAME
|
from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||||
from lib.core.enums import OS
|
from lib.core.enums import OS
|
||||||
|
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.5.6.0"
|
VERSION = "1.5.9.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)
|
||||||
@@ -906,6 +907,9 @@ KB_CHARS_BOUNDARY_CHAR = 'q'
|
|||||||
# Letters of lower frequency used in kb.chars
|
# Letters of lower frequency used in kb.chars
|
||||||
KB_CHARS_LOW_FREQUENCY_ALPHABET = "zqxjkvbp"
|
KB_CHARS_LOW_FREQUENCY_ALPHABET = "zqxjkvbp"
|
||||||
|
|
||||||
|
# Printable bytes
|
||||||
|
PRINTABLE_BYTES = set(bytes(string.printable, "ascii") if six.PY3 else string.printable)
|
||||||
|
|
||||||
# SQL keywords used for splitting in HTTP chunked transfer encoded requests (switch --chunk)
|
# SQL keywords used for splitting in HTTP chunked transfer encoded requests (switch --chunk)
|
||||||
HTTP_CHUNKED_SPLIT_KEYWORDS = ("SELECT", "UPDATE", "INSERT", "FROM", "LOAD_FILE", "UNION", "information_schema", "sysdatabases", "msysaccessobjects", "msysqueries", "sysmodules")
|
HTTP_CHUNKED_SPLIT_KEYWORDS = ("SELECT", "UPDATE", "INSERT", "FROM", "LOAD_FILE", "UNION", "information_schema", "sysdatabases", "msysaccessobjects", "msysqueries", "sysmodules")
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,6 @@ def update():
|
|||||||
infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads"
|
infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads"
|
||||||
else:
|
else:
|
||||||
infoMsg = "for Linux platform it's recommended "
|
infoMsg = "for Linux platform it's recommended "
|
||||||
infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt install git')"
|
infoMsg += "to install a standard 'git' package (e.g.: 'apt install git')"
|
||||||
|
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ from lib.core.settings import IDENTYWAF_PARSE_LIMIT
|
|||||||
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
||||||
from lib.core.settings import META_CHARSET_REGEX
|
from lib.core.settings import META_CHARSET_REGEX
|
||||||
from lib.core.settings import PARSE_HEADERS_LIMIT
|
from lib.core.settings import PARSE_HEADERS_LIMIT
|
||||||
|
from lib.core.settings import PRINTABLE_BYTES
|
||||||
from lib.core.settings import SELECT_FROM_TABLE_REGEX
|
from lib.core.settings import SELECT_FROM_TABLE_REGEX
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.settings import VIEWSTATE_REGEX
|
from lib.core.settings import VIEWSTATE_REGEX
|
||||||
@@ -324,7 +325,7 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
|
|||||||
|
|
||||||
metaCharset = checkCharEncoding(extractRegexResult(META_CHARSET_REGEX, page))
|
metaCharset = checkCharEncoding(extractRegexResult(META_CHARSET_REGEX, page))
|
||||||
|
|
||||||
if (any((httpCharset, metaCharset)) and not all((httpCharset, metaCharset))) or (httpCharset == metaCharset and all((httpCharset, metaCharset))):
|
if (any((httpCharset, metaCharset)) and (not all((httpCharset, metaCharset)) or isinstance(page, six.binary_type) and all(_ in PRINTABLE_BYTES for _ in page))) or (httpCharset == metaCharset and all((httpCharset, metaCharset))):
|
||||||
kb.pageEncoding = httpCharset or metaCharset # Reference: http://bytes.com/topic/html-css/answers/154758-http-equiv-vs-true-header-has-precedence
|
kb.pageEncoding = httpCharset or metaCharset # Reference: http://bytes.com/topic/html-css/answers/154758-http-equiv-vs-true-header-has-precedence
|
||||||
debugMsg = "declared web page charset '%s'" % kb.pageEncoding
|
debugMsg = "declared web page charset '%s'" % kb.pageEncoding
|
||||||
singleTimeLogMessage(debugMsg, logging.DEBUG, debugMsg)
|
singleTimeLogMessage(debugMsg, logging.DEBUG, debugMsg)
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ class Connect(object):
|
|||||||
if conn:
|
if conn:
|
||||||
code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes)
|
code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes)
|
||||||
responseHeaders = conn.info()
|
responseHeaders = conn.info()
|
||||||
responseHeaders[URI_HTTP_HEADER] = conn.geturl()
|
responseHeaders[URI_HTTP_HEADER] = conn.geturl() if hasattr(conn, "geturl") else url
|
||||||
|
|
||||||
if hasattr(conn, "redurl"):
|
if hasattr(conn, "redurl"):
|
||||||
responseHeaders[HTTP_HEADER.LOCATION] = conn.redurl
|
responseHeaders[HTTP_HEADER.LOCATION] = conn.redurl
|
||||||
@@ -695,7 +695,7 @@ class Connect(object):
|
|||||||
|
|
||||||
except SqlmapConnectionException as ex:
|
except SqlmapConnectionException as ex:
|
||||||
if conf.proxyList and not kb.threadException:
|
if conf.proxyList and not kb.threadException:
|
||||||
warnMsg = "unable to connect to the target URL ('%s')" % ex
|
warnMsg = "unable to connect to the target URL ('%s')" % getSafeExString(ex)
|
||||||
logger.critical(warnMsg)
|
logger.critical(warnMsg)
|
||||||
threadData.retriesCount = conf.retries
|
threadData.retriesCount = conf.retries
|
||||||
return Connect._retryProxy(**kwargs)
|
return Connect._retryProxy(**kwargs)
|
||||||
@@ -978,7 +978,7 @@ class Connect(object):
|
|||||||
|
|
||||||
if conf.httpHeaders:
|
if conf.httpHeaders:
|
||||||
headers = OrderedDict(conf.httpHeaders)
|
headers = OrderedDict(conf.httpHeaders)
|
||||||
contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else "" for _ in headers) or None
|
contentType = max(headers[_] or "" if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else "" for _ in headers) or None
|
||||||
|
|
||||||
if (kb.postHint or conf.skipUrlEncode) and postUrlEncode:
|
if (kb.postHint or conf.skipUrlEncode) and postUrlEncode:
|
||||||
postUrlEncode = False
|
postUrlEncode = False
|
||||||
@@ -1275,7 +1275,7 @@ class Connect(object):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
compile(getBytes(conf.evalCode.replace(';', '\n')), "", "exec")
|
compile(getBytes(re.sub(r"\s*;\s*", "\n", conf.evalCode)), "", "exec")
|
||||||
except SyntaxError as ex:
|
except SyntaxError as ex:
|
||||||
if ex.text:
|
if ex.text:
|
||||||
original = replacement = ex.text.strip()
|
original = replacement = ex.text.strip()
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class SmartRedirectHandler(_urllib.request.HTTPRedirectHandler):
|
|||||||
delimiter = conf.cookieDel or DEFAULT_COOKIE_DELIMITER
|
delimiter = conf.cookieDel or DEFAULT_COOKIE_DELIMITER
|
||||||
last = None
|
last = None
|
||||||
|
|
||||||
for part in req.headers.get(HTTP_HEADER.COOKIE, "").split(delimiter) + ([headers[HTTP_HEADER.SET_COOKIE]] if HTTP_HEADER.SET_COOKIE in headers else []):
|
for part in getUnicode(req.headers.get(HTTP_HEADER.COOKIE, "")).split(delimiter) + ([headers[HTTP_HEADER.SET_COOKIE]] if HTTP_HEADER.SET_COOKIE in headers else []):
|
||||||
if '=' in part:
|
if '=' in part:
|
||||||
part = part.strip()
|
part = part.strip()
|
||||||
key, value = part.split('=', 1)
|
key, value = part.split('=', 1)
|
||||||
|
|||||||
@@ -724,7 +724,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
|||||||
errMsg += "List of supported adapters: %s" % ', '.join(sorted(list(server_names.keys())))
|
errMsg += "List of supported adapters: %s" % ', '.join(sorted(list(server_names.keys())))
|
||||||
else:
|
else:
|
||||||
errMsg = "Server support for adapter '%s' is not installed on this system " % adapter
|
errMsg = "Server support for adapter '%s' is not installed on this system " % adapter
|
||||||
errMsg += "(Note: you can try to install it with 'sudo apt install python-%s' or 'sudo pip%s install %s')" % (adapter, '3' if six.PY3 else "", adapter)
|
errMsg += "(Note: you can try to install it with 'apt install python-%s' or 'pip%s install %s')" % (adapter, '3' if six.PY3 else "", adapter)
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
|
|
||||||
def _client(url, options=None):
|
def _client(url, options=None):
|
||||||
@@ -773,7 +773,7 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
|||||||
if not isinstance(ex, _urllib.error.HTTPError) or ex.code == _http_client.UNAUTHORIZED:
|
if not isinstance(ex, _urllib.error.HTTPError) or ex.code == _http_client.UNAUTHORIZED:
|
||||||
errMsg = "There has been a problem while connecting to the "
|
errMsg = "There has been a problem while connecting to the "
|
||||||
errMsg += "REST-JSON API server at '%s' " % addr
|
errMsg += "REST-JSON API server at '%s' " % addr
|
||||||
errMsg += "(%s)" % ex
|
errMsg += "(%s)" % getSafeExString(ex)
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -825,7 +825,7 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
|||||||
try:
|
try:
|
||||||
argv = ["sqlmap.py"] + shlex.split(command)[1:]
|
argv = ["sqlmap.py"] + shlex.split(command)[1:]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logger.error("Error occurred while parsing arguments ('%s')" % ex)
|
logger.error("Error occurred while parsing arguments ('%s')" % getSafeExString(ex))
|
||||||
taskid = None
|
taskid = None
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class Response(object):
|
|||||||
try:
|
try:
|
||||||
content = response.read()
|
content = response.read()
|
||||||
except _http_client.IncompleteRead:
|
except _http_client.IncompleteRead:
|
||||||
content = raw[raw.find("\r\n\r\n") + 4:].rstrip("\r\n")
|
content = raw[raw.find(b"\r\n\r\n") + 4:].rstrip(b"\r\n")
|
||||||
|
|
||||||
return cls(httpVersion="HTTP/1.1" if response.version == 11 else "HTTP/1.0",
|
return cls(httpVersion="HTTP/1.1" if response.version == 11 else "HTTP/1.0",
|
||||||
status=response.status,
|
status=response.status,
|
||||||
|
|||||||
@@ -636,7 +636,10 @@ def storeHashesToFile(attack_dict):
|
|||||||
|
|
||||||
with openFile(filename, "w+") as f:
|
with openFile(filename, "w+") as f:
|
||||||
for item in items:
|
for item in items:
|
||||||
f.write(item)
|
try:
|
||||||
|
f.write(item)
|
||||||
|
except (UnicodeError, TypeError):
|
||||||
|
pass
|
||||||
|
|
||||||
def attackCachedUsersPasswords():
|
def attackCachedUsersPasswords():
|
||||||
if kb.data.cachedUsersPasswords:
|
if kb.data.cachedUsersPasswords:
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import re
|
|||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info >= (3, 0):
|
PY3 = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
|
if PY3:
|
||||||
xrange = range
|
xrange = range
|
||||||
text_type = str
|
text_type = str
|
||||||
string_types = (str,)
|
string_types = (str,)
|
||||||
@@ -92,7 +94,7 @@ def safechardecode(value, binary=False):
|
|||||||
|
|
||||||
if binary:
|
if binary:
|
||||||
if isinstance(retVal, text_type):
|
if isinstance(retVal, text_type):
|
||||||
retVal = retVal.encode("utf8")
|
retVal = retVal.encode("utf8", errors="surrogatepass" if PY3 else "strict")
|
||||||
|
|
||||||
elif isinstance(value, (list, tuple)):
|
elif isinstance(value, (list, tuple)):
|
||||||
for i in xrange(len(value)):
|
for i in xrange(len(value)):
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ from lib.core.exception import SqlmapConnectionException
|
|||||||
from lib.core.exception import SqlmapFilePathException
|
from lib.core.exception import SqlmapFilePathException
|
||||||
from lib.core.exception import SqlmapMissingDependence
|
from lib.core.exception import SqlmapMissingDependence
|
||||||
from plugins.generic.connector import Connector as GenericConnector
|
from plugins.generic.connector import Connector as GenericConnector
|
||||||
|
from thirdparty import six
|
||||||
|
|
||||||
def getSafeExString(ex, encoding=None): # Cross-referenced function
|
def getSafeExString(ex, encoding=None): # Cross-referenced function
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@@ -88,7 +89,7 @@ class SQLAlchemy(GenericConnector):
|
|||||||
|
|
||||||
self.printConnected()
|
self.printConnected()
|
||||||
else:
|
else:
|
||||||
raise SqlmapMissingDependence("SQLAlchemy not available")
|
raise SqlmapMissingDependence("SQLAlchemy not available (e.g. 'pip%s install SQLAlchemy')" % ('3' if six.PY3 else ""))
|
||||||
|
|
||||||
def fetchall(self):
|
def fetchall(self):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ class Fingerprint(GenericFingerprint):
|
|||||||
# Reference: https://dev.mysql.com/doc/relnotes/mysql/<major>.<minor>/en/
|
# Reference: https://dev.mysql.com/doc/relnotes/mysql/<major>.<minor>/en/
|
||||||
|
|
||||||
versions = (
|
versions = (
|
||||||
(80000, 80028), # MySQL 8.0
|
(80000, 80029), # MySQL 8.0
|
||||||
(60000, 60014), # MySQL 6.0
|
(60000, 60014), # MySQL 6.0
|
||||||
(50700, 50736), # MySQL 5.7
|
(50700, 50737), # MySQL 5.7
|
||||||
(50600, 50652), # MySQL 5.6
|
(50600, 50652), # MySQL 5.6
|
||||||
(50500, 50563), # MySQL 5.5
|
(50500, 50563), # MySQL 5.5
|
||||||
(50400, 50404), # MySQL 5.4
|
(50400, 50404), # MySQL 5.4
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class Takeover(GenericTakeover):
|
|||||||
|
|
||||||
banVer = kb.bannerFp["dbmsVersion"]
|
banVer = kb.bannerFp["dbmsVersion"]
|
||||||
|
|
||||||
if not banVer:
|
if not banVer or not banVer[0].isdigit():
|
||||||
errMsg = "unsupported feature on unknown version of PostgreSQL"
|
errMsg = "unsupported feature on unknown version of PostgreSQL"
|
||||||
raise SqlmapUnsupportedFeatureException(errMsg)
|
raise SqlmapUnsupportedFeatureException(errMsg)
|
||||||
elif distutils.version.LooseVersion(banVer) >= distutils.version.LooseVersion("10"):
|
elif distutils.version.LooseVersion(banVer) >= distutils.version.LooseVersion("10"):
|
||||||
|
|||||||
@@ -363,78 +363,85 @@ class Databases(object):
|
|||||||
singleTimeLogMessage(infoMsg)
|
singleTimeLogMessage(infoMsg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
infoMsg = "fetching number of tables for "
|
for _query, _count in ((rootQuery.blind.query, rootQuery.blind.count), (getattr(rootQuery.blind, "query2", None), getattr(rootQuery.blind, "count2", None))):
|
||||||
infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db)
|
if _query is None:
|
||||||
logger.info(infoMsg)
|
break
|
||||||
|
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB):
|
infoMsg = "fetching number of tables for "
|
||||||
query = rootQuery.blind.count
|
infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db)
|
||||||
else:
|
logger.info(infoMsg)
|
||||||
query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db)
|
|
||||||
|
|
||||||
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB):
|
||||||
|
query = _count % unsafeSQLIdentificatorNaming(db)
|
||||||
if count == 0:
|
|
||||||
warnMsg = "database '%s' " % unsafeSQLIdentificatorNaming(db)
|
|
||||||
warnMsg += "appears to be empty"
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif not isNumPosStrValue(count):
|
|
||||||
warnMsg = "unable to retrieve the number of "
|
|
||||||
warnMsg += "tables for database '%s'" % unsafeSQLIdentificatorNaming(db)
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
continue
|
|
||||||
|
|
||||||
tables = []
|
|
||||||
|
|
||||||
plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES
|
|
||||||
indexRange = getLimitRange(count, plusOne=plusOne)
|
|
||||||
|
|
||||||
for index in indexRange:
|
|
||||||
if Backend.isDbms(DBMS.SYBASE):
|
|
||||||
query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB):
|
|
||||||
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
|
|
||||||
query = rootQuery.blind.query % index
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.INFORMIX, DBMS.FRONTBASE, DBMS.VIRTUOSO):
|
|
||||||
query = rootQuery.blind.query % (index, unsafeSQLIdentificatorNaming(db))
|
|
||||||
else:
|
else:
|
||||||
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(db), index)
|
query = _count
|
||||||
|
|
||||||
table = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
||||||
|
|
||||||
if not isNoneValue(table):
|
if count == 0:
|
||||||
kb.hintValue = table
|
warnMsg = "database '%s' " % unsafeSQLIdentificatorNaming(db)
|
||||||
table = safeSQLIdentificatorNaming(table, True)
|
warnMsg += "appears to be empty"
|
||||||
tables.append(table)
|
logger.warn(warnMsg)
|
||||||
|
break
|
||||||
|
|
||||||
|
elif not isNumPosStrValue(count):
|
||||||
|
warnMsg = "unable to retrieve the number of "
|
||||||
|
warnMsg += "tables for database '%s'" % unsafeSQLIdentificatorNaming(db)
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
continue
|
||||||
|
|
||||||
|
tables = []
|
||||||
|
|
||||||
|
plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES
|
||||||
|
indexRange = getLimitRange(count, plusOne=plusOne)
|
||||||
|
|
||||||
|
for index in indexRange:
|
||||||
|
if Backend.isDbms(DBMS.SYBASE):
|
||||||
|
query = _query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " "))
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB):
|
||||||
|
query = _query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
|
||||||
|
query = _query % index
|
||||||
|
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.INFORMIX, DBMS.FRONTBASE, DBMS.VIRTUOSO):
|
||||||
|
query = _query % (index, unsafeSQLIdentificatorNaming(db))
|
||||||
|
else:
|
||||||
|
query = _query % (unsafeSQLIdentificatorNaming(db), index)
|
||||||
|
|
||||||
|
table = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||||
|
|
||||||
|
if not isNoneValue(table):
|
||||||
|
kb.hintValue = table
|
||||||
|
table = safeSQLIdentificatorNaming(table, True)
|
||||||
|
tables.append(table)
|
||||||
|
|
||||||
|
if tables:
|
||||||
|
kb.data.cachedTables[db] = tables
|
||||||
|
|
||||||
if conf.getComments:
|
if conf.getComments:
|
||||||
_ = queries[Backend.getIdentifiedDbms()].table_comment
|
for table in tables:
|
||||||
if hasattr(_, "query"):
|
_ = queries[Backend.getIdentifiedDbms()].table_comment
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE):
|
if hasattr(_, "query"):
|
||||||
query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper()))
|
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE):
|
||||||
|
query = _.query % (unsafeSQLIdentificatorNaming(db.upper()), unsafeSQLIdentificatorNaming(table.upper()))
|
||||||
|
else:
|
||||||
|
query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table))
|
||||||
|
|
||||||
|
comment = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||||
|
if not isNoneValue(comment):
|
||||||
|
infoMsg = "retrieved comment '%s' for table '%s'" % (comment, unsafeSQLIdentificatorNaming(table))
|
||||||
|
if METADB_SUFFIX not in db:
|
||||||
|
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(db)
|
||||||
|
logger.info(infoMsg)
|
||||||
else:
|
else:
|
||||||
query = _.query % (unsafeSQLIdentificatorNaming(db), unsafeSQLIdentificatorNaming(table))
|
warnMsg = "on %s it is not " % Backend.getIdentifiedDbms()
|
||||||
|
warnMsg += "possible to get table comments"
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
comment = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
break
|
||||||
if not isNoneValue(comment):
|
else:
|
||||||
infoMsg = "retrieved comment '%s' for table '%s'" % (comment, unsafeSQLIdentificatorNaming(table))
|
warnMsg = "unable to retrieve the table names "
|
||||||
if METADB_SUFFIX not in db:
|
warnMsg += "for database '%s'" % unsafeSQLIdentificatorNaming(db)
|
||||||
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(db)
|
logger.warn(warnMsg)
|
||||||
logger.info(infoMsg)
|
|
||||||
else:
|
|
||||||
warnMsg = "on %s it is not " % Backend.getIdentifiedDbms()
|
|
||||||
warnMsg += "possible to get table comments"
|
|
||||||
singleTimeWarnMessage(warnMsg)
|
|
||||||
|
|
||||||
if tables:
|
|
||||||
kb.data.cachedTables[db] = tables
|
|
||||||
else:
|
|
||||||
warnMsg = "unable to retrieve the table names "
|
|
||||||
warnMsg += "for database '%s'" % unsafeSQLIdentificatorNaming(db)
|
|
||||||
logger.warn(warnMsg)
|
|
||||||
|
|
||||||
if isNoneValue(kb.data.cachedTables):
|
if isNoneValue(kb.data.cachedTables):
|
||||||
kb.data.cachedTables.clear()
|
kb.data.cachedTables.clear()
|
||||||
@@ -618,7 +625,7 @@ class Databases(object):
|
|||||||
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
|
||||||
query += condQuery
|
query += condQuery
|
||||||
|
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = re.sub("column_type", "data_type", query, flags=re.I)
|
query = re.sub("column_type", "data_type", query, flags=re.I)
|
||||||
|
|
||||||
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
|
||||||
@@ -1022,7 +1029,7 @@ class Databases(object):
|
|||||||
rootQuery = queries[Backend.getIdentifiedDbms()].statements
|
rootQuery = queries[Backend.getIdentifiedDbms()].statements
|
||||||
|
|
||||||
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
else:
|
else:
|
||||||
query = rootQuery.inband.query
|
query = rootQuery.inband.query
|
||||||
@@ -1049,7 +1056,7 @@ class Databases(object):
|
|||||||
|
|
||||||
query = rootQuery.blind.count
|
query = rootQuery.blind.count
|
||||||
|
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
|
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
|
||||||
|
|
||||||
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
||||||
@@ -1077,7 +1084,7 @@ class Databases(object):
|
|||||||
if isNoneValue(value):
|
if isNoneValue(value):
|
||||||
query = rootQuery.blind.query % index
|
query = rootQuery.blind.query % index
|
||||||
|
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
|
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
|
||||||
|
|
||||||
value = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
value = unArrayizeValue(inject.getValue(query, union=False, error=False))
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class Miscellaneous(object):
|
|||||||
udfDict = {"master..new_xp_cmdshell": {}}
|
udfDict = {"master..new_xp_cmdshell": {}}
|
||||||
|
|
||||||
if udfDict is None:
|
if udfDict is None:
|
||||||
udfDict = self.sysUdfs
|
udfDict = getattr(self, "sysUdfs", {})
|
||||||
|
|
||||||
for udf, inpRet in udfDict.items():
|
for udf, inpRet in udfDict.items():
|
||||||
message = "do you want to remove UDF '%s'? [Y/n] " % udf
|
message = "do you want to remove UDF '%s'? [Y/n] " % udf
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class Users(object):
|
|||||||
|
|
||||||
if Backend.isDbms(DBMS.MYSQL):
|
if Backend.isDbms(DBMS.MYSQL):
|
||||||
self.getCurrentUser()
|
self.getCurrentUser()
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
kb.data.isDba = "root" in (kb.data.currentUser or "")
|
kb.data.isDba = "root" in (kb.data.currentUser or "")
|
||||||
elif kb.data.currentUser:
|
elif kb.data.currentUser:
|
||||||
query = queries[Backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0]
|
query = queries[Backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0]
|
||||||
@@ -106,7 +106,7 @@ class Users(object):
|
|||||||
condition |= (Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema)
|
condition |= (Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema)
|
||||||
|
|
||||||
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = rootQuery.inband.query3
|
query = rootQuery.inband.query3
|
||||||
elif condition:
|
elif condition:
|
||||||
query = rootQuery.inband.query2
|
query = rootQuery.inband.query2
|
||||||
@@ -126,7 +126,7 @@ class Users(object):
|
|||||||
infoMsg = "fetching number of database users"
|
infoMsg = "fetching number of database users"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if Backend.isFork(FORK.DRIZZLE):
|
if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = rootQuery.blind.count3
|
query = rootQuery.blind.count3
|
||||||
elif condition:
|
elif condition:
|
||||||
query = rootQuery.blind.count2
|
query = rootQuery.blind.count2
|
||||||
@@ -147,7 +147,7 @@ class Users(object):
|
|||||||
for index in indexRange:
|
for index in indexRange:
|
||||||
if Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB):
|
if Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB):
|
||||||
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
|
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
|
||||||
elif Backend.isFork(FORK.DRIZZLE):
|
elif Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
|
||||||
query = rootQuery.blind.query3 % index
|
query = rootQuery.blind.query3 % index
|
||||||
elif condition:
|
elif condition:
|
||||||
query = rootQuery.blind.query2 % index
|
query = rootQuery.blind.query2 % index
|
||||||
|
|||||||
243
sqlmapapi.yaml
Normal file
243
sqlmapapi.yaml
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
title: sqlmapapi OpenAPI/Swagger specification
|
||||||
|
version: '0.1'
|
||||||
|
paths:
|
||||||
|
/version:
|
||||||
|
get:
|
||||||
|
description: Fetch server version
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
example: "1.5.7.7#dev"
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/task/new:
|
||||||
|
get:
|
||||||
|
description: Create a new task
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
taskid:
|
||||||
|
type: string
|
||||||
|
example: "fad44d6beef72285"
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/scan/{taskid}/start:
|
||||||
|
post:
|
||||||
|
description: Launch a scan
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
examples:
|
||||||
|
'0':
|
||||||
|
value: '{"url":"http://testphp.vulnweb.com/artists.php?artist=1"}'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
engineid:
|
||||||
|
type: integer
|
||||||
|
example: 19720
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/scan/{taskid}/stop:
|
||||||
|
get:
|
||||||
|
description: Stop a scan
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/scan/{taskid}/status:
|
||||||
|
get:
|
||||||
|
description: Fetch status of a scan
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: terminated
|
||||||
|
returncode:
|
||||||
|
type: integer
|
||||||
|
example: 0
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/scan/{taskid}/list:
|
||||||
|
get:
|
||||||
|
description: List options for a given task ID
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
options:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
/scan/{taskid}/data:
|
||||||
|
get:
|
||||||
|
description: Retrieve the scan resulting data
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
error:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
/scan/{taskid}/log:
|
||||||
|
get:
|
||||||
|
description: Retrieve the log messages
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
log:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/scan/{taskid}/kill:
|
||||||
|
get:
|
||||||
|
description: Kill a scan
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
/task/{taskid}/delete:
|
||||||
|
get:
|
||||||
|
description: Delete an existing task
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: taskid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Scan task ID
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
Reference in New Issue
Block a user