diff --git a/lib/core/compat.py b/lib/core/compat.py index 72006044c..7c164596f 100644 --- a/lib/core/compat.py +++ b/lib/core/compat.py @@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission import binascii import os import random +import uuid class WichmannHill(random.Random): """ @@ -159,3 +160,7 @@ class WichmannHill(random.Random): y = (y + a) % 256 or 1 z = (z + a) % 256 or 1 self.__whseed(x, y, z) + +# Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py +def choose_boundary(): + return uuid.uuid4().hex \ No newline at end of file diff --git a/lib/core/patch.py b/lib/core/patch.py index 4cb018051..0dd3e4a41 100644 --- a/lib/core/patch.py +++ b/lib/core/patch.py @@ -24,3 +24,11 @@ def dirtyPatches(): # Reference: https://github.com/nodejs/node/issues/12786#issuecomment-298652440 codecs.register(lambda name: codecs.lookup("utf-8") if name == "cp65001" else None) + + # Reference: http://bugs.python.org/issue17849 + if hasattr(_http_client, "LineAndFileWrapper"): + def _(self, *args): + return self._readline() + + _http_client.LineAndFileWrapper._readline = _http_client.LineAndFileWrapper.readline + _http_client.LineAndFileWrapper.readline = _ diff --git a/lib/core/settings.py b/lib/core/settings.py index df16b96a4..63fe97f98 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import OS # sqlmap version (...) -VERSION = "1.3.3.61" +VERSION = "1.3.3.62" 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/request/httpshandler.py b/lib/request/httpshandler.py index 1c66b993c..dcb71abb0 100644 --- a/lib/request/httpshandler.py +++ b/lib/request/httpshandler.py @@ -97,11 +97,3 @@ class HTTPSConnection(_http_client.HTTPSConnection): class HTTPSHandler(_urllib.request.HTTPSHandler): def https_open(self, req): return self.do_open(HTTPSConnection if ssl else _http_client.HTTPSConnection, req) - -# Bug fix (http://bugs.python.org/issue17849) - -def _(self, *args): - return self._readline() - -_http_client.LineAndFileWrapper._readline = _http_client.LineAndFileWrapper.readline -_http_client.LineAndFileWrapper.readline = _ diff --git a/lib/utils/har.py b/lib/utils/har.py index 08b0464c7..cd165caa4 100644 --- a/lib/utils/har.py +++ b/lib/utils/har.py @@ -6,7 +6,6 @@ See the file 'LICENSE' for copying permission """ import base64 -import BaseHTTPServer import datetime import io import re @@ -14,6 +13,7 @@ import time from lib.core.bigarray import BigArray from lib.core.settings import VERSION +from thirdparty.six.moves import BaseHTTPServer as _BaseHTTPServer # Reference: https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HAR/Overview.html # http://www.softwareishard.com/har/viewer/ @@ -207,7 +207,7 @@ class FakeSocket: def makefile(self, *args, **kwargs): return self._file -class HTTPRequest(BaseHTTPServer.BaseHTTPRequestHandler): +class HTTPRequest(_BaseHTTPServer.BaseHTTPRequestHandler): # Original source: # https://stackoverflow.com/questions/4685217/parse-raw-http-headers diff --git a/lib/utils/sgmllib.py b/lib/utils/sgmllib.py new file mode 100644 index 000000000..227529789 --- /dev/null +++ b/lib/utils/sgmllib.py @@ -0,0 +1,551 @@ +"""A parser for SGML, using the derived class as a static DTD.""" + +# Note: missing in Python3 + +# XXX This only supports those SGML features used by HTML. + +# XXX There should be a way to distinguish between PCDATA (parsed +# character data -- the normal case), RCDATA (replaceable character +# data -- only char and entity references and end tags are special) +# and CDATA (character data -- only end tags are special). RCDATA is +# not supported at all. + +from __future__ import print_function + +import _markupbase +import re + +__all__ = ["SGMLParser", "SGMLParseError"] + +# Regular expressions used for parsing + +interesting = re.compile('[&<]') +incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|' + '<([a-zA-Z][^<>]*|' + '/([a-zA-Z][^<>]*)?|' + '![^<>]*)?') + +entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]') +charref = re.compile('&#([0-9]+)[^0-9]') + +starttagopen = re.compile('<[>a-zA-Z]') +shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/') +shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/') +piclose = re.compile('>') +endbracket = re.compile('[<>]') +tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*') +attrfind = re.compile( + r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*' + r'(\'[^\']*\'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?') + + +class SGMLParseError(RuntimeError): + """Exception raised for all parse errors.""" + pass + + +# SGML parser base class -- find tags and call handler functions. +# Usage: p = SGMLParser(); p.feed(data); ...; p.close(). +# The dtd is defined by deriving a class which defines methods +# with special names to handle tags: start_foo and end_foo to handle +# and , respectively, or do_foo to handle by itself. +# (Tags are converted to lower case for this purpose.) The data +# between tags is passed to the parser by calling self.handle_data() +# with some data as argument (the data may be split up in arbitrary +# chunks). Entity references are passed by calling +# self.handle_entityref() with the entity reference as argument. + +class SGMLParser(_markupbase.ParserBase): + # Definition of entities -- derived classes may override + entity_or_charref = re.compile('&(?:' + '([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)' + ')(;?)') + + def __init__(self, verbose=0): + """Initialize and reset this instance.""" + self.verbose = verbose + self.reset() + + def reset(self): + """Reset this instance. Loses all unprocessed data.""" + self.__starttag_text = None + self.rawdata = '' + self.stack = [] + self.lasttag = '???' + self.nomoretags = 0 + self.literal = 0 + _markupbase.ParserBase.reset(self) + + def setnomoretags(self): + """Enter literal mode (CDATA) till EOF. + + Intended for derived classes only. + """ + self.nomoretags = self.literal = 1 + + def setliteral(self, *args): + """Enter literal mode (CDATA). + + Intended for derived classes only. + """ + self.literal = 1 + + def feed(self, data): + """Feed some data to the parser. + + Call this as often as you want, with as little or as much text + as you want (may include '\n'). (This just saves the text, + all the processing is done by goahead().) + """ + + self.rawdata = self.rawdata + data + self.goahead(0) + + def close(self): + """Handle the remaining data.""" + self.goahead(1) + + def error(self, message): + raise SGMLParseError(message) + + # Internal -- handle data as far as reasonable. May leave state + # and data to be processed by a subsequent call. If 'end' is + # true, force handling all data as if followed by EOF marker. + def goahead(self, end): + rawdata = self.rawdata + i = 0 + n = len(rawdata) + while i < n: + if self.nomoretags: + self.handle_data(rawdata[i:n]) + i = n + break + match = interesting.search(rawdata, i) + if match: j = match.start() + else: j = n + if i < j: + self.handle_data(rawdata[i:j]) + i = j + if i == n: break + if rawdata[i] == '<': + if starttagopen.match(rawdata, i): + if self.literal: + self.handle_data(rawdata[i]) + i = i+1 + continue + k = self.parse_starttag(i) + if k < 0: break + i = k + continue + if rawdata.startswith(" (i + 1): + self.handle_data("<") + i = i+1 + else: + # incomplete + break + continue + if rawdata.startswith("