From d2670be7674fb7356f2e91581456c5378f3bbcc5 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 15 Mar 2019 18:08:58 +0200 Subject: [PATCH] Sketches of config implementation --- monkey/monkey_island/cc/app.py | 4 +- monkey/monkey_island/cc/resources/attck.py | 13 ++++++ .../cc/services/attck/__init__.py | 1 + .../monkey_island/cc/services/attck/attck.py | 43 +++++++++++++++++ .../cc/services/attck/attck_schema.py | 46 +++++++++++++++++++ .../cc/ui/src/components/Main.js | 3 ++ .../components/config-components/Att&ck.js | 18 -------- .../cc/ui/src/components/pages/AttckPage.js | 45 ++++++++++++++++++ .../ui/src/components/pages/ConfigurePage.js | 12 ++--- 9 files changed, 158 insertions(+), 27 deletions(-) create mode 100644 monkey/monkey_island/cc/resources/attck.py create mode 100644 monkey/monkey_island/cc/services/attck/__init__.py create mode 100644 monkey/monkey_island/cc/services/attck/attck.py create mode 100644 monkey/monkey_island/cc/services/attck/attck_schema.py delete mode 100644 monkey/monkey_island/cc/ui/src/components/config-components/Att&ck.js create mode 100644 monkey/monkey_island/cc/ui/src/components/pages/AttckPage.js diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index d43930206..4d3148414 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -28,8 +28,9 @@ from cc.resources.root import Root from cc.resources.telemetry import Telemetry from cc.resources.telemetry_feed import TelemetryFeed from cc.resources.pba_file_download import PBAFileDownload -from cc.services.config import ConfigService from cc.resources.pba_file_upload import FileUpload +from cc.resources.attck import AttckConfiguration +from cc.services.config import ConfigService __author__ = 'Barak' @@ -123,5 +124,6 @@ def init_app(mongo_url): '/api/fileUpload/?load=', '/api/fileUpload/?restore=') api.add_resource(RemoteRun, '/api/remote-monkey', '/api/remote-monkey/') + api.add_resource(AttckConfiguration, '/api/attck') return app diff --git a/monkey/monkey_island/cc/resources/attck.py b/monkey/monkey_island/cc/resources/attck.py new file mode 100644 index 000000000..be0d09061 --- /dev/null +++ b/monkey/monkey_island/cc/resources/attck.py @@ -0,0 +1,13 @@ +import flask_restful +from flask import jsonify + +from cc.auth import jwt_required +from cc.services.attck.attck import AttckService + + +class AttckConfiguration(flask_restful.Resource): + @jwt_required() + def get(self): + return jsonify(schema=AttckService.get_config_schema(), + configuration=AttckService.get_config()) + diff --git a/monkey/monkey_island/cc/services/attck/__init__.py b/monkey/monkey_island/cc/services/attck/__init__.py new file mode 100644 index 000000000..98867ed4d --- /dev/null +++ b/monkey/monkey_island/cc/services/attck/__init__.py @@ -0,0 +1 @@ +__author__ = 'VakarisZ' diff --git a/monkey/monkey_island/cc/services/attck/attck.py b/monkey/monkey_island/cc/services/attck/attck.py new file mode 100644 index 000000000..1c7965a4a --- /dev/null +++ b/monkey/monkey_island/cc/services/attck/attck.py @@ -0,0 +1,43 @@ +import logging +from cc.database import mongo +from attck_schema import SCHEMA +from jsonschema import Draft4Validator, validators + +__author__ = "VakarisZ" + +logger = logging.getLogger(__name__) + + +class AttckService: + default_config = None + + def __init__(self): + pass + + @staticmethod + def get_config(): + config = mongo.db.attck.find_one({'name': 'newconfig'}) or AttckService.get_default_config() + return config + + @staticmethod + def get_config_schema(): + return SCHEMA + + @staticmethod + def reset_config(): + config = AttckService.get_default_config() + AttckService.update_config(config) + logger.info('Monkey config reset was called') + + @staticmethod + def update_config(config_json): + mongo.db.attck.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True) + logger.info('Attck config was updated') + return True + + @staticmethod + def get_default_config(): + if not AttckService.default_config: + AttckService.update_config(SCHEMA) + AttckService.default_config = SCHEMA + return AttckService.default_config diff --git a/monkey/monkey_island/cc/services/attck/attck_schema.py b/monkey/monkey_island/cc/services/attck/attck_schema.py new file mode 100644 index 000000000..67f2316ef --- /dev/null +++ b/monkey/monkey_island/cc/services/attck/attck_schema.py @@ -0,0 +1,46 @@ +SCHEMA = { + "title": "ATT&CK configuration", + "type": "object", + "properties": { + "lateral_movement": { + "title": "Lateral movement", + "type": "object", + "properties": { + "T1210": { + "title": "T1210 Exploitation of Remote services", + "type": "bool", + "default": True, + "description": "Exploitation of a software vulnerability occurs when an adversary " + "takes advantage of a programming error in a program, service, or within the " + "operating system software or kernel itself to execute adversary-controlled code." + } + } + }, + "credential_access": { + "title": "Credential access", + "type": "object", + "properties": { + "T1110": { + "title": "T1110 Brute force", + "type": "bool", + "default": True, + "description": "Adversaries may use brute force techniques to attempt access to accounts " + "when passwords are unknown or when password hashes are obtained." + } + } + }, + "defence_evasion": { + "title": "Defence evasion", + "type": "object", + "properties": { + "T1197": { + "title": "T1197 Bits jobs", + "type": "bool", + "default": True, + "description": "Adversaries may abuse BITS to download, execute, " + "and even clean up after running malicious code." + } + } + }, + } +} diff --git a/monkey/monkey_island/cc/ui/src/components/Main.js b/monkey/monkey_island/cc/ui/src/components/Main.js index da8e59113..5dfe465fa 100644 --- a/monkey/monkey_island/cc/ui/src/components/Main.js +++ b/monkey/monkey_island/cc/ui/src/components/Main.js @@ -14,6 +14,7 @@ import ReportPage from 'components/pages/ReportPage'; import LicensePage from 'components/pages/LicensePage'; import AuthComponent from 'components/AuthComponent'; import LoginPageComponent from 'components/pages/LoginPage'; +import AttckPage from 'components/pages/AttckPage' import 'normalize.css/normalize.css'; import 'react-data-components/css/table-twbs.css'; @@ -161,6 +162,7 @@ class AppComponent extends AuthComponent {
    +
  • ATT&CK Configuration
  • Configuration
  • Log
@@ -186,6 +188,7 @@ class AppComponent extends AuthComponent { {this.renderRoute('/start-over', )} {this.renderRoute('/report', )} {this.renderRoute('/license', )} + {this.renderRoute('/attck', )} diff --git a/monkey/monkey_island/cc/ui/src/components/config-components/Att&ck.js b/monkey/monkey_island/cc/ui/src/components/config-components/Att&ck.js deleted file mode 100644 index d5b13b6aa..000000000 --- a/monkey/monkey_island/cc/ui/src/components/config-components/Att&ck.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -// ATT&CK component -class AttackComponent extends React.Component { - constructor(props) { - super(props); - } - - render() { - return ( -
- ATT&CK component -
- ); - } -} - -export default AttackComponent; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/AttckPage.js b/monkey/monkey_island/cc/ui/src/components/pages/AttckPage.js new file mode 100644 index 000000000..5d9e300c7 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/AttckPage.js @@ -0,0 +1,45 @@ +import React from 'react'; +import Form from 'react-jsonschema-form'; +import {Col, Nav, NavItem} from 'react-bootstrap'; +import AuthComponent from '../AuthComponent'; +import 'filepond/dist/filepond.min.css'; + +class AttckComponent extends AuthComponent { + constructor(props) { + super(props); + this.currentSection = 'ATT&CK matrix'; + this.currentFormData = {}; + this.sectionsOrder = ['ATT&CK matrix']; + // set schema from server + this.state = { + schema: {}, + configuration: {}, + lastAction: 'none', + sections: [], + selectedSection: 'ATT&CK matrix', + }; + } + + componentDidMount() { + this.authFetch('/api/attck') + .then(res => res.json()) + .then(res => { + let sections = []; + for (let sectionKey of this.sectionsOrder) { + sections.push({key: sectionKey, title: res.configuration.title}); + } + this.setState({ + schema: res.schema, + configuration: res.configuration, + sections: sections, + selectedSection: 'ATT&CK matrix' + }) + }); + } + + render() { + return ( Vakaris ); + } +} + +export default AttckComponent; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index 0d48251de..a3626ae1a 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -3,7 +3,6 @@ import Form from 'react-jsonschema-form'; import {Col, Nav, NavItem} from 'react-bootstrap'; import fileDownload from 'js-file-download'; import AuthComponent from '../AuthComponent'; -import AttackComponent from 'components/config-components/Att&ck' import { FilePond } from 'react-filepond'; import 'filepond/dist/filepond.min.css'; @@ -14,8 +13,6 @@ class ConfigurePageComponent extends AuthComponent { this.PBAlinuxPond = null; this.currentSection = 'basic'; this.currentFormData = {}; - this.sectionsOrder = ['basic', 'basic_network', 'monkey', 'cnc', 'network', 'exploits', 'internal', 'ATT&CK']; - this.sectionsOrder = ['basic', 'basic_network', 'monkey', 'cnc', 'network', 'exploits', 'internal']; this.uiSchema = { behaviour: { @@ -280,6 +277,7 @@ class ConfigurePageComponent extends AuthComponent { displayedSchema = this.state.schema['properties'][this.state.selectedSection]; displayedSchema['definitions'] = this.state.schema['definitions']; } + return (

Monkey Configuration

@@ -299,14 +297,11 @@ class ConfigurePageComponent extends AuthComponent { :
} - { this.state.selectedSection === 'ATT&CK' ? - : this.state.selectedSection ? + { this.state.selectedSection ?
+ onChange={this.onChange}>
{ this.state.allMonkeysAreDead ? '' : @@ -369,6 +364,7 @@ class ConfigurePageComponent extends AuthComponent {
: ''}
+ ); }