Merge pull request #1865 from guardicore/1613-agent-timeouts
1613 agent timeouts
This commit is contained in:
commit
252b314dc2
|
@ -87,7 +87,7 @@ class Configuration(object):
|
||||||
# Configuration servers to try to connect to, in this order.
|
# Configuration servers to try to connect to, in this order.
|
||||||
command_servers = []
|
command_servers = []
|
||||||
|
|
||||||
keep_tunnel_open_time = 60
|
keep_tunnel_open_time = 30
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# testing configuration
|
# testing configuration
|
||||||
|
|
|
@ -86,13 +86,15 @@ class SSHExploiter(HostExploiter):
|
||||||
self.exploit_result.exploitation_success = True
|
self.exploit_result.exploitation_success = True
|
||||||
self.report_login_attempt(True, user, ssh_key=ssh_string)
|
self.report_login_attempt(True, user, ssh_key=ssh_string)
|
||||||
return ssh
|
return ssh
|
||||||
except Exception:
|
except paramiko.AuthenticationException as err:
|
||||||
ssh.close()
|
ssh.close()
|
||||||
logger.debug(
|
logger.info(
|
||||||
"Error logging into victim %r with %s" " private key", self.host, ssh_string
|
f"Failed logging into victim {self.host} with {ssh_string} private key: {err}",
|
||||||
)
|
)
|
||||||
self.report_login_attempt(False, user, ssh_key=ssh_string)
|
self.report_login_attempt(False, user, ssh_key=ssh_string)
|
||||||
continue
|
continue
|
||||||
|
except Exception as err:
|
||||||
|
logger.error(f"Unknown error while attempting to login with ssh key: {err}")
|
||||||
raise FailedExploitationError
|
raise FailedExploitationError
|
||||||
|
|
||||||
def exploit_with_login_creds(self, port) -> paramiko.SSHClient:
|
def exploit_with_login_creds(self, port) -> paramiko.SSHClient:
|
||||||
|
@ -130,16 +132,18 @@ class SSHExploiter(HostExploiter):
|
||||||
self.report_login_attempt(True, user, current_password)
|
self.report_login_attempt(True, user, current_password)
|
||||||
return ssh
|
return ssh
|
||||||
|
|
||||||
except Exception as exc:
|
except paramiko.AuthenticationException as err:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Error logging into victim %r with user" " %s: (%s)",
|
"Failed logging into victim %r with user" " %s: (%s)",
|
||||||
self.host,
|
self.host,
|
||||||
user,
|
user,
|
||||||
exc,
|
err,
|
||||||
)
|
)
|
||||||
self.report_login_attempt(False, user, current_password)
|
self.report_login_attempt(False, user, current_password)
|
||||||
ssh.close()
|
ssh.close()
|
||||||
continue
|
continue
|
||||||
|
except Exception as err:
|
||||||
|
logger.error(f"Unknown error occurred while trying to login to ssh: {err}")
|
||||||
raise FailedExploitationError
|
raise FailedExploitationError
|
||||||
|
|
||||||
def _exploit_host(self) -> ExploiterResultData:
|
def _exploit_host(self) -> ExploiterResultData:
|
||||||
|
|
|
@ -343,6 +343,7 @@ class InfectionMonkey:
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
logger.info("Monkey cleanup started")
|
logger.info("Monkey cleanup started")
|
||||||
|
deleted = None
|
||||||
try:
|
try:
|
||||||
if self._master:
|
if self._master:
|
||||||
self._master.cleanup()
|
self._master.cleanup()
|
||||||
|
@ -357,7 +358,7 @@ class InfectionMonkey:
|
||||||
firewall.remove_firewall_rule()
|
firewall.remove_firewall_rule()
|
||||||
firewall.close()
|
firewall.close()
|
||||||
|
|
||||||
InfectionMonkey._self_delete()
|
deleted = InfectionMonkey._self_delete()
|
||||||
|
|
||||||
InfectionMonkey._send_log()
|
InfectionMonkey._send_log()
|
||||||
|
|
||||||
|
@ -365,13 +366,12 @@ class InfectionMonkey:
|
||||||
is_done=True, version=get_version()
|
is_done=True, version=get_version()
|
||||||
).send() # Signal the server (before closing the tunnel)
|
).send() # Signal the server (before closing the tunnel)
|
||||||
|
|
||||||
# TODO: Determine how long between when we
|
|
||||||
# send telemetry and the monkey actually exits
|
|
||||||
InfectionMonkey._close_tunnel()
|
InfectionMonkey._close_tunnel()
|
||||||
self._singleton.unlock()
|
self._singleton.unlock()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"An error occurred while cleaning up the monkey agent: {e}")
|
logger.error(f"An error occurred while cleaning up the monkey agent: {e}")
|
||||||
InfectionMonkey._self_delete()
|
if deleted is None:
|
||||||
|
InfectionMonkey._self_delete()
|
||||||
|
|
||||||
logger.info("Monkey is shutting down")
|
logger.info("Monkey is shutting down")
|
||||||
|
|
||||||
|
@ -400,9 +400,10 @@ class InfectionMonkey:
|
||||||
ControlClient.send_log(log)
|
ControlClient.send_log(log)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _self_delete():
|
def _self_delete() -> bool:
|
||||||
status = ScanStatus.USED if remove_monkey_dir() else ScanStatus.SCANNED
|
status = ScanStatus.USED if remove_monkey_dir() else ScanStatus.SCANNED
|
||||||
T1107Telem(status, get_monkey_dir_path()).send()
|
T1107Telem(status, get_monkey_dir_path()).send()
|
||||||
|
deleted = False
|
||||||
|
|
||||||
if -1 == sys.executable.find("python"):
|
if -1 == sys.executable.find("python"):
|
||||||
try:
|
try:
|
||||||
|
@ -421,11 +422,14 @@ class InfectionMonkey:
|
||||||
close_fds=True,
|
close_fds=True,
|
||||||
startupinfo=startupinfo,
|
startupinfo=startupinfo,
|
||||||
)
|
)
|
||||||
|
deleted = True
|
||||||
else:
|
else:
|
||||||
os.remove(sys.executable)
|
os.remove(sys.executable)
|
||||||
status = ScanStatus.USED
|
status = ScanStatus.USED
|
||||||
|
deleted = True
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error("Exception in self delete: %s", exc)
|
logger.error("Exception in self delete: %s", exc)
|
||||||
status = ScanStatus.SCANNED
|
status = ScanStatus.SCANNED
|
||||||
if status:
|
if status:
|
||||||
T1107Telem(status, sys.executable).send()
|
T1107Telem(status, sys.executable).send()
|
||||||
|
return deleted
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
|
import logging
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from common.common_consts.timeouts import SHORT_REQUEST_TIMEOUT
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _run_netsh_cmd(command, args):
|
def _run_netsh_cmd(command, args):
|
||||||
cmd = subprocess.Popen(
|
output = subprocess.check_output(
|
||||||
"netsh %s %s"
|
"netsh %s %s"
|
||||||
% (
|
% (
|
||||||
command,
|
command,
|
||||||
" ".join(['%s="%s"' % (key, value) for key, value in list(args.items()) if value]),
|
" ".join(['%s="%s"' % (key, value) for key, value in list(args.items()) if value]),
|
||||||
),
|
),
|
||||||
stdout=subprocess.PIPE,
|
timeout=SHORT_REQUEST_TIMEOUT,
|
||||||
)
|
)
|
||||||
return cmd.stdout.read().strip().lower().endswith("ok.")
|
return output.strip().lower().endswith(b"ok.")
|
||||||
|
|
||||||
|
|
||||||
class FirewallApp(object):
|
class FirewallApp(object):
|
||||||
|
@ -44,19 +49,23 @@ class WinAdvFirewall(FirewallApp):
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
try:
|
try:
|
||||||
cmd = subprocess.Popen("netsh advfirewall show currentprofile", stdout=subprocess.PIPE)
|
out = subprocess.check_output(
|
||||||
out = cmd.stdout.readlines()
|
"netsh advfirewall show currentprofile", timeout=SHORT_REQUEST_TIMEOUT
|
||||||
|
)
|
||||||
for line in out:
|
except subprocess.TimeoutExpired:
|
||||||
if line.startswith("State"):
|
return None
|
||||||
state = line.split()[-1].strip()
|
|
||||||
|
|
||||||
return state == "ON"
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
for line in out.decode().splitlines():
|
||||||
|
if line.startswith("State"):
|
||||||
|
state = line.split()[-1].strip()
|
||||||
|
return state == "ON"
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def add_firewall_rule(
|
def add_firewall_rule(
|
||||||
self, name="Firewall", direction="in", action="allow", program=sys.executable, **kwargs
|
self, name="MonkeyRule", direction="in", action="allow", program=sys.executable, **kwargs
|
||||||
):
|
):
|
||||||
netsh_args = {"name": name, "dir": direction, "action": action, "program": program}
|
netsh_args = {"name": name, "dir": direction, "action": action, "program": program}
|
||||||
netsh_args.update(kwargs)
|
netsh_args.update(kwargs)
|
||||||
|
@ -66,8 +75,11 @@ class WinAdvFirewall(FirewallApp):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
except Exception:
|
except subprocess.CalledProcessError as err:
|
||||||
return None
|
logger.info(f"Failed adding a firewall rule: {err.stdout}")
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
logger.info("Timeout expired trying to add a firewall rule.")
|
||||||
|
return None
|
||||||
|
|
||||||
def remove_firewall_rule(self, name="Firewall", **kwargs):
|
def remove_firewall_rule(self, name="Firewall", **kwargs):
|
||||||
netsh_args = {"name": name}
|
netsh_args = {"name": name}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
g_last_served = None
|
g_last_served = None
|
||||||
|
PROXY_TIMEOUT = 2.5
|
||||||
|
|
||||||
|
|
||||||
class TransportProxyBase(Thread):
|
class TransportProxyBase(Thread):
|
||||||
|
|
|
@ -7,7 +7,11 @@ from logging import getLogger
|
||||||
from urllib.parse import urlsplit
|
from urllib.parse import urlsplit
|
||||||
|
|
||||||
from infection_monkey.network.tools import get_interface_to_target
|
from infection_monkey.network.tools import get_interface_to_target
|
||||||
from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time
|
from infection_monkey.transport.base import (
|
||||||
|
PROXY_TIMEOUT,
|
||||||
|
TransportProxyBase,
|
||||||
|
update_last_serve_time,
|
||||||
|
)
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
@ -227,6 +231,6 @@ class LockedHTTPServer(threading.Thread):
|
||||||
class HTTPConnectProxy(TransportProxyBase):
|
class HTTPConnectProxy(TransportProxyBase):
|
||||||
def run(self):
|
def run(self):
|
||||||
httpd = http.server.HTTPServer((self.local_host, self.local_port), HTTPConnectProxyHandler)
|
httpd = http.server.HTTPServer((self.local_host, self.local_port), HTTPConnectProxyHandler)
|
||||||
httpd.timeout = 10
|
httpd.timeout = PROXY_TIMEOUT
|
||||||
while not self._stopped:
|
while not self._stopped:
|
||||||
httpd.handle_request()
|
httpd.handle_request()
|
||||||
|
|
|
@ -3,16 +3,20 @@ import socket
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time
|
from infection_monkey.transport.base import (
|
||||||
|
PROXY_TIMEOUT,
|
||||||
|
TransportProxyBase,
|
||||||
|
update_last_serve_time,
|
||||||
|
)
|
||||||
|
|
||||||
READ_BUFFER_SIZE = 8192
|
READ_BUFFER_SIZE = 8192
|
||||||
DEFAULT_TIMEOUT = 10
|
SOCKET_READ_TIMEOUT = 10
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SocketsPipe(Thread):
|
class SocketsPipe(Thread):
|
||||||
def __init__(self, source, dest, timeout=DEFAULT_TIMEOUT):
|
def __init__(self, source, dest, timeout=SOCKET_READ_TIMEOUT):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.source = source
|
self.source = source
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
|
@ -51,7 +55,7 @@ class TcpProxy(TransportProxyBase):
|
||||||
pipes = []
|
pipes = []
|
||||||
l_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
l_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
l_socket.bind((self.local_host, self.local_port))
|
l_socket.bind((self.local_host, self.local_port))
|
||||||
l_socket.settimeout(DEFAULT_TIMEOUT)
|
l_socket.settimeout(PROXY_TIMEOUT)
|
||||||
l_socket.listen(5)
|
l_socket.listen(5)
|
||||||
|
|
||||||
while not self._stopped:
|
while not self._stopped:
|
||||||
|
|
|
@ -9,7 +9,7 @@ INTERNAL = {
|
||||||
"keep_tunnel_open_time": {
|
"keep_tunnel_open_time": {
|
||||||
"title": "Keep tunnel open time",
|
"title": "Keep tunnel open time",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"default": 60,
|
"default": 30,
|
||||||
"description": "Time to keep tunnel open before going down after last exploit "
|
"description": "Time to keep tunnel open before going down after last exploit "
|
||||||
"(in seconds)",
|
"(in seconds)",
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue