Skip to content

Commit

Permalink
Merge pull request #688 from guardicore/password_setup
Browse files Browse the repository at this point in the history
Password setup and bootstrap v4 migration
  • Loading branch information
VakarisZ authored Jun 25, 2020
2 parents f34a607 + 8a31ff2 commit 6cc4c85
Show file tree
Hide file tree
Showing 1,749 changed files with 29,674 additions and 6,219 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ profiler_logs/

# vim swap files
*.swp

# Server config might contain credentials. Don't commit by default.
/monkey/monkey_island/cc/server_config.json
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ script:
- cd monkey_island/cc/ui
- npm ci # See https://docs.npmjs.com/cli/ci.html
- eslint ./src --quiet # Test for errors
- JS_WARNINGS_AMOUNT_UPPER_LIMIT=90
- JS_WARNINGS_AMOUNT_UPPER_LIMIT=70
- eslint ./src --max-warnings $JS_WARNINGS_AMOUNT_UPPER_LIMIT # Test for max warnings

after_success:
Expand Down
1 change: 1 addition & 0 deletions envs/monkey_zoo/blackbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Configure a PyTest configuration with the additional arguments `-s --island=35.2
**Before running performance test make sure browser is not sending requests to island!**

To run telemetry performance test follow these steps:
0. Set `server_config.json` to "standard" (no password protection) setting.
1. Gather monkey telemetries.
1. Enable "Export monkey telemetries" in Configuration -> Internal -> Tests if you don't have
exported telemetries already.
Expand Down
2 changes: 2 additions & 0 deletions envs/monkey_zoo/blackbox/test_blackbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def test_wmi_and_mimikatz_exploiters(self, island_client):
def test_wmi_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, "WMI_PTH.conf", "WMI_PTH")

@pytest.mark.skip(reason="Perfomance test that creates env from fake telemetries is faster, use that instead.")
def test_report_generation_performance(self, island_client, quick_performance_tests):
"""
This test includes the SSH + Elastic + Hadoop + MSSQL machines all in one test
Expand All @@ -149,6 +150,7 @@ def test_report_generation_performance(self, island_client, quick_performance_te
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
assert False

@pytest.mark.skip(reason="Perfomance test that creates env from fake telemetries is faster, use that instead.")
def test_map_generation_performance(self, island_client, quick_performance_tests):
if not quick_performance_tests:
TestMonkeyBlackbox.run_performance_test(MapGenerationTest,
Expand Down
22 changes: 22 additions & 0 deletions monkey/common/utils/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class ExploitingVulnerableMachineError(Exception):
""" Raise when exploiter failed, but machine is vulnerable """


class FailedExploitationError(Exception):
""" Raise when exploiter fails instead of returning False """


class InvalidRegistrationCredentialsError(Exception):
""" Raise when server config file changed and island needs to restart """


class RegistrationNotNeededError(Exception):
""" Raise to indicate the reason why registration is not required """


class CredentialsNotRequiredError(RegistrationNotNeededError):
""" Raise to indicate the reason why registration is not required """


class AlreadyRegisteredError(RegistrationNotNeededError):
""" Raise to indicate the reason why registration is not required """
2 changes: 1 addition & 1 deletion monkey/infection_monkey/exploit/mssqlexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from infection_monkey.exploit.tools.helpers import get_monkey_dest_path, build_monkey_commandline, get_monkey_depth
from infection_monkey.model import DROPPER_ARG
from infection_monkey.exploit.tools.payload_parsing import LimitedSizePayload
from infection_monkey.exploit.tools.exceptions import ExploitingVulnerableMachineError, FailedExploitationError
from common.utils.exceptions import ExploitingVulnerableMachineError, FailedExploitationError

LOG = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion monkey/infection_monkey/exploit/sshexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline
from infection_monkey.model import MONKEY_ARG
from infection_monkey.network.tools import check_tcp_port, get_interface_to_target
from infection_monkey.exploit.tools.exceptions import FailedExploitationError
from common.utils.exceptions import FailedExploitationError
from common.utils.exploit_enum import ExploitType
from common.utils.attack_utils import ScanStatus
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
Expand Down
6 changes: 0 additions & 6 deletions monkey/infection_monkey/exploit/tools/exceptions.py

This file was deleted.

2 changes: 1 addition & 1 deletion monkey/infection_monkey/monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from infection_monkey.windows_upgrader import WindowsUpgrader
from infection_monkey.post_breach.post_breach_handler import PostBreach
from infection_monkey.network.tools import get_interface_to_target, is_running_on_server
from infection_monkey.exploit.tools.exceptions import ExploitingVulnerableMachineError, FailedExploitationError
from common.utils.exceptions import ExploitingVulnerableMachineError, FailedExploitationError
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
from common.utils.attack_utils import ScanStatus, UsageEnum
from common.version import get_version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
'kerberos_creds', 'credman_creds', 'tspkg_creds']
PypykatzCredential = NewType('PypykatzCredential', Dict)


def get_windows_creds() -> List[WindowsCredentials]:
pypy_handle = pypykatz.go_live()
logon_data = pypy_handle.to_dict()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@ class TestPypykatzHandler(TestCase):
'password': 'canyoufindm3', 'luid': 123086}],
'dpapi_creds': [
{'credtype': 'dpapi', 'key_guid': '9123-123ae123de4-121239-3123-421f',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975ef051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975e'
'f051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'sha1_masterkey': 'bbdabc3cd2f6bcbe3e2cee6ce4ce4cebcef4c6da', 'luid': 123086},
{'credtype': 'dpapi', 'key_guid': '9123-123ae123de4-121239-3123-421f',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975ef051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975e'
'f051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'sha1_masterkey': 'bbdabc3cd2f6bcbe3e2cee6ce4ce4cebcef4c6da', 'luid': 123086},
{'credtype': 'dpapi', 'key_guid': '9123-123ae123de4-121239-3123-421f',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975ef051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975e'
'f051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'sha1_masterkey': 'bbdabc3cd2f6bcbe3e2cee6ce4ce4cebcef4c6da', 'luid': 123086},
{'credtype': 'dpapi', 'key_guid': '9123-123ae123de4-121239-3123-421f',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975ef051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'masterkey': '6e81d0cfd5e9ec083cfbdaf4d25b9cc9cc6b72947f5e80920034d1275d8613532025975e'
'f051e891c30e6e9af6db54500fedfed1c968389bf6262c77fbaa68c9',
'sha1_masterkey': 'bbdabc3cd2f6bcbe3e2cee6ce4ce4cebcef4c6da', 'luid': 123086},
{'credtype': 'dpapi', 'key_guid': '9123-123ae123de4-121239-3123-421f'}],
'kerberos_creds': [
Expand Down
10 changes: 7 additions & 3 deletions monkey/monkey_island/cc/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
from flask import Flask, send_from_directory, Response
from werkzeug.exceptions import NotFound

from monkey_island.cc.auth import init_jwt
from monkey_island.cc.resources.auth.auth import init_jwt
from monkey_island.cc.database import mongo, database
from monkey_island.cc.environment.environment import env
import monkey_island.cc.environment.environment_singleton as env_singleton
from monkey_island.cc.resources.client_run import ClientRun
from monkey_island.cc.resources.edge import Edge
from monkey_island.cc.resources.environment import Environment
from monkey_island.cc.resources.local_run import LocalRun
from monkey_island.cc.resources.log import Log
from monkey_island.cc.resources.island_logs import IslandLog
Expand All @@ -22,6 +23,7 @@
from monkey_island.cc.resources.node import Node
from monkey_island.cc.resources.node_states import NodeStates
from monkey_island.cc.resources.monkey_control.remote_port_check import RemotePortCheck
from monkey_island.cc.resources.registration import Registration
from monkey_island.cc.resources.remote_run import RemoteRun
from monkey_island.cc.resources.reporting.report import Report
from monkey_island.cc.resources.root import Root
Expand Down Expand Up @@ -69,7 +71,7 @@ def init_app_config(app, mongo_url):
app.config['MONGO_URI'] = mongo_url
app.config['SECRET_KEY'] = str(uuid.getnode())
app.config['JWT_AUTH_URL_RULE'] = '/api/auth'
app.config['JWT_EXPIRATION_DELTA'] = env.get_auth_expiration_time()
app.config['JWT_EXPIRATION_DELTA'] = env_singleton.env.get_auth_expiration_time()


def init_app_services(app):
Expand All @@ -91,6 +93,8 @@ def init_app_url_rules(app):

def init_api_resources(api):
api.add_resource(Root, '/api')
api.add_resource(Registration, '/api/registration')
api.add_resource(Environment, '/api/environment')
api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/<string:guid>')
api.add_resource(Bootloader, '/api/bootloader/<string:os>')
api.add_resource(LocalRun, '/api/local-monkey', '/api/local-monkey/')
Expand Down
89 changes: 68 additions & 21 deletions monkey/monkey_island/cc/environment/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import hashlib
import logging
import os
from abc import ABCMeta, abstractmethod
from datetime import timedelta
import os
import hashlib

__author__ = 'itay.mizeretz'

from common.utils.exceptions import InvalidRegistrationCredentialsError, \
CredentialsNotRequiredError, AlreadyRegisteredError
from monkey_island.cc.environment.environment_config import EnvironmentConfig
from monkey_island.cc.environment.user_creds import UserCreds

logger = logging.getLogger(__name__)


class Environment(object, metaclass=ABCMeta):
_ISLAND_PORT = 5000
Expand All @@ -18,6 +26,53 @@ class Environment(object, metaclass=ABCMeta):

_testing = False

def __init__(self, config: EnvironmentConfig):
self._config = config
self._testing = False # Assume env is not for unit testing.

@property
@abstractmethod
def _credentials_required(self) -> bool:
pass

@abstractmethod
def get_auth_users(self):
pass

def needs_registration(self) -> bool:
try:
needs_registration = self._try_needs_registration()
return needs_registration
except (CredentialsNotRequiredError, AlreadyRegisteredError) as e:
logger.info(e)
return False

def try_add_user(self, credentials: UserCreds):
if not credentials:
raise InvalidRegistrationCredentialsError("Missing part of credentials.")
if self._try_needs_registration():
self._config.add_user(credentials)
logger.info(f"New user {credentials.username} registered!")

def _try_needs_registration(self) -> bool:
if not self._credentials_required:
raise CredentialsNotRequiredError("Credentials are not required "
"for current environment.")
else:
if self._is_registered():
raise AlreadyRegisteredError("User has already been registered. "
"Reset credentials or login.")
return True

def _is_registered(self) -> bool:
return self._credentials_required and self._is_credentials_set_up()

def _is_credentials_set_up(self) -> bool:
if self._config and self._config.user_creds:
return True
else:
return False

@property
def testing(self):
return self._testing
Expand All @@ -26,12 +81,11 @@ def testing(self):
def testing(self, value):
self._testing = value

def __init__(self):
self.config = None
self._testing = False # Assume env is not for unit testing.
def save_config(self):
self._config.save_to_file()

def set_config(self, config):
self.config = config
def get_config(self) -> EnvironmentConfig:
return self._config

def get_island_port(self):
return self._ISLAND_PORT
Expand All @@ -51,21 +105,14 @@ def hash_secret(secret):
hash_obj.update(secret.encode('utf-8'))
return hash_obj.hexdigest()

def get_deployment(self):
return self._get_from_config('deployment', 'unknown')
def get_deployment(self) -> str:
deployment = 'unknown'
if self._config and self._config.deployment:
deployment = self._config.deployment
return deployment

def is_develop(self):
return self.get_deployment() == 'develop'

def _get_from_config(self, key, default_value=None):
val = default_value
if self.config is not None:
val = self.config.get(key, val)
return val

@abstractmethod
def get_auth_users(self):
return
def set_deployment(self, deployment: str):
self._config.deployment = deployment

@property
def mongo_db_name(self):
Expand Down
16 changes: 10 additions & 6 deletions monkey/monkey_island/cc/environment/aws.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import monkey_island.cc.auth
from monkey_island.cc.resources.auth.auth_user import User
from monkey_island.cc.environment import Environment
from common.cloud.aws.aws_instance import AwsInstance

__author__ = 'itay.mizeretz'


class AwsEnvironment(Environment):
def __init__(self):
super(AwsEnvironment, self).__init__()

_credentials_required = True

def __init__(self, config):
super(AwsEnvironment, self).__init__(config)
# Not suppressing error here on purpose. This is critical if we're on AWS env.
self.aws_info = AwsInstance()
self._instance_id = self._get_instance_id()
Expand All @@ -20,6 +23,7 @@ def _get_region(self):
return self.aws_info.get_region()

def get_auth_users(self):
return [
monkey_island.cc.auth.User(1, 'monkey', self.hash_secret(self._instance_id))
]
if self._is_registered():
return self._config.get_users()
else:
return []
49 changes: 0 additions & 49 deletions monkey/monkey_island/cc/environment/environment.py

This file was deleted.

Loading

0 comments on commit 6cc4c85

Please sign in to comment.