mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Patches for dbwire
This commit is contained in:
parent
921870ccf0
commit
2acc8a5540
5 changed files with 32 additions and 10 deletions
|
|
@ -14,6 +14,7 @@ backslash escaping and \\N for NULL). Covers ClickHouse and its HTTP-compatible
|
|||
"""
|
||||
|
||||
import base64
|
||||
import socket
|
||||
|
||||
try:
|
||||
from urllib.request import Request, urlopen # Python 3
|
||||
|
|
@ -29,14 +30,14 @@ def _unescape(value):
|
|||
return None
|
||||
if "\\" not in value:
|
||||
return value
|
||||
out, it = [], iter(range(len(value)))
|
||||
out = []
|
||||
i = 0
|
||||
n = len(value)
|
||||
while i < n:
|
||||
ch = value[i]
|
||||
if ch == "\\" and i + 1 < n:
|
||||
nxt = value[i + 1]
|
||||
out.append({"t": "\t", "n": "\n", "r": "\r", "0": "\0", "\\": "\\", "'": "'"}.get(nxt, nxt))
|
||||
out.append({"t": "\t", "n": "\n", "r": "\r", "0": "\0", "b": "\b", "f": "\f", "a": "\a", "v": "\v", "\\": "\\", "'": "'"}.get(nxt, nxt))
|
||||
i += 2
|
||||
else:
|
||||
out.append(ch)
|
||||
|
|
@ -103,6 +104,8 @@ class Connection(object):
|
|||
raise ProgrammingError("(remote) %s" % ex.read().decode("utf-8", "replace").strip())
|
||||
except URLError as ex:
|
||||
raise OperationalError("(remote) %s" % ex)
|
||||
except (socket.timeout, socket.error) as ex:
|
||||
raise OperationalError("(remote) %s" % ex)
|
||||
|
||||
if not body:
|
||||
return None, []
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import os
|
|||
import socket
|
||||
import struct
|
||||
|
||||
from extra.dbwire import DatabaseError
|
||||
from extra.dbwire import DataError
|
||||
from extra.dbwire import IntegrityError
|
||||
from extra.dbwire import InterfaceError
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ headers are sent so the same client works against Presto and Trino.
|
|||
|
||||
import base64
|
||||
import json
|
||||
import time
|
||||
import socket
|
||||
|
||||
try:
|
||||
from urllib.request import Request, urlopen # Python 3
|
||||
|
|
@ -27,6 +27,20 @@ from extra.dbwire import NotSupportedError
|
|||
from extra.dbwire import OperationalError
|
||||
from extra.dbwire import ProgrammingError
|
||||
|
||||
def _convert(value, coltype):
|
||||
# normalize Presto/Trino JSON cells for sqlmap: VARBINARY arrives base64-encoded (decode to bytes so
|
||||
# direct()'s binary handling hex-encodes it), ARRAY/MAP/ROW arrive as JSON structures (serialize to text)
|
||||
if value is None:
|
||||
return value
|
||||
if coltype.startswith("varbinary"):
|
||||
try:
|
||||
return base64.b64decode(value)
|
||||
except Exception:
|
||||
return value
|
||||
if isinstance(value, (list, dict)):
|
||||
return json.dumps(value)
|
||||
return value
|
||||
|
||||
class Cursor(object):
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
|
@ -65,9 +79,13 @@ class Connection(object):
|
|||
self._headers = {"Content-Type": "text/plain"}
|
||||
for prefix in ("X-Presto-", "X-Trino-"):
|
||||
self._headers[prefix + "User"] = user or "sqlmap"
|
||||
self._headers[prefix + "Catalog"] = catalog or ""
|
||||
self._headers[prefix + "Schema"] = schema or "default"
|
||||
self._headers[prefix + "Source"] = "dbwire"
|
||||
# only send Catalog/Schema when supplied: a Schema without a Catalog makes Trino reject every
|
||||
# request ("Schema is set but catalog is not"), so never force a "default" schema
|
||||
if catalog:
|
||||
self._headers[prefix + "Catalog"] = catalog
|
||||
if schema:
|
||||
self._headers[prefix + "Schema"] = schema
|
||||
if password:
|
||||
token = base64.b64encode(("%s:%s" % (user or "", password)).encode("utf-8")).decode("ascii")
|
||||
self._headers["Authorization"] = "Basic %s" % token
|
||||
|
|
@ -92,6 +110,8 @@ class Connection(object):
|
|||
raise ProgrammingError("(remote) HTTP %s: %s" % (ex.code, ex.read().decode("utf-8", "replace")[:200]))
|
||||
except URLError as ex:
|
||||
raise OperationalError("(remote) %s" % ex)
|
||||
except (socket.timeout, socket.error) as ex:
|
||||
raise OperationalError("(remote) %s" % ex)
|
||||
try:
|
||||
return json.loads(body)
|
||||
except ValueError as ex:
|
||||
|
|
@ -99,15 +119,16 @@ class Connection(object):
|
|||
|
||||
def _query(self, query):
|
||||
page = self._request(self._statement_url, data=query)
|
||||
columns, rows = None, []
|
||||
columns, rows, types = None, [], []
|
||||
while True:
|
||||
if page.get("error"):
|
||||
message = page["error"].get("message", "unknown error")
|
||||
raise ProgrammingError("(remote) %s" % message)
|
||||
if page.get("columns") and columns is None:
|
||||
columns = [(c.get("name"), c.get("type"), None, None, None, None, None) for c in page["columns"]]
|
||||
types = [(c.get("type") or "") for c in page["columns"]]
|
||||
for row in page.get("data") or []:
|
||||
rows.append(tuple(row))
|
||||
rows.append(tuple(_convert(v, types[i] if i < len(types) else "") for i, v in enumerate(row)))
|
||||
next_uri = page.get("nextUri")
|
||||
if not next_uri:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -355,7 +355,6 @@ def _parse_tokens(sock, login=False):
|
|||
rows.append(tuple(row))
|
||||
elif token == 0xaa: # ERROR
|
||||
(tlen,) = struct.unpack("<H", data[off:off + 2]); off += 2
|
||||
number = struct.unpack("<i", data[off:off + 4])[0]
|
||||
msg_off = off + 4 + 1 + 1 # number(4) state(1) class(1)
|
||||
(mlen,) = struct.unpack("<H", data[msg_off:msg_off + 2])
|
||||
error = data[msg_off + 2:msg_off + 2 + mlen * 2].decode("utf-16-le", "replace")
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.7.85"
|
||||
VERSION = "1.10.7.86"
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue