Merge pull request #2263 from guardicore/2216-remove-unused-code

2216 remove unused code
This commit is contained in:
Mike Salvatore 2022-09-09 08:01:15 -04:00
commit 20649b5e3c
24 changed files with 22 additions and 671 deletions

View File

@ -8,4 +8,3 @@ class TelemCategoryEnum:
SCAN = "scan"
STATE = "state"
TRACE = "trace"
TUNNEL = "tunnel"

View File

@ -2,20 +2,16 @@ import json
import logging
import platform
from socket import gethostname
from typing import Mapping, Optional
import requests
from urllib3 import disable_warnings
import infection_monkey.tunnel as tunnel
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
from infection_monkey.config import GUID
from infection_monkey.network.info import get_host_subnets, local_ips
from infection_monkey.transport.http import HTTPConnectProxy
from infection_monkey.transport.tcp import TcpProxy
from infection_monkey.utils import agent_process
from infection_monkey.utils.environment import is_windows_os
requests.packages.urllib3.disable_warnings()
disable_warnings() # noqa DUO131
logger = logging.getLogger(__name__)
@ -28,8 +24,7 @@ class ControlClient:
# https://github.com/guardicore/monkey/blob/133f7f5da131b481561141171827d1f9943f6aec/monkey/infection_monkey/telemetry/base_telem.py
control_client_object = None
def __init__(self, server_address: str, proxies: Optional[Mapping[str, str]] = None):
self.proxies = {} if not proxies else proxies
def __init__(self, server_address: str):
self.server_address = server_address
def wakeup(self, parent=None):
@ -50,37 +45,14 @@ class ControlClient:
"launch_time": agent_process.get_start_time(),
}
if self.proxies:
monkey["tunnel"] = self.proxies.get("https")
requests.post( # noqa: DUO123
f"https://{self.server_address}/api/agent",
data=json.dumps(monkey),
headers={"content-type": "application/json"},
verify=False,
proxies=self.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
def set_proxies(self, proxy_find):
"""
Note: The proxy schema changes between different versions of requests and urllib3,
which causes the machine to not open a tunnel back.
If we get "ValueError: check_hostname requires server_hostname" or
"Proxy URL had not schema, should start with http:// or https://" errors,
the proxy schema needs to be changed.
Keep this in mind when upgrading to newer python version or when urllib3 and
requests are updated there is possibility that the proxy schema is changed.
https://github.com/psf/requests/issues/5297
https://github.com/psf/requests/issues/5855
"""
proxy_address, proxy_port = proxy_find
logger.info("Found tunnel at %s:%s" % (proxy_address, proxy_port))
if is_windows_os():
self.proxies["https"] = f"http://{proxy_address}:{proxy_port}"
else:
self.proxies["https"] = f"{proxy_address}:{proxy_port}"
def send_telemetry(self, telem_category, json_data: str):
if not self.server_address:
logger.error(
@ -95,7 +67,6 @@ class ControlClient:
data=json.dumps(telemetry),
headers={"content-type": "application/json"},
verify=False,
proxies=self.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
except Exception as exc:
@ -111,41 +82,16 @@ class ControlClient:
data=json.dumps(telemetry),
headers={"content-type": "application/json"},
verify=False,
proxies=self.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
except Exception as exc:
logger.warning(f"Error connecting to control server {self.server_address}: {exc}")
def create_control_tunnel(self, keep_tunnel_open_time: int):
if not self.server_address:
return None
my_proxy = self.proxies.get("https", "").replace("https://", "")
if my_proxy:
proxy_class = TcpProxy
try:
target_addr, target_port = my_proxy.split(":", 1)
target_port = int(target_port)
except ValueError:
return None
else:
proxy_class = HTTPConnectProxy
target_addr, target_port = None, None
return tunnel.MonkeyTunnel(
proxy_class,
keep_tunnel_open_time=keep_tunnel_open_time,
target_addr=target_addr,
target_port=target_port,
)
def get_pba_file(self, filename):
try:
return requests.get( # noqa: DUO123
PBA_FILE_DOWNLOAD % (self.server_address, filename),
verify=False,
proxies=self.proxies,
timeout=LONG_REQUEST_TIMEOUT,
)
except requests.exceptions.RequestException:

View File

@ -1,7 +1,6 @@
import io
import threading
from functools import lru_cache
from typing import Mapping
import requests
@ -18,9 +17,8 @@ class CachingAgentBinaryRepository(IAgentBinaryRepository):
request is actually sent to the island for each requested binary.
"""
def __init__(self, island_url: str, proxies: Mapping[str, str]):
def __init__(self, island_url: str):
self._island_url = island_url
self._proxies = proxies
self._lock = threading.Lock()
def get_agent_binary(
@ -40,7 +38,6 @@ class CachingAgentBinaryRepository(IAgentBinaryRepository):
response = requests.get( # noqa: DUO123
f"{self._island_url}/api/agent-binaries/{os_name}",
verify=False,
proxies=self._proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)

View File

@ -1,7 +1,7 @@
import json
import logging
from pprint import pformat
from typing import MutableMapping, Optional, Sequence
from typing import Optional, Sequence
from uuid import UUID
import requests
@ -22,10 +22,9 @@ logger = logging.getLogger(__name__)
class ControlChannel(IControlChannel):
def __init__(self, server: str, agent_id: str, proxies: MutableMapping[str, str]):
def __init__(self, server: str, agent_id: str):
self._agent_id = agent_id
self._control_channel_server = server
self._proxies = proxies
def register_agent(self, parent: Optional[UUID] = None):
agent_registration_data = AgentRegistrationData(
@ -44,7 +43,6 @@ class ControlChannel(IControlChannel):
url,
json=agent_registration_data.dict(simplify=True),
verify=False,
proxies=self._proxies,
timeout=SHORT_REQUEST_TIMEOUT,
)
response.raise_for_status()
@ -68,7 +66,6 @@ class ControlChannel(IControlChannel):
response = requests.get( # noqa: DUO123
url,
verify=False,
proxies=self._proxies,
timeout=SHORT_REQUEST_TIMEOUT,
)
response.raise_for_status()
@ -89,7 +86,6 @@ class ControlChannel(IControlChannel):
response = requests.get( # noqa: DUO123
f"https://{self._control_channel_server}/api/agent-configuration",
verify=False,
proxies=self._proxies,
timeout=SHORT_REQUEST_TIMEOUT,
)
response.raise_for_status()
@ -116,7 +112,6 @@ class ControlChannel(IControlChannel):
response = requests.get( # noqa: DUO123
propagation_credentials_url,
verify=False,
proxies=self._proxies,
timeout=SHORT_REQUEST_TIMEOUT,
)
response.raise_for_status()

View File

@ -1,4 +1,4 @@
from typing import Optional
from typing import Any, Dict, Optional
from common import OperatingSystem
@ -7,10 +7,9 @@ class VictimHost(object):
def __init__(self, ip_addr: str, domain_name: str = ""):
self.ip_addr = ip_addr
self.domain_name = str(domain_name)
self.os = {}
self.services = {}
self.os: Dict[str, Any] = {}
self.services: Dict[str, Any] = {}
self.icmp = False
self.default_tunnel = None
self.default_server = None
def as_dict(self):

View File

@ -4,7 +4,6 @@ from typing import Optional, Tuple
from infection_monkey.model import VictimHost
from infection_monkey.network import NetworkAddress
from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.tunnel import MonkeyTunnel
logger = logging.getLogger(__name__)
@ -12,12 +11,10 @@ logger = logging.getLogger(__name__)
class VictimHostFactory:
def __init__(
self,
tunnel: Optional[MonkeyTunnel],
island_ip: Optional[str],
island_port: Optional[str],
on_island: bool,
):
self.tunnel = tunnel
self.island_ip = island_ip
self.island_port = island_port
self.on_island = on_island
@ -26,19 +23,15 @@ class VictimHostFactory:
domain = network_address.domain or ""
victim_host = VictimHost(network_address.ip, domain)
if self.tunnel:
victim_host.default_tunnel = self.tunnel.get_tunnel_for_ip(victim_host.ip_addr)
if self.island_ip:
ip, port = self._choose_island_address(victim_host.ip_addr)
victim_host.set_island_address(ip, port)
logger.debug(f"Default tunnel for {victim_host} set to {victim_host.default_tunnel}")
logger.debug(f"Default server for {victim_host} set to {victim_host.default_server}")
return victim_host
def _choose_island_address(self, victim_ip: str) -> Tuple[str, Optional[str]]:
def _choose_island_address(self, victim_ip: str) -> Tuple[Optional[str], Optional[str]]:
# Victims need to connect back to the interface they can reach
# On island, choose the right interface to pass to children monkeys
if self.on_island:

View File

@ -78,7 +78,6 @@ from infection_monkey.telemetry.messengers.legacy_telemetry_messenger_adapter im
LegacyTelemetryMessengerAdapter,
)
from infection_monkey.telemetry.state_telem import StateTelem
from infection_monkey.telemetry.tunnel_telem import TunnelTelem
from infection_monkey.utils.aws_environment_check import run_aws_environment_check
from infection_monkey.utils.environment import is_windows_os
from infection_monkey.utils.file_utils import mark_file_for_deletion_on_windows
@ -162,9 +161,7 @@ class InfectionMonkey:
run_aws_environment_check(self._telemetry_messenger)
should_stop = ControlChannel(
self._control_client.server_address, GUID, self._control_client.proxies
).should_agent_stop()
should_stop = ControlChannel(self._control_client.server_address, GUID).should_agent_stop()
if should_stop:
logger.info("The Monkey Island has instructed this agent to stop")
return
@ -180,9 +177,7 @@ class InfectionMonkey:
if firewall.is_enabled():
firewall.add_firewall_rule()
control_channel = ControlChannel(
self._control_client.server_address, GUID, self._control_client.proxies
)
control_channel = ControlChannel(self._control_client.server_address, GUID)
control_channel.register_agent(self._opts.parent)
config = control_channel.get_config()
@ -199,7 +194,6 @@ class InfectionMonkey:
self._relay.start()
StateTelem(is_done=False, version=get_version()).send()
TunnelTelem(self._control_client.proxies).send()
self._build_master()
@ -209,9 +203,7 @@ class InfectionMonkey:
local_network_interfaces = InfectionMonkey._get_local_network_interfaces()
# TODO control_channel and control_client have same responsibilities, merge them
control_channel = ControlChannel(
self._control_client.server_address, GUID, self._control_client.proxies
)
control_channel = ControlChannel(self._control_client.server_address, GUID)
propagation_credentials_repository = AggregatingPropagationCredentialsRepository(
control_channel
)
@ -283,7 +275,7 @@ class InfectionMonkey:
puppet.load_plugin("ssh", SSHFingerprinter(), PluginType.FINGERPRINTER)
agent_binary_repository = CachingAgentBinaryRepository(
f"https://{self._control_client.server_address}", self._control_client.proxies
f"https://{self._control_client.server_address}"
)
exploit_wrapper = ExploiterWrapper(
self._telemetry_messenger, event_queue, agent_binary_repository
@ -383,7 +375,7 @@ class InfectionMonkey:
on_island = self._running_on_island(local_network_interfaces)
logger.debug(f"This agent is running on the island: {on_island}")
return VictimHostFactory(None, self._cmd_island_ip, self._cmd_island_port, on_island)
return VictimHostFactory(self._cmd_island_ip, self._cmd_island_port, on_island)
def _running_on_island(self, local_network_interfaces: List[IPv4Interface]) -> bool:
server_ip, _ = address_to_ip_port(self._control_client.server_address)

View File

@ -1,18 +0,0 @@
from typing import Mapping
from common.common_consts.telem_categories import TelemCategoryEnum
from infection_monkey.telemetry.base_telem import BaseTelem
class TunnelTelem(BaseTelem):
def __init__(self, proxy: Mapping[str, str]):
"""
Default tunnel telemetry constructor
"""
super(TunnelTelem, self).__init__()
self.proxy = proxy.get("https")
telem_category = TelemCategoryEnum.TUNNEL
def get_data(self):
return {"proxy": self.proxy}

View File

@ -1,31 +0,0 @@
import time
from threading import Thread
g_last_served = None
PROXY_TIMEOUT = 2.5
class TransportProxyBase(Thread):
def __init__(self, local_port, dest_host=None, dest_port=None, local_host=""):
global g_last_served
self.local_host = local_host
self.local_port = local_port
self.dest_host = dest_host
self.dest_port = dest_port
self._stopped = False
super(TransportProxyBase, self).__init__()
self.daemon = True
def stop(self):
self._stopped = True
def update_last_serve_time():
global g_last_served
g_last_served = time.time()
def get_last_serve_time():
global g_last_served
return g_last_served

View File

@ -1,17 +1,9 @@
import http.server
import select
import socket
import threading
import urllib
from logging import getLogger
from urllib.parse import urlsplit
from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.transport.base import (
PROXY_TIMEOUT,
TransportProxyBase,
update_last_serve_time,
)
logger = getLogger(__name__)
@ -110,56 +102,6 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
)
class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler):
timeout = 30 # timeout with clients, set to None not to make persistent connection
def version_string(self):
return ""
def do_CONNECT(self):
logger.info("Received a connect request!")
# just provide a tunnel, transfer the data with no modification
req = self
req.path = "https://%s/" % req.path.replace(":443", "")
u = urlsplit(req.path)
address = (u.hostname, u.port or 443)
try:
conn = socket.create_connection(address)
except socket.error as e:
logger.debug(
"HTTPConnectProxyHandler: Got exception while trying to connect to %s: %s"
% (repr(address), e)
)
self.send_error(504) # 504 Gateway Timeout
return
self.send_response(200, "Connection Established")
self.send_header("Connection", "close")
self.end_headers()
conns = [self.connection, conn]
keep_connection = True
while keep_connection:
keep_connection = False
rlist, wlist, xlist = select.select(conns, [], conns, self.timeout)
if xlist:
break
for r in rlist:
other = conns[1] if r is conns[0] else conns[0]
data = r.recv(8192)
if data:
other.sendall(data)
keep_connection = True
update_last_serve_time()
conn.close()
def log_message(self, format_string, *args):
logger.debug(
"HTTPConnectProxyHandler: %s - [%s] %s"
% (self.address_string(), self.log_date_time_string(), format_string % args)
)
class LockedHTTPServer(threading.Thread):
"""
Same as HTTPServer used for file downloads just with locks to avoid racing conditions.
@ -226,11 +168,3 @@ class LockedHTTPServer(threading.Thread):
def stop(self, timeout=STOP_TIMEOUT):
self._stopped = True
self.join(timeout)
class HTTPConnectProxy(TransportProxyBase):
def run(self):
httpd = http.server.HTTPServer((self.local_host, self.local_port), HTTPConnectProxyHandler)
httpd.timeout = PROXY_TIMEOUT
while not self._stopped:
httpd.handle_request()

View File

@ -1,88 +0,0 @@
import select
import socket
from logging import getLogger
from threading import Thread
from infection_monkey.transport.base import (
PROXY_TIMEOUT,
TransportProxyBase,
update_last_serve_time,
)
READ_BUFFER_SIZE = 8192
SOCKET_READ_TIMEOUT = 10
logger = getLogger(__name__)
class SocketsPipe(Thread):
def __init__(self, source, dest, timeout=SOCKET_READ_TIMEOUT):
Thread.__init__(self)
self.source = source
self.dest = dest
self.timeout = timeout
self._keep_connection = True
super(SocketsPipe, self).__init__()
self.daemon = True
def run(self):
sockets = [self.source, self.dest]
while self._keep_connection:
self._keep_connection = False
rlist, wlist, xlist = select.select(sockets, [], sockets, self.timeout)
if xlist:
break
for r in rlist:
other = self.dest if r is self.source else self.source
try:
data = r.recv(READ_BUFFER_SIZE)
except Exception:
break
if data:
try:
other.sendall(data)
update_last_serve_time()
except Exception:
break
self._keep_connection = True
self.source.close()
self.dest.close()
class TcpProxy(TransportProxyBase):
def run(self):
pipes = []
l_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
l_socket.bind((self.local_host, self.local_port))
l_socket.settimeout(PROXY_TIMEOUT)
l_socket.listen(5)
while not self._stopped:
try:
source, address = l_socket.accept()
except socket.timeout:
continue
dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
dest.connect((self.dest_host, self.dest_port))
except socket.error:
source.close()
dest.close()
continue
pipe = SocketsPipe(source, dest)
pipes.append(pipe)
logger.debug(
"piping sockets %s:%s->%s:%s",
address[0],
address[1],
self.dest_host,
self.dest_port,
)
pipe.start()
l_socket.close()
for pipe in pipes:
pipe.join()

View File

@ -1,230 +0,0 @@
import logging
import socket
import struct
import time
from threading import Event, Thread
from common.utils import Timer
from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.info import get_free_tcp_port, local_ips
from infection_monkey.network.tools import check_tcp_port, get_interface_to_target
from infection_monkey.transport.base import get_last_serve_time
logger = logging.getLogger(__name__)
MCAST_GROUP = "224.1.1.1"
MCAST_PORT = 5007
BUFFER_READ = 1024
DEFAULT_TIMEOUT = 10
QUIT_TIMEOUT = 60 * 10 # 10 minutes
def _set_multicast_socket(timeout=DEFAULT_TIMEOUT, adapter=""):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.settimeout(timeout)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((adapter, MCAST_PORT))
sock.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
struct.pack("4sl", socket.inet_aton(MCAST_GROUP), socket.INADDR_ANY),
)
return sock
def _check_tunnel(address, port, existing_sock=None):
if not existing_sock:
sock = _set_multicast_socket()
else:
sock = existing_sock
logger.debug("Checking tunnel %s:%s", address, port)
is_open, _ = check_tcp_port(address, int(port))
if not is_open:
logger.debug("Could not connect to %s:%s", address, port)
if not existing_sock:
sock.close()
return False
try:
sock.sendto(b"+", (address, MCAST_PORT))
except Exception as exc:
logger.debug("Caught exception in tunnel registration: %s", exc)
if not existing_sock:
sock.close()
return True
def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT):
l_ips = local_ips()
if default:
if default.find(":") != -1:
address, port = default.split(":", 1)
if _check_tunnel(address, port):
return address, port
for adapter in l_ips:
for attempt in range(0, attempts):
try:
logger.info("Trying to find using adapter %s", adapter)
sock = _set_multicast_socket(timeout, adapter)
sock.sendto(b"?", (MCAST_GROUP, MCAST_PORT))
tunnels = []
while True:
try:
answer, address = sock.recvfrom(BUFFER_READ)
if answer not in [b"?", b"+", b"-"]:
tunnels.append(answer)
except socket.timeout:
break
for tunnel in tunnels:
if tunnel.find(":") != -1:
address, port = tunnel.split(":", 1)
if address in l_ips:
continue
if _check_tunnel(address, port, sock):
sock.close()
return address, port
except Exception as exc:
logger.debug("Caught exception in tunnel lookup: %s", exc)
continue
return None
def quit_tunnel(address, timeout=DEFAULT_TIMEOUT):
try:
sock = _set_multicast_socket(timeout)
sock.sendto(b"-", (address, MCAST_PORT))
sock.close()
logger.debug("Success quitting tunnel")
except Exception as exc:
logger.debug("Exception quitting tunnel: %s", exc)
return
class MonkeyTunnel(Thread):
def __init__(
self,
proxy_class,
keep_tunnel_open_time,
target_addr=None,
target_port=None,
timeout=DEFAULT_TIMEOUT,
):
self._target_addr = target_addr
self._target_port = target_port
self._proxy_class = proxy_class
self._keep_tunnel_open_time = keep_tunnel_open_time
self._broad_sock = None
self._timeout = timeout
self._stopped = Event()
self._clients = []
self.local_port = None
super(MonkeyTunnel, self).__init__(name="MonkeyTunnelThread")
self.daemon = True
self.l_ips = None
self._wait_for_exploited_machines = Event()
def run(self):
self._broad_sock = _set_multicast_socket(self._timeout)
self.l_ips = local_ips()
self.local_port = get_free_tcp_port()
if not self.local_port:
return
if not firewall.listen_allowed(localport=self.local_port):
logger.info("Machine firewalled, listen not allowed, not running tunnel.")
return
proxy = self._proxy_class(
local_port=self.local_port, dest_host=self._target_addr, dest_port=self._target_port
)
logger.info(
"Running tunnel using proxy class: %s, listening on port %s, routing to: %s:%s",
proxy.__class__.__name__,
self.local_port,
self._target_addr,
self._target_port,
)
proxy.start()
while not self._stopped.is_set():
try:
search, address = self._broad_sock.recvfrom(BUFFER_READ)
if b"?" == search:
ip_match = get_interface_to_target(address[0])
if ip_match:
answer = "%s:%d" % (ip_match, self.local_port)
logger.debug(
"Got tunnel request from %s, answering with %s", address[0], answer
)
self._broad_sock.sendto(answer.encode(), (address[0], MCAST_PORT))
elif b"+" == search:
if not address[0] in self._clients:
logger.debug("Tunnel control: Added %s to watchlist", address[0])
self._clients.append(address[0])
elif b"-" == search:
logger.debug("Tunnel control: Removed %s from watchlist", address[0])
self._clients = [client for client in self._clients if client != address[0]]
except socket.timeout:
continue
logger.info("Stopping tunnel, waiting for clients: %s" % repr(self._clients))
# wait till all of the tunnel clients has been disconnected, or no one used the tunnel in
# QUIT_TIMEOUT seconds
timer = Timer()
timer.set(self._calculate_timeout())
while self._clients and not timer.is_expired():
try:
search, address = self._broad_sock.recvfrom(BUFFER_READ)
if b"-" == search:
logger.debug("Tunnel control: Removed %s from watchlist", address[0])
self._clients = [client for client in self._clients if client != address[0]]
except socket.timeout:
continue
timer.set(self._calculate_timeout())
logger.info("Closing tunnel")
self._broad_sock.close()
proxy.stop()
proxy.join()
def _calculate_timeout(self) -> float:
try:
return QUIT_TIMEOUT - (time.time() - get_last_serve_time())
except TypeError: # get_last_serve_time() may return None
return 0.0
def get_tunnel_for_ip(self, ip: str):
if not self.local_port:
return
ip_match = get_interface_to_target(ip)
return "%s:%d" % (ip_match, self.local_port)
def set_wait_for_exploited_machines(self):
self._wait_for_exploited_machines.set()
def stop(self):
self._wait_for_exploited_machine_connection()
self._stopped.set()
def _wait_for_exploited_machine_connection(self):
if self._wait_for_exploited_machines.is_set():
logger.info(
f"Waiting {self._keep_tunnel_open_time} seconds for exploited machines to connect "
"to the tunnel."
)
time.sleep(self._keep_tunnel_open_time)

