mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 20:51:31 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37ebae89f2 | ||
|
|
8bcaed171a | ||
|
|
22e7b35ef4 | ||
|
|
067c3bc353 | ||
|
|
4d9dbdb36d | ||
|
|
309d08850f | ||
|
|
3b07b70864 | ||
|
|
97b88b0949 | ||
|
|
cb8861fde8 |
@@ -1,3 +1,8 @@
|
|||||||
|
# Version 1.6 (2022-01-03)
|
||||||
|
|
||||||
|
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.5...1.6)
|
||||||
|
* [View issues](https://github.com/sqlmapproject/sqlmap/milestone/7?closed=1)
|
||||||
|
|
||||||
# Version 1.5 (2021-01-03)
|
# Version 1.5 (2021-01-03)
|
||||||
|
|
||||||
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.4...1.5)
|
* [View changes](https://github.com/sqlmapproject/sqlmap/compare/1.4...1.5)
|
||||||
|
|||||||
@@ -163,8 +163,6 @@ Links
|
|||||||
- Demos: http://www.youtube.com/user/inquisb/videos
|
- Demos: http://www.youtube.com/user/inquisb/videos
|
||||||
- Screenshots: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
|
- Screenshots: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
|
||||||
|
|
||||||
.. |Build Status| image:: https://api.travis-ci.org/sqlmapproject/sqlmap.svg?branch=master
|
|
||||||
:target: https://api.travis-ci.org/sqlmapproject/sqlmap
|
|
||||||
.. |Python 2.6|2.7|3.x| image:: https://img.shields.io/badge/python-2.6|2.7|3.x-yellow.svg
|
.. |Python 2.6|2.7|3.x| image:: https://img.shields.io/badge/python-2.6|2.7|3.x-yellow.svg
|
||||||
:target: https://www.python.org/
|
:target: https://www.python.org/
|
||||||
.. |License| image:: https://img.shields.io/badge/license-GPLv2-red.svg
|
.. |License| image:: https://img.shields.io/badge/license-GPLv2-red.svg
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import random
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from extra.beep.beep import beep
|
from extra.beep.beep import beep
|
||||||
@@ -46,7 +45,6 @@ from lib.core.common import unArrayizeValue
|
|||||||
from lib.core.common import wasLastResponseDBMSError
|
from lib.core.common import wasLastResponseDBMSError
|
||||||
from lib.core.common import wasLastResponseHTTPError
|
from lib.core.common import wasLastResponseHTTPError
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
from lib.core.convert import getBytes
|
|
||||||
from lib.core.convert import getUnicode
|
from lib.core.convert import getUnicode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -95,7 +93,6 @@ from lib.core.settings import SINGLE_QUOTE_MARKER
|
|||||||
from lib.core.settings import SLEEP_TIME_MARKER
|
from lib.core.settings import SLEEP_TIME_MARKER
|
||||||
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
|
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
|
||||||
from lib.core.settings import SUPPORTED_DBMS
|
from lib.core.settings import SUPPORTED_DBMS
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
|
||||||
from lib.core.settings import UPPER_RATIO_BOUND
|
from lib.core.settings import UPPER_RATIO_BOUND
|
||||||
from lib.core.settings import URI_HTTP_HEADER
|
from lib.core.settings import URI_HTTP_HEADER
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
@@ -792,7 +789,7 @@ def checkSqlInjection(place, parameter, value):
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
process = subprocess.Popen(getBytes(conf.alert, sys.getfilesystemencoding() or UNICODE_ENCODING), shell=True)
|
process = subprocess.Popen(conf.alert, shell=True)
|
||||||
process.wait()
|
process.wait()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
|
errMsg = "error occurred while executing '%s' ('%s')" % (conf.alert, getSafeExString(ex))
|
||||||
|
|||||||
@@ -2116,6 +2116,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.pageStable = None
|
kb.pageStable = None
|
||||||
kb.partRun = None
|
kb.partRun = None
|
||||||
kb.permissionFlag = False
|
kb.permissionFlag = False
|
||||||
|
kb.place = None
|
||||||
kb.postHint = None
|
kb.postHint = None
|
||||||
kb.postSpaceToPlus = False
|
kb.postSpaceToPlus = False
|
||||||
kb.postUrlEncode = True
|
kb.postUrlEncode = True
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from thirdparty import six
|
|||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.6"
|
VERSION = "1.6.2.0"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|||||||
@@ -25,8 +25,11 @@ from lib.core.common import randomStr
|
|||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import removePostHintPrefix
|
from lib.core.common import removePostHintPrefix
|
||||||
from lib.core.common import resetCookieJar
|
from lib.core.common import resetCookieJar
|
||||||
|
from lib.core.common import safeStringFormat
|
||||||
|
from lib.core.common import unArrayizeValue
|
||||||
from lib.core.common import urldecode
|
from lib.core.common import urldecode
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
|
from lib.core.convert import decodeBase64
|
||||||
from lib.core.convert import getUnicode
|
from lib.core.convert import getUnicode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -622,7 +625,7 @@ def _createDumpDir():
|
|||||||
if not conf.dumpTable and not conf.dumpAll and not conf.search:
|
if not conf.dumpTable and not conf.dumpAll and not conf.search:
|
||||||
return
|
return
|
||||||
|
|
||||||
conf.dumpPath = paths.SQLMAP_DUMP_PATH % conf.hostname
|
conf.dumpPath = safeStringFormat(paths.SQLMAP_DUMP_PATH, conf.hostname)
|
||||||
|
|
||||||
if not os.path.isdir(conf.dumpPath):
|
if not os.path.isdir(conf.dumpPath):
|
||||||
try:
|
try:
|
||||||
@@ -740,6 +743,15 @@ def initTargetEnv():
|
|||||||
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
||||||
kb.postSpaceToPlus = '+' in original
|
kb.postSpaceToPlus = '+' in original
|
||||||
|
|
||||||
|
if conf.data and unArrayizeValue(conf.base64Parameter) == HTTPMETHOD.POST:
|
||||||
|
if '=' not in conf.data.strip('='):
|
||||||
|
try:
|
||||||
|
original = conf.data
|
||||||
|
conf.data = _(decodeBase64(conf.data, binary=False))
|
||||||
|
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
match = re.search(INJECT_HERE_REGEX, "%s %s %s" % (conf.url, conf.data, conf.httpHeaders))
|
match = re.search(INJECT_HERE_REGEX, "%s %s %s" % (conf.url, conf.data, conf.httpHeaders))
|
||||||
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
|
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ def vulnTest():
|
|||||||
("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter=\"OR boolean\" --tamper=space2dash", ("banner: '3.", " LIKE ")),
|
("-u <url> --flush-session --banner --invalid-logical --technique=B --predict-output --test-filter=\"OR boolean\" --tamper=space2dash", ("banner: '3.", " LIKE ")),
|
||||||
("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3", ("might be injectable", "Cookie #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
("-u <url> --flush-session --cookie=\"PHPSESSID=d41d8cd98f00b204e9800998ecf8427e; id=1*; id2=2\" --tables --union-cols=3", ("might be injectable", "Cookie #1* ((custom) HEADER)", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", " users ")),
|
||||||
("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner --count -T users", ("NULL connection is supported with HEAD method", "banner: '3.", "users | 5")),
|
("-u <url> --flush-session --null-connection --technique=B --tamper=between,randomcase --banner --count -T users", ("NULL connection is supported with HEAD method", "banner: '3.", "users | 5")),
|
||||||
|
("-u <base> --data=\"aWQ9MQ==\" --flush-session --base64=POST -v 6", ("aWQ9MTtXQUlURk9SIERFTEFZICcwOjA",)),
|
||||||
("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
|
("-u <url> --flush-session --parse-errors --test-filter=\"subquery\" --eval=\"import hashlib; id2=2; id3=hashlib.md5(id.encode()).hexdigest()\" --referer=\"localhost\"", ("might be injectable", ": syntax error", "back-end DBMS: SQLite", "WHERE or HAVING clause (subquery")),
|
||||||
("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
("-u <url> --banner --schema --dump -T users --binary-fields=surname --where \"id>3\"", ("banner: '3.", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
||||||
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --dump-format=HTML --answers=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary", "dumped to HTML file")),
|
("-u <url> --technique=U --fresh-queries --force-partial --dump -T users --dump-format=HTML --answers=\"crack=n\" -v 3", ("performed 6 queries", "nameisnull", "~using default dictionary", "dumped to HTML file")),
|
||||||
|
|||||||
@@ -56,12 +56,14 @@ from lib.core.common import safeVariableNaming
|
|||||||
from lib.core.common import singleTimeLogMessage
|
from lib.core.common import singleTimeLogMessage
|
||||||
from lib.core.common import singleTimeWarnMessage
|
from lib.core.common import singleTimeWarnMessage
|
||||||
from lib.core.common import stdev
|
from lib.core.common import stdev
|
||||||
|
from lib.core.common import unArrayizeValue
|
||||||
from lib.core.common import unsafeVariableNaming
|
from lib.core.common import unsafeVariableNaming
|
||||||
from lib.core.common import urldecode
|
from lib.core.common import urldecode
|
||||||
from lib.core.common import urlencode
|
from lib.core.common import urlencode
|
||||||
from lib.core.common import wasLastResponseDelayed
|
from lib.core.common import wasLastResponseDelayed
|
||||||
from lib.core.compat import patchHeaders
|
from lib.core.compat import patchHeaders
|
||||||
from lib.core.compat import xrange
|
from lib.core.compat import xrange
|
||||||
|
from lib.core.convert import encodeBase64
|
||||||
from lib.core.convert import getBytes
|
from lib.core.convert import getBytes
|
||||||
from lib.core.convert import getText
|
from lib.core.convert import getText
|
||||||
from lib.core.convert import getUnicode
|
from lib.core.convert import getUnicode
|
||||||
@@ -147,9 +149,12 @@ class Connect(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _getPageProxy(**kwargs):
|
def _getPageProxy(**kwargs):
|
||||||
|
try:
|
||||||
if (len(inspect.stack()) > sys.getrecursionlimit() // 2): # Note: https://github.com/sqlmapproject/sqlmap/issues/4525
|
if (len(inspect.stack()) > sys.getrecursionlimit() // 2): # Note: https://github.com/sqlmapproject/sqlmap/issues/4525
|
||||||
warnMsg = "unable to connect to the target URL"
|
warnMsg = "unable to connect to the target URL"
|
||||||
raise SqlmapConnectionException(warnMsg)
|
raise SqlmapConnectionException(warnMsg)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return Connect.getPage(**kwargs)
|
return Connect.getPage(**kwargs)
|
||||||
@@ -463,7 +468,7 @@ class Connect(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if post is not None and not multipart and not getHeader(headers, HTTP_HEADER.CONTENT_TYPE):
|
if post is not None and not multipart and not getHeader(headers, HTTP_HEADER.CONTENT_TYPE):
|
||||||
headers[HTTP_HEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE)
|
headers[HTTP_HEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE if unArrayizeValue(conf.base64Parameter) != HTTPMETHOD.POST else PLAIN_TEXT_CONTENT_TYPE)
|
||||||
|
|
||||||
if headers.get(HTTP_HEADER.CONTENT_TYPE) == POST_HINT_CONTENT_TYPES[POST_HINT.MULTIPART]:
|
if headers.get(HTTP_HEADER.CONTENT_TYPE) == POST_HINT_CONTENT_TYPES[POST_HINT.MULTIPART]:
|
||||||
warnMsg = "missing 'boundary parameter' in '%s' header. " % HTTP_HEADER.CONTENT_TYPE
|
warnMsg = "missing 'boundary parameter' in '%s' header. " % HTTP_HEADER.CONTENT_TYPE
|
||||||
@@ -549,6 +554,13 @@ class Connect(object):
|
|||||||
else:
|
else:
|
||||||
post = getBytes(post)
|
post = getBytes(post)
|
||||||
|
|
||||||
|
if unArrayizeValue(conf.base64Parameter) == HTTPMETHOD.POST:
|
||||||
|
if kb.place != HTTPMETHOD.POST:
|
||||||
|
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
|
||||||
|
else:
|
||||||
|
post = urldecode(post, convall=True)
|
||||||
|
post = encodeBase64(post)
|
||||||
|
|
||||||
if target and cmdLineOptions.method or method and method not in (HTTPMETHOD.GET, HTTPMETHOD.POST):
|
if target and cmdLineOptions.method or method and method not in (HTTPMETHOD.GET, HTTPMETHOD.POST):
|
||||||
req = MethodRequest(url, post, headers)
|
req = MethodRequest(url, post, headers)
|
||||||
req.set_method(cmdLineOptions.method or method)
|
req.set_method(cmdLineOptions.method or method)
|
||||||
@@ -973,6 +985,8 @@ class Connect(object):
|
|||||||
if not place:
|
if not place:
|
||||||
place = kb.injection.place or PLACE.GET
|
place = kb.injection.place or PLACE.GET
|
||||||
|
|
||||||
|
kb.place = place
|
||||||
|
|
||||||
if not auxHeaders:
|
if not auxHeaders:
|
||||||
auxHeaders = {}
|
auxHeaders = {}
|
||||||
|
|
||||||
@@ -1188,7 +1202,7 @@ class Connect(object):
|
|||||||
|
|
||||||
if not token:
|
if not token:
|
||||||
if conf.csrfUrl and conf.csrfToken and conf.csrfUrl != conf.url and code == _http_client.OK:
|
if conf.csrfUrl and conf.csrfToken and conf.csrfUrl != conf.url and code == _http_client.OK:
|
||||||
if headers and "text/plain" in headers.get(HTTP_HEADER.CONTENT_TYPE, ""):
|
if headers and PLAIN_TEXT_CONTENT_TYPE in headers.get(HTTP_HEADER.CONTENT_TYPE, ""):
|
||||||
token.name = conf.csrfToken
|
token.name = conf.csrfToken
|
||||||
token.value = page
|
token.value = page
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
|||||||
for row in json.loads(output):
|
for row in json.loads(output):
|
||||||
retVal += "%s%s%s" % (kb.chars.start, kb.chars.delimiter.join(getUnicode(row[field] or NULL) for field in fields), kb.chars.stop)
|
retVal += "%s%s%s" % (kb.chars.start, kb.chars.delimiter.join(getUnicode(row[field] or NULL) for field in fields), kb.chars.stop)
|
||||||
except:
|
except:
|
||||||
pass
|
retVal = None
|
||||||
else:
|
else:
|
||||||
retVal = getUnicode(retVal)
|
retVal = getUnicode(retVal)
|
||||||
elif Backend.isDbms(DBMS.PGSQL):
|
elif Backend.isDbms(DBMS.PGSQL):
|
||||||
@@ -128,7 +128,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
|||||||
for row in json.loads(output):
|
for row in json.loads(output):
|
||||||
retVal += "%s%s%s" % (kb.chars.start, row, kb.chars.stop)
|
retVal += "%s%s%s" % (kb.chars.start, row, kb.chars.stop)
|
||||||
except:
|
except:
|
||||||
pass
|
retVal = None
|
||||||
else:
|
else:
|
||||||
retVal = getUnicode(retVal)
|
retVal = getUnicode(retVal)
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ try:
|
|||||||
from lib.core.common import checkPipedInput
|
from lib.core.common import checkPipedInput
|
||||||
from lib.core.common import createGithubIssue
|
from lib.core.common import createGithubIssue
|
||||||
from lib.core.common import dataToStdout
|
from lib.core.common import dataToStdout
|
||||||
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import filterNone
|
from lib.core.common import filterNone
|
||||||
from lib.core.common import getDaysFromLastUpdate
|
from lib.core.common import getDaysFromLastUpdate
|
||||||
from lib.core.common import getFileItems
|
from lib.core.common import getFileItems
|
||||||
@@ -349,6 +350,11 @@ def main():
|
|||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
|
elif all(_ in excMsg for _ in ("OSError: [Errno 22] Invalid argument: '", "importlib")):
|
||||||
|
errMsg = "unable to read file '%s'" % extractRegexResult(r"OSError: \[Errno 22\] Invalid argument: '(?P<result>[^']+)", excMsg)
|
||||||
|
logger.critical(errMsg)
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
elif "hash_randomization" in excMsg:
|
elif "hash_randomization" in excMsg:
|
||||||
errMsg = "error occurred at Python interpreter which "
|
errMsg = "error occurred at Python interpreter which "
|
||||||
errMsg += "is fixed in 2.7.3. Please update accordingly "
|
errMsg += "is fixed in 2.7.3. Please update accordingly "
|
||||||
@@ -429,7 +435,7 @@ def main():
|
|||||||
dataToStdout(excMsg)
|
dataToStdout(excMsg)
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
elif any(_ in excMsg for _ in ("ImportError", "ModuleNotFoundError", "Can't find file for module", "SAXReaderNotAvailable", "source code string cannot contain null bytes", "No module named", "tp_name field")):
|
elif any(_ in excMsg for _ in ("ImportError", "ModuleNotFoundError", "Can't find file for module", "SAXReaderNotAvailable", "source code string cannot contain null bytes", "No module named", "tp_name field", "module 'sqlite3' has no attribute 'OperationalError'")):
|
||||||
errMsg = "invalid runtime environment ('%s')" % excMsg.split("Error: ")[-1].strip()
|
errMsg = "invalid runtime environment ('%s')" % excMsg.split("Error: ")[-1].strip()
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|||||||
Reference in New Issue
Block a user