From db0a1e58b9e93a271d9f21a4c1fe15095c0c08ee Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Mon, 11 Mar 2013 14:58:05 +0100 Subject: [PATCH] Update for an Issue #352 --- lib/core/common.py | 2 +- lib/core/convert.py | 87 +++++++++++++++++++++++++++--- plugins/dbms/db2/syntax.py | 5 ++ plugins/dbms/firebird/syntax.py | 12 +++++ plugins/dbms/maxdb/syntax.py | 5 ++ plugins/dbms/mssqlserver/syntax.py | 5 ++ plugins/dbms/mysql/syntax.py | 5 ++ plugins/dbms/oracle/syntax.py | 5 ++ plugins/dbms/postgresql/syntax.py | 3 ++ plugins/dbms/sqlite/syntax.py | 12 +++++ plugins/dbms/sybase/syntax.py | 5 ++ 11 files changed, 138 insertions(+), 8 deletions(-) diff --git a/lib/core/common.py b/lib/core/common.py index afcc9a152..be502679f 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -1480,7 +1480,7 @@ def isWindowsDriveLetterPath(filepath): def posixToNtSlashes(filepath): """ Replaces all occurances of Posix slashes (/) in provided - filepath with NT ones (/) + filepath with NT ones (\) >>> posixToNtSlashes('C:/Windows') 'C:\\\\Windows' diff --git a/lib/core/convert.py b/lib/core/convert.py index 28afe17bd..7dbaee1e2 100644 --- a/lib/core/convert.py +++ b/lib/core/convert.py @@ -13,12 +13,33 @@ from lib.core.settings import IS_WIN from lib.core.settings import UNICODE_ENCODING def base64decode(value): + """ + Decodes string value from Base64 to plain format + + >>> base64decode('Zm9vYmFy') + 'foobar' + """ + return value.decode("base64") def base64encode(value): + """ + Encodes string value from plain to Base64 format + + >>> base64encode('foobar') + 'Zm9vYmFy' + """ + return value.encode("base64")[:-1].replace("\n", "") def base64pickle(value): + """ + Serializes (with pickle) and encodes to Base64 format supplied (binary) value + + >>> base64pickle('foobar') + 'gAJVBmZvb2JhcnEALg==' + """ + retVal = None try: retVal = base64encode(pickle.dumps(value, pickle.HIGHEST_PROTOCOL)) @@ -31,21 +52,42 @@ def base64pickle(value): return retVal def base64unpickle(value): + """ + Decodes value from Base64 to plain format and deserializes (with pickle) it's content + + >>> base64unpickle('gAJVBmZvb2JhcnEALg==') + 'foobar' + """ + return pickle.loads(base64decode(value)) def hexdecode(value): + """ + Decodes string value from hex to plain format + + >>> hexdecode('666f6f626172') + 'foobar' + """ + value = value.lower() return (value[2:] if value.startswith("0x") else value).decode("hex") def hexencode(value): + """ + Encodes string value from plain to hex format + + >>> hexencode('foobar') + '666f6f626172' + """ + return utf8encode(value).encode("hex") def unicodeencode(value, encoding=None): """ - Return 8-bit string representation of the supplied unicode value: + Returns 8-bit string representation of the supplied unicode value - >>> unicodeencode(u'test') - 'test' + >>> unicodeencode(u'foobar') + 'foobar' """ retVal = value @@ -57,16 +99,33 @@ def unicodeencode(value, encoding=None): return retVal def utf8encode(value): + """ + Returns 8-bit string representation of the supplied UTF-8 value + + >>> utf8encode(u'foobar') + 'foobar' + """ + return unicodeencode(value, "utf-8") def utf8decode(value): + """ + Returns UTF-8 representation of the supplied 8-bit string representation + + >>> utf8decode('foobar') + u'foobar' + """ + return value.decode("utf-8") -def htmlescape(value): - codes = (('&', '&'), ('<', '<'), ('>', '>'), ('"', '"'), ("'", '''), (' ', ' ')) - return reduce(lambda x, y: x.replace(y[0], y[1]), codes, value) - def htmlunescape(value): + """ + Returns (basic conversion) HTML unescaped value + + >>> htmlunescape('a<b') + 'a'), ('"', '"'), (' ', ' '), ('&', '&')) @@ -103,7 +162,21 @@ def stdoutencode(data): return retVal def jsonize(data): + """ + Returns JSON serialized data + + >>> jsonize({'foo':'bar'}) + '{\\n "foo": "bar"\\n}' + """ + return json.dumps(data, sort_keys=False, indent=4) def dejsonize(data): + """ + Returns JSON deserialized data + + >>> dejsonize('{\\n "foo": "bar"\\n}') + {u'foo': u'bar'} + """ + return json.loads(data) diff --git a/plugins/dbms/db2/syntax.py b/plugins/dbms/db2/syntax.py index 9a8186336..7aeaac22e 100644 --- a/plugins/dbms/db2/syntax.py +++ b/plugins/dbms/db2/syntax.py @@ -13,6 +13,11 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar' + """ + def escaper(value): return "||".join("CHR(%d)" % ord(_) for _ in value) diff --git a/plugins/dbms/firebird/syntax.py b/plugins/dbms/firebird/syntax.py index f3f801a91..695a4598d 100644 --- a/plugins/dbms/firebird/syntax.py +++ b/plugins/dbms/firebird/syntax.py @@ -5,6 +5,7 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/) See the file 'doc/COPYING' for copying permission """ +from lib.core.common import Backend from lib.core.common import isDBMSVersionAtLeast from plugins.generic.syntax import Syntax as GenericSyntax @@ -14,6 +15,17 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Backend.setVersion('2.0') + ['2.0'] + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + "SELECT 'abcdefgh' FROM foobar" + >>> Backend.setVersion('2.1') + ['2.1'] + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT ASCII_CHAR(97)||ASCII_CHAR(98)||ASCII_CHAR(99)||ASCII_CHAR(100)||ASCII_CHAR(101)||ASCII_CHAR(102)||ASCII_CHAR(103)||ASCII_CHAR(104) FROM foobar' + """ + def escaper(value): return "||".join("ASCII_CHAR(%d)" % ord(_) for _ in value) diff --git a/plugins/dbms/maxdb/syntax.py b/plugins/dbms/maxdb/syntax.py index 44b62b332..f1ac416f0 100644 --- a/plugins/dbms/maxdb/syntax.py +++ b/plugins/dbms/maxdb/syntax.py @@ -13,4 +13,9 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + "SELECT 'abcdefgh' FROM foobar" + """ + return expression diff --git a/plugins/dbms/mssqlserver/syntax.py b/plugins/dbms/mssqlserver/syntax.py index 21a0503dc..e33d9d58a 100644 --- a/plugins/dbms/mssqlserver/syntax.py +++ b/plugins/dbms/mssqlserver/syntax.py @@ -13,6 +13,11 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT CHAR(97)+CHAR(98)+CHAR(99)+CHAR(100)+CHAR(101)+CHAR(102)+CHAR(103)+CHAR(104) FROM foobar' + """ + def escaper(value): return "+".join("%s(%d)" % ("CHAR" if ord(value[i]) < 256 else "NCHAR", ord(value[i])) for i in xrange(len(value))) diff --git a/plugins/dbms/mysql/syntax.py b/plugins/dbms/mysql/syntax.py index 0eb65208c..e58e4b481 100644 --- a/plugins/dbms/mysql/syntax.py +++ b/plugins/dbms/mysql/syntax.py @@ -16,6 +16,11 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT 0x6162636465666768 FROM foobar' + """ + def escaper(value): retVal = None try: diff --git a/plugins/dbms/oracle/syntax.py b/plugins/dbms/oracle/syntax.py index 3cd775e57..48c878147 100644 --- a/plugins/dbms/oracle/syntax.py +++ b/plugins/dbms/oracle/syntax.py @@ -13,6 +13,11 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar' + """ + def escaper(value): return "||".join("%s(%d)" % ("CHR" if ord(value[i]) < 256 else "NCHR", ord(value[i])) for i in xrange(len(value))) diff --git a/plugins/dbms/postgresql/syntax.py b/plugins/dbms/postgresql/syntax.py index 6b887a773..f75f410ca 100644 --- a/plugins/dbms/postgresql/syntax.py +++ b/plugins/dbms/postgresql/syntax.py @@ -16,6 +16,9 @@ class Syntax(GenericSyntax): """ Note: PostgreSQL has a general problem with concenation operator (||) precedence (hence the parentheses enclosing) e.g. SELECT 1 WHERE 'a'!='a'||'b' will trigger error ("argument of WHERE must be type boolean, not type text") + + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT (CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104)) FROM foobar' """ def escaper(value): diff --git a/plugins/dbms/sqlite/syntax.py b/plugins/dbms/sqlite/syntax.py index 6b3863b3d..6e9896548 100644 --- a/plugins/dbms/sqlite/syntax.py +++ b/plugins/dbms/sqlite/syntax.py @@ -7,6 +7,7 @@ See the file 'doc/COPYING' for copying permission import binascii +from lib.core.common import Backend from lib.core.common import isDBMSVersionAtLeast from lib.core.settings import UNICODE_ENCODING from plugins.generic.syntax import Syntax as GenericSyntax @@ -17,6 +18,17 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Backend.setVersion('2') + ['2'] + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + "SELECT 'abcdefgh' FROM foobar" + >>> Backend.setVersion('3') + ['3'] + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + "SELECT CAST(X'6162636465666768' AS TEXT) FROM foobar" + """ + def escaper(value): # Reference: http://stackoverflow.com/questions/3444335/how-do-i-quote-a-utf-8-string-literal-in-sqlite3 return "CAST(X'%s' AS TEXT)" % binascii.hexlify(value.encode(UNICODE_ENCODING) if isinstance(value, unicode) else value) diff --git a/plugins/dbms/sybase/syntax.py b/plugins/dbms/sybase/syntax.py index add401260..3cf73627b 100644 --- a/plugins/dbms/sybase/syntax.py +++ b/plugins/dbms/sybase/syntax.py @@ -13,6 +13,11 @@ class Syntax(GenericSyntax): @staticmethod def escape(expression, quote=True): + """ + >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") + 'SELECT CHAR(97)+CHAR(98)+CHAR(99)+CHAR(100)+CHAR(101)+CHAR(102)+CHAR(103)+CHAR(104) FROM foobar' + """ + def escaper(value): return "+".join("%s(%d)" % ("CHAR" if ord(value[i]) < 256 else "TO_UNICHAR", ord(value[i])) for i in xrange(len(value)))