View File

@ -64,16 +64,6 @@ class TelemetryFeed(AbstractResource):
def get_telem_brief_parser_by_category(telem_category):
return TELEM_PROCESS_DICT[telem_category]
@staticmethod
def get_tunnel_telem_brief(telem):
tunnel = telem["data"]["proxy"]
if tunnel is None:
return "No tunnel is used."
else:
tunnel_host_ip = tunnel.split(":")[-2].replace("//", "")
tunnel_host = NodeService.get_monkey_by_ip(tunnel_host_ip)["hostname"]
return "Tunnel set up to machine: %s." % tunnel_host
@staticmethod
def get_state_telem_brief(telem):
if telem["data"]["done"]:
@ -132,7 +122,6 @@ TELEM_PROCESS_DICT = {
TelemCategoryEnum.SCAN: TelemetryFeed.get_scan_telem_brief,
TelemCategoryEnum.STATE: TelemetryFeed.get_state_telem_brief,
TelemCategoryEnum.TRACE: TelemetryFeed.get_trace_telem_brief,
TelemCategoryEnum.TUNNEL: TelemetryFeed.get_tunnel_telem_brief,
}

View File

@ -8,7 +8,6 @@ from monkey_island.cc.services.telemetry.processing.exploit import process_explo
from monkey_island.cc.services.telemetry.processing.post_breach import process_post_breach_telemetry
from monkey_island.cc.services.telemetry.processing.scan import process_scan_telemetry
from monkey_island.cc.services.telemetry.processing.state import process_state_telemetry
from monkey_island.cc.services.telemetry.processing.tunnel import process_tunnel_telemetry
logger = logging.getLogger(__name__)
@ -22,7 +21,6 @@ TELEMETRY_CATEGORY_TO_PROCESSING_FUNC = {
TelemCategoryEnum.SCAN: process_scan_telemetry,
TelemCategoryEnum.STATE: process_state_telemetry,
TelemCategoryEnum.TRACE: lambda *args, **kwargs: None,
TelemCategoryEnum.TUNNEL: process_tunnel_telemetry,
}
# Don't save credential telemetries in telemetries collection.

View File

@ -1,15 +0,0 @@
from monkey_island.cc.services.node import NodeService
from monkey_island.cc.services.telemetry.processing.utils import get_tunnel_host_ip_from_proxy_field
from monkey_island.cc.services.telemetry.zero_trust_checks.tunneling import (
check_tunneling_violation,
)
def process_tunnel_telemetry(telemetry_json, _):
check_tunneling_violation(telemetry_json)
monkey_id = NodeService.get_monkey_by_guid(telemetry_json["monkey_guid"])["_id"]
if telemetry_json["data"]["proxy"] is not None:
tunnel_host_ip = get_tunnel_host_ip_from_proxy_field(telemetry_json)
NodeService.set_monkey_tunnel(monkey_id, tunnel_host_ip)
else:
NodeService.unset_all_monkey_tunnels(monkey_id)

View File

@ -14,8 +14,3 @@ def get_edge_by_scan_or_exploit_telemetry(telemetry_json):
dst_label = NodeService.get_label_for_endpoint(dst_node["_id"])
return EdgeService.get_or_create_edge(src_monkey["_id"], dst_node["_id"], src_label, dst_label)
def get_tunnel_host_ip_from_proxy_field(telemetry_json):
tunnel_host_ip = telemetry_json["data"]["proxy"].split(":")[-2].replace("//", "")
return tunnel_host_ip

