diff --git a/lib/core/common.py b/lib/core/common.py index f9820e337..a9db652a1 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -4108,8 +4108,8 @@ def asciifyUrl(url, forceQuote=False): # Reference: http://blog.elsdoerfer.name/2008/12/12/opening-iris-in-python/ - >>> asciifyUrl(u'http://www.\\u0161u\\u0107uraj.com') == u'http://www.xn--uuraj-gxa24d.com' - True + >>> asciifyUrl(u'http://www.\\u0161u\\u0107uraj.com') + 'http://www.xn--uuraj-gxa24d.com' """ parts = _urllib.parse.urlsplit(url) diff --git a/lib/core/compat.py b/lib/core/compat.py index 5741ef985..385c8f4ec 100644 --- a/lib/core/compat.py +++ b/lib/core/compat.py @@ -204,5 +204,7 @@ def round(x, d=0): if sys.version_info >= (3, 0): xrange = range + buffer = memoryview else: xrange = xrange + buffer = buffer diff --git a/lib/core/settings.py b/lib/core/settings.py index 13a65690f..d0009926a 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -18,7 +18,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.3.5.13" +VERSION = "1.3.5.14" 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) diff --git a/lib/core/subprocessng.py b/lib/core/subprocessng.py index 19fd1a06d..2ffecc88e 100644 --- a/lib/core/subprocessng.py +++ b/lib/core/subprocessng.py @@ -10,6 +10,7 @@ import os import subprocess import time +from lib.core.compat import buffer from lib.core.settings import IS_WIN if IS_WIN: @@ -26,7 +27,7 @@ else: def blockingReadFromFD(fd): # Quick twist around original Twisted function # Blocking read from a non-blocking file descriptor - output = "" + output = b"" while True: try: @@ -183,7 +184,7 @@ def recv_some(p, t=.1, e=1, tr=5, stderr=0): y.append(r) else: time.sleep(max((x - time.time()) / tr, 0)) - return ''.join(y) + return b''.join(y) def send_all(p, data): if not data: @@ -193,4 +194,4 @@ def send_all(p, data): sent = p.send(data) if not isinstance(sent, int): break - data = buffer(data, sent) + data = buffer(data[sent:]) diff --git a/lib/request/connect.py b/lib/request/connect.py index 8697677d5..f60e17e53 100644 --- a/lib/request/connect.py +++ b/lib/request/connect.py @@ -420,6 +420,7 @@ class Connect(object): value = re.sub(r"(%s)([^ \t])" % char, r"\g<1>\t\g<2>", value) headers[getBytes(key)] = getBytes(value.strip("\r\n")) + url = getBytes(url) post = getBytes(post) if websocket_: @@ -671,6 +672,7 @@ class Connect(object): except (_urllib.error.URLError, socket.error, socket.timeout, _http_client.HTTPException, struct.error, binascii.Error, ProxyError, SqlmapCompressionException, WebSocketException, TypeError, ValueError, OverflowError): tbMsg = traceback.format_exc() + print(tbMsg) if checking: return None, None, None elif "no host given" in tbMsg: diff --git a/lib/takeover/metasploit.py b/lib/takeover/metasploit.py index d8f40d7be..a1a780cba 100644 --- a/lib/takeover/metasploit.py +++ b/lib/takeover/metasploit.py @@ -28,6 +28,8 @@ from lib.core.common import pollProcess from lib.core.common import randomRange from lib.core.common import randomStr from lib.core.common import readInput +from lib.core.convert import getBytes +from lib.core.convert import getText from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -555,14 +557,14 @@ class Metasploit: pass out = recv_some(proc, t=.1, e=0) - blockingWriteToFD(sys.stdout.fileno(), out) + blockingWriteToFD(sys.stdout.fileno(), getBytes(out)) # For --os-pwn and --os-bof pwnBofCond = self.connectionStr.startswith("reverse") - pwnBofCond &= any(_ in out for _ in ("Starting the payload handler", "Started reverse")) + pwnBofCond &= any(_ in out for _ in (b"Starting the payload handler", b"Started reverse")) # For --os-smbrelay - smbRelayCond = "Server started" in out + smbRelayCond = b"Server started" in out if pwnBofCond or smbRelayCond: func() @@ -570,7 +572,7 @@ class Metasploit: timeout = time.time() - start_time > METASPLOIT_SESSION_TIMEOUT if not initialized: - match = re.search(r"Meterpreter session ([\d]+) opened", out) + match = re.search(b"Meterpreter session ([\d]+) opened", out) if match: self._loadMetExtensions(proc, match.group(1)) @@ -616,7 +618,7 @@ class Metasploit: pollProcess(process) payloadStderr = process.communicate()[1] - match = re.search(r"(Total size:|Length:|succeeded with size|Final size of exe file:) ([\d]+)", payloadStderr) + match = re.search(b"(Total size:|Length:|succeeded with size|Final size of exe file:) ([\d]+)", payloadStderr) if match: payloadSize = int(match.group(2)) @@ -627,7 +629,7 @@ class Metasploit: debugMsg = "the shellcode size is %d bytes" % payloadSize logger.debug(debugMsg) else: - errMsg = "failed to create the shellcode (%s)" % payloadStderr.replace("\n", " ").replace("\r", "") + errMsg = "failed to create the shellcode ('%s')" % getText(payloadStderr).replace("\n", " ").replace("\r", "") raise SqlmapFilePathException(errMsg) self._shellcodeFP = open(self._shellcodeFilePath, "rb") diff --git a/lib/takeover/web.py b/lib/takeover/web.py index 08d5c00e2..cc6b08885 100644 --- a/lib/takeover/web.py +++ b/lib/takeover/web.py @@ -96,11 +96,11 @@ class Web: if filepath.endswith('_'): content = decloak(filepath) # cloaked file else: - with open(filepath, "rb") as f: + with openFile(filepath, "rb", encoding=None) as f: content = f.read() if content is not None: - stream = io.BytesIO(content) # string content + stream = io.BytesIO(getBytes(content)) # string content # Reference: https://github.com/sqlmapproject/sqlmap/issues/3560 # Reference: https://stackoverflow.com/a/4677542 @@ -131,7 +131,7 @@ class Web: page, _, _ = Request.getPage(url=self.webStagerUrl, multipart=multipartParams, raise404=False) - if "File uploaded" not in page: + if "File uploaded" not in (page or ""): warnMsg = "unable to upload the file through the web file " warnMsg += "stager to '%s'" % directory logger.warn(warnMsg) diff --git a/thirdparty/multipart/multipartpost.py b/thirdparty/multipart/multipartpost.py index 524f93602..11d6ef95f 100644 --- a/thirdparty/multipart/multipartpost.py +++ b/thirdparty/multipart/multipartpost.py @@ -28,13 +28,10 @@ import sys from lib.core.compat import choose_boundary from lib.core.convert import getBytes +from lib.core.convert import getText from lib.core.exception import SqlmapDataException from thirdparty.six.moves import urllib as _urllib -class Callable: - def __init__(self, anycallable): - self.__call__ = anycallable - # Controls how sequences are uncoded. If true, elements may be given # multiple values by assigning a sequence. doseq = 1 @@ -72,40 +69,38 @@ class MultipartPostHandler(_urllib.request.BaseHandler): request.data = data return request - def multipart_encode(vars, files, boundary=None, buf=None): + def multipart_encode(self, vars, files, boundary=None, buf=None): if boundary is None: boundary = choose_boundary() if buf is None: - buf = "" + buf = b"" for (key, value) in vars: if key is not None and value is not None: - buf += "--%s\r\n" % boundary - buf += "Content-Disposition: form-data; name=\"%s\"" % key - buf += "\r\n\r\n" + value + "\r\n" + buf += b"--%s\r\n" % getBytes(boundary) + buf += b"Content-Disposition: form-data; name=\"%s\"" % getBytes(key) + buf += b"\r\n\r\n" + getBytes(value) + b"\r\n" for (key, fd) in files: - file_size = os.fstat(fd.fileno())[stat.ST_SIZE] if hasattr(fd, "fileno") else fd.len + file_size = fd.len if hasattr(fd, "len") else os.fstat(fd.fileno())[stat.ST_SIZE] filename = fd.name.split("/")[-1] if "/" in fd.name else fd.name.split("\\")[-1] try: - contenttype = mimetypes.guess_type(filename)[0] or "application/octet-stream" + contenttype = mimetypes.guess_type(filename)[0] or b"application/octet-stream" except: # Reference: http://bugs.python.org/issue9291 - contenttype = "application/octet-stream" - buf += "--%s\r\n" % boundary - buf += "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" % (key, filename) - buf += "Content-Type: %s\r\n" % contenttype - # buf += "Content-Length: %s\r\n" % file_size + contenttype = b"application/octet-stream" + buf += b"--%s\r\n" % getBytes(boundary) + buf += b"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" % (getBytes(key), getBytes(filename)) + buf += b"Content-Type: %s\r\n" % getBytes(contenttype) + # buf += b"Content-Length: %s\r\n" % file_size fd.seek(0) - buf = getBytes(buf) buf += b"\r\n%s\r\n" % fd.read() - buf += "--%s--\r\n\r\n" % boundary + buf += b"--%s--\r\n\r\n" % getBytes(boundary) + buf = getBytes(buf) return boundary, buf - multipart_encode = Callable(multipart_encode) - https_request = http_request