forked from p34709852/monkey
Merge branch 'master' of https://github.com/guardicore/monkey
This commit is contained in:
commit
3cd0d5818a
|
@ -162,6 +162,9 @@ class ChaosMonkey(object):
|
|||
break
|
||||
else:
|
||||
LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__)
|
||||
ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__,
|
||||
'exploiter': exploiter.__class__.__name__})
|
||||
|
||||
except Exception, exc:
|
||||
LOG.error("Exception while attacking %s using %s: %s",
|
||||
machine, exploiter.__class__.__name__, exc)
|
||||
|
@ -169,7 +172,7 @@ class ChaosMonkey(object):
|
|||
|
||||
if successful_exploiter:
|
||||
self._exploited_machines.add(machine)
|
||||
ControlClient.send_telemetry('exploit', {'machine': machine.__dict__,
|
||||
ControlClient.send_telemetry('exploit', {'result': True, 'machine': machine.__dict__,
|
||||
'exploiter': successful_exploiter.__class__.__name__})
|
||||
|
||||
LOG.info("Successfully propagated to %s using %s",
|
||||
|
|
|
@ -1,4 +1,45 @@
|
|||
dependencies:
|
||||
sudo pip install pyVmomi
|
||||
sudo pip install celery
|
||||
sudo pip install -U celery[mongodb]
|
||||
How to install Monkey Business server:
|
||||
|
||||
---------------- On Linux ----------------:
|
||||
1. Create the following directories:
|
||||
sudo mkdir /var/monkey_business
|
||||
sudo chmod 777 /var/monkey_business
|
||||
mkdir -p /var/monkey_business/bin/mongodb
|
||||
mkdir -p /var/monkey_business/db
|
||||
mkdir -p /var/monkey_business/cc
|
||||
|
||||
2. Install the following packages:
|
||||
sudo pip install flask
|
||||
sudo pip install Flask-Pymongo
|
||||
sudo pip install Flask-Restful
|
||||
sudo pip install python-dateutil
|
||||
sudo pip install pyVmomi
|
||||
sudo pip install celery
|
||||
sudo pip install -U celery[mongodb]
|
||||
|
||||
4. Download MongoDB and extract it to /var/monkey_business/bin/mongodb
|
||||
for debian64 - https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-debian71-3.0.7.tgz
|
||||
for ubuntu64 14.10 - https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1410-clang-3.0.7.tgz
|
||||
find more at - https://www.mongodb.org/downloads#production
|
||||
untar.gz with: tar -zxvf filename.tar.gz -C /var/monkey_business/bin/mongodb
|
||||
(make sure the content of the mongo folder is in this directory, meaning this path exists:
|
||||
/var/monkey_business/bin/mongodb/bin)
|
||||
|
||||
5. install OpenSSL
|
||||
sudo apt-get install openssl
|
||||
|
||||
6. Generate SSL Certificate, Run create_certificate.sh (located under /linux)
|
||||
|
||||
7. Copy monkey business server to /var/monkey_business:
|
||||
cp -r [monkey_island_source]/cc /var/monkey_business/
|
||||
|
||||
|
||||
How to run:
|
||||
1. run run.sh
|
||||
* This performs:
|
||||
DB startup:
|
||||
/var/monkey_business/bin/mongodb/bin/mongod --dbpath db --fork --logpath db.log
|
||||
Jobs worker startup:
|
||||
nohup celery -A tasks_manager worker --loglevel=info
|
||||
Main Web Server startup:
|
||||
nohup python main.py
|
|
@ -83,8 +83,9 @@
|
|||
</div>
|
||||
<div id="info" class="panel-body panel-collapse collapse in">
|
||||
<div>
|
||||
Num of Monkeys: <label id="infoNumOfMonkeys">0</label> (<label id="infoNumOfParents">0</label> by exploiting)<br/>
|
||||
Num of Hosts Detected: <label id="infoNumOfHosts">0</label><br/>
|
||||
Num of Monkeys: <label id="infoNumOfMonkeys">0</label> (<label id="infoNumOfParents">0</label> exploiting were done)<br/>
|
||||
Monkyes Alive: <label id="infoNumOfAlive">0</label><br/>
|
||||
Num of Hosts Not Exploited: <label id="infoNumOfHosts">0</label><br/>
|
||||
Num of Tunnels Used: <label id="infoNumOfTunnels">0</label><br/>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -132,7 +133,7 @@
|
|||
</div>
|
||||
<hr>
|
||||
<div id="selectionInfo">
|
||||
<label>No selection</label>
|
||||
<label>Monkey not selected</label>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="panel panel-default">
|
||||
|
@ -188,6 +189,24 @@
|
|||
</div>
|
||||
<!-- /.Config section -->
|
||||
|
||||
<!-- Config section -->
|
||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="#reset" data-toggle="collapse">Reset Database</a>
|
||||
</div>
|
||||
<div id="reset" style="overflow: visible" class="panel-body panel-collapse collapse" aria-expanded="true">
|
||||
<span class="input-group-btn">
|
||||
<button id="btnResetDB" class="btn btn-default" type="button"
|
||||
onclick="resetDB()" style="margin-top:-4px">
|
||||
Reset Database
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.Config section -->
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -62,12 +62,13 @@ function initAdmin() {
|
|||
nodes = [];
|
||||
edges = [];
|
||||
|
||||
createNodes();
|
||||
createEdges();
|
||||
createTunnels();
|
||||
createScanned();
|
||||
|
||||
var data = {
|
||||
nodes: createNodes(),
|
||||
nodes: nodes,
|
||||
edges: edges
|
||||
};
|
||||
|
||||
|
@ -196,8 +197,19 @@ function updateMonkeys() {
|
|||
else
|
||||
{
|
||||
monkeys.push(new_monkeys[i]);
|
||||
nodes.push(createMonkeyNode(new_monkeys[i]));
|
||||
updateCounters();
|
||||
var exiting_scan = undefined;
|
||||
for (var j=0; j<new_monkeys[i].ip_addresses.length; j++) {
|
||||
exiting_scan = getScannedByIP(new_monkeys[i].ip_addresses[j]);
|
||||
if (exiting_scan != undefined) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exiting_scan == undefined) {
|
||||
nodes.push(createMonkeyNode(new_monkeys[i]));
|
||||
}
|
||||
else {
|
||||
convertScanNodeToMonkey(exiting_scan, new_monkeys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,6 +220,7 @@ function updateMonkeys() {
|
|||
refreshDrawing();
|
||||
}
|
||||
createScanned();
|
||||
updateCounters();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -238,9 +251,16 @@ function createMonkeyNode(monkey) {
|
|||
}
|
||||
img = ICONS_DIR + img + ICONS_EXT;
|
||||
|
||||
if (monkey.parent == monkey.guid) {
|
||||
if (monkey.parent == null) {
|
||||
font = { color: 'red' };
|
||||
}
|
||||
else {
|
||||
for (var i=0; i<monkey.parent.length; i++) {
|
||||
if (monkey.parent[i][1] == null) {
|
||||
font = { color: 'red' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'id': monkey.id,
|
||||
|
@ -283,15 +303,52 @@ function createMachineNode(machine) {
|
|||
};
|
||||
}
|
||||
|
||||
function convertScanNodeToMonkey(scanned, monkey) {
|
||||
var monNode = createMonkeyNode(monkey);
|
||||
nodes.push(monNode);
|
||||
|
||||
// move edges to new node
|
||||
for (var i = 0; i < edges.length; i++) {
|
||||
if (edges[i].to == scanned.id) {
|
||||
edges[i].to = monNode.id;
|
||||
}
|
||||
if (edges[i].from == scanned.id) {
|
||||
edges[i].from = monNode.id;
|
||||
}
|
||||
}
|
||||
for (var i=0; i<scannedMachines.length; i++) {
|
||||
if (scannedMachines[i].id == scanned.id) {
|
||||
scannedMachines.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i=0; i<nodes.length; i++) {
|
||||
if (nodes[i].id == scanned.id) {
|
||||
nodes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createEdges() {
|
||||
for (var i = 0; i < monkeys.length; i++) {
|
||||
var monkey = monkeys[i];
|
||||
if(monkey.parent != monkey.guid) {
|
||||
var parent = getMonkeyByGuid(monkey.parent);
|
||||
|
||||
if(parent && !edgeExists([parent.id, monkey.id, EDGE_TYPE_PARENT])) {
|
||||
edges.push({from: parent.id, to: monkey.id, arrows:'middle', type: EDGE_TYPE_PARENT, color: EDGE_COLOR_PARENT});
|
||||
numOfParentLinks++;
|
||||
if (monkey.parent == null) { continue; };
|
||||
|
||||
for (var j=0; j<monkey.parent.length; j++) {
|
||||
if(monkey.parent[j][0] != monkey.guid) {
|
||||
var parent = getMonkeyByGuid(monkey.parent[j][0]);
|
||||
var exploit = monkey.parent[j][1];
|
||||
|
||||
if(parent && !edgeExists([parent.id, monkey.id, EDGE_TYPE_PARENT])) {
|
||||
var title = "<center><b>" + exploit + "</b></center>From: " + parent.hostname + "<br/>To: " + monkey.hostname;
|
||||
edges.push({from: parent.id, to: monkey.id, arrows:'middle', type: EDGE_TYPE_PARENT, title: title, /*label: exploit, font: {color: 'red', size: 10, align: 'top'},*/ color: EDGE_COLOR_PARENT});
|
||||
if (removeEdge([parent.id, monkey.id, EDGE_TYPE_SCAN])) {
|
||||
numOfScanLinks--;
|
||||
}
|
||||
numOfParentLinks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -327,24 +384,20 @@ function createScanned() {
|
|||
var scan = scans[i];
|
||||
var monkey = getMonkeyByGuid(scan.monkey_guid);
|
||||
|
||||
//Check if we already exploited this machine from another PoV, if so no point in scanning.
|
||||
if (null != getMonkeyByIP(scan.data.machine.ip_addr)) {
|
||||
//if so, make sure we don't already have such a node
|
||||
nodes = nodes.filter(function (node) {
|
||||
return (node.id != ip_addr);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
// And check if we've already added this scanned machine
|
||||
var machineNode = getMonkeyByIP(scan.data.machine.ip_addr);
|
||||
|
||||
//And check if we've already added this scanned machine
|
||||
var machineNode = getScannedByIP(scan.data.machine.ip_addr)
|
||||
if (null == machineNode) {
|
||||
machineNode = createMachineNode(scan.data.machine);
|
||||
scannedMachines.push(machineNode);
|
||||
nodes.push(machineNode);
|
||||
machineNode = getScannedByIP(scan.data.machine.ip_addr);
|
||||
|
||||
if (null == machineNode) {
|
||||
machineNode = createMachineNode(scan.data.machine);
|
||||
scannedMachines.push(machineNode);
|
||||
nodes.push(machineNode);
|
||||
}
|
||||
}
|
||||
|
||||
if(!edgeExists([monkey.id, machineNode.id, EDGE_TYPE_SCAN])) {
|
||||
if(!edgeExists([monkey.id, machineNode.id, EDGE_TYPE_SCAN]) && !edgeExists([monkey.id, machineNode.id, EDGE_TYPE_PARENT])) {
|
||||
edges.push({from: monkey.id, to: machineNode.id, arrows:'middle', type: EDGE_TYPE_SCAN, color: EDGE_COLOR_SCAN});
|
||||
numOfScanLinks++;
|
||||
}
|
||||
|
@ -372,10 +425,34 @@ function buildMonkeyDescription(monkey) {
|
|||
}
|
||||
html +=
|
||||
"<label>Last Seen:</label> " + monkey.keepalive + "</br>" +
|
||||
"<label>IP Address:</label></br>";
|
||||
"<label>IP Address:</label><br/>";
|
||||
|
||||
html += "<ul>";
|
||||
for (var i = 0; i < monkey.ip_addresses.length; i++) {
|
||||
html += monkey.ip_addresses[i] + "</br>"
|
||||
html += "<li>" + monkey.ip_addresses[i];
|
||||
}
|
||||
html += "</ul>";
|
||||
|
||||
|
||||
if (monkey.parent != null) {
|
||||
html += "<label>Exploited by:</label><br/>"
|
||||
html += "<ul>";
|
||||
for (var i = 0; i < monkey.parent.length; i++) {
|
||||
html += "<li>";
|
||||
if (monkey.parent[i][0] == monkey.guid) {
|
||||
html += "Manual Run<br/>";
|
||||
}
|
||||
else {
|
||||
parent = getMonkeyByGuid(monkey.parent[i][0]);
|
||||
if (!parent) { html += "Unknown Source"; continue; }
|
||||
|
||||
html += parent.hostname + " (";
|
||||
if (monkey.parent[i][1] == null) {html += "Unknown"}
|
||||
else {html += monkey.parent[i][1];}
|
||||
html += ")";
|
||||
}
|
||||
}
|
||||
html += "</ul>";
|
||||
}
|
||||
|
||||
return html;
|
||||
|
@ -386,6 +463,11 @@ function updateCounters() {
|
|||
$('#infoNumOfHosts').html(scannedMachines.length);
|
||||
$('#infoNumOfParents').html(numOfParentLinks);
|
||||
$('#infoNumOfTunnels').html(numOfTunnelLinks);
|
||||
var numOfAlive = monkeys.length;
|
||||
for (var i=0;i<monkeys.length;i++) {
|
||||
if (monkeys[i].dead) {numOfAlive--;}
|
||||
}
|
||||
$('#infoNumOfAlive').html(numOfAlive);
|
||||
}
|
||||
|
||||
|
||||
|
@ -451,22 +533,22 @@ function onDoubleClick(properties) {
|
|||
*/
|
||||
function onSelect(properties) {
|
||||
|
||||
if (properties.nodes.length > 0) {
|
||||
if ((properties.nodes.length > 0) && getMonkey(properties.nodes[0])){
|
||||
onNodeSelect(properties.nodes);
|
||||
}
|
||||
else
|
||||
{
|
||||
var content = "<b>No selection</b>"
|
||||
var content = "<b>Monkey not selected</b>"
|
||||
$("#selectionInfo").html(content);
|
||||
$('#monkey-config').hide()
|
||||
$('#btnConfigLoad, #btnConfigUpdate').hide();
|
||||
$('#monkey-enabled').hide();
|
||||
telemTable.clear();
|
||||
telemTable.draw();
|
||||
}
|
||||
|
||||
if (properties.edges.length > 0) {
|
||||
onEdgeSelect(properties.edges);
|
||||
if (properties.edges.length > 0) {
|
||||
onEdgeSelect(properties.edges);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -483,33 +565,32 @@ function onNodeSelect(nodeId) {
|
|||
if (monkey) {
|
||||
htmlContent = buildMonkeyDescription(monkey);
|
||||
$("#monkeySearch").val(monkey.hostname);
|
||||
$("#selectionInfo").html(htmlContent);
|
||||
$('#monkey-config').show()
|
||||
$('#btnConfigLoad, #btnConfigUpdate').show();
|
||||
|
||||
loadMonkeyConfig();
|
||||
|
||||
if (monkey.config.alive) {
|
||||
$("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', true, true);
|
||||
}
|
||||
else {
|
||||
$("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', false, true);
|
||||
}
|
||||
$('#monkey-enabled').show();
|
||||
|
||||
$.getJSON('/api/telemetry?monkey_guid=' + monkey.guid, function(json) {
|
||||
telemTable.clear();
|
||||
var telemetries = json.objects;
|
||||
|
||||
for (var i = 0; i < telemetries.length; i++) {
|
||||
telemTable.row.add([telemetries[i].timestamp, telemetries[i].telem_type, JSON.stringify(telemetries[i].data)]);
|
||||
}
|
||||
|
||||
telemTable.draw();
|
||||
});
|
||||
}
|
||||
|
||||
$("#selectionInfo").html(htmlContent);
|
||||
$('#monkey-config').show()
|
||||
$('#btnConfigLoad, #btnConfigUpdate').show();
|
||||
|
||||
loadMonkeyConfig();
|
||||
|
||||
if (monkey.config.alive) {
|
||||
$("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', true);
|
||||
}
|
||||
else {
|
||||
$("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', false);
|
||||
}
|
||||
$('#monkey-enabled').show();
|
||||
|
||||
$.getJSON('/api/telemetry?monkey_guid=' + monkey.guid, function(json) {
|
||||
telemTable.clear();
|
||||
var telemetries = json.objects;
|
||||
|
||||
for (var i = 0; i < telemetries.length; i++) {
|
||||
telemTable.row.add([telemetries[i].timestamp, telemetries[i].telem_type, JSON.stringify(telemetries[i].data)]);
|
||||
}
|
||||
|
||||
telemTable.draw();
|
||||
});
|
||||
|
||||
network.selectNodes([nodeId]);
|
||||
}
|
||||
|
||||
|
@ -518,7 +599,32 @@ function onNodeSelect(nodeId) {
|
|||
*/
|
||||
function onEdgeSelect(edge) {
|
||||
var edge = getEdge(edge);
|
||||
var monkey = getMonkey(edge.from);
|
||||
if (!monkey) {return;};
|
||||
|
||||
var target = undefined;
|
||||
if (edge.type == 'scan') {
|
||||
target = getScannedByIP(edge.to)
|
||||
}
|
||||
else {
|
||||
target = getMonkey(edge.to)
|
||||
}
|
||||
|
||||
$.getJSON(jsonFileTelemetry + '?monkey_guid=' + monkey.guid, function(json) {
|
||||
telemTable.clear();
|
||||
var telemetries = json.objects;
|
||||
|
||||
for (var i = 0; i < telemetries.length; i++) {
|
||||
var telem = telemetries[i]
|
||||
if (telem.telem_type == 'scan' || telem.telem_type == 'exploit') {
|
||||
if (((edge.type == 'scan') && (telem.data.machine.ip_addr == target.id)) ||
|
||||
((edge.type == 'parent') && (0 <= $.inArray(telem.data.machine.ip_addr, target.ip_addresses)))) {
|
||||
telemTable.row.add([telemetries[i].timestamp, telemetries[i].telem_type, JSON.stringify(telemetries[i].data)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
telemTable.draw();
|
||||
});
|
||||
}
|
||||
|
||||
function toggleMonkeyEnabled(event, state) {
|
||||
|
@ -694,8 +800,17 @@ function resetDB() {
|
|||
url : '/api?action=reset',
|
||||
type : 'GET',
|
||||
success : function(response, textStatus, jqXhr) {
|
||||
console.log("DB was successfully reset!");
|
||||
location.reload();
|
||||
console.log(response);
|
||||
if (response.status != 'OK') {
|
||||
BootstrapDialog.show({
|
||||
title: "Reset DB",
|
||||
message: "The following error occured: " + response.reason
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log("DB was successfully reset!");
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
error : function(jqXHR, textStatus, errorThrown) {
|
||||
// log the error to the console
|
||||
|
@ -728,24 +843,24 @@ function getMonkeyByGuid(guid) {
|
|||
if (monkeys[i].guid == guid) {
|
||||
return monkeys[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getMonkeyByIP(ip) {
|
||||
for (var i = 0; i < monkeys.length; i++) {
|
||||
for (var i = 0; i < monkeys.length; i++) {
|
||||
var monkey = monkeys[i];
|
||||
for (var j = 0; j< monkey.ip_addresses; j++) {
|
||||
if (monkeys[i].ip == ip) {
|
||||
return monkeys[i];
|
||||
for (var j = 0; j< monkey.ip_addresses.length; j++) {
|
||||
if (monkey.ip_addresses[j] == ip) {
|
||||
return monkey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getScannedByIP(ip)
|
||||
{
|
||||
for (var i = 0; i < scannedMachines.length; i++) {
|
||||
function getScannedByIP(ip) {
|
||||
for (var i = 0; i < scannedMachines.length; i++) {
|
||||
var machine = scannedMachines[i];
|
||||
if (machine.id == ip) {
|
||||
return machine
|
||||
|
@ -801,13 +916,23 @@ function edgeExists(link) {
|
|||
var to = edges[i].to;
|
||||
var type = edges[i].type;
|
||||
if (from == link[0] && to == link[1] && type == link[2]) {
|
||||
return true;
|
||||
return edges[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function removeEdge(link) {
|
||||
for (var i = 0; i < edges.length; i++) {
|
||||
var from = edges[i].from;
|
||||
var to = edges[i].to;
|
||||
var type = edges[i].type;
|
||||
if (from == link[0] && to == link[1] && type == link[2]) {
|
||||
edges.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the value in the local storage
|
||||
|
|
|
@ -5,7 +5,7 @@ from flask.ext.pymongo import PyMongo
|
|||
from flask import make_response
|
||||
import bson.json_util
|
||||
import json
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import dateutil.parser
|
||||
|
||||
MONKEY_DOWNLOADS = [
|
||||
|
@ -50,6 +50,7 @@ mongo = PyMongo(app)
|
|||
|
||||
class Monkey(restful.Resource):
|
||||
def get(self, guid=None, **kw):
|
||||
update_dead_monkeys() # refresh monkeys status
|
||||
if not guid:
|
||||
guid = request.args.get('guid')
|
||||
timestamp = request.args.get('timestamp')
|
||||
|
@ -59,7 +60,7 @@ class Monkey(restful.Resource):
|
|||
else:
|
||||
result = {'timestamp': datetime.now().isoformat()}
|
||||
find_filter = {}
|
||||
if None != timestamp:
|
||||
if timestamp is not None:
|
||||
find_filter['modifytime'] = {'$gt': dateutil.parser.parse(timestamp)}
|
||||
result['objects'] = [x for x in mongo.db.monkey.find(find_filter)]
|
||||
return result
|
||||
|
@ -67,7 +68,7 @@ class Monkey(restful.Resource):
|
|||
def patch(self, guid):
|
||||
monkey_json = json.loads(request.data)
|
||||
update = {"$set": {'modifytime': datetime.now()}}
|
||||
|
||||
|
||||
if monkey_json.has_key('keepalive'):
|
||||
update['$set']['keepalive'] = dateutil.parser.parse(monkey_json['keepalive'])
|
||||
else:
|
||||
|
@ -76,7 +77,7 @@ class Monkey(restful.Resource):
|
|||
update['$set']['config'] = monkey_json['config']
|
||||
if monkey_json.has_key('tunnel'):
|
||||
update['$set']['tunnel'] = monkey_json['tunnel']
|
||||
|
||||
|
||||
return mongo.db.monkey.update({"guid": guid}, update, upsert=False)
|
||||
|
||||
def post(self, **kw):
|
||||
|
@ -88,7 +89,7 @@ class Monkey(restful.Resource):
|
|||
|
||||
monkey_json['modifytime'] = datetime.now()
|
||||
|
||||
# if new monkey, change config according to "new monkeys" config.
|
||||
# if new monkey telem, change config according to "new monkeys" config.
|
||||
db_monkey = mongo.db.monkey.find_one({"guid": monkey_json["guid"]})
|
||||
if not db_monkey:
|
||||
new_config = mongo.db.config.find_one({'name': 'newconfig'}) or {}
|
||||
|
@ -99,18 +100,31 @@ class Monkey(restful.Resource):
|
|||
if db_config.has_key('current_server'):
|
||||
del db_config['current_server']
|
||||
monkey_json.get('config', {}).update(db_config)
|
||||
|
||||
if not monkey_json.has_key('parent') and db_monkey.get('parent'):
|
||||
monkey_json['parent'] = db_monkey.get('parent')
|
||||
|
||||
# try to find new monkey parent
|
||||
parent = monkey_json.get('parent')
|
||||
if (not parent or parent == monkey_json.get('guid')) and monkey_json.has_key('ip_addresses'):
|
||||
parent_to_add = (monkey_json.get('guid'), None) # default values in case of manual run
|
||||
if parent and parent != monkey_json.get('guid'): # current parent is known
|
||||
exploit_telem = [x for x in
|
||||
mongo.db.telemetry.find({'telem_type': {'$eq': 'exploit'}, 'data.machine.ip_addr':
|
||||
{'$in': monkey_json['ip_addresses']}})]
|
||||
mongo.db.telemetry.find({'telem_type': {'$eq': 'exploit'}, 'data.result': {'$eq': True},
|
||||
'data.machine.ip_addr': {'$in': monkey_json['ip_addresses']},
|
||||
'monkey_guid': {'$eq': parent}})]
|
||||
if 1 == len(exploit_telem):
|
||||
monkey_json['parent'] = exploit_telem[0].get('monkey_guid')
|
||||
parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter'))
|
||||
else:
|
||||
parent_to_add = (parent, None)
|
||||
elif (not parent or parent == monkey_json.get('guid')) and monkey_json.has_key('ip_addresses'):
|
||||
exploit_telem = [x for x in
|
||||
mongo.db.telemetry.find({'telem_type': {'$eq': 'exploit'}, 'data.result': {'$eq': True},
|
||||
'data.machine.ip_addr': {'$in': monkey_json['ip_addresses']}})]
|
||||
|
||||
if 1 == len(exploit_telem):
|
||||
parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter'))
|
||||
|
||||
if not db_monkey:
|
||||
monkey_json['parent'] = [parent_to_add]
|
||||
else:
|
||||
monkey_json['parent'] = db_monkey.get('parent') + [parent_to_add]
|
||||
|
||||
return mongo.db.monkey.update({"guid": monkey_json["guid"]},
|
||||
{"$set": monkey_json},
|
||||
|
@ -122,7 +136,7 @@ class Telemetry(restful.Resource):
|
|||
monkey_guid = request.args.get('monkey_guid')
|
||||
telem_type = request.args.get('telem_type')
|
||||
timestamp = request.args.get('timestamp')
|
||||
if "null" == timestamp: #special case to avoid ugly JS code...
|
||||
if "null" == timestamp: # special case to avoid ugly JS code...
|
||||
timestamp = None
|
||||
|
||||
result = {'timestamp': datetime.now().isoformat()}
|
||||
|
@ -146,37 +160,26 @@ class Telemetry(restful.Resource):
|
|||
|
||||
# update exploited monkeys parent
|
||||
try:
|
||||
if telemetry_json.get('telem_type') == 'exploit':
|
||||
update_parent = []
|
||||
for monkey in mongo.db.monkey.find({"ip_addresses":
|
||||
{'$elemMatch':
|
||||
{'$eq': telemetry_json['data']['machine']['ip_addr']}}}):
|
||||
parent = monkey.get('parent')
|
||||
if parent == monkey.get('guid') or not parent:
|
||||
update_parent.append(monkey)
|
||||
if 1 == len(update_parent):
|
||||
update_parent[0]['parent'] = telemetry_json['monkey_guid']
|
||||
mongo.db.monkey.update({"guid": update_parent[0]['guid']}, {"$set": update_parent[0]}, upsert=False)
|
||||
elif telemetry_json.get('telem_type') == 'tunnel':
|
||||
if telemetry_json.get('telem_type') == 'tunnel':
|
||||
if telemetry_json['data']:
|
||||
host = telemetry_json['data'].split(":")[-2].replace("//", "")
|
||||
tunnel_host = mongo.db.monkey.find_one({"ip_addresses": host})
|
||||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$set': {'tunnel_guid': tunnel_host.get('guid')}},
|
||||
upsert=True)
|
||||
upsert=False)
|
||||
else:
|
||||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$unset': {'tunnel_guid':''}},
|
||||
upsert=True)
|
||||
{'$unset': {'tunnel_guid': ''}},
|
||||
upsert=False)
|
||||
elif telemetry_json.get('telem_type') == 'state':
|
||||
if telemetry_json['data']['done']:
|
||||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$set': {'dead': True}},
|
||||
upsert=True)
|
||||
upsert=False)
|
||||
else:
|
||||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$set': {'dead': False}},
|
||||
upsert=True)
|
||||
upsert=False)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -220,11 +223,24 @@ class MonkeyDownload(restful.Resource):
|
|||
|
||||
|
||||
class Root(restful.Resource):
|
||||
def get(self):
|
||||
return {
|
||||
'status': 'OK',
|
||||
'mongo': str(mongo.db),
|
||||
}
|
||||
def get(self, action=None):
|
||||
if not action:
|
||||
action = request.args.get('action')
|
||||
if not action:
|
||||
return {
|
||||
'status': 'OK',
|
||||
'mongo': str(mongo.db),
|
||||
}
|
||||
elif action=="reset":
|
||||
mongo.db.config.drop()
|
||||
mongo.db.monkey.drop()
|
||||
mongo.db.telemetry.drop()
|
||||
return {
|
||||
'status': 'OK',
|
||||
}
|
||||
else:
|
||||
return {'status': 'BAD',
|
||||
'reason': 'unknown action'}
|
||||
|
||||
|
||||
def normalize_obj(obj):
|
||||
|
@ -232,15 +248,15 @@ def normalize_obj(obj):
|
|||
obj['id'] = obj['_id']
|
||||
del obj['_id']
|
||||
|
||||
for key,value in obj.items():
|
||||
for key, value in obj.items():
|
||||
if type(value) is bson.objectid.ObjectId:
|
||||
obj[key] = str(value)
|
||||
if type(value) is datetime:
|
||||
obj[key] = str(value)
|
||||
obj[key] = str(value)
|
||||
if type(value) is dict:
|
||||
obj[key] = normalize_obj(value)
|
||||
if type(value) is list:
|
||||
for i in range(0,len(value)):
|
||||
for i in range(0, len(value)):
|
||||
if type(value[i]) is dict:
|
||||
value[i] = normalize_obj(value[i])
|
||||
return obj
|
||||
|
@ -253,10 +269,17 @@ def output_json(obj, code, headers=None):
|
|||
return resp
|
||||
|
||||
|
||||
def update_dead_monkeys():
|
||||
mongo.db.monkey.update(
|
||||
{'keepalive': {'$lte': datetime.now() - timedelta(minutes=10)}, 'dead': {'$ne': True}},
|
||||
{'$set': {'dead': True, 'modifytime': datetime.now()}}, upsert=False)
|
||||
|
||||
|
||||
@app.route('/admin/<path:path>')
|
||||
def send_admin(path):
|
||||
return send_from_directory('admin/ui', path)
|
||||
|
||||
|
||||
DEFAULT_REPRESENTATIONS = {'application/json': output_json}
|
||||
api = restful.Api(app)
|
||||
api.representations = DEFAULT_REPRESENTATIONS
|
||||
|
|
Loading…
Reference in New Issue