View File

@ -1,32 +0,0 @@
import common.common_consts.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models import Monkey
from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.services.telemetry.processing.utils import get_tunnel_host_ip_from_proxy_field
from monkey_island.cc.services.zero_trust.monkey_findings.monkey_zt_finding_service import (
MonkeyZTFindingService,
)
def check_tunneling_violation(tunnel_telemetry_json):
if tunnel_telemetry_json["data"]["proxy"] is not None:
# Monkey is tunneling, create findings
tunnel_host_ip = get_tunnel_host_ip_from_proxy_field(tunnel_telemetry_json)
current_monkey = Monkey.get_single_monkey_by_guid(tunnel_telemetry_json["monkey_guid"])
tunneling_events = [
Event.create_event(
title="Tunneling event",
message="Monkey on {hostname} tunneled traffic through {proxy}.".format(
hostname=current_monkey.hostname, proxy=tunnel_host_ip
),
event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK,
timestamp=tunnel_telemetry_json["timestamp"],
)
]
MonkeyZTFindingService.create_or_add_to_existing(
test=zero_trust_consts.TEST_TUNNELING,
status=zero_trust_consts.STATUS_FAILED,
events=tunneling_events,
)
MonkeyZTFindingService.add_malicious_activity_to_timeline(tunneling_events)

