diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 08eb0e329..cc203ba9f 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -97,6 +97,64 @@ SCHEMA = { } }, "properties": { + "basic": { + "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", + "properties": { + "exploit_user_list": { + "title": "Exploit user list", + "type": "array", + "uniqueItems": True, + "items": { + "type": "string" + }, + "default": [ + "Administrator", + "root", + "user" + ], + "description": "List of usernames to use on exploits using credentials" + }, + "exploit_password_list": { + "title": "Exploit password list", + "type": "array", + "uniqueItems": True, + "items": { + "type": "string" + }, + "default": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "description": "List of password to use on exploits using credentials" + } + } + } + } + }, "monkey": { "title": "Monkey", "type": "object", @@ -393,41 +451,6 @@ SCHEMA = { } } }, - "credentials": { - "title": "Credentials", - "type": "object", - "properties": { - "exploit_user_list": { - "title": "Exploit user list", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string" - }, - "default": [ - "Administrator", - "root", - "user" - ], - "description": "List of usernames to use on exploits using credentials" - }, - "exploit_password_list": { - "title": "Exploit password list", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string" - }, - "default": [ - "Password1!", - "1234", - "password", - "12345678" - ], - "description": "List of password to use on exploits using credentials" - } - } - }, "ms08_067": { "title": "MS08_067", "type": "object", @@ -605,17 +628,6 @@ SCHEMA = { "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", diff --git a/monkey_island/cc/services/edge.py b/monkey_island/cc/services/edge.py index 320c197fc..9cfd440d8 100644 --- a/monkey_island/cc/services/edge.py +++ b/monkey_island/cc/services/edge.py @@ -55,16 +55,13 @@ class EdgeService: exploit_container["result"] = True exploit_container["end_timestamp"] = new_exploit["timestamp"] - return \ - { - "id": edge["_id"], - "from": edge["from"], - "to": edge["to"], - "ip_address": edge["ip_address"], - "services": services, - "os": os, - "exploits": exploits - } + displayed_edge = EdgeService.edge_to_net_edge(edge) + displayed_edge["ip_address"] = edge["ip_address"] + displayed_edge["services"] = services + displayed_edge["os"] = os + displayed_edge["exploits"] = exploits + displayed_edge["_label"] = EdgeService.get_edge_label(displayed_edge) + return displayed_edge @staticmethod def exploit_to_displayed_exploit(exploit): @@ -113,13 +110,15 @@ class EdgeService: @staticmethod def generate_pseudo_edge(edge_id, edge_from, edge_to): - return \ + edge = \ { "id": edge_id, "from": edge_from, "to": edge_to, "group": "island" } + edge["_label"] = EdgeService.get_edge_label(edge) + return edge @staticmethod def get_monkey_island_pseudo_edges(): @@ -184,6 +183,22 @@ class EdgeService: {"_id": edge["_id"]}, {"$set": {"exploited": True}} ) - cc.services.node.NodeService.set_node_exploited(edge["to"]) + @staticmethod + def get_edge_label(edge): + NodeService = cc.services.node.NodeService + from_label = NodeService.get_monkey_label(NodeService.get_monkey_by_id(edge["from"])) + to_id = NodeService.get_monkey_by_id(edge["to"]) + if to_id is None: + to_label = NodeService.get_node_label(NodeService.get_node_by_id(edge["to"])) + else: + to_label = NodeService.get_monkey_label(to_id) + + RIGHT_ARROW = unichr(8594) + return "%s %s %s" % ( + from_label, + RIGHT_ARROW, + to_label) + + diff --git a/monkey_island/cc/services/node.py b/monkey_island/cc/services/node.py index c196546ca..720bd06db 100644 --- a/monkey_island/cc/services/node.py +++ b/monkey_island/cc/services/node.py @@ -85,7 +85,6 @@ class NodeService: return True - @staticmethod def get_monkey_label(monkey): label = monkey["hostname"] + " : " + monkey["ip_addresses"][0] diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index 8b2636e22..4606af898 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -93,13 +93,12 @@ class MapPageComponent extends React.Component { .then(res => this.setState({selected: res, selectedType: 'node'})); } else if (event.edges.length === 1) { - let edgeGroup = this.state.graph.edges.filter( + let displayedEdge = this.state.graph.edges.find( function(edge) { return edge['id'] === event.edges[0]; - })[0]['group']; - if (edgeGroup == 'island') { - console.log('selection cleared.'); // eslint-disable-line no-console - this.setState({selected: null, selectedType: null}); + }); + if (displayedEdge['group'] == 'island') { + this.setState({selected: displayedEdge, selectedType: 'island_edge'}); } else { fetch('/api/netmap/edge?id='+event.edges[0]) .then(res => res.json()) diff --git a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js index eae417d60..f125ddff1 100644 --- a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js +++ b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js @@ -30,8 +30,16 @@ class RunMonkeyPageComponent extends React.Component { this.props.onStatusChange(); } - generateCmd(ip) { - return `curl http://${ip}:5000/get-monkey | sh`; + generateLinuxCmd(ip, is32Bit) { + let bitText = is32Bit ? '32' : '64'; + return `curl http://${ip}:5000/api/monkey/download/monkey-linux-${bitText} | sh`; + } + + generateWindowsCmd(ip, is32Bit) { + let bitText = is32Bit ? '32' : '64'; + return ` + PowerShell (New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/monkey-windows-${bitText}.exe','monkey.exe'); + Start-Process -FilePath 'monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`; } runLocalMonkey = () => { @@ -50,6 +58,27 @@ class RunMonkeyPageComponent extends React.Component { }); }; + generateCmdDiv(ip, isLinux, is32Bit) { + let cmdText = ""; + if (isLinux) { + cmdText = this.generateLinuxCmd(ip, is32Bit); + } else { + cmdText = this.generateWindowsCmd(ip, is32Bit); + } + return ( + +
+ + + + {cmdText} +
+
+ ) + } + render() { return ( @@ -83,18 +112,18 @@ class RunMonkeyPageComponent extends React.Component {
(The IP address is used as the monkey's C&C address)

- + {this.state.ips.map(ip => -
- - - - {this.generateCmd(ip)} -
+ + [ + this.generateCmdDiv(ip, true, true), + this.generateCmdDiv(ip, true, false), + this.generateCmdDiv(ip, false, true), + this.generateCmdDiv(ip, false, false) + ] + )} -
+

Go ahead and monitor the ongoing infection in the Infection Map view. diff --git a/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js b/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js index 2f49f6257..e8711dba4 100644 --- a/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js +++ b/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js @@ -30,6 +30,8 @@ class PreviewPaneComponent extends React.Component { } infectedAssetInfo(asset) { + // TODO: Have exploit info expandable (show detailed attempts) + // TODO: consider showing scans with exploits on same timeline return (

{this.assetInfo(asset)} @@ -50,17 +52,54 @@ class PreviewPaneComponent extends React.Component { } infectionInfo(edge) { - return ( -
- -
- ); + return this.scanInfo(edge); } scanInfo(edge) { return (
+ + + + + + + + + + + + + + + +
Operating System{edge.os.type}
IP Address{edge.ip_address}
Services{edge.services.map(val =>
{val}
)}
+

Timeline

+ +
+ ); + } + islandEdgeInfo() { + return ( +
+ + + + + + + +
Communicates directly with islandTrue
); } @@ -71,13 +110,28 @@ class PreviewPaneComponent extends React.Component { case 'edge': info = this.props.item.exploits.length ? this.infectionInfo(this.props.item) : this.scanInfo(this.props.item); + break; case 'node': info = this.props.item.exploits.some(exploit => exploit.result) ? this.infectedAssetInfo(this.props.item) : this.assetInfo(this.props.item); + break; + case 'island_edge': + info = this.islandEdgeInfo(); + break; } + + let label = ''; + if (!this.props.item) { + label = ''; + } else if (this.props.item.hasOwnProperty('label')) { + label = this.props.item['label']; + } else if (this.props.item.hasOwnProperty('_label')) { + label = this.props.item['_label']; + } + return (
- { !this.props.item ? + { !info ? Select an item on the map for a preview @@ -85,7 +139,7 @@ class PreviewPaneComponent extends React.Component { :

- {this.props.item.label} + {label}