Compare commits

..
26 Commits
Author SHA1 Message Date
Miroslav Stampar d72660ef04 Adding a support for option-less URL arg 2019-10-01 15:37:09 +02:00
Miroslav Stampar 4833fb3aa6 Adding autocompletion script 2019-09-30 17:50:25 +02:00
Miroslav Stampar f437a54561 Update regarding #3944 2019-09-27 21:59:20 +02:00
Miroslav Stampar f05f84b6e5 Minor bug fix 2019-09-27 21:35:21 +02:00
Miroslav Stampar 871ebfdb70 Fixes #3943 2019-09-27 21:03:21 +02:00
Miroslav Stampar d34619232f Implements #3940 2019-09-26 10:36:47 +02:00
Miroslav Stampar 5168daf6ce Fixes #3939 2019-09-24 10:24:43 +02:00
Miroslav Stampar 95e476d5c9 Fixes #3937 2019-09-22 20:14:43 +02:00
Miroslav Stampar cc8209d648 Patch related to the #3927 2019-09-16 19:29:38 +02:00
Miroslav Stampar 6ec6e86937 Update regarding #3928 2019-09-16 10:18:51 +02:00
Miroslav Stampar 018908c2b1 Fixes #3925 2019-09-16 10:11:28 +02:00
Miroslav Stampar 9e69d6076d Fixes #3929 2019-09-16 10:08:10 +02:00
Miroslav Stampar ad785ea0a2 Fixes #3926 2019-09-16 10:03:19 +02:00
Miroslav Stampar b51f02c2ca Patch related to #3918 2019-09-13 16:30:26 +02:00
Miroslav Stampar ea3de16f24 Implementing PEP 479 (fixes #3924) 2019-09-13 11:38:26 +02:00
Miroslav Stampar f29c4e1e07 Minor generalization regarding last commit (#3917) 2019-09-12 15:29:15 +02:00
Miroslav Stampar e8871b8a99 Fixes #3917 2019-09-12 15:20:00 +02:00
Miroslav Stampar 8b88bb82d3 Minor refactoring 2019-09-11 14:05:25 +02:00
Miroslav Stampar 30fba849e2 Implements #3916 2019-09-09 13:56:37 +02:00
Miroslav Stampar 617c336813 Minor improvements 2019-09-09 11:45:23 +02:00
Miroslav Stampar 89a5892dd9 Dirty patch for #3915 2019-09-09 11:15:13 +02:00
Miroslav Stampar af8a2afde1 Cosmetics (trivial) 2019-09-05 11:33:56 +02:00
Miroslav Stampar ceaf387533 Fixes #3912 2019-09-05 11:22:10 +02:00
Miroslav Stampar e5a1377c36 Minor update 2019-09-05 11:15:43 +02:00
Miroslav Stampar bb61b08c83 Minor update of fingerprints 2019-09-03 14:01:37 +02:00
Miroslav Stampar 2d63441cc4 Minor update 2019-09-02 15:58:57 +02:00
39 changed files with 180 additions and 143 deletions
+11
View File
@@ -192,6 +192,17 @@
/var/log/mysqld.log
/var/www/index.php
# Reference: https://github.com/sqlmapproject/sqlmap/blob/master/lib/core/settings.py#L809-L810
/var/www/index.php
/usr/local/apache/index.php
/usr/local/apache2/index.php
/usr/local/www/apache22/index.php
/usr/local/www/apache24/index.php
/usr/local/httpd/index.php
/var/www/nginx-default/index.php
/srv/www/index.php
# Reference: https://www.gracefulsecurity.com/path-traversal-cheat-sheet-linux
/etc/passwd
+17 -4
View File
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
References:
* https://en.wikipedia.org/wiki/Debian_version_history
-->
<root>
<regexp value="^([\d\.\-]+)[\-\_\ ].*">
<info dbms_version="1"/>
@@ -36,19 +41,27 @@
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+wheezy">
<info dbms_version="1" type="Linux" distrib="Debian" release="7.0" codename="wheezy"/>
<info dbms_version="1" type="Linux" distrib="Debian" release="7" codename="wheezy"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+jessie">
<info dbms_version="1" type="Linux" distrib="Debian" release="8.0" codename="jessie"/>
<info dbms_version="1" type="Linux" distrib="Debian" release="8" codename="jessie"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+stretch">
<info dbms_version="1" type="Linux" distrib="Debian" release="9.0" codename="stretch"/>
<info dbms_version="1" type="Linux" distrib="Debian" release="9" codename="stretch"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+buster">
<info dbms_version="1" type="Linux" distrib="Debian" release="10.0" codename="buster"/>
<info dbms_version="1" type="Linux" distrib="Debian" release="10" codename="buster"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+bullseye">
<info dbms_version="1" type="Linux" distrib="Debian" release="11" codename="bullseye"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+bookworm">
<info dbms_version="1" type="Linux" distrib="Debian" release="12" codename="bookworm"/>
</regexp>
<regexp value="^([\d\.]+)[\-\_]Debian[\-\_][\d\.]+(sid|unstable)">
+13 -4
View File
@@ -15,11 +15,13 @@ BEEP_WAV_FILENAME = os.path.join(os.path.dirname(__file__), "beep.wav")
def beep():
try:
if sys.platform == "nt":
if sys.platform.startswith("win"):
_win_wav_play(BEEP_WAV_FILENAME)
elif sys.platform == "darwin":
elif sys.platform.startswith("darwin"):
_mac_beep()
elif sys.platform.startswith("linux"):
elif sys.platform.startswith("cygwin"):
_cygwin_beep(BEEP_WAV_FILENAME)
elif any(sys.platform.startswith(_) for _ in ("linux", "freebsd")):
_linux_wav_play(BEEP_WAV_FILENAME)
else:
_speaker_beep()
@@ -34,6 +36,10 @@ def _speaker_beep():
except IOError:
pass
# Reference: https://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00815.html
def _cygwin_beep(filename):
os.system("play-sound-file '%s' 2>/dev/null" % filename)
def _mac_beep():
import Carbon.Snd
Carbon.Snd.SysBeep(1)
@@ -57,7 +63,10 @@ def _linux_wav_play(filename):
class struct_pa_sample_spec(ctypes.Structure):
_fields_ = [("format", ctypes.c_int), ("rate", ctypes.c_uint32), ("channels", ctypes.c_uint8)]
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
try:
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
except OSError:
return
wave_file = wave.open(filename, "rb")
-17
View File
@@ -1,17 +0,0 @@
To use safe2bin.py you need to pass it the original file,
and optionally the output file name.
Example:
$ python ./safe2bin.py -i output.txt -o output.txt.bin
This will create an binary decoded file output.txt.bin. For example,
if the content of output.txt is: "\ttest\t\x32\x33\x34\nnewline" it will
be decoded to: " test 234
newline"
If you skip the output file name, general rule is that the binary
file names are suffixed with the string '.bin'. So, that means that
the upper example can also be written in the following form:
$ python ./safe2bin.py -i output.txt
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
pass
+9
View File
@@ -0,0 +1,9 @@
#/usr/bin/env bash
# source ./extra/shutils/autocompletion.sh
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
WORDLIST=`python "$DIR/../../sqlmap.py" -hh | grep -Eo '\s\--?\w[^ =,]*' | grep -vF '..' | paste -sd "" -`
complete -W "$WORDLIST" sqlmap
complete -W "$WORDLIST" ./sqlmap.py
+1 -1
View File
@@ -7,7 +7,7 @@
export SQLMAP_DREI=1
#for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3.7 -m compileall $i; done
for i in $(find . -iname "*.py" | grep -v __init__); do PYTHONWARNINGS=all python3.7 -m compileall $i | sed 's/Compiling/Checking/g'; done
unset SQLMAP_DREI
source `dirname "$0"`"/junk.sh"
+5 -4
View File
@@ -5,7 +5,6 @@ Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
import base64
import re
from lib.core.common import Backend
@@ -27,6 +26,7 @@ from lib.core.common import unArrayizeValue
from lib.core.common import urlencode
from lib.core.common import zeroDepthSearch
from lib.core.compat import xrange
from lib.core.convert import encodeBase64
from lib.core.convert import getUnicode
from lib.core.data import conf
from lib.core.data import kb
@@ -50,6 +50,7 @@ from lib.core.settings import PAYLOAD_DELIMITER
from lib.core.settings import REPLACEMENT_MARKER
from lib.core.settings import SINGLE_QUOTE_MARKER
from lib.core.settings import SLEEP_TIME_MARKER
from lib.core.settings import UNICODE_ENCODING
from lib.core.unescaper import unescaper
from thirdparty import six
@@ -170,8 +171,8 @@ class Agent(object):
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
# TODO: support for POST_HINT
newValue = base64.b64encode(newValue)
origValue = base64.b64encode(origValue)
newValue = encodeBase64(newValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
_ = "%s%s" % (origValue, kb.customInjectionMark)
@@ -654,7 +655,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)), r"\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
+2 -2
View File
@@ -46,7 +46,6 @@ from xml.sax import SAXParseException
from extra.beep.beep import beep
from extra.cloak.cloak import decloak
from extra.safe2bin.safe2bin import safecharencode
from lib.core.bigarray import BigArray
from lib.core.compat import cmp
from lib.core.compat import round
@@ -180,6 +179,7 @@ from lib.core.settings import VERSION_STRING
from lib.core.settings import ZIP_HEADER
from lib.core.settings import WEBSCARAB_SPLITTER
from lib.core.threads import getCurrentThreadData
from lib.utils.safe2bin import safecharencode
from lib.utils.sqlalchemy import _sqlalchemy
from thirdparty import six
from thirdparty.clientform.clientform import ParseResponse
@@ -623,7 +623,7 @@ def paramToDict(place, parameters=None):
if parameter in (conf.base64Parameter or []):
try:
oldValue = value
value = decodeBase64(value, binary=False)
value = decodeBase64(value, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
parameters = re.sub(r"\b%s(\b|\Z)" % re.escape(oldValue), value, parameters)
except:
errMsg = "parameter '%s' does not contain " % parameter
+7 -7
View File
@@ -184,7 +184,7 @@ def encodeHex(value, binary=True):
return retVal
def decodeBase64(value, binary=True):
def decodeBase64(value, binary=True, encoding=None):
"""
Returns a decoded representation of provided Base64 value
@@ -197,11 +197,11 @@ def decodeBase64(value, binary=True):
retVal = base64.b64decode(value)
if not binary:
retVal = getText(retVal)
retVal = getText(retVal, encoding)
return retVal
def encodeBase64(value, binary=True):
def encodeBase64(value, binary=True, encoding=None):
"""
Returns a decoded representation of provided Base64 value
@@ -212,12 +212,12 @@ def encodeBase64(value, binary=True):
"""
if isinstance(value, six.text_type):
value = value.encode(UNICODE_ENCODING)
value = value.encode(encoding or UNICODE_ENCODING)
retVal = base64.b64encode(value)
if not binary:
retVal = getText(retVal)
retVal = getText(retVal, encoding)
return retVal
@@ -305,7 +305,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
except UnicodeDecodeError:
return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances
def getText(value):
def getText(value, encoding=None):
"""
Returns textual value of a given value (Note: not necessary Unicode on Python2)
@@ -318,7 +318,7 @@ def getText(value):
retVal = value
if isinstance(value, six.binary_type):
retVal = getUnicode(value)
retVal = getUnicode(value, encoding)
if six.PY2:
try:
+1 -1
View File
@@ -13,7 +13,6 @@ import shutil
import tempfile
import threading
from extra.safe2bin.safe2bin import safechardecode
from lib.core.common import Backend
from lib.core.common import checkFile
from lib.core.common import dataToDumpFile
@@ -53,6 +52,7 @@ from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
from lib.core.settings import VERSION_STRING
from lib.core.settings import WINDOWS_RESERVED_NAMES
from lib.utils.safe2bin import safechardecode
from thirdparty import six
from thirdparty.magic import magic
+19 -4
View File
@@ -341,7 +341,8 @@ def _setCrawler():
if conf.bulkFile:
targets = getFileItems(conf.bulkFile)
else:
targets = parseSitemap(conf.sitemapUrl)
targets = list(parseSitemap(conf.sitemapUrl))
for i in xrange(len(targets)):
try:
target = targets[i]
@@ -473,10 +474,13 @@ def _findPageForms():
if conf.bulkFile:
targets = getFileItems(conf.bulkFile)
elif conf.sitemapUrl:
targets = parseSitemap(conf.sitemapUrl)
targets = list(parseSitemap(conf.sitemapUrl))
elif conf.googleDork:
targets = [_[0] for _ in kb.targets]
kb.targets.clear()
else:
targets = []
for i in xrange(len(targets)):
try:
target = targets[i]
@@ -1273,8 +1277,8 @@ def _setHTTPAuthentication():
from ntlm import HTTPNtlmAuthHandler
except ImportError:
errMsg = "sqlmap requires Python NTLM third-party library "
errMsg += "in order to authenticate via NTLM, "
errMsg += "https://github.com/mullender/python-ntlm"
errMsg += "in order to authenticate via NTLM. Download from "
errMsg += "'https://github.com/mullender/python-ntlm'"
raise SqlmapMissingDependence(errMsg)
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr)
@@ -2447,6 +2451,13 @@ def _basicOptionValidation():
errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex))
raise SqlmapSyntaxException(errMsg)
if conf.paramExclude:
try:
re.compile(conf.paramExclude)
except Exception as ex:
errMsg = "invalid regular expression '%s' ('%s')" % (conf.paramExclude, getSafeExString(ex))
raise SqlmapSyntaxException(errMsg)
if conf.crawlExclude:
try:
re.compile(conf.crawlExclude)
@@ -2490,6 +2501,10 @@ def _basicOptionValidation():
errMsg = "option '--csrf-url' requires usage of option '--csrf-token'"
raise SqlmapSyntaxException(errMsg)
if conf.csrfMethod and not conf.csrfToken:
errMsg = "option '--csrf-method' requires usage of option '--csrf-token'"
raise SqlmapSyntaxException(errMsg)
if conf.csrfToken and conf.threads > 1:
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
raise SqlmapSyntaxException(errMsg)
+1
View File
@@ -61,6 +61,7 @@ optDict = {
"skipUrlEncode": "boolean",
"csrfToken": "string",
"csrfUrl": "string",
"csrfMethod": "string",
"forceSSL": "boolean",
"chunked": "boolean",
"hpp": "boolean",
+1 -1
View File
@@ -7,13 +7,13 @@ See the file 'LICENSE' for copying permission
import sqlite3
from extra.safe2bin.safe2bin import safechardecode
from lib.core.common import getSafeExString
from lib.core.common import unsafeSQLIdentificatorNaming
from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapGenericException
from lib.core.exception import SqlmapValueException
from lib.core.settings import UNICODE_ENCODING
from lib.utils.safe2bin import safechardecode
class Replication(object):
"""
+1 -1
View File
@@ -18,7 +18,7 @@ from lib.core.enums import OS
from thirdparty.six import unichr as _unichr
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.3.9.0"
VERSION = "1.3.10.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)
+7 -6
View File
@@ -151,12 +151,13 @@ def _setRequestParams():
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*".+?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
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'("[^"]+)"', 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), _))
for match in re.finditer(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data):
if not (conf.testParameter and match.group("name") not in conf.testParameter):
_ = match.group(2)
if kb.customInjectionMark not in _: # Note: only for unprocessed (simple) forms - i.e. non-associative arrays (e.g. [1,2,3])
_ = 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
+1 -1
View File
@@ -42,7 +42,7 @@ class Wordlist(six.Iterator):
def adjust(self):
self.closeFP()
if self.index > len(self.filenames):
raise StopIteration
return # Note: https://stackoverflow.com/a/30217723 (PEP 479)
elif self.index == len(self.filenames):
self.iter = iter(self.custom)
else:
+32 -11
View File
@@ -44,6 +44,26 @@ finally:
def get_groups(parser):
return getattr(parser, "option_groups", None) or getattr(parser, "_action_groups")
def get_all_options(parser):
retVal = set()
for option in get_actions(parser):
if hasattr(option, "option_strings"):
retVal.update(option.option_strings)
else:
retVal.update(option._long_opts)
retVal.update(option._short_opts)
for group in get_groups(parser):
for option in get_actions(group):
if hasattr(option, "option_strings"):
retVal.update(option.option_strings)
else:
retVal.update(option._long_opts)
retVal.update(option._short_opts)
return retVal
from lib.core.common import checkOldOptions
from lib.core.common import checkSystemEncoding
from lib.core.common import dataToStdout
@@ -245,6 +265,9 @@ def cmdLineParser(argv=None):
request.add_argument("--csrf-url", dest="csrfUrl",
help="URL address to visit for extraction of anti-CSRF token")
request.add_argument("--csrf-method", dest="csrfMethod",
help="HTTP method to use during anti-CSRF token page visit")
request.add_argument("--force-ssl", dest="forceSSL", action="store_true",
help="Force usage of SSL/HTTPS")
@@ -841,18 +864,10 @@ def cmdLineParser(argv=None):
parser.usage = ""
cmdLineOptions.sqlmapShell = True
_ = ["x", "q", "exit", "quit", "clear"]
commands = set(("x", "q", "exit", "quit", "clear"))
commands.update(get_all_options(parser))
for option in get_actions(parser):
_.extend(option._long_opts)
_.extend(option._short_opts)
for group in get_groups(parser):
for option in get_actions(group):
_.extend(option._long_opts)
_.extend(option._short_opts)
autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=_)
autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=commands)
while True:
command = None
@@ -887,8 +902,11 @@ def cmdLineParser(argv=None):
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % getSafeExString(ex))
for i in xrange(len(argv)):
longOptions = set(re.findall(r"\-\-([^= ]+?)=", parser.format_help()))
if argv[i] == "-hh":
argv[i] = "-h"
elif i == 1 and argv[i].startswith("http"):
argv[i] = "--url=%s" % argv[i]
elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):
dataToStdout("[!] copy-pasting illegal (non-console) quote characters from Internet is, well, illegal (%s)\n" % argv[i])
raise SystemExit
@@ -934,6 +952,9 @@ def cmdLineParser(argv=None):
found = True
if not found:
get_groups(parser).remove(group)
elif '=' in argv[i] and not argv[i].startswith('-') and argv[i].split('=')[0] in longOptions and re.search(r"\A-\w\Z", argv[i - 1]) is None:
dataToStdout("[!] detected usage of long-option without a starting hyphen ('%s')\n" % argv[i])
raise SystemExit
for verbosity in (_ for _ in argv if re.search(r"\A\-v+\Z", _)):
try:
+2 -2
View File
@@ -22,7 +22,6 @@ except ImportError:
class WebSocketException(Exception):
pass
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.common import asciifyUrl
from lib.core.common import calculateDeltaSeconds
@@ -125,6 +124,7 @@ from lib.request.basic import processResponse
from lib.request.comparison import comparison
from lib.request.direct import direct
from lib.request.methodrequest import MethodRequest
from lib.utils.safe2bin import safecharencode
from thirdparty import six
from thirdparty.odict import OrderedDict
from thirdparty.six import unichr as _unichr
@@ -1039,7 +1039,7 @@ class Connect(object):
return retVal
token = AttribDict()
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.method if conf.csrfUrl == conf.url else None, cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
+1 -1
View File
@@ -7,7 +7,6 @@ See the file 'LICENSE' for copying permission
import time
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.common import calculateDeltaSeconds
@@ -26,6 +25,7 @@ from lib.core.enums import DBMS
from lib.core.enums import EXPECTED
from lib.core.enums import TIMEOUT_STATE
from lib.core.settings import UNICODE_ENCODING
from lib.utils.safe2bin import safecharencode
from lib.utils.timeout import timeout
def direct(query, content=True):
+1 -1
View File
@@ -9,7 +9,6 @@ from __future__ import print_function
import sys
from extra.safe2bin.safe2bin import safechardecode
from lib.core.common import Backend
from lib.core.common import dataToStdout
from lib.core.common import getSQLSnippet
@@ -28,6 +27,7 @@ from lib.request import inject
from lib.takeover.udf import UDF
from lib.takeover.web import Web
from lib.takeover.xp_cmdshell import XP_cmdshell
from lib.utils.safe2bin import safechardecode
from thirdparty.six.moves import input as _input
class Abstraction(Web, UDF, XP_cmdshell):
+1 -1
View File
@@ -10,7 +10,6 @@ from __future__ import division
import re
import time
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.common import calculateDeltaSeconds
@@ -58,6 +57,7 @@ from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.progress import ProgressBar
from lib.utils.safe2bin import safecharencode
from lib.utils.xrange import xrange
def bisection(payload, expression, length=None, charsetType=None, firstChar=None, lastChar=None, dump=False):
+1 -1
View File
@@ -8,7 +8,6 @@ See the file 'LICENSE' for copying permission
import re
import time
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.common import calculateDeltaSeconds
@@ -33,6 +32,7 @@ from lib.core.settings import MAX_DNS_LABEL
from lib.core.settings import PARTIAL_VALUE_MARKER
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.safe2bin import safecharencode
def dnsUse(payload, expression):
"""
+1 -1
View File
@@ -10,7 +10,6 @@ from __future__ import print_function
import re
import time
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import Backend
@@ -60,6 +59,7 @@ from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.progress import ProgressBar
from lib.utils.safe2bin import safecharencode
from thirdparty import six
def _oneShotErrorUse(expression, field=None, chunkTest=False):
+1 -1
View File
@@ -10,7 +10,6 @@ import re
import time
import xml.etree.ElementTree
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import arrayizeValue
@@ -62,6 +61,7 @@ from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.utils.progress import ProgressBar
from lib.utils.safe2bin import safecharencode
from thirdparty import six
from thirdparty.odict import OrderedDict
+1 -1
View File
@@ -7,7 +7,6 @@ See the file 'LICENSE' for copying permission
import re
from extra.safe2bin.safe2bin import safechardecode
from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import Backend
@@ -33,6 +32,7 @@ from lib.core.settings import MAX_INT
from lib.core.settings import NULL
from lib.core.unescaper import unescaper
from lib.request import inject
from lib.utils.safe2bin import safechardecode
from thirdparty.six import unichr as _unichr
def pivotDumpTable(table, colList, count=None, blind=True, alias=None):
+2 -1
View File
@@ -15,6 +15,7 @@ import string
from lib.core.common import getSafeExString
from lib.core.common import openFile
from lib.core.compat import xrange
from lib.core.convert import getUnicode
from lib.core.data import logger
from thirdparty.six import unichr as _unichr
@@ -84,4 +85,4 @@ def purge(directory):
try:
shutil.rmtree(directory)
except OSError as ex:
logger.error("problem occurred while removing directory '%s' ('%s')" % (directory, getSafeExString(ex)))
logger.error("problem occurred while removing directory '%s' ('%s')" % (getUnicode(directory), getSafeExString(ex)))
@@ -1,23 +1,15 @@
#!/usr/bin/env python
"""
safe2bin.py - Simple safe(hex) to binary format converter
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from __future__ import print_function
import binascii
import re
import string
import os
import sys
from optparse import OptionError
from optparse import OptionParser
if sys.version_info >= (3, 0):
xrange = range
text_type = str
@@ -49,10 +41,10 @@ def safecharencode(value):
"""
Returns safe representation of a given basestring value
>>> safecharencode(u'test123')
u'test123'
>>> safecharencode(u'test\x01\x02\xff')
u'test\\01\\02\\03\\ff'
>>> safecharencode(u'test123') == u'test123'
True
>>> safecharencode(u'test\x01\x02\xaf') == u'test\\\\x01\\\\x02\\xaf'
True
"""
retVal = value
@@ -107,37 +99,3 @@ def safechardecode(value, binary=False):
retVal[i] = safechardecode(value[i])
return retVal
def main():
usage = '%s -i <input file> [-o <output file>]' % sys.argv[0]
parser = OptionParser(usage=usage, version='0.1')
try:
parser.add_option('-i', dest='inputFile', help='Input file')
parser.add_option('-o', dest='outputFile', help='Output file')
(args, _) = parser.parse_args()
if not args.inputFile:
parser.error('Missing the input file, -h for help')
except (OptionError, TypeError) as ex:
parser.error(ex)
if not os.path.isfile(args.inputFile):
print('ERROR: the provided input file \'%s\' is not a regular file' % args.inputFile)
sys.exit(1)
f = open(args.inputFile, 'r')
data = f.read()
f.close()
if not args.outputFile:
args.outputFile = args.inputFile + '.bin'
f = open(args.outputFile, 'wb')
f.write(safechardecode(data))
f.close()
if __name__ == '__main__':
main()
+2 -1
View File
@@ -76,7 +76,8 @@ class SQLAlchemy(GenericConnector):
pass
elif "invalid literal for int() with base 10: '0b" in traceback.format_exc():
raise SqlmapConnectionException("SQLAlchemy connection issue ('https://bitbucket.org/zzzeek/sqlalchemy/issues/3975')")
raise
else:
pass
except SqlmapFilePathException:
raise
except Exception as ex:
+1 -1
View File
@@ -96,7 +96,7 @@ class Fingerprint(GenericFingerprint):
infoMsg = "actively fingerprinting %s" % DBMS.INFORMIX
logger.info(infoMsg)
for version in ("12.1", "11.7", "11.5"):
for version in ("14.1", "12.1", "11.7", "11.5", "10.0"):
output = inject.checkBooleanExpression("EXISTS(SELECT 1 FROM SYSMASTER:SYSDUAL WHERE DBINFO('VERSION,'FULL') LIKE '%%%s%%')" % version)
if output:
+2 -1
View File
@@ -94,7 +94,8 @@ class Fingerprint(GenericFingerprint):
("2008", "SYSDATETIME()=SYSDATETIME()"),
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"),
("2014", "CHARINDEX('12.0.2000',@@version)>0"),
("2016", "ISJSON(NULL) IS NULL")
("2016", "ISJSON(NULL) IS NULL"),
("2017", "TRIM(NULL) IS NULL")
):
result = inject.checkBooleanExpression(check)
+1 -1
View File
@@ -53,7 +53,7 @@ class Fingerprint(GenericFingerprint):
(50600, 50646), # MySQL 5.6
(50700, 50726), # MySQL 5.7
(60000, 60014), # MySQL 6.0
(80000, 80015), # MySQL 8.0
(80000, 80017), # MySQL 8.0
)
index = -1
+1 -1
View File
@@ -105,7 +105,7 @@ class Fingerprint(GenericFingerprint):
logger.info(infoMsg)
# Reference: https://en.wikipedia.org/wiki/Oracle_Database
for version in ("18c", "12c", "11g", "10g", "9i", "8i"):
for version in ("18c", "12c", "11g", "10g", "9i", "8i", "7"):
number = int(re.search(r"([\d]+)", version).group(1))
output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION),1,%d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))
+2 -1
View File
@@ -10,6 +10,7 @@ import os
from lib.core.common import Backend
from lib.core.common import checkFile
from lib.core.common import decloakToTemp
from lib.core.common import flattenValue
from lib.core.common import isListLike
from lib.core.common import isStackingAvailable
from lib.core.common import randomStr
@@ -104,7 +105,7 @@ class Takeover(GenericTakeover):
output = inject.getValue(query, resumeValue=False)
if isListLike(output):
output = os.linesep.join(output)
output = os.linesep.join(flattenValue(output))
self._cleanupCmd = "DROP TABLE %s" % self.cmdTblName
inject.goStacked(self._cleanupCmd)
+5 -2
View File
@@ -180,16 +180,19 @@ safeReqFile =
# Default: 0
safeFreq = 0
# Skip URL encoding of payload data
# Skip URL encoding of payload data.
# Valid: True or False
skipUrlEncode = False
# Parameter used to hold anti-CSRF token
# Parameter used to hold anti-CSRF token.
csrfToken =
# URL address to visit to extract anti-CSRF token
csrfUrl =
# HTTP method to use during anti-CSRF token page visit.
csrfMethod =
# Force usage of SSL/HTTPS
# Valid: True or False
forceSSL = False
+5
View File
@@ -263,6 +263,11 @@ def main():
logger.critical(errMsg)
raise SystemExit
elif all(_ in excMsg for _ in ("Access is denied", "subprocess", "metasploit")):
errMsg = "permission error occurred while running Metasploit"
logger.critical(errMsg)
raise SystemExit
elif all(_ in excMsg for _ in ("No such file", "_'")):
errMsg = "corrupted installation detected ('%s'). " % excMsg.strip().split('\n')[-1]
errMsg += "You should retrieve the latest development version from official GitHub "
+14 -5
View File
@@ -16,20 +16,29 @@ def dependencies():
pass
def randomIP():
numbers = []
octets = []
while not numbers or numbers[0] in (10, 172, 192):
numbers = random.sample(xrange(1, 255), 4)
while not octets or octets[0] in (10, 172, 192):
octets = random.sample(xrange(1, 255), 4)
return '.'.join(str(_) for _ in numbers)
return '.'.join(str(_) for _ in octets)
def tamper(payload, **kwargs):
"""
Append a fake HTTP header 'X-Forwarded-For'
Append a fake HTTP header 'X-Forwarded-For' (and alike)
"""
headers = kwargs.get("headers", {})
headers["X-Forwarded-For"] = randomIP()
headers["X-Client-Ip"] = randomIP()
headers["X-Real-Ip"] = randomIP()
headers["CF-Connecting-IP"] = randomIP()
headers["True-Client-IP"] = randomIP()
# Reference: https://developer.chrome.com/multidevice/data-compression-for-isps#proxy-connection
headers["Via"] = "1.1 Chrome-Compression-Proxy"
# Reference: https://wordpress.org/support/topic/blocked-country-gaining-access-via-cloudflare/#post-9812007
headers["CF-IPCountry"] = random.sample(('GB', 'US', 'FR', 'AU', 'CA', 'NZ', 'BE', 'DK', 'FI', 'IE', 'AT', 'IT', 'LU', 'NL', 'NO', 'PT', 'SE', 'ES', 'CH'), 1)[0]
return payload
+1 -1
View File
@@ -894,7 +894,7 @@ class Tag(PageElement):
def recursiveChildGenerator(self):
if not len(self.contents):
raise StopIteration
return # Note: https://stackoverflow.com/a/30217723 (PEP 479)
stopNode = self._lastRecursiveChild().next
current = self.contents[0]
while current is not stopNode:
+3 -1
View File
@@ -227,6 +227,9 @@ def unescape(data, entities, encoding=DEFAULT_ENCODING):
if data is None or "&" not in data:
return data
if isinstance(data, six.string_types):
encoding = None
def replace_entities(match, entities=entities, encoding=encoding):
ent = match.group()
if ent[1] == "#":
@@ -279,7 +282,6 @@ def get_entitydefs():
entitydefs["&%s;" % name] = _unichr(codepoint)
return entitydefs
def issequence(x):
try:
x[0]