forked from p15670423/monkey
commit
c79bc8f47b
|
@ -72,7 +72,7 @@ script:
|
||||||
## Display the linter issues
|
## Display the linter issues
|
||||||
- cat flake8_warnings.txt
|
- cat flake8_warnings.txt
|
||||||
## Make sure that we haven't increased the amount of warnings.
|
## Make sure that we haven't increased the amount of warnings.
|
||||||
- PYTHON_WARNINGS_AMOUNT_UPPER_LIMIT=120
|
- PYTHON_WARNINGS_AMOUNT_UPPER_LIMIT=90
|
||||||
- if [ $(tail -n 1 flake8_warnings.txt) -gt $PYTHON_WARNINGS_AMOUNT_UPPER_LIMIT ]; then echo "Too many python linter warnings! Failing this build. Lower the amount of linter errors in this and try again. " && exit 1; fi
|
- if [ $(tail -n 1 flake8_warnings.txt) -gt $PYTHON_WARNINGS_AMOUNT_UPPER_LIMIT ]; then echo "Too many python linter warnings! Failing this build. Lower the amount of linter errors in this and try again. " && exit 1; fi
|
||||||
|
|
||||||
## Check import order
|
## Check import order
|
||||||
|
@ -89,7 +89,7 @@ script:
|
||||||
- cd monkey_island/cc/ui
|
- cd monkey_island/cc/ui
|
||||||
- npm ci # See https://docs.npmjs.com/cli/ci.html
|
- npm ci # See https://docs.npmjs.com/cli/ci.html
|
||||||
- eslint ./src --quiet # Test for errors
|
- eslint ./src --quiet # Test for errors
|
||||||
- JS_WARNINGS_AMOUNT_UPPER_LIMIT=28
|
- JS_WARNINGS_AMOUNT_UPPER_LIMIT=4
|
||||||
- eslint ./src --max-warnings $JS_WARNINGS_AMOUNT_UPPER_LIMIT # Test for max warnings
|
- eslint ./src --max-warnings $JS_WARNINGS_AMOUNT_UPPER_LIMIT # Test for max warnings
|
||||||
|
|
||||||
# Build documentation
|
# Build documentation
|
||||||
|
|
|
@ -91,16 +91,14 @@ class MonkeyIslandRequests(object):
|
||||||
return requests.patch(self.addr + url, # noqa: DUO123
|
return requests.patch(self.addr + url, # noqa: DUO123
|
||||||
data=data,
|
data=data,
|
||||||
headers=self.get_jwt_header(),
|
headers=self.get_jwt_header(),
|
||||||
verify=False
|
verify=False)
|
||||||
)
|
|
||||||
|
|
||||||
@_Decorators.refresh_jwt_token
|
@_Decorators.refresh_jwt_token
|
||||||
def delete(self, url):
|
def delete(self, url):
|
||||||
return requests.delete( # noqa: DOU123
|
return requests.delete( # noqa: DOU123
|
||||||
self.addr + url,
|
self.addr + url,
|
||||||
headers=self.get_jwt_header(),
|
headers=self.get_jwt_header(),
|
||||||
verify=False
|
verify=False)
|
||||||
)
|
|
||||||
|
|
||||||
@_Decorators.refresh_jwt_token
|
@_Decorators.refresh_jwt_token
|
||||||
def get_jwt_header(self):
|
def get_jwt_header(self):
|
||||||
|
|
|
@ -28,7 +28,7 @@ class NetworkRange(object, metaclass=ABCMeta):
|
||||||
"""
|
"""
|
||||||
base_range = self.get_range()
|
base_range = self.get_range()
|
||||||
if self._shuffle:
|
if self._shuffle:
|
||||||
random.shuffle(base_range)
|
random.shuffle(base_range) # noqa: DUO102
|
||||||
|
|
||||||
for x in base_range:
|
for x in base_range:
|
||||||
yield self._number_to_ip(x)
|
yield self._number_to_ip(x)
|
||||||
|
|
|
@ -7,8 +7,9 @@ import sys
|
||||||
import traceback
|
import traceback
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
|
# dummy import for pyinstaller
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
import infection_monkey.post_breach # dummy import for pyinstaller
|
import infection_monkey.post_breach # noqa: F401
|
||||||
from common.version import get_version
|
from common.version import get_version
|
||||||
from infection_monkey.config import EXTERNAL_CONFIG_FILE, WormConfiguration
|
from infection_monkey.config import EXTERNAL_CONFIG_FILE, WormConfiguration
|
||||||
from infection_monkey.dropper import MonkeyDrops
|
from infection_monkey.dropper import MonkeyDrops
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from infection_monkey.model.host import VictimHost
|
from infection_monkey.model.host import VictimHost # noqa: F401
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ class InfectionMonkey(object):
|
||||||
if self._opts.depth is not None:
|
if self._opts.depth is not None:
|
||||||
WormConfiguration._depth_from_commandline = True
|
WormConfiguration._depth_from_commandline = True
|
||||||
WormConfiguration.depth = self._opts.depth
|
WormConfiguration.depth = self._opts.depth
|
||||||
LOG.debug(f"Setting propagation depth from command line")
|
LOG.debug("Setting propagation depth from command line")
|
||||||
LOG.debug(f"Set propagation depth to {WormConfiguration.depth}")
|
LOG.debug(f"Set propagation depth to {WormConfiguration.depth}")
|
||||||
|
|
||||||
self._keep_running = True
|
self._keep_running = True
|
||||||
|
|
|
@ -12,7 +12,7 @@ __author__ = 'itamar'
|
||||||
|
|
||||||
PING_COUNT_FLAG = "-n" if "win32" == sys.platform else "-c"
|
PING_COUNT_FLAG = "-n" if "win32" == sys.platform else "-c"
|
||||||
PING_TIMEOUT_FLAG = "-w" if "win32" == sys.platform else "-W"
|
PING_TIMEOUT_FLAG = "-w" if "win32" == sys.platform else "-W"
|
||||||
TTL_REGEX_STR = '(?<=TTL\=)[0-9]+'
|
TTL_REGEX_STR = r'(?<=TTL\=)[0-9]+'
|
||||||
LINUX_TTL = 64
|
LINUX_TTL = 64
|
||||||
WINDOWS_TTL = 128
|
WINDOWS_TTL = 128
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from infection_monkey.network.tools import check_tcp_port
|
||||||
|
|
||||||
SSH_PORT = 22
|
SSH_PORT = 22
|
||||||
SSH_SERVICE_DEFAULT = 'tcp-22'
|
SSH_SERVICE_DEFAULT = 'tcp-22'
|
||||||
SSH_REGEX = 'SSH-\d\.\d-OpenSSH'
|
SSH_REGEX = r'SSH-\d\.\d-OpenSSH'
|
||||||
TIMEOUT = 10
|
TIMEOUT = 10
|
||||||
BANNER_READ = 1024
|
BANNER_READ = 1024
|
||||||
LINUX_DIST_SSH = ['ubuntu', 'debian']
|
LINUX_DIST_SSH = ['ubuntu', 'debian']
|
||||||
|
|
|
@ -44,7 +44,7 @@ class CommunicateAsNewUser(PBA):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_random_new_user_name():
|
def get_random_new_user_name():
|
||||||
return USERNAME_PREFIX + ''.join(random.choice(string.ascii_lowercase) for _ in range(5))
|
return USERNAME_PREFIX + ''.join(random.choice(string.ascii_lowercase) for _ in range(5)) # noqa: DUO102
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_commandline_for_http_request(url, is_windows=is_windows_os()):
|
def get_commandline_for_http_request(url, is_windows=is_windows_os()):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
SCHEDULED_TASK_NAME = 'monkey-spawn-cmd'
|
SCHEDULED_TASK_NAME = 'monkey-spawn-cmd'
|
||||||
SCHEDULED_TASK_COMMAND = 'C:\windows\system32\cmd.exe'
|
SCHEDULED_TASK_COMMAND = r'C:\windows\system32\cmd.exe'
|
||||||
|
|
||||||
# Commands from: https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1053.005/T1053.005.md
|
# Commands from: https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1053.005/T1053.005.md
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,10 @@ from infection_monkey.system_info.windows_cred_collector.mimikatz_cred_collector
|
||||||
MimikatzCredentialCollector
|
MimikatzCredentialCollector
|
||||||
|
|
||||||
sys.coinit_flags = 0 # needed for proper destruction of the wmi python module
|
sys.coinit_flags = 0 # needed for proper destruction of the wmi python module
|
||||||
# noinspection PyPep8
|
import infection_monkey.config # noqa: E402
|
||||||
import infection_monkey.config
|
from common.utils.wmi_utils import WMIUtils # noqa: E402
|
||||||
# noinspection PyPep8
|
from infection_monkey.system_info import InfoCollector # noqa: E402
|
||||||
from common.utils.wmi_utils import WMIUtils
|
from infection_monkey.system_info.wmi_consts import WMI_CLASSES # noqa: E402
|
||||||
# noinspection PyPep8
|
|
||||||
from infection_monkey.system_info import InfoCollector
|
|
||||||
# noinspection PyPep8
|
|
||||||
from infection_monkey.system_info.wmi_consts import WMI_CLASSES
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
LOG.info('started windows info collector')
|
LOG.info('started windows info collector')
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
from infection_monkey.transport.http import HTTPServer, LockedHTTPServer
|
from infection_monkey.transport.http import HTTPServer # noqa: F401
|
||||||
|
from infection_monkey.transport.http import LockedHTTPServer # noqa: F401
|
||||||
|
|
|
@ -65,7 +65,7 @@ class TcpProxy(TransportProxyBase):
|
||||||
dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
try:
|
try:
|
||||||
dest.connect((self.dest_host, self.dest_port))
|
dest.connect((self.dest_host, self.dest_port))
|
||||||
except socket.error as ex:
|
except socket.error:
|
||||||
source.close()
|
source.close()
|
||||||
dest.close()
|
dest.close()
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -5,8 +5,8 @@ from infection_monkey.utils.linux.hidden_files import (
|
||||||
get_linux_commands_to_delete, get_linux_commands_to_hide_files,
|
get_linux_commands_to_delete, get_linux_commands_to_hide_files,
|
||||||
get_linux_commands_to_hide_folders)
|
get_linux_commands_to_hide_folders)
|
||||||
from infection_monkey.utils.windows.hidden_files import (
|
from infection_monkey.utils.windows.hidden_files import (
|
||||||
get_winAPI_to_hide_files, get_windows_commands_to_delete,
|
get_windows_commands_to_delete, get_windows_commands_to_hide_files,
|
||||||
get_windows_commands_to_hide_files, get_windows_commands_to_hide_folders)
|
get_windows_commands_to_hide_folders)
|
||||||
|
|
||||||
|
|
||||||
def get_commands_to_hide_files():
|
def get_commands_to_hide_files():
|
||||||
|
|
|
@ -51,13 +51,13 @@ def get_winAPI_to_hide_files():
|
||||||
fileCreation = win32file.CREATE_ALWAYS # overwrite existing file
|
fileCreation = win32file.CREATE_ALWAYS # overwrite existing file
|
||||||
fileFlags = win32file.FILE_ATTRIBUTE_HIDDEN # make hidden
|
fileFlags = win32file.FILE_ATTRIBUTE_HIDDEN # make hidden
|
||||||
|
|
||||||
hiddenFile = win32file.CreateFile(HIDDEN_FILE_WINAPI,
|
win32file.CreateFile(HIDDEN_FILE_WINAPI,
|
||||||
fileAccess,
|
fileAccess,
|
||||||
0, # sharing mode: 0 => can't be shared
|
0, # sharing mode: 0 => can't be shared
|
||||||
None, # security attributes
|
None, # security attributes
|
||||||
fileCreation,
|
fileCreation,
|
||||||
fileFlags,
|
fileFlags,
|
||||||
0) # template file
|
0) # template file
|
||||||
|
|
||||||
return "Succesfully created hidden file: {}".format(HIDDEN_FILE_WINAPI), True
|
return "Succesfully created hidden file: {}".format(HIDDEN_FILE_WINAPI), True
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from Crypto import Random
|
# PyCrypto is deprecated, but we use pycryptodome, which uses the exact same imports but it maintained
|
||||||
from Crypto.Cipher import AES
|
from Crypto import Random # noqa: DOU133
|
||||||
|
from Crypto.Cipher import AES # noqa: DOU133
|
||||||
|
|
||||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from common.cloud.aws.aws_instance import AwsInstance
|
from common.cloud.aws.aws_instance import AwsInstance
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.environment import Environment
|
||||||
from monkey_island.cc.resources.auth.auth_user import User
|
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
env = None
|
|
||||||
|
|
||||||
import monkey_island.cc.resources.auth.user_store as user_store
|
import monkey_island.cc.resources.auth.user_store as user_store
|
||||||
from monkey_island.cc.environment import (EnvironmentConfig, aws, password,
|
from monkey_island.cc.environment import (EnvironmentConfig, aws, password,
|
||||||
standard, testing)
|
standard, testing)
|
||||||
|
@ -22,6 +20,8 @@ ENV_DICT = {
|
||||||
TESTING: testing.TestingEnvironment
|
TESTING: testing.TestingEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env = None
|
||||||
|
|
||||||
|
|
||||||
def set_env(env_type: str, env_config: EnvironmentConfig):
|
def set_env(env_type: str, env_config: EnvironmentConfig):
|
||||||
global env
|
global env
|
||||||
|
|
|
@ -112,4 +112,3 @@ class TestEnvironment(TestCase):
|
||||||
self.assertTrue(method())
|
self.assertTrue(method())
|
||||||
else:
|
else:
|
||||||
self.assertFalse(method())
|
self.assertFalse(method())
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ class TestEnvironmentConfig(TestCase):
|
||||||
|
|
||||||
def test_get_server_config_file_path(self):
|
def test_get_server_config_file_path(self):
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
server_file_path = MONKEY_ISLAND_ABS_PATH + "\cc\server_config.json"
|
server_file_path = MONKEY_ISLAND_ABS_PATH + r"\cc\server_config.json"
|
||||||
else:
|
else:
|
||||||
server_file_path = MONKEY_ISLAND_ABS_PATH + "/cc/server_config.json"
|
server_file_path = MONKEY_ISLAND_ABS_PATH + "/cc/server_config.json"
|
||||||
self.assertEqual(EnvironmentConfig.get_config_file_path(), server_file_path)
|
self.assertEqual(EnvironmentConfig.get_config_file_path(), server_file_path)
|
||||||
|
|
|
@ -1,35 +1,38 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
MINIMUM_MONGO_DB_VERSION_REQUIRED = "4.2.0"
|
# Add the monkey_island directory to the path, to make sure imports that don't start with "monkey_island." work.
|
||||||
|
MONKEY_ISLAND_DIR_BASE_PATH = str(Path(__file__).parent.parent)
|
||||||
|
if str(MONKEY_ISLAND_DIR_BASE_PATH) not in sys.path:
|
||||||
|
sys.path.insert(0, MONKEY_ISLAND_DIR_BASE_PATH)
|
||||||
|
|
||||||
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH # noqa: E402
|
||||||
|
from monkey_island.cc.island_logger import json_setup_logging # noqa: E402
|
||||||
if BASE_PATH not in sys.path:
|
|
||||||
sys.path.insert(0, BASE_PATH)
|
|
||||||
|
|
||||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
|
||||||
from monkey_island.cc.island_logger import json_setup_logging
|
|
||||||
|
|
||||||
# This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top.
|
# 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'),
|
json_setup_logging(default_path=Path(MONKEY_ISLAND_ABS_PATH, 'cc', 'island_logger_default_config.json'),
|
||||||
default_level=logging.DEBUG)
|
default_level=logging.DEBUG)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
import monkey_island.cc.environment.environment_singleton as env_singleton # noqa: E402
|
||||||
from common.version import get_version
|
from common.version import get_version # noqa: E402
|
||||||
from monkey_island.cc.app import init_app
|
from monkey_island.cc.app import init_app # noqa: E402
|
||||||
from monkey_island.cc.bootloader_server import BootloaderHttpServer
|
from monkey_island.cc.bootloader_server import \
|
||||||
from monkey_island.cc.database import get_db_version, is_db_server_up
|
BootloaderHttpServer # noqa: E402
|
||||||
from monkey_island.cc.network_utils import local_ip_addresses
|
from monkey_island.cc.database import get_db_version # noqa: E402
|
||||||
from monkey_island.cc.resources.monkey_download import MonkeyDownload
|
from monkey_island.cc.database import is_db_server_up # noqa: E402
|
||||||
|
from monkey_island.cc.network_utils import local_ip_addresses # noqa: E402
|
||||||
|
from monkey_island.cc.resources.monkey_download import \
|
||||||
|
MonkeyDownload # noqa: E402
|
||||||
from monkey_island.cc.services.reporting.exporter_init import \
|
from monkey_island.cc.services.reporting.exporter_init import \
|
||||||
populate_exporter_list
|
populate_exporter_list # noqa: E402
|
||||||
from monkey_island.cc.setup import setup
|
from monkey_island.cc.setup import setup # noqa: E402
|
||||||
|
|
||||||
|
MINIMUM_MONGO_DB_VERSION_REQUIRED = "4.2.0"
|
||||||
|
|
||||||
|
|
||||||
def main(should_setup_only=False):
|
def main(should_setup_only=False):
|
||||||
|
@ -54,8 +57,8 @@ def start_island_server(should_setup_only):
|
||||||
populate_exporter_list()
|
populate_exporter_list()
|
||||||
app = init_app(mongo_url)
|
app = init_app(mongo_url)
|
||||||
|
|
||||||
crt_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.crt')
|
crt_path = str(Path(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.crt'))
|
||||||
key_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.key')
|
key_path = str(Path(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.key'))
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ class Monkey(Document):
|
||||||
try:
|
try:
|
||||||
_ = Monkey.get_single_monkey_by_id(object_id)
|
_ = Monkey.get_single_monkey_by_id(object_id)
|
||||||
return True
|
return True
|
||||||
except:
|
except: # noqa: E722
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -77,7 +77,7 @@ class TestMonkey(IslandTestCase):
|
||||||
self.assertIsNotNone(Monkey.get_single_monkey_by_id(a_monkey.id))
|
self.assertIsNotNone(Monkey.get_single_monkey_by_id(a_monkey.id))
|
||||||
|
|
||||||
# Raise on non-existent monkey
|
# Raise on non-existent monkey
|
||||||
with pytest.raises(MonkeyNotFoundError) as e_info:
|
with pytest.raises(MonkeyNotFoundError) as _:
|
||||||
_ = Monkey.get_single_monkey_by_id("abcdefabcdefabcdefabcdef")
|
_ = Monkey.get_single_monkey_by_id("abcdefabcdefabcdefabcdef")
|
||||||
|
|
||||||
def test_get_os(self):
|
def test_get_os(self):
|
||||||
|
|
|
@ -15,5 +15,5 @@ class IslandLog(flask_restful.Resource):
|
||||||
def get(self):
|
def get(self):
|
||||||
try:
|
try:
|
||||||
return IslandLogService.get_log_file()
|
return IslandLogService.get_log_file()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.error('Monkey Island logs failed to download', exc_info=True)
|
logger.error('Monkey Island logs failed to download', exc_info=True)
|
||||||
|
|
|
@ -217,7 +217,8 @@ class ConfigService:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_server_ips_in_config(config):
|
def set_server_ips_in_config(config):
|
||||||
ips = local_ip_addresses()
|
ips = local_ip_addresses()
|
||||||
config["internal"]["island_server"]["command_servers"] = ["%s:%d" % (ip, env_singleton.env.get_island_port()) for ip in ips]
|
config["internal"]["island_server"]["command_servers"] = \
|
||||||
|
["%s:%d" % (ip, env_singleton.env.get_islaned_port()) for ip in ips]
|
||||||
config["internal"]["island_server"]["current_server"] = "%s:%d" % (ips[0], env_singleton.env.get_island_port())
|
config["internal"]["island_server"]["current_server"] = "%s:%d" % (ips[0], env_singleton.env.get_island_port())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
|
||||||
from monkey_island.cc.models.edge import Edge
|
|
||||||
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
||||||
from monkey_island.cc.services.edge.edge import RIGHT_ARROW, EdgeService
|
from monkey_island.cc.services.edge.edge import RIGHT_ARROW, EdgeService
|
||||||
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
|
||||||
from monkey_island.cc.models import Monkey
|
from monkey_island.cc.models import Monkey
|
||||||
from monkey_island.cc.models.edge import Edge
|
|
||||||
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
||||||
from monkey_island.cc.services.edge.edge import EdgeService
|
from monkey_island.cc.services.edge.edge import EdgeService
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
|
|
|
@ -3,13 +3,11 @@ from datetime import datetime, timedelta
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from mongoengine import DoesNotExist
|
|
||||||
|
|
||||||
import monkey_island.cc.services.log
|
import monkey_island.cc.services.log
|
||||||
from monkey_island.cc import models
|
from monkey_island.cc import models
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.models import Monkey
|
from monkey_island.cc.models import Monkey
|
||||||
from monkey_island.cc.models.edge import Edge
|
|
||||||
from monkey_island.cc.network_utils import is_local_ips, local_ip_addresses
|
from monkey_island.cc.network_utils import is_local_ips, local_ip_addresses
|
||||||
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService
|
||||||
from monkey_island.cc.services.edge.edge import EdgeService
|
from monkey_island.cc.services.edge.edge import EdgeService
|
||||||
|
|
|
@ -299,7 +299,7 @@ class AWSExporter(Exporter):
|
||||||
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
|
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 "
|
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
|
||||||
"network.",
|
"network.",
|
||||||
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over "
|
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(
|
"the WMI protocol with user {username} and its password.".format(
|
||||||
machine=issue['machine'],
|
machine=issue['machine'],
|
||||||
ip_address=issue['ip_address'],
|
ip_address=issue['ip_address'],
|
||||||
|
@ -316,7 +316,7 @@ class AWSExporter(Exporter):
|
||||||
title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.",
|
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 "
|
description="Change {0}'s password to a complex one-use password that is not shared with other computers on the "
|
||||||
"network.".format(issue['username']),
|
"network.".format(issue['username']),
|
||||||
recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a "
|
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(
|
"pass-the-hash attack over WMI protocol with user {username}".format(
|
||||||
machine=issue['machine'],
|
machine=issue['machine'],
|
||||||
ip_address=issue['ip_address'],
|
ip_address=issue['ip_address'],
|
||||||
|
|
|
@ -4,7 +4,6 @@ import dateutil
|
||||||
|
|
||||||
from monkey_island.cc.encryptor import encryptor
|
from monkey_island.cc.encryptor import encryptor
|
||||||
from monkey_island.cc.models import Monkey
|
from monkey_island.cc.models import Monkey
|
||||||
from monkey_island.cc.models.edge import Edge
|
|
||||||
from monkey_island.cc.services.edge.displayed_edge import EdgeService
|
from monkey_island.cc.services.edge.displayed_edge import EdgeService
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
from monkey_island.cc.services.telemetry.processing.utils import \
|
from monkey_island.cc.services.telemetry.processing.utils import \
|
||||||
|
|
|
@ -274,9 +274,9 @@ class PreviewPaneComponent extends AuthComponent {
|
||||||
let label = '';
|
let label = '';
|
||||||
if (!this.props.item) {
|
if (!this.props.item) {
|
||||||
label = '';
|
label = '';
|
||||||
} else if (this.props.item.hasOwnProperty('label')) {
|
} else if (Object.prototype.hasOwnProperty.call(this.props.item, 'label')) {
|
||||||
label = this.props.item['label'];
|
label = this.props.item['label'];
|
||||||
} else if (this.props.item.hasOwnProperty('_label')) {
|
} else if (Object.prototype.hasOwnProperty.call(this.props.item, '_label')) {
|
||||||
label = this.props.item['_label'];
|
label = this.props.item['_label'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ class ConfigurePageComponent extends AuthComponent {
|
||||||
// Change value in attack configuration
|
// Change value in attack configuration
|
||||||
// Go trough each column in matrix, searching for technique
|
// Go trough each column in matrix, searching for technique
|
||||||
Object.entries(this.state.attackConfig).forEach(techType => {
|
Object.entries(this.state.attackConfig).forEach(techType => {
|
||||||
if (techType[1].properties.hasOwnProperty(technique)) {
|
if (Object.prototype.hasOwnProperty.call(techType[1].properties, technique)) {
|
||||||
let tempMatrix = this.state.attackConfig;
|
let tempMatrix = this.state.attackConfig;
|
||||||
tempMatrix[techType[0]].properties[technique].value = value;
|
tempMatrix[techType[0]].properties[technique].value = value;
|
||||||
this.setState({attackConfig: tempMatrix});
|
this.setState({attackConfig: tempMatrix});
|
||||||
|
@ -151,7 +151,8 @@ class ConfigurePageComponent extends AuthComponent {
|
||||||
Object.entries(this.state.attackConfig).forEach(otherType => {
|
Object.entries(this.state.attackConfig).forEach(otherType => {
|
||||||
Object.entries(otherType[1].properties).forEach(otherTech => {
|
Object.entries(otherType[1].properties).forEach(otherTech => {
|
||||||
// If this technique depends on a technique that was changed
|
// If this technique depends on a technique that was changed
|
||||||
if (otherTech[1].hasOwnProperty('depends_on') && otherTech[1]['depends_on'].includes(technique)) {
|
if (Object.prototype.hasOwnProperty.call(otherTech[1], 'depends_on') &&
|
||||||
|
otherTech[1]['depends_on'].includes(technique)) {
|
||||||
this.attackTechniqueChange(otherTech[0], value, true)
|
this.attackTechniqueChange(otherTech[0], value, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -393,7 +394,7 @@ class ConfigurePageComponent extends AuthComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let displayedSchema = {};
|
let displayedSchema = {};
|
||||||
if (this.state.schema.hasOwnProperty('properties') && this.state.selectedSection !== 'attack') {
|
if (Object.prototype.hasOwnProperty.call(this.state.schema, 'properties') && this.state.selectedSection !== 'attack') {
|
||||||
displayedSchema = this.state.schema['properties'][this.state.selectedSection];
|
displayedSchema = this.state.schema['properties'][this.state.selectedSection];
|
||||||
displayedSchema['definitions'] = this.state.schema['definitions'];
|
displayedSchema['definitions'] = this.state.schema['definitions'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ class MapPageComponent extends AuthComponent {
|
||||||
this.authFetch('/api/netmap')
|
this.authFetch('/api/netmap')
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.hasOwnProperty('edges')) {
|
if (Object.prototype.hasOwnProperty.call(res, 'edges')) {
|
||||||
res.edges.forEach(edge => {
|
res.edges.forEach(edge => {
|
||||||
edge.color = {'color': edgeGroupToColor(edge.group)};
|
edge.color = {'color': edgeGroupToColor(edge.group)};
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {Row, Col, Container, Form, Button} from 'react-bootstrap';
|
||||||
|
|
||||||
import AuthService from '../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
import monkeyDetective from '../../images/detective-monkey.svg';
|
import monkeyDetective from '../../images/detective-monkey.svg';
|
||||||
import ParticleBackground from "../ui-components/ParticleBackground";
|
import ParticleBackground from '../ui-components/ParticleBackground';
|
||||||
|
|
||||||
class RegisterPageComponent extends React.Component {
|
class RegisterPageComponent extends React.Component {
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class ReportPageComponent extends AuthComponent {
|
||||||
static selectReport(reports) {
|
static selectReport(reports) {
|
||||||
let url = window.location.href;
|
let url = window.location.href;
|
||||||
for (let report_name in reports) {
|
for (let report_name in reports) {
|
||||||
if (reports.hasOwnProperty(report_name) && url.endsWith(reports[report_name])) {
|
if (Object.prototype.hasOwnProperty.call(reports, report_name) && url.endsWith(reports[report_name])) {
|
||||||
return reports[report_name];
|
return reports[report_name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
||||||
// update existing state, not run-over
|
// update existing state, not run-over
|
||||||
let prevRes = this.awsTable.state.result;
|
let prevRes = this.awsTable.state.result;
|
||||||
for (let key in result) {
|
for (let key in result) {
|
||||||
if (result.hasOwnProperty(key)) {
|
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
||||||
prevRes[key] = result[key];
|
prevRes[key] = result[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ class AttackReport extends React.Component {
|
||||||
|
|
||||||
getTechniqueByTitle(title){
|
getTechniqueByTitle(title){
|
||||||
for (const tech_id in this.state.techniques){
|
for (const tech_id in this.state.techniques){
|
||||||
if (! this.state.techniques.hasOwnProperty(tech_id)) {return false;}
|
if (! Object.prototype.hasOwnProperty.call(this.state.techniques, tech_id)) {return false;}
|
||||||
let technique = this.state.techniques[tech_id];
|
let technique = this.state.techniques[tech_id];
|
||||||
if (technique.title === title){
|
if (technique.title === title){
|
||||||
technique['tech_id'] = tech_id;
|
technique['tech_id'] = tech_id;
|
||||||
|
@ -148,10 +148,10 @@ class AttackReport extends React.Component {
|
||||||
// add links to techniques
|
// add links to techniques
|
||||||
schema = schema.properties;
|
schema = schema.properties;
|
||||||
for(const type in schema){
|
for(const type in schema){
|
||||||
if (! schema.hasOwnProperty(type)) {return false;}
|
if (! Object.prototype.hasOwnProperty.call(schema, type)) {return false;}
|
||||||
let typeTechniques = schema[type].properties;
|
let typeTechniques = schema[type].properties;
|
||||||
for(const tech_id in typeTechniques){
|
for(const tech_id in typeTechniques){
|
||||||
if (! typeTechniques.hasOwnProperty(tech_id)) {return false;}
|
if (! Object.prototype.hasOwnProperty.call(typeTechniques, tech_id)) {return false;}
|
||||||
if (typeTechniques[tech_id] !== undefined){
|
if (typeTechniques[tech_id] !== undefined){
|
||||||
techniques[tech_id]['link'] = typeTechniques[tech_id].link
|
techniques[tech_id]['link'] = typeTechniques[tech_id].link
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ReportMatrixComponent extends React.Component {
|
||||||
getColumns() {
|
getColumns() {
|
||||||
let columns = [];
|
let columns = [];
|
||||||
for(const type_key in this.state.schema.properties){
|
for(const type_key in this.state.schema.properties){
|
||||||
if (! this.state.schema.properties.hasOwnProperty(type_key)){
|
if (! Object.prototype.hasOwnProperty.call(this.state.schema.properties, type_key)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let tech_type = this.state.schema.properties[type_key];
|
let tech_type = this.state.schema.properties[type_key];
|
||||||
|
@ -32,11 +32,11 @@ class ReportMatrixComponent extends React.Component {
|
||||||
getTableRows() {
|
getTableRows() {
|
||||||
let rows = [];
|
let rows = [];
|
||||||
for (const tech_id in this.state.techniques) {
|
for (const tech_id in this.state.techniques) {
|
||||||
if (this.state.techniques.hasOwnProperty(tech_id)){
|
if (Object.prototype.hasOwnProperty.call(this.state.techniques, tech_id)){
|
||||||
let technique_added = false;
|
let technique_added = false;
|
||||||
let technique = this.state.techniques[tech_id];
|
let technique = this.state.techniques[tech_id];
|
||||||
for(const row of rows){
|
for(const row of rows){
|
||||||
if (! row.hasOwnProperty(technique.type)){
|
if (! Object.prototype.hasOwnProperty.call(row, technique.type)){
|
||||||
row[technique.type] = technique;
|
row[technique.type] = technique;
|
||||||
technique_added = true;
|
technique_added = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -79,13 +79,13 @@ class TechniqueDropdowns extends React.Component{
|
||||||
getOrderedTechniqueList(){
|
getOrderedTechniqueList(){
|
||||||
let content = [];
|
let content = [];
|
||||||
for(const type_key in this.state.schema.properties){
|
for(const type_key in this.state.schema.properties){
|
||||||
if (! this.state.schema.properties.hasOwnProperty(type_key)){
|
if (! Object.prototype.hasOwnProperty.call(this.state.schema.properties, type_key)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let tech_type = this.state.schema.properties[type_key];
|
let tech_type = this.state.schema.properties[type_key];
|
||||||
content.push(<h3>{tech_type.title}</h3>);
|
content.push(<h3>{tech_type.title}</h3>);
|
||||||
for(const tech_id in this.state.techniques){
|
for(const tech_id in this.state.techniques){
|
||||||
if (! this.state.techniques.hasOwnProperty(tech_id)){
|
if (! Object.prototype.hasOwnProperty.call(this.state.techniques, tech_id)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let technique = this.state.techniques[tech_id];
|
let technique = this.state.techniques[tech_id];
|
||||||
|
|
|
@ -209,7 +209,7 @@ class VennDiagram extends React.Component {
|
||||||
|
|
||||||
if (key_ === 'Data') {
|
if (key_ === 'Data') {
|
||||||
this.layout[key_].fontStyle = this.fontStyles[0];
|
this.layout[key_].fontStyle = this.fontStyles[0];
|
||||||
} else if (this.layout[key_].hasOwnProperty('cx')) {
|
} else if (Object.prototype.hasOwnProperty.call(this.layout[key_], 'cx')) {
|
||||||
this.layout[key_].fontStyle = this.fontStyles[1];
|
this.layout[key_].fontStyle = this.fontStyles[1];
|
||||||
} else {
|
} else {
|
||||||
this.layout[key_].fontStyle = this.fontStyles[2];
|
this.layout[key_].fontStyle = this.fontStyles[2];
|
||||||
|
@ -229,7 +229,7 @@ class VennDiagram extends React.Component {
|
||||||
// equivalent to center translate (width/2, height/2)
|
// equivalent to center translate (width/2, height/2)
|
||||||
let viewPortParameters = (-this.width / 2) + ' ' + (-this.height / 2) + ' ' + this.width + ' ' + this.height;
|
let viewPortParameters = (-this.width / 2) + ' ' + (-this.height / 2) + ' ' + this.width + ' ' + this.height;
|
||||||
let nodes = Object.values(this.layout).map((d_, i_) => {
|
let nodes = Object.values(this.layout).map((d_, i_) => {
|
||||||
if (d_.hasOwnProperty('cx')) {
|
if (Object.prototype.hasOwnProperty.call(d_, 'cx')) {
|
||||||
return (
|
return (
|
||||||
<CircularNode
|
<CircularNode
|
||||||
prefix={this.prefix}
|
prefix={this.prefix}
|
||||||
|
|
|
@ -73,7 +73,7 @@ class AwsRunTableComponent extends React.Component {
|
||||||
let instId = r.original.instance_id;
|
let instId = r.original.instance_id;
|
||||||
if (this.isSelected(instId)) {
|
if (this.isSelected(instId)) {
|
||||||
color = '#ffed9f';
|
color = '#ffed9f';
|
||||||
} else if (this.state.result.hasOwnProperty(instId)) {
|
} else if (Object.prototype.hasOwnProperty.call(this.state.result, instId)) {
|
||||||
color = this.state.result[instId] ? '#00f01b' : '#f00000'
|
color = this.state.result[instId] ? '#00f01b' : '#f00000'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class CheckboxComponent extends React.PureComponent {
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
if (this.props.hasOwnProperty('status')){
|
if (Object.prototype.hasOwnProperty.call(this.props, 'status')){
|
||||||
this.status = this.props.status;
|
this.status = this.props.status;
|
||||||
} else {
|
} else {
|
||||||
this.status = false
|
this.status = false
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default class AuthService {
|
||||||
})
|
})
|
||||||
}).then(response => response.json())
|
}).then(response => response.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.hasOwnProperty('access_token')) {
|
if (Object.prototype.hasOwnProperty.call(res, 'access_token')) {
|
||||||
this._setToken(res['access_token']);
|
this._setToken(res['access_token']);
|
||||||
return {result: true};
|
return {result: true};
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,7 +86,7 @@ export default class AuthService {
|
||||||
headers['Authorization'] = 'Bearer ' + this._getToken();
|
headers['Authorization'] = 'Bearer ' + this._getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hasOwnProperty('headers')) {
|
if (Object.prototype.hasOwnProperty.call(options, 'headers')) {
|
||||||
for (let header in headers) {
|
for (let header in headers) {
|
||||||
options['headers'][header] = headers[header];
|
options['headers'][header] = headers[header];
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ for more details.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from Crypto.Hash import SHA3_512
|
from Crypto.Hash import SHA3_512 # noqa: DUO133
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
Loading…
Reference in New Issue