View File

@ -1,18 +1,9 @@
from unittest.mock import MagicMock
import pytest
from infection_monkey.model import VictimHostFactory
from infection_monkey.network import NetworkAddress
@pytest.fixture
def mock_tunnel():
tunnel = MagicMock()
tunnel.get_tunnel_for_ip = lambda _: "1.2.3.4:1234"
return tunnel
@pytest.fixture(autouse=True)
def mock_get_interface_to_target(monkeypatch):
monkeypatch.setattr(
@ -21,37 +12,18 @@ def mock_get_interface_to_target(monkeypatch):
def test_factory_no_tunnel():
factory = VictimHostFactory(
tunnel=None, island_ip="192.168.56.1", island_port="5000", on_island=False
)
factory = VictimHostFactory(island_ip="192.168.56.1", island_port="5000", on_island=False)
network_address = NetworkAddress("192.168.56.2", None)
victim = factory.build_victim_host(network_address)
assert victim.default_server == "192.168.56.1:5000"
assert victim.ip_addr == "192.168.56.2"
assert victim.default_tunnel is None
assert victim.domain_name == ""
def test_factory_with_tunnel(mock_tunnel):
factory = VictimHostFactory(
tunnel=mock_tunnel, island_ip="192.168.56.1", island_port="5000", on_island=False
)
network_address = NetworkAddress("192.168.56.2", None)
victim = factory.build_victim_host(network_address)
assert victim.default_server == "192.168.56.1:5000"
assert victim.ip_addr == "192.168.56.2"
assert victim.default_tunnel == "1.2.3.4:1234"
assert victim.domain_name == ""
def test_factory_on_island(mock_tunnel):
factory = VictimHostFactory(
tunnel=mock_tunnel, island_ip="192.168.56.1", island_port="99", on_island=True
)
def test_factory_on_island():
factory = VictimHostFactory(island_ip="192.168.56.1", island_port="99", on_island=True)
network_address = NetworkAddress("192.168.56.2", "www.bogus.monkey")
victim = factory.build_victim_host(network_address)
@ -59,14 +31,11 @@ def test_factory_on_island(mock_tunnel):
assert victim.default_server == "1.1.1.1:99"
assert victim.domain_name == "www.bogus.monkey"
assert victim.ip_addr == "192.168.56.2"
assert victim.default_tunnel == "1.2.3.4:1234"
@pytest.mark.parametrize("default_port", ["", None])
def test_factory_no_port(mock_tunnel, default_port):
factory = VictimHostFactory(
tunnel=mock_tunnel, island_ip="192.168.56.1", island_port=default_port, on_island=True
)
def test_factory_no_port(default_port):
factory = VictimHostFactory(island_ip="192.168.56.1", island_port=default_port, on_island=True)
network_address = NetworkAddress("192.168.56.2", "www.bogus.monkey")
victim = factory.build_victim_host(network_address)
@ -74,8 +43,8 @@ def test_factory_no_port(mock_tunnel, default_port):
assert victim.default_server == "1.1.1.1"
def test_factory_no_default_server(mock_tunnel):
factory = VictimHostFactory(tunnel=mock_tunnel, island_ip=None, island_port="", on_island=True)
def test_factory_no_default_server():
factory = VictimHostFactory(island_ip=None, island_port="", on_island=True)
network_address = NetworkAddress("192.168.56.2", "www.bogus.monkey")
victim = factory.build_victim_host(network_address)

View File

@ -16,7 +16,6 @@ HOST_AS_DICT = {
"os": {},
"services": {},
"icmp": False,
"default_tunnel": None,
"default_server": None,
}
EXPLOITER_NAME = "SSHExploiter"

View File

@ -14,7 +14,6 @@ HOST_AS_DICT = {
"os": {},
"services": {},
"icmp": False,
"default_tunnel": None,
"default_server": None,
}
HOST_SERVICES = {}

View File

@ -1,19 +0,0 @@
import json
import pytest
from infection_monkey.telemetry.tunnel_telem import TunnelTelem
@pytest.fixture
def tunnel_telem_test_instance():
return TunnelTelem({})
def test_tunnel_telem_send(tunnel_telem_test_instance, spy_send_telemetry):
tunnel_telem_test_instance.send()
expected_data = {"proxy": None}
expected_data = json.dumps(expected_data, cls=tunnel_telem_test_instance.json_encoder)
assert spy_send_telemetry.data == expected_data
assert spy_send_telemetry.telem_category == "tunnel"

View File

@ -1,16 +0,0 @@
import pytest
from monkey.infection_monkey.control import ControlClient
@pytest.mark.parametrize(
"is_windows_os,expected_proxy_string",
[(True, "http://8.8.8.8:45455"), (False, "8.8.8.8:45455")],
)
def test_control_set_proxies(monkeypatch, is_windows_os, expected_proxy_string):
monkeypatch.setattr("monkey.infection_monkey.control.is_windows_os", lambda: is_windows_os)
control_client = ControlClient("8.8.8.8:5000")
control_client.set_proxies(("8.8.8.8", "45455"))
assert control_client.proxies["https"] == expected_proxy_string

View File

@ -18,7 +18,6 @@ SCAN_DATA_MOCK = [
},
},
"monkey_exe": None,
"default_tunnel": None,
"default_server": None,
},
}

View File

@ -299,9 +299,6 @@ event
deserialize
serialized_event
# TODO: Remove when removing Tunnel code
create_control_tunnel
set_wait_for_exploited_machines
# pydantic base models
underscore_attrs_are_private