Refactoring DBMS string escaping functions

This commit is contained in:
Miroslav Stampar 2013-01-20 13:45:58 +01:00
parent 3b57fe2924
commit b4a55a809e
12 changed files with 52 additions and 206 deletions

View File

@ -7,7 +7,6 @@ See the file 'doc/COPYING' for copying permission
import copy import copy
import httplib import httplib
import random
import re import re
import socket import socket
import time import time

View File

@ -23,7 +23,6 @@ from lib.core.common import incrementCounter
from lib.core.common import initTechnique from lib.core.common import initTechnique
from lib.core.common import isListLike from lib.core.common import isListLike
from lib.core.common import isNumPosStrValue from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable
from lib.core.common import listToStrValue from lib.core.common import listToStrValue
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import unArrayizeValue from lib.core.common import unArrayizeValue

View File

@ -5,7 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -14,34 +13,7 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if quote: def escaper(value):
while True: return "&".join("CHR(%d)" % ord(_) for _ in value)
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = ""
for i in xrange(firstIndex, lastIndex):
unescaped += "CHR(%d)" % (ord(expression[i]))
if i < lastIndex - 1:
unescaped += "&"
expression = expression.replace(old, unescaped)
else:
unescaped = "".join("CHR(%d)&" % ord(c) for c in expression)
if unescaped[-1] == "&":
unescaped = unescaped[:-1]
expression = unescaped
return expression
return Syntax._escape(expression, quote, escaper)

View File

@ -5,8 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.data import logger
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -15,32 +13,7 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if expression == u"'''": def escaper(value):
return "CHR(%d)" % (ord("'")) return "||".join("CHR(%d)" % ord(_) for _ in value)
if quote: return Syntax._escape(expression, quote, escaper)
while True:
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = ""
for i in xrange(firstIndex, lastIndex):
unescaped += "CHR(%d)" % (ord(expression[i]))
if i < lastIndex - 1:
unescaped += "||"
expression = expression.replace(old, unescaped)
else:
expression = "||".join("CHR(%d)" % ord(c) for c in expression)
return expression

View File

@ -6,7 +6,6 @@ See the file 'doc/COPYING' for copying permission
""" """
from lib.core.common import isDBMSVersionAtLeast from lib.core.common import isDBMSVersionAtLeast
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -15,38 +14,10 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
def escaper(value):
retVal = value
if isDBMSVersionAtLeast('2.1'): if isDBMSVersionAtLeast('2.1'):
if expression == u"'''": retVal = "||".join("ASCII_CHAR(%d)" % ord(_) for _ in value)
return "ASCII_CHAR(%d)" % (ord("'")) return retVal
if quote:
while True:
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = ""
for i in xrange(firstIndex, lastIndex):
unescaped += "ASCII_CHAR(%d)" % (ord(expression[i]))
if i < lastIndex - 1:
unescaped += "||"
expression = expression.replace(old, unescaped)
else:
unescaped = "".join("ASCII_CHAR(%d)||" % ord(c) for c in expression)
if unescaped[-1] == "||":
unescaped = unescaped[:-1]
expression = unescaped
return expression
return Syntax._escape(expression, quote, escaper)

View File

@ -5,7 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -14,25 +13,7 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if quote: def escaper(value):
while True: return "+".join("%s(%d)" % ("CHAR" if ord(value[i]) < 256 else "NCHAR", ord(value[i])) for i in xrange(len(value)))
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1 return Syntax._escape(expression, quote, escaper)
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = "+".join("%s(%d)" % ("CHAR" if ord(expression[i]) < 256 else "NCHAR", ord(expression[i])) for i in xrange(firstIndex, lastIndex))
expression = expression.replace(old, unescaped)
else:
expression = "+".join("CHAR(%d)" % ord(c) for c in expression)
return expression

View File

@ -6,10 +6,8 @@ See the file 'doc/COPYING' for copying permission
""" """
import binascii import binascii
import re
from lib.core.convert import utf8encode from lib.core.convert import utf8encode
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -18,14 +16,12 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if quote: def escaper(value):
unescaped = expression retVal = None
for item in re.findall(r"'[^']+'", expression, re.S):
try: try:
unescaped = unescaped.replace(item, "0x%s" % binascii.hexlify(item.strip("'"))) retVal = "0x%s" % binascii.hexlify(value.strip("'"))
except UnicodeEncodeError: except UnicodeEncodeError:
unescaped = unescaped.replace(item, "CONVERT(0x%s USING utf8)" % "".join("%.2x" % ord(_) for _ in utf8encode(item.strip("'")))) retVal = "CONVERT(0x%s USING utf8)" % "".join("%.2x" % ord(_) for _ in utf8encode(value.strip("'")))
else: return retVal
unescaped = "0x%s" % binascii.hexlify(expression)
return unescaped return Syntax._escape(expression, quote, escaper)

View File

@ -5,7 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -14,24 +13,7 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if quote: def escaper(value):
while True: return "||".join("%s(%d)" % ("CHR" if ord(value[i]) < 256 else "NCHR", ord(value[i])) for i in xrange(len(value)))
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1 return Syntax._escape(expression, quote, escaper)
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = "||".join("%s(%d)" % ("CHR" if ord(expression[i]) < 256 else "NCHR", ord(expression[i])) for i in xrange(firstIndex, lastIndex))
expression = expression.replace(old, unescaped)
else:
expression = "||".join("CHR(%d)" % ord(c) for c in expression)
return expression

View File

@ -5,7 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -19,24 +18,7 @@ class Syntax(GenericSyntax):
e.g. SELECT 1 WHERE 'a'!='a'||'b' will trigger error ("argument of WHERE must be type boolean, not type text") e.g. SELECT 1 WHERE 'a'!='a'||'b' will trigger error ("argument of WHERE must be type boolean, not type text")
""" """
if quote: def escaper(value):
while True: return "(%s)" % "||".join("CHR(%d)" % ord(_) for _ in value) # Postgres CHR() function already accepts Unicode code point of character(s)
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1 return Syntax._escape(expression, quote, escaper)
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = "(%s)" % "||".join("CHR(%d)" % (ord(expression[i])) for i in xrange(firstIndex, lastIndex)) # Postgres CHR() function already accepts Unicode code point of character(s)
expression = expression.replace(old, unescaped)
else:
expression = "(%s)" % "||".join("CHR(%d)" % ord(c) for c in expression)
return expression

View File

@ -6,10 +6,8 @@ See the file 'doc/COPYING' for copying permission
""" """
import binascii import binascii
import re
from lib.core.common import isDBMSVersionAtLeast from lib.core.common import isDBMSVersionAtLeast
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -18,13 +16,10 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
unescaped = expression def escaper(value):
retVal = value
if isDBMSVersionAtLeast('3'): if isDBMSVersionAtLeast('3'):
if quote: retVal = "X'%s'" % binascii.hexlify(value)
for item in re.findall(r"'[^']+'", expression, re.S): return retVal
unescaped = unescaped.replace(item, "X'%s'" % binascii.hexlify(item.strip("'")))
else:
unescaped = "X'%s'" % binascii.hexlify(expression)
return unescaped return Syntax._escape(expression, quote, escaper)

View File

@ -5,7 +5,6 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
from lib.core.exception import SqlmapSyntaxException
from plugins.generic.syntax import Syntax as GenericSyntax from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax): class Syntax(GenericSyntax):
@ -14,24 +13,7 @@ class Syntax(GenericSyntax):
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
if quote: def escaper(value):
while True: return "+".join("%s(%d)" % ("CHAR" if ord(value[i]) < 256 else "TO_UNICHAR", ord(value[i])) for i in xrange(len(value)))
index = expression.find("'")
if index == -1:
break
firstIndex = index + 1 return Syntax._escape(expression, quote, escaper)
index = expression[firstIndex:].find("'")
if index == -1:
raise SqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
unescaped = "+".join("%s(%d)" % ("CHAR" if ord(expression[i]) < 256 else "TO_UNICHAR", ord(expression[i])) for i in xrange(firstIndex, lastIndex))
expression = expression.replace(old, unescaped)
else:
expression = "+".join("CHAR(%d)" % ord(c) for c in expression)
return expression

View File

@ -5,6 +5,8 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission See the file 'doc/COPYING' for copying permission
""" """
import re
from lib.core.exception import SqlmapUndefinedMethod from lib.core.exception import SqlmapUndefinedMethod
class Syntax: class Syntax:
@ -15,6 +17,18 @@ class Syntax:
def __init__(self): def __init__(self):
pass pass
@staticmethod
def _escape(expression, quote=True, escaper=None):
retVal = expression
if quote:
for item in re.findall(r"'[^']+'", expression, re.S):
retVal = retVal.replace(item, escaper(item[1:-1]))
else:
retVal = escaper(expression)
return retVal
@staticmethod @staticmethod
def escape(expression, quote=True): def escape(expression, quote=True):
errMsg = "'escape' method must be defined " errMsg = "'escape' method must be defined "