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

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

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

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

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

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

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

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

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

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

View File

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

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

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
"""
import logging
import subprocess
import sys
# sqlmap version and site
VERSION = "0.8-rc2"
VERSION = "0.8-rc3"
VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net"

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

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

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

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
"""
class Unescaper:
def __init__(self):
self.__unescaper = None
def setUnescape(self, unescapeFunction):
self.__unescaper = unescapeFunction
def unescape(self, expression, quote=True):
return self.__unescaper(expression, quote=quote)
unescaper = Unescaper()

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