From 5f171340f5308a0d05d312b34bcb2cadbdea7a12 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Fri, 15 Jan 2010 16:06:59 +0000 Subject: [PATCH] introduced safe string formatting --- lib/core/common.py | 18 ++++++++++++++++++ lib/techniques/blind/inference.py | 3 ++- lib/techniques/inband/union/test.py | 5 +++-- lib/techniques/inband/union/use.py | 1 + lib/utils/resume.py | 13 +++++++------ 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/lib/core/common.py b/lib/core/common.py index 7ecf48e57..884ada6c4 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -41,6 +41,7 @@ from lib.core.data import queries from lib.core.data import temp from lib.core.convert import urlencode from lib.core.exception import sqlmapFilePathException +from lib.core.exception import sqlmapNoneDataException from lib.core.settings import IS_WIN from lib.core.settings import SQL_STATEMENTS from lib.core.settings import VERSION_STRING @@ -847,3 +848,20 @@ def normalizePath(path): else: retVal = ntpath.normpath(path) return retVal + +def safeStringFormat(formatStr, params): + index = 0 + count = 0 + + retVal = formatStr.replace('%d', '%s') + + while index !=- 1: + index = retVal.find('%s') + if index != -1: + if count < len(params): + retVal = retVal[:index] + str(params[count]) + retVal[index+2:] + else: + raise sqlmapNoneDataException, "wrong number of parameters during string formatting" + count += 1 + + return retVal diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 5a22fc088..825c8b08a 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -31,6 +31,7 @@ from lib.core.common import dataToSessionFile from lib.core.common import dataToStdout from lib.core.common import getCharset from lib.core.common import replaceNewlineTabs +from lib.core.common import safeStringFormat from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -117,7 +118,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None queriesCount[0] += 1 position = (len(asciiTbl) / 2) posValue = asciiTbl[position] - forgedPayload = payload % (expressionUnescaped, idx, posValue) + forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue)) result = Request.queryPage(forgedPayload) if result: diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 414f8bc05..67d616b97 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -24,6 +24,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from lib.core.agent import agent from lib.core.common import randomStr +from lib.core.common import safeStringFormat from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -121,7 +122,7 @@ def __forgeUserFriendlyValue(payload): value = "" if kb.injPlace == "GET": - value = "%s?%s" % (conf.url, payload) + value = safeStringFormat("%s?%s", (conf.url, payload)) elif kb.injPlace == "POST": value = "URL:\t'%s'" % conf.url value += "\nPOST:\t'%s'\n" % payload @@ -202,7 +203,7 @@ def unionTest(): technique = "NULL bruteforcing" infoMsg = "testing inband sql injection on parameter " - infoMsg += "'%s' with %s technique" % (kb.injParameter, technique) + infoMsg += safeStringFormat("'%s' with %s technique", (kb.injParameter, technique)) logger.info(infoMsg) value = "" diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 60f31f348..3ebafe864 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -27,6 +27,7 @@ import time from lib.core.agent import agent from lib.core.common import parseUnionPage +from lib.core.common import safeStringFormat from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger diff --git a/lib/utils/resume.py b/lib/utils/resume.py index 39e1ffea0..ffb5a5868 100644 --- a/lib/utils/resume.py +++ b/lib/utils/resume.py @@ -25,6 +25,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import re from lib.core.common import dataToSessionFile +from lib.core.common import safeStringFormat from lib.core.data import conf from lib.core.data import kb from lib.core.data import logger @@ -74,7 +75,7 @@ def queryOutputLength(expression, payload): if output: return 0, output, regExpr - dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], lengthExpr)) + dataToSessionFile(safeStringFormat("[%s][%s][%s][%s][", (conf.url, kb.injPlace, conf.parameters[kb.injPlace], lengthExpr))) lengthExprUnescaped = unescaper.unescape(lengthExpr) count, length = bisection(payload, lengthExprUnescaped) @@ -144,7 +145,7 @@ def resume(expression, payload): infoMsg += "%s" % resumedValue.split("\n")[0] logger.info(infoMsg) - dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue)) + dataToSessionFile(safeStringFormat("[%s][%s][%s][%s][%s]\n", (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue))) return resumedValue elif len(resumedValue) < int(length): @@ -152,12 +153,12 @@ def resume(expression, payload): infoMsg += "%s..." % resumedValue.split("\n")[0] logger.info(infoMsg) - dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue)) + dataToSessionFile(safeStringFormat("[%s][%s][%s][%s][%s", (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, resumedValue))) if select: - newExpr = expression.replace(regExpr, substringQuery % (regExpr, len(resumedValue) + 1, int(length)), 1) + newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1) else: - newExpr = substringQuery % (expression, len(resumedValue) + 1, int(length)) + newExpr = safeStringFormat(substringQuery, (expression, len(resumedValue) + 1, int(length))) missingCharsLength = int(length) - len(resumedValue) @@ -175,6 +176,6 @@ def resume(expression, payload): return None - return "%s%s" % (resumedValue, finalValue) + return safeStringFormat("%s%s", (resumedValue, finalValue)) return None