diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 36ca54b2c..c86593260 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -15,6 +15,7 @@ from lib.core.agent import agent from lib.core.common import beep from lib.core.common import extractRegexResult from lib.core.common import findDynamicContent +from lib.core.common import getComparePageRatio from lib.core.common import getCompiledRegex from lib.core.common import getErrorParsedDBMSes from lib.core.common import getErrorParsedDBMSesFormatted @@ -49,6 +50,7 @@ from lib.core.exception import sqlmapUserQuitException from lib.core.session import setDynamicMarkings from lib.core.session import setString from lib.core.session import setRegexp +from lib.core.settings import CONSTANT_RATIO from lib.core.settings import UPPER_RATIO_BOUND from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request @@ -466,7 +468,7 @@ def heuristicCheckSqlInjection(place, parameter, value): payload = "%s%s%s%s" % (value, prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix) payload = agent.payload(place, parameter, value, payload) - Request.queryPage(payload, place, content=False, raise404=False) + Request.queryPage(payload, place, content=True, raise404=False) result = wasLastRequestDBMSError() @@ -482,6 +484,37 @@ def heuristicCheckSqlInjection(place, parameter, value): return result +def simpletonCheckSqlInjection(place, parameter, value): + """ + This is a function for the quickest and simplest + sql injection check (e.g. AND 1=1) + """ + + result = False + randInt = randomInt() + payload = "%s OR %d>%d" % (value, randInt, randInt+1) + payload = agent.payload(place, parameter, value, payload) + firstPage, _ = Request.queryPage(payload, place, content=True, raise404=False) + + if not (wasLastRequestDBMSError() or wasLastRequestHTTPError()): + if getComparePageRatio(kb.originalPage, firstPage) > CONSTANT_RATIO: + payload = "%s AND %d>%d" % (value, randInt, randInt+1) + payload = agent.payload(place, parameter, value, payload) + secondPage, _ = Request.queryPage(payload, place, content=True, raise404=False) + result = getComparePageRatio(firstPage, secondPage) <= CONSTANT_RATIO + + infoMsg = "simpleton test shows that %s " % place + infoMsg += "parameter '%s' might " % parameter + + if result: + infoMsg += "be injectable" + logger.info(infoMsg) + else: + infoMsg += "not be injectable" + logger.warn(infoMsg) + + return result + def checkDynParam(place, parameter, value): """ This function checks if the url parameter is dynamic. If it is diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 71e8422fe..151f4b12a 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -11,13 +11,14 @@ import re from lib.controller.action import action from lib.controller.checks import checkSqlInjection -from lib.controller.checks import heuristicCheckSqlInjection from lib.controller.checks import checkDynParam from lib.controller.checks import checkStability from lib.controller.checks import checkString from lib.controller.checks import checkRegexp from lib.controller.checks import checkConnection from lib.controller.checks import checkNullConnection +from lib.controller.checks import heuristicCheckSqlInjection +from lib.controller.checks import simpletonCheckSqlInjection from lib.core.agent import agent from lib.core.common import getUnicode from lib.core.common import paramToDict @@ -343,7 +344,8 @@ def start(): if testSqlInj: check = heuristicCheckSqlInjection(place, parameter, value) - if not check and conf.realTest: + if not check and conf.realTest and\ + not simpletonCheckSqlInjection(place, parameter, value): continue logMsg = "testing sql injection on %s " % place diff --git a/lib/core/common.py b/lib/core/common.py index b2dec8b97..a1a5b13fc 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -1963,3 +1963,8 @@ def showHttpErrorCodes(): if code in httplib.responses else '?', count)\ for code, count in kb.httpErrorCodes.items()) logger.warn(warnMsg) + +def getComparePageRatio(firstPage, secondPage): + conf.seqMatcher.set_seq1(firstPage) + conf.seqMatcher.set_seq2(secondPage) + return conf.seqMatcher.quick_ratio() diff --git a/lib/core/settings.py b/lib/core/settings.py index acfffdd22..5a755990f 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -25,6 +25,10 @@ SITE = "http://sqlmap.sourceforge.net" DIFF_TOLERANCE = 0.05 CONSTANT_RATIO = 0.9 +# lower and upper values for match ratio in case of stable page +LOWER_RATIO_BOUND = 0.02 +UPPER_RATIO_BOUND = 0.98 + # sqlmap logger logging.addLevelName(9, "PAYLOAD") logging.addLevelName(8, "TRAFFIC OUT") @@ -67,10 +71,6 @@ INFERENCE_BLANK_BREAK = 10 # string used for representation of unknown dbms version UNKNOWN_DBMS_VERSION = "Unknown" -# lower and upper values for match ratio in case of stable page -LOWER_RATIO_BOUND = 0.02 -UPPER_RATIO_BOUND = 0.98 - # dynamicity mark length used in dynamicity removal engine DYNAMICITY_MARK_LENGTH = 32