From 46253787370a25ee5edf516f7b1e4a427ee82d00 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 14:07:38 +0300 Subject: [PATCH 01/12] minor fixes --- monkey_island/cc/resources/local_run.py | 2 +- monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/monkey_island/cc/resources/local_run.py b/monkey_island/cc/resources/local_run.py index ed8949501..2fe7be3d1 100644 --- a/monkey_island/cc/resources/local_run.py +++ b/monkey_island/cc/resources/local_run.py @@ -61,7 +61,7 @@ class LocalRun(flask_restful.Resource): body = json.loads(request.data) if body.get('action') == 'run': local_run = run_local_monkey() - return jsonify(is_running=local_run[0]) + return jsonify(is_running=local_run[0], error_text=local_run[1]) # default action return make_response({'error': 'Invalid action'}, 500) diff --git a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js index d84fe6c1f..ab462a713 100644 --- a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js +++ b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js @@ -112,7 +112,7 @@ class RunMonkeyPageComponent extends React.Component { renderIconByState(state) { if (state === 'running') { return - } else if (state == 'installing') { + } else if (state === 'installing') { return } else { return ''; From 70c4a99e83b725da5a5da891e86a8b60ae9b1c98 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 14:08:43 +0300 Subject: [PATCH 02/12] Add clean node image --- .../cc/ui/src/components/pages/MapPage.js | 8 ++++---- .../cc/ui/src/images/nodes/clean_unknown.png | Bin 0 -> 19466 bytes 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 monkey_island/cc/ui/src/images/nodes/clean_unknown.png diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index 65c407102..a418cc05f 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -5,7 +5,7 @@ import PreviewPane from 'components/preview-pane/PreviewPane'; import {Link} from 'react-router-dom'; import {Icon} from 'react-fa'; -let groupNames = ['clean_linux', 'clean_windows', 'exploited_linux', 'exploited_windows', 'island', +let groupNames = ['clean_unknown', 'clean_linux', 'clean_windows', 'exploited_linux', 'exploited_windows', 'island', 'island_monkey_linux', 'island_monkey_linux_running', 'island_monkey_windows', 'island_monkey_windows_running', 'manual_linux', 'manual_linux_running', 'manual_windows', 'manual_windows_running', 'monkey_linux', 'monkey_linux_running', 'monkey_windows', 'monkey_windows_running']; @@ -59,7 +59,7 @@ class MapPageComponent extends React.Component { select: event => this.selectionChanged(event) }; - edgeGroupToColor(group) { + static edgeGroupToColor(group) { switch (group) { case 'exploited': return '#c00'; @@ -87,7 +87,7 @@ class MapPageComponent extends React.Component { .then(res => res.json()) .then(res => { res.edges.forEach(edge => { - edge.color = this.edgeGroupToColor(edge.group); + edge.color = MapPageComponent.edgeGroupToColor(edge.group); }); this.setState({graph: res}); this.props.onStatusChange(); @@ -106,7 +106,7 @@ class MapPageComponent extends React.Component { function(edge) { return edge['id'] === event.edges[0]; }); - if (displayedEdge['group'] == 'island') { + if (displayedEdge['group'] === 'island') { this.setState({selected: displayedEdge, selectedType: 'island_edge'}); } else { fetch('/api/netmap/edge?id='+event.edges[0]) diff --git a/monkey_island/cc/ui/src/images/nodes/clean_unknown.png b/monkey_island/cc/ui/src/images/nodes/clean_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..3b1e9b6387377d9fc2e39d7bede361041f3b6104 GIT binary patch literal 19466 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 literal 0 HcmV?d00001 From 8ecb8952440f2b5e0b748bc4acaa1eec1535460d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 14:57:56 +0300 Subject: [PATCH 03/12] Change default for victims_max_find Move things around in config --- chaos_monkey/config.py | 2 +- chaos_monkey/example.conf | 2 +- monkey_island/cc/services/config.py | 198 ++++++++---------- .../ui/src/components/pages/ConfigurePage.js | 22 +- 4 files changed, 108 insertions(+), 116 deletions(-) diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index 6b49d3bb3..501663958 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -150,7 +150,7 @@ class Configuration(object): ] # how many victims to look for in a single scan iteration - victims_max_find = 14 + victims_max_find = 30 # how many victims to exploit before stopping victims_max_exploit = 7 diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index 285bffd11..d04b82a55 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -89,5 +89,5 @@ "timeout_between_iterations": 10, "use_file_logging": true, "victims_max_exploit": 7, - "victims_max_find": 14 + "victims_max_find": 30 } diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 5e4d5abe0..700dbed90 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -126,23 +126,6 @@ SCHEMA = { "title": "Basic", "type": "object", "properties": { - "network": { - "title": "Network", - "type": "object", - "properties": { - "blocked_ips": { - "title": "Blocked IPs", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string" - }, - "default": [ - ], - "description": "List of IPs to not scan" - } - } - }, "credentials": { "title": "Credentials", "type": "object", @@ -180,6 +163,80 @@ SCHEMA = { } } }, + "basic_network": { + "title": "Basic - Network", + "type": "object", + "properties": { + "general": { + "title": "General", + "type": "object", + "properties": { + "blocked_ips": { + "title": "Blocked IPs", + "type": "array", + "uniqueItems": True, + "items": { + "type": "string" + }, + "default": [ + ], + "description": "List of IPs to not scan" + }, + "local_network_scan": { + "title": "Local network scan", + "type": "boolean", + "default": True, + "description": "Determines whether monkey should scan its subnets additionally" + }, + "depth": { + "title": "Depth", + "type": "integer", + "default": 2, + "description": "Amount of hops allowed for the monkey to spread" + } + } + }, + "network_range": { + "title": "Network range", + "type": "object", + "properties": { + "range_class": { + "title": "Range class", + "type": "string", + "default": "FixedRange", + "enum": [ + "FixedRange", + "RelativeRange", + "ClassCRange" + ], + "enumNames": [ + "FixedRange", + "RelativeRange", + "ClassCRange" + ], + "description": "Determines which class to use to determine scan range" + }, + "range_size": { + "title": "Relative range size", + "type": "integer", + "default": 1, + "description": "Determines the size of the RelativeRange - amount of IPs to include" + }, + "range_fixed": { + "title": "Fixed range IP list", + "type": "array", + "uniqueItems": True, + "items": { + "type": "string" + }, + "default": [ + ], + "description": "List of IPs to include when using FixedRange" + } + } + } + } + }, "monkey": { "title": "Monkey", "type": "object", @@ -193,12 +250,6 @@ SCHEMA = { "type": "boolean", "default": True, "description": "Is the monkey alive" - }, - "depth": { - "title": "Depth", - "type": "integer", - "default": 2, - "description": "Amount of hops allowed from this monkey to spread" } } }, @@ -239,7 +290,7 @@ SCHEMA = { "victims_max_find": { "title": "Max victims to find", "type": "integer", - "default": 14, + "default": 30, "description": "Determines after how many discovered machines should the monkey stop scanning" }, "victims_max_exploit": { @@ -277,6 +328,12 @@ SCHEMA = { "type": "string", "default": "{2384ec59-0df8-4ab9-918c-843740924a28}", "description": "The name of the mutex used to determine whether the monkey is already running" + }, + "collect_system_info": { + "title": "Collect system info", + "type": "boolean", + "default": True, + "description": "Determines whether to collect system info" } } }, @@ -449,6 +506,18 @@ SCHEMA = { "description": "List of NTLM hashes to use on exploits using credentials" } } + }, + "mimikatz": { + "title": "Mimikatz", + "type": "object", + "properties": { + "mimikatz_dll_name": { + "title": "Mimikatz DLL name", + "type": "string", + "default": "mk.dll", + "description": "Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)" + } + } } } }, @@ -610,91 +679,10 @@ SCHEMA = { } } }, - "system_info": { - "title": "System info", - "type": "object", - "properties": { - "general": { - "title": "General", - "type": "object", - "properties": { - "collect_system_info": { - "title": "Collect system info", - "type": "boolean", - "default": True, - "description": "Determines whether to collect system info" - } - } - }, - "mimikatz": { - "title": "Mimikatz", - "type": "object", - "properties": { - "mimikatz_dll_name": { - "title": "Mimikatz DLL name", - "type": "string", - "default": "mk.dll", - "description": "Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)" - } - } - } - } - }, "network": { "title": "Network", "type": "object", "properties": { - "general": { - "title": "General", - "type": "object", - "properties": { - "local_network_scan": { - "title": "Local network scan", - "type": "boolean", - "default": True, - "description": "Determines whether monkey should scan its subnets additionally" - } - } - }, - "network_range": { - "title": "Network range", - "type": "object", - "properties": { - "range_class": { - "title": "Range class", - "type": "string", - "default": "FixedRange", - "enum": [ - "FixedRange", - "RelativeRange", - "ClassCRange" - ], - "enumNames": [ - "FixedRange", - "RelativeRange", - "ClassCRange" - ], - "description": "Determines which class to use to determine scan range" - }, - "range_size": { - "title": "Relative range size", - "type": "integer", - "default": 1, - "description": "Determines the size of the RelativeRange - amount of IPs to include" - }, - "range_fixed": { - "title": "Fixed range IP list", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string" - }, - "default": [ - ], - "description": "List of IPs to include when using FixedRange" - } - } - }, "tcp_scanner": { "title": "TCP scanner", "type": "object", diff --git a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index ff7b91c5a..f24c76f53 100644 --- a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -8,6 +8,7 @@ class ConfigurePageComponent extends React.Component { this.currentSection = 'basic'; this.currentFormData = {}; + this.sectionsOrder = ['basic', 'basic_network', 'monkey', 'cnc', 'network', 'exploits', 'internal']; // set schema from server this.state = { @@ -23,15 +24,18 @@ class ConfigurePageComponent extends React.Component { componentDidMount() { fetch('/api/configuration') .then(res => res.json()) - .then(res => this.setState({ - schema: res.schema, - configuration: res.configuration, - sections: Object.keys(res.schema.properties) - .map(key => { - return {key: key, title: res.schema.properties[key].title} - }), - selectedSection: 'basic' - })); + .then(res => { + let sections = []; + for (let sectionKey of this.sectionsOrder) { + sections.push({key: sectionKey, title: res.schema.properties[sectionKey].title}); + } + this.setState({ + schema: res.schema, + configuration: res.configuration, + sections: sections, + selectedSection: 'basic' + }) + }); } onSubmit = ({formData}) => { From f9206ff8174dfd389ebea3725579ec5b0771d4b3 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 15:25:34 +0300 Subject: [PATCH 04/12] Remove unsafe exploits from default config --- chaos_monkey/config.py | 2 +- chaos_monkey/example.conf | 2 -- monkey_island/cc/services/config.py | 6 ++---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index 501663958..2a0e58cae 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -144,7 +144,7 @@ class Configuration(object): scanner_class = TcpScanner finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger] - exploiter_classes = [SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter, # Windows exploits + exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux ElasticGroovyExploiter, # multi ] diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index d04b82a55..a2476bd03 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -32,8 +32,6 @@ "SSHExploiter", "SmbExploiter", "WmiExploiter", - "RdpExploiter", - "Ms08_067_Exploiter", "ShellShockExploiter", "ElasticGroovyExploiter", "SambaCryExploiter", diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 700dbed90..6e81e716a 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -33,14 +33,14 @@ SCHEMA = { "enum": [ "RdpExploiter" ], - "title": "RdpExploiter" + "title": "RdpExploiter (UNSAFE)" }, { "type": "string", "enum": [ "Ms08_067_Exploiter" ], - "title": "Ms08_067_Exploiter" + "title": "Ms08-067 Exploiter (UNSAFE)" }, { "type": "string", @@ -380,8 +380,6 @@ SCHEMA = { "default": [ "SmbExploiter", "WmiExploiter", - "RdpExploiter", - "Ms08_067_Exploiter", "SSHExploiter", "ShellShockExploiter", "SambaCryExploiter", From 6197f4253e1cb095ec7e7239a100bb882bcc0d8d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 15:26:02 +0300 Subject: [PATCH 05/12] Improve config buttons and message --- .../ui/src/components/pages/ConfigurePage.js | 47 ++++++++++++------- .../ui/src/components/pages/StartOverPage.js | 4 +- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index f24c76f53..cc8118b17 100644 --- a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -122,26 +122,37 @@ class ConfigurePageComponent extends React.Component {
+ onChange={this.onChange}> +
+
+ + This configuration will only apply to new infections. +
+
+ + +
+ { this.state.reset ? +
+ + Configuration reset successfully. +
+ : ''} + { this.state.saved ? +
+ + Configuration saved successfully. +
+ : ''} +
+ : ''} - Reset to defaults -
- - This configuration will only apply to new infections. -
- { this.state.reset ? -
- - Configuration reset successfully. -
- : ''} - { this.state.saved ? -
- - Configuration saved successfully. -
- : ''} + ); } diff --git a/monkey_island/cc/ui/src/components/pages/StartOverPage.js b/monkey_island/cc/ui/src/components/pages/StartOverPage.js index 26b404137..6ecb2cc69 100644 --- a/monkey_island/cc/ui/src/components/pages/StartOverPage.js +++ b/monkey_island/cc/ui/src/components/pages/StartOverPage.js @@ -27,8 +27,8 @@ class StartOverPageComponent extends React.Component { Reset Environment

{ this.state.cleaned ? -
- +
+ Environment was reset successfully
: ''} From ff4c68f94c6067a70e58e0200154ace42718263a Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 4 Oct 2017 16:01:01 +0300 Subject: [PATCH 06/12] Add warning to unsafe config values --- monkey_island/cc/services/config.py | 8 +++++--- monkey_island/cc/ui/src/components/pages/ConfigurePage.js | 7 +++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 6e81e716a..97dae84cd 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -6,6 +6,8 @@ from cc.utils import local_ip_addresses __author__ = "itay.mizeretz" +WARNING_SIGN = u" \u26A0" + SCHEMA = { "title": "Monkey", "type": "object", @@ -189,7 +191,7 @@ SCHEMA = { "description": "Determines whether monkey should scan its subnets additionally" }, "depth": { - "title": "Depth", + "title": "Depth" + WARNING_SIGN, "type": "integer", "default": 2, "description": "Amount of hops allowed for the monkey to spread" @@ -294,7 +296,7 @@ SCHEMA = { "description": "Determines after how many discovered machines should the monkey stop scanning" }, "victims_max_exploit": { - "title": "Max victims to exploit", + "title": "Max victims to exploit" + WARNING_SIGN, "type": "integer", "default": 7, "description": "Determines after how many infected machines should the monkey stop infecting" @@ -371,7 +373,7 @@ SCHEMA = { "description": "Determines which classes to use for fingerprinting" }, "exploiter_classes": { - "title": "Exploiter classes", + "title": "Exploiter classes" + WARNING_SIGN, "type": "array", "uniqueItems": True, "items": { diff --git a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index cc8118b17..4fcff5c72 100644 --- a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -109,7 +109,6 @@ class ConfigurePageComponent extends React.Component { return (

Monkey Configuration

-
); diff --git a/monkey_island/cc/ui/src/components/reactive-graph/ReactiveGraph.js b/monkey_island/cc/ui/src/components/reactive-graph/ReactiveGraph.js new file mode 100644 index 000000000..c175becd3 --- /dev/null +++ b/monkey_island/cc/ui/src/components/reactive-graph/ReactiveGraph.js @@ -0,0 +1,15 @@ +import React from 'react'; +import Graph from 'react-graph-vis'; +import Dimensions from 'react-dimensions' + +class GraphWrapper extends React.Component { + render() { + let newOptions = this.props.options; + newOptions.height = this.props.containerHeight.toString() + 'px'; + newOptions.width = this.props.containerWidth.toString() + 'px'; + return () + } +} + +let ReactiveGraph = Dimensions()(GraphWrapper); +export {ReactiveGraph}; From a807e3f8b66a4fdb37dbd75fa1d19272ef02eacf Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Sun, 8 Oct 2017 15:36:12 +0300 Subject: [PATCH 08/12] Organize and improve documentation of config --- monkey_island/cc/services/config.py | 122 +++++++++++------- .../ui/src/components/pages/ConfigurePage.js | 10 +- 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 97dae84cd..69ac22c97 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -21,56 +21,56 @@ SCHEMA = { "enum": [ "SmbExploiter" ], - "title": "SmbExploiter" + "title": "SMB Exploiter" }, { "type": "string", "enum": [ "WmiExploiter" ], - "title": "WmiExploiter" + "title": "WMI Exploiter" }, { "type": "string", "enum": [ "RdpExploiter" ], - "title": "RdpExploiter (UNSAFE)" + "title": "RDP Exploiter (UNSAFE)" }, { "type": "string", "enum": [ "Ms08_067_Exploiter" ], - "title": "Ms08-067 Exploiter (UNSAFE)" + "title": "MS08-067 Exploiter (UNSAFE)" }, { "type": "string", "enum": [ "SSHExploiter" ], - "title": "SSHExploiter" + "title": "SSH Exploiter" }, { "type": "string", "enum": [ "ShellShockExploiter" ], - "title": "ShellShockExploiter" + "title": "ShellShock Exploiter" }, { "type": "string", "enum": [ "SambaCryExploiter" ], - "title": "SambaCryExploiter" + "title": "SambaCry Exploiter" }, { "type": "string", "enum": [ "ElasticGroovyExploiter" ], - "title": "ElasticGroovyExploiter" + "title": "ElasticGroovy Exploiter" }, ] }, @@ -125,7 +125,7 @@ SCHEMA = { }, "properties": { "basic": { - "title": "Basic", + "title": "Basic - Credentials", "type": "object", "properties": { "credentials": { @@ -188,7 +188,7 @@ SCHEMA = { "title": "Local network scan", "type": "boolean", "default": True, - "description": "Determines whether monkey should scan its subnets additionally" + "description": "Determines whether the monkey should scan its subnets additionally" }, "depth": { "title": "Depth" + WARNING_SIGN, @@ -212,17 +212,23 @@ SCHEMA = { "ClassCRange" ], "enumNames": [ - "FixedRange", - "RelativeRange", - "ClassCRange" + "Fixed Range", + "Relative Range", + "Class C Range" ], - "description": "Determines which class to use to determine scan range" + "description": + "Determines which class to use to determine scan range." + " Fixed Range will scan only specific IPs listed under Fixed range IP list." + " Relative Range will scan the closest ips to the machine's IP." + " Class C Range will scan machines in the Class C network the monkey's on." }, "range_size": { "title": "Relative range size", "type": "integer", "default": 1, - "description": "Determines the size of the RelativeRange - amount of IPs to include" + "description": + "Determines the size of the RelativeRange - amount of IPs to scan" + " (Only relevant for Relative Range)" }, "range_fixed": { "title": "Fixed range IP list", @@ -233,7 +239,9 @@ SCHEMA = { }, "default": [ ], - "description": "List of IPs to include when using FixedRange" + "description": + "List of IPs to include when using FixedRange" + " (Only relevant for Fixed Range)" } } } @@ -293,25 +301,30 @@ SCHEMA = { "title": "Max victims to find", "type": "integer", "default": 30, - "description": "Determines after how many discovered machines should the monkey stop scanning" + "description": "Determines the maximum number of machines the monkey is allowed to scan" }, "victims_max_exploit": { "title": "Max victims to exploit" + WARNING_SIGN, "type": "integer", "default": 7, - "description": "Determines after how many infected machines should the monkey stop infecting" + "description": + "Determines the maximum number of machines the monkey" + " is allowed to successfully exploit" }, "timeout_between_iterations": { "title": "Wait time between iterations", "type": "integer", "default": 100, - "description": "Determines for how long (in seconds) should the monkey wait between iterations" + "description": + "Determines for how long (in seconds) should the monkey wait between iterations" }, "retry_failed_explotation": { "title": "Retry failed exploitation", "type": "boolean", "default": True, - "description": "Determines whether the monkey should retry exploiting machines it didn't successfuly exploit on previous iterations" + "description": + "Determines whether the monkey should retry exploiting machines" + " it didn't successfuly exploit on previous iterations" } } } @@ -329,7 +342,8 @@ SCHEMA = { "title": "Singleton mutex name", "type": "string", "default": "{2384ec59-0df8-4ab9-918c-843740924a28}", - "description": "The name of the mutex used to determine whether the monkey is already running" + "description": + "The name of the mutex used to determine whether the monkey is already running" }, "collect_system_info": { "title": "Collect system info", @@ -371,23 +385,6 @@ SCHEMA = { "ElasticFinger" ], "description": "Determines which classes to use for fingerprinting" - }, - "exploiter_classes": { - "title": "Exploiter classes" + WARNING_SIGN, - "type": "array", - "uniqueItems": True, - "items": { - "$ref": "#/definitions/exploiter_classes" - }, - "default": [ - "SmbExploiter", - "WmiExploiter", - "SSHExploiter", - "ShellShockExploiter", - "SambaCryExploiter", - "ElasticGroovyExploiter" - ], - "description": "Determines which classes to use for exploiting" } } }, @@ -417,19 +414,25 @@ SCHEMA = { "title": "Dropper sets date", "type": "boolean", "default": True, - "description": "Determines whether the dropper should set the monkey's file date to be the same as another file" + "description": + "Determines whether the dropper should set the monkey's file date to be the same as" + " another file" }, "dropper_date_reference_path_windows": { "title": "Dropper date reference path (Windows)", "type": "string", "default": "%windir%\\system32\\kernel32.dll", - "description": "Determines which file the dropper should copy the date from if it's configured to do so on Windows (use fullpath)" + "description": + "Determines which file the dropper should copy the date from if it's configured to do" + " so on Windows (use fullpath)" }, "dropper_date_reference_path_linux": { "title": "Dropper date reference path (Linux)", "type": "string", "default": "/bin/sh", - "description": "Determines which file the dropper should copy the date from if it's configured to do so on Linux (use fullpath)" + "description": + "Determines which file the dropper should copy the date from if it's configured to do" + " so on Linux (use fullpath)" }, "dropper_target_path_linux": { "title": "Dropper target path on Linux", @@ -447,7 +450,9 @@ SCHEMA = { "title": "Try to move first", "type": "boolean", "default": True, - "description": "Determines whether the dropper should try to move itself instead of copying itself to target path" + "description": + "Determines whether the dropper should try to move itsel instead of copying itself" + " to target path" } } }, @@ -515,7 +520,8 @@ SCHEMA = { "title": "Mimikatz DLL name", "type": "string", "default": "mk.dll", - "description": "Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)" + "description": + "Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)" } } } @@ -552,7 +558,9 @@ SCHEMA = { "monkey.guardicore.com", "www.google.com" ], - "description": "List of internet services to try and communicate with to determine internet connectivity (use either ip or domain)" + "description": + "List of internet services to try and communicate with to determine internet" + " connectivity (use either ip or domain)" }, "current_server": { "title": "Current server", @@ -572,11 +580,29 @@ SCHEMA = { "title": "General", "type": "object", "properties": { + "exploiter_classes": { + "title": "Exploits" + WARNING_SIGN, + "type": "array", + "uniqueItems": True, + "items": { + "$ref": "#/definitions/exploiter_classes" + }, + "default": [ + "SmbExploiter", + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter" + ], + "description": "Determines which exploits to use" + }, "skip_exploit_if_file_exist": { "title": "Skip exploit if file exists", "type": "boolean", "default": False, - "description": "Determines whether the monkey should skip the exploit if the monkey's file is already on the remote machine" + "description": "Determines whether the monkey should skip the exploit if the monkey's file" + " is already on the remote machine" } } }, @@ -612,7 +638,8 @@ SCHEMA = { "title": "Use VBS download", "type": "boolean", "default": True, - "description": "Determines whether to use VBS or BITS to download monkey to remote machine (true=VBS, false=BITS)" + "description": "Determines whether to use VBS or BITS to download monkey to remote machine" + " (true=VBS, false=BITS)" } } }, @@ -667,7 +694,8 @@ SCHEMA = { "title": "SMB download timeout", "type": "integer", "default": 300, - "description": "Timeout (in seconds) for SMB download operation (used in various exploits using SMB)" + "description": + "Timeout (in seconds) for SMB download operation (used in various exploits using SMB)" }, "smb_service_name": { "title": "SMB service name", diff --git a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index 4fcff5c72..ad98f5564 100644 --- a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -116,7 +116,15 @@ class ConfigurePageComponent extends React.Component { {section.title} )} - + { + this.state.selectedSection === 'basic_network' ? +
+ + The Monkey scans its subnet if "Local network scan" is ticked. Additionally the monkey will scan machines + according to its range class. +
+ :
+ } { this.state.selectedSection ?
Date: Sun, 8 Oct 2017 17:11:46 +0300 Subject: [PATCH 09/12] Add warning to kill all monkeys --- monkey_island/cc/ui/package.json | 1 + .../cc/ui/src/components/pages/MapPage.js | 35 +++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index e47f4bae0..64d7643ce 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -76,6 +76,7 @@ "react-graph-vis": "^0.1.3", "react-json-tree": "^0.10.9", "react-jsonschema-form": "^0.50.1", + "react-modal-dialog": "^4.0.7", "react-redux": "^5.0.6", "react-router-dom": "^4.2.2", "react-toggle": "^4.0.1", diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index 4fe280714..1433ac515 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -4,6 +4,7 @@ import {Link} from 'react-router-dom'; import {Icon} from 'react-fa'; import PreviewPane from 'components/preview-pane/PreviewPane'; import {ReactiveGraph} from '../reactive-graph/ReactiveGraph'; +import {ModalContainer, ModalDialog} from 'react-modal-dialog'; let groupNames = ['clean_unknown', 'clean_linux', 'clean_windows', 'exploited_linux', 'exploited_windows', 'island', 'island_monkey_linux', 'island_monkey_linux_running', 'island_monkey_windows', 'island_monkey_windows_running', @@ -52,7 +53,8 @@ class MapPageComponent extends React.Component { graph: {nodes: [], edges: []}, selected: null, selectedType: null, - killPressed: false + killPressed: false, + showKillDialog: false }; } @@ -127,9 +129,38 @@ class MapPageComponent extends React.Component { .then(res => this.setState({killPressed: (res.status === 'OK')})); }; + renderKillDialogModal = () => { + if (!this.state.showKillDialog) { + return
+ } + + return ( + this.setState({showKillDialog: false})}> + this.setState({showKillDialog: false})}> +

Kill all monkeys

+

+ Are you sure you want to kill all monkeys? +

+ + +
+
+ ) + }; + render() { return (
+ {this.renderKillDialogModal()}

Infection Map

@@ -149,7 +180,7 @@ class MapPageComponent extends React.Component {
Monkey Telemetry - From 8ba6ccf939bc3d42b9a8fd118e271fe75a7e2db8 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Sun, 8 Oct 2017 17:58:40 +0300 Subject: [PATCH 10/12] Add warning to reset environment --- .../ui/src/components/pages/StartOverPage.js | 73 +++++++++++++++++-- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/monkey_island/cc/ui/src/components/pages/StartOverPage.js b/monkey_island/cc/ui/src/components/pages/StartOverPage.js index 6ecb2cc69..0152c9b61 100644 --- a/monkey_island/cc/ui/src/components/pages/StartOverPage.js +++ b/monkey_island/cc/ui/src/components/pages/StartOverPage.js @@ -1,19 +1,71 @@ import React from 'react'; import {Col} from 'react-bootstrap'; import {Link} from 'react-router-dom'; +import {ModalContainer, ModalDialog} from 'react-modal-dialog'; class StartOverPageComponent extends React.Component { constructor(props) { super(props); this.state = { - cleaned: false + cleaned: false, + showCleanDialog: false, + allMonkeysAreDead: false }; } + updateMonkeysRunning = () => { + fetch('/api') + .then(res => res.json()) + .then(res => { + // This check is used to prevent unnecessary re-rendering + this.setState({ + allMonkeysAreDead: (!res['completed_steps']['run_monkey']) || (res['completed_steps']['infection_done']) + }); + }); + }; + + renderCleanDialogModal = () => { + if (!this.state.showCleanDialog) { + return
+ } + + return ( + this.setState({showCleanDialog: false})}> + this.setState({showCleanDialog: false})}> +

Reset environment

+

+ Are you sure you want to reset the environment? +

+ { + !this.state.allMonkeysAreDead ? +
+ + Some monkeys are still running. It's advised to kill all monkeys before resetting. +
+ : +
+ } + + + + + ) + }; + render() { return ( + {this.renderCleanDialogModal()}

Start Over

@@ -23,19 +75,26 @@ class StartOverPageComponent extends React.Component {

After that you could go back to the Run Monkey page to start new infections.

-

- Reset Environment +

+

+
+ + You can continue and Run More Monkeys as you wish, + and see the results on the Infection Map without deleting anything. +
{ this.state.cleaned ?
Environment was reset successfully
: ''} -

- * BTW you can just continue and run more monkeys as you wish, - and see the results on the Infection Map without deleting anything. -

); From 48790b6ecbfb7da03e3afb21da0207a03e710bfb Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Sun, 8 Oct 2017 19:57:41 +0300 Subject: [PATCH 11/12] Improve map physics --- monkey_island/cc/ui/src/components/pages/MapPage.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index 1433ac515..f59018425 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -38,10 +38,11 @@ let options = { } }, physics: { - solver: 'forceAtlas2Based', - forceAtlas2Based: { - gravitationalConstant: -370 - } + barnesHut: { + gravitationalConstant: -120000, + avoidOverlap: 0.5 + }, + minVelocity: 0.75 }, groups: getGroupsOptions() }; From 1b558e72be314450fa31547cb2f6745cfd682b3f Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 10 Oct 2017 19:26:25 +0300 Subject: [PATCH 12/12] Add readme section --- monkey_island/cc/ui/package.json | 3 + monkey_island/cc/ui/src/README.md | 191 ++++++++++++++++++ monkey_island/cc/ui/src/components/Main.js | 4 + .../cc/ui/src/components/pages/ReadMePage.js | 24 +++ monkey_island/cc/ui/src/styles/App.css | 14 ++ 5 files changed, 236 insertions(+) create mode 100644 monkey_island/cc/ui/src/README.md create mode 100644 monkey_island/cc/ui/src/components/pages/ReadMePage.js diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 64d7643ce..d744b8c89 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -64,8 +64,11 @@ "bootstrap": "^3.3.7", "core-js": "^2.5.1", "fetch": "^1.1.0", + "github-markdown-css": "^2.8.0", + "marked": "^0.3.6", "normalize.css": "^4.0.0", "prop-types": "^15.5.10", + "raw-loader": "^0.5.1", "react": "^15.6.1", "react-bootstrap": "^0.31.2", "react-copy-to-clipboard": "^5.0.0", diff --git a/monkey_island/cc/ui/src/README.md b/monkey_island/cc/ui/src/README.md new file mode 100644 index 000000000..32d530e74 --- /dev/null +++ b/monkey_island/cc/ui/src/README.md @@ -0,0 +1,191 @@ +Infection Monkey +==================== + +### Data center Security Testing Tool +------------------------ + +Welcome to the Infection Monkey! + +The Infection Monkey is an open source security tool for testing a data center's resiliency to perimeter breaches and internal server infection. The Monkey uses various methods to self propagate across a data center and reports success to a centralized C&C server. To read more about the Monkey, visit https://www.guardicore.com/infectionmonkey/ + +### http://www.guardicore.com/the-infected-chaos-monkey/ + +Features include: + +* Multiple propagation techniques: + * Predefined passwords + * Common exploits +* Multiple exploit methods: + * SSH + * SMB + * RDP + * WMI + * Shellshock +* A C&C server with a dedicated UI to visualize the Monkey's progress inside the data center + +Getting Started +--------------- + +The Infection Monkey is comprised of two parts: the Monkey and the C&C server. +The monkey is the tool which infects other machines and propagates to them, while the C&C server collects all Monkey reports and displays them to the user. + +### Requirements + +The C&C Server has been tested on Ubuntu 14.04,15.04 and 16.04. +The Monkey itself has been tested on Windows XP, 7, 8.1 and 10. The Linux build has been tested on Ubuntu server 14.04 and 15.10. + +### Installation + +Warning! The Debian package will uninstall the python library 'bson' because of an issue with pymongo. You can reinstall it later, but monkey island will probably not work. + +For off-the-shelf use, download our Debian package from our website and follow the guide [written in our blog](https://www.guardicore.com/2016/07/infection-monkey-loose-2/). + To manually set up and the C&C server follow the instructions on [Monkey Island readme](monkey_island/readme.txt). If you wish to compile the binaries yourself, follow the instructions under Building the Monkey from Source. + +### Initial configuration. +Whether you're downloading or building the Monkey from source, the Infection Monkey is comprised of 4 executable files for different platforms plus a default configuration file. + +Monkey configuration is stored in two places: +1. By default, the Monkey uses a local configuration file (usually, config.bin). This configuration file must include the address of the Monkey's C&C server. +2. After successfully connecting to the C&C server, the monkey downloads a new configuration from the server and discards the local configuration. It is possible to change the default configuration from the C&C server's UI. + +In both cases the command server hostname should be modified to point to your local instance of the Monkey Island (note that this doesn't require connectivity right off the bat). In addition, to improve the Monkey's chances of spreading, you can pre-seed it with credentials and usernames commonly used. + +Both configuration options use a JSON format for specifying options; see "Options" below for details. + +### Running the C&C Server + +To run the C&C Server, install our infected Monkey debian package on a specific server. The initial infected machine doesn't require a direct link to this server. + +### Unleashing the Monkey + +Once configured, run the monkey using ```./monkey-linux-64 m0nk3y -c config.bin -s 41.50.73.31:5000``` (Windows is identical). This can be done at multiple points in the network simultaneously. + +Command line options include: +* `-c`, `--config`: set configuration file. JSON file with configuration values, will override compiled configuration. +* `-p`, `--parent`: set monkey’s parent uuid, allows better recognition of exploited monkeys in c&c +* `-t`, `--tunnel`: ip:port, set default tunnel for Monkey when connecting to c&c. +* `-d`, `--depth` : sets the Monkey's current operation depth. + + +How the Monkey works +--------------------- + +1. Wakeup connection to c&c, sends basic info of the current machine and the configuration the monkey uses to the c&c. + 1. First try direct connection to c&c. + 2. If direct connection fails, try connection through a tunnel, a tunnel is found according to specified parameter (the default tunnel) or by sending a multicast query and waiting for another monkey to answer. + 3. If no connection can be made to c&c, continue without it. +2. If a firewall app is running on the machine (supports Windows Firewall for Win XP and Windows Advanced Firewall for Win 7+), try to add a rule to allow all our traffic. +3. Startup of tunnel for other Monkeys (if connection to c&c works). + 1. Firewall is checked to allow listening sockets (if we failed to add a rule to Windows firewall for example, the tunnel will not be created) + 2. Will answer multicast requests from other Monkeys in search of a tunnel. +4. Running exploitation sessions, will run x sessions according to configuration: + 1. Connect to c&c and get the latest configuration + 2. Scan ip ranges according to configuration. + 3. Try fingerprinting each host that answers, using the classes defined in the configuration (SMBFinger, SSHFinger, etc) + 4. Try exploitation on each host found, for each exploit class in configuration: + 1. check exploit class supports target host (can be disabled by configuration) + 2. each exploitation class will use the data acquired in fingerprinting, or during the exploit, to find the suitable Monkey executable for the host from the c&c. + 1. If c&c connection fails, and the source monkey’s executable is suitable, we use it. + 2. If a suitable executable isn’t found, exploitation will fail. + 3. Executables are cached in memory. + 5. will skip hosts that are already exploited in next run + 6. will skip hosts that failed during exploitation in next run (can be disabled by configuration) +5. Close tunnel before exiting +Wait for monkeys using the tunnel to unregister for it +Cleanup +Remove firewall rules if added + +Configuration Options +--------------------- + +Key | Type | Description | Possible Values +--- | ---- | ----------- | --------------- +alive | bool | sets whether or not the monkey is alive. if false will stop scanning and exploiting +command_servers | array | addresses of c&c servers to try to connect | example: ["russian-mail-brides.com:5000"] +singleton_mutex_name | string | string of the mutex name for single instance | example: {2384ec59-0df8-4ab9-918c-843740924a28} +self_delete_in_cleanup | bool | sets whether or not to self delete the monkey executable when stopped +use_file_logging | bool | sets whether or not to use a log file +monkey_log_path_[windows/linux] | string | file path for monkey logger. +kill_file_path_[windows/linux] | string | file path that the Monkey checks to prevent running +timeout_between_iterations | int | how long to wait between scan iterations +max_iterations | int | how many scan iterations to perform on each run +internet_services | array | addresses of internet servers to ping and check if the monkey has internet acccess +victims_max_find | int | how many victims to look for in a single scan iteration +victims_max_exploit | int | how many victims to exploit before stopping +retry_failed_explotation | bool | sets whether or not to retry failed hosts on next scan +local_network_scan | bool | sets whether to auto detect and scan local subnets +range_class | class name | sets which ip ranges class is used to construct the list of ips to scan | `FixedRange` - scan list is a static ips list, `RelativeRange` - scan list will be constructed according to ip address of the machine and size of the scan, `ClassCRange` - will scan the entire class c the machine is in. +range_fixed | tuple of strings | list of ips to scan +RelativeRange range_size | int | number of hosts to scan in relative range +scanner_class | class name | sets which scan class to use when scanning for hosts to exploit | `TCPScanner` - searches for hosts according to open tcp ports, `PingScanner` - searches for hosts according to ping scan +finger_classes | tuple of class names | sets which fingerprinting classes to use | in the list: `SMBFinger` - get host os info by checking smb info, `SSHFinger` - get host os info by checking ssh banner, `PingScanner` - get host os type by checking ping ttl. For example: `(SMBFinger, SSHFinger, PingScanner)` +exploiter_classes | tuple of class names | | `SmbExploiter` - exploit using smb connection, `WmiExploiter` - exploit using wmi connection, `RdpExploiter` - exploit using rdp connection, `Ms08_067_Exploiter` - exploit using ms08_067 smb exploit, `SSHExploiter` - exploit using ssh connection +tcp_target_ports | list of int | which ports to scan using TCPScanner +tcp_scan_timeout | int | timeout for tcp connection in tcp scan (in milliseconds) +tcp_scan_interval | int | time to wait between ports in the tcp scan (in milliseconds) +tcp_scan_get_banner | bool | sets whether or not to read a banner from the tcp ports when scanning +ping_scan_timeout | int | timeout for the ping command (in milliseconds) utilised by PingScanner +skip_exploit_if_file_exist | bool | sets whether or not to abort exploit if the monkey already exists in target, used by SmbExploiter +psexec_user | string | user to use for connection, utilised by SmbExploiter/WmiExploiter/RdpExploiter +psexec_passwords | list of strings | list of passwords to use when trying to exploit +rdp_use_vbs_download | bool | sets whether to use vbs payload for rdp exploitation in RdpExploiter. If false, bits payload is used (will fail if bitsadmin.exe doesn’t exist) +ms08_067_exploit_attempt | int | number of times to try and exploit using ms08_067 exploit +ms08_067_remote_user_add | string | user to add to target when using ms08_067 exploit +ms08_067_remote_user_pass | string | password of the user the exploit will add +ssh_user | string | user to use for ssh connection, used by SSHExploiter +ssh_passwords | list of strings | list of passwords to use when trying to exploit using SSHExploiter +dropper_set_date | bool | whether or not to change the monkey file date to match other files +dropper_target_path_[windows/linux] | string | path for the dropper +serialize_config | bool | sets whether or not to locally save the running configuration after finishing + + +Building the Monkey from source +------------------------------- +If you want to build the monkey from source instead of using our provided packages, follow the instructions at the readme files under [chaos_monkey](chaos_monkey) and [monkey_island](monkey_island). + + +License +======= +Copyright (c) 2016 Guardicore Ltd + +See the [LICENSE](LICENSE) file for license rights and limitations (GPLv3). + +Dependent packages +--------------------- + +Dependency | License | Notes +----------------------------|----------------------------|---------------------------- + libffi-dev | https://github.com/atgreen/libffi/blob/master/LICENSE + PyCrypto | Public domain + upx | Custom license, http://upx.sourceforge.net/upx-license.html + bson | BSD + enum34 | BSD + pyasn1 | BSD + psutil | BSD + flask | BSD + flask-Pymongo | BSD + Flask-Restful | BSD + python-dateutil | Simplified BSD + zope | ZPL 2.1 + Bootstrap | MIT + Bootstrap Switch | Apache 2.0 + Bootstrap Dialog | MIT + JSON Editor | MIT + Datatables | MIT + jQuery | MIT + cffi | MIT + twisted | MIT + typeahead.js | MIT + Font Awesome | MIT + vis.js | MIT/Apache 2.0 + impacket | Apache Modified + Start Bootstrap (UI Theme) | Apache 2.0 + requests | Apache 2.0 + grequests | BSD + odict | Python Software Foundation License + paramiko | LGPL + rdpy | GPL-3 + winbind | GPL-3 + pyinstaller | GPL + Celery | BSD + mimikatz | CC BY 4.0 | We use an altered version of mimikatz made by gentilkiwi: https://github.com/guardicore/mimikatz diff --git a/monkey_island/cc/ui/src/components/Main.js b/monkey_island/cc/ui/src/components/Main.js index 22aa91df4..34e6f0137 100644 --- a/monkey_island/cc/ui/src/components/Main.js +++ b/monkey_island/cc/ui/src/components/Main.js @@ -10,11 +10,13 @@ import MapPage from 'components/pages/MapPage'; import TelemetryPage from 'components/pages/TelemetryPage'; import StartOverPage from 'components/pages/StartOverPage'; import ReportPage from 'components/pages/ReportPage'; +import ReadMePage from 'components/pages/ReadMePage'; require('normalize.css/normalize.css'); require('react-data-components/css/table-twbs.css'); require('styles/App.css') require('react-toggle/style.css'); +require('github-markdown-css/github-markdown.css'); let logoImage = require('../images/monkey-logo.png'); let guardicoreLogoImage = require('../images/guardicore-logo.png'); @@ -114,6 +116,7 @@ class AppComponent extends React.Component {
  • Configuration
  • Monkey Telemetry
  • +
  • Read Me

@@ -133,6 +136,7 @@ class AppComponent extends React.Component { ( )} /> ( )} /> ( )} /> + ( )} /> diff --git a/monkey_island/cc/ui/src/components/pages/ReadMePage.js b/monkey_island/cc/ui/src/components/pages/ReadMePage.js new file mode 100644 index 000000000..81329b982 --- /dev/null +++ b/monkey_island/cc/ui/src/components/pages/ReadMePage.js @@ -0,0 +1,24 @@ +import React from 'react'; +import {Col} from 'react-bootstrap'; +var marked = require('marked'); + +var markdown = require('raw!../../README.md'); + +class ReadMePageComponent extends React.Component { + constructor(props) { + super(props); + } + + render() { + + return ( + +

Read Me

+
+
+ + ); + } +} + +export default ReadMePageComponent; diff --git a/monkey_island/cc/ui/src/styles/App.css b/monkey_island/cc/ui/src/styles/App.css index bf051bca8..300e14cf8 100644 --- a/monkey_island/cc/ui/src/styles/App.css +++ b/monkey_island/cc/ui/src/styles/App.css @@ -317,3 +317,17 @@ body { .data-table-container .pagination { margin: 0 !important; } + +.markdown-body { + box-sizing: border-box; + min-width: 200px; + max-width: 980px; + margin: 0 auto; + padding: 45px; +} + +@media (max-width: 767px) { + .markdown-body { + padding: 15px; + } +}