Add monkey kill option from island
This commit is contained in:
parent
84496dd3f5
commit
3d5d972cf8
|
@ -120,7 +120,7 @@ class ControlClient(object):
|
|||
return
|
||||
|
||||
try:
|
||||
WormConfiguration.from_dict(reply.json().get('config'))
|
||||
WormConfiguration.from_dict(reply.json()["objects"][0].get('config'))
|
||||
LOG.info("New configuration was loaded from server: %r" % (WormConfiguration.as_dict(),))
|
||||
except Exception, exc:
|
||||
# we don't continue with default conf here because it might be dangerous
|
||||
|
@ -128,6 +128,11 @@ class ControlClient(object):
|
|||
WormConfiguration.current_server, reply._content, exc)
|
||||
raise Exception("Couldn't load from from server's configuration, aborting. %s" % exc)
|
||||
|
||||
@staticmethod
|
||||
def check_for_stop():
|
||||
ControlClient.load_control_config()
|
||||
return not WormConfiguration.alive
|
||||
|
||||
@staticmethod
|
||||
def download_monkey_exe(host):
|
||||
if not WormConfiguration.current_server:
|
||||
|
|
|
@ -46,7 +46,7 @@ class ChaosMonkey(object):
|
|||
arg_parser.add_argument('-s', '--server')
|
||||
arg_parser.add_argument('-d', '--depth')
|
||||
opts, self._args = arg_parser.parse_known_args(self._args)
|
||||
|
||||
|
||||
self._parent = opts.parent
|
||||
self._default_tunnel = opts.tunnel
|
||||
self._default_server = opts.server
|
||||
|
@ -69,10 +69,18 @@ class ChaosMonkey(object):
|
|||
if firewall.is_enabled():
|
||||
firewall.add_firewall_rule()
|
||||
ControlClient.wakeup(parent=self._parent, default_tunnel=self._default_tunnel)
|
||||
ControlClient.load_control_config()
|
||||
|
||||
if not WormConfiguration.alive:
|
||||
LOG.info("Marked not alive from configuration")
|
||||
return
|
||||
|
||||
monkey_tunnel = ControlClient.create_control_tunnel()
|
||||
if monkey_tunnel:
|
||||
monkey_tunnel.start()
|
||||
|
||||
ControlClient.send_telemetry("state", {'done': False})
|
||||
|
||||
self._default_server = WormConfiguration.current_server
|
||||
LOG.debug("default server: %s" % self._default_server)
|
||||
ControlClient.send_telemetry("tunnel", ControlClient.proxies.get('https'))
|
||||
|
@ -103,12 +111,16 @@ class ChaosMonkey(object):
|
|||
break
|
||||
|
||||
machines = self._network.get_victim_machines(WormConfiguration.scanner_class,
|
||||
max_find=WormConfiguration.victims_max_find)
|
||||
max_find=WormConfiguration.victims_max_find,
|
||||
stop_callback=ControlClient.check_for_stop)
|
||||
is_empty = True
|
||||
for machine in machines:
|
||||
if ControlClient.check_for_stop():
|
||||
break
|
||||
|
||||
is_empty = False
|
||||
for finger in self._fingerprint:
|
||||
LOG.info("Trying to get OS fingerprint from %r with module %s",
|
||||
LOG.info("Trying to get OS fingerprint from %r with module %s",
|
||||
machine, finger.__class__.__name__)
|
||||
finger.get_host_fingerprint(machine)
|
||||
|
||||
|
@ -156,8 +168,8 @@ class ChaosMonkey(object):
|
|||
|
||||
if successful_exploiter:
|
||||
self._exploited_machines.add(machine)
|
||||
ControlClient.send_telemetry('exploit', {'machine': machine.__dict__,
|
||||
'exploiter': successful_exploiter.__class__.__name__})
|
||||
ControlClient.send_telemetry('exploit', {'machine': machine.__dict__,
|
||||
'exploiter': successful_exploiter.__class__.__name__})
|
||||
|
||||
LOG.info("Successfully propagated to %s using %s",
|
||||
machine, successful_exploiter.__class__.__name__)
|
||||
|
@ -202,13 +214,14 @@ class ChaosMonkey(object):
|
|||
from _subprocess import SW_HIDE, STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags = CREATE_NEW_CONSOLE | STARTF_USESHOWWINDOW
|
||||
startupinfo.wShowWindow = SW_HIDE
|
||||
startupinfo.wShowWindow = SW_HIDE
|
||||
subprocess.Popen(DELAY_DELETE_CMD % {'file_path': sys.executable},
|
||||
stdin=None, stdout=None, stderr=None,
|
||||
stdin=None, stdout=None, stderr=None,
|
||||
close_fds=True, startupinfo=startupinfo)
|
||||
else:
|
||||
os.remove(sys.executable)
|
||||
except Exception, exc:
|
||||
LOG.error("Exception in self delete: %s", exc)
|
||||
|
||||
LOG.info("Monkey is shutting down")
|
||||
ControlClient.send_telemetry("state", {'done': True})
|
||||
LOG.info("Monkey is shutting down")
|
|
@ -33,7 +33,7 @@ class NetworkScanner(object):
|
|||
for ip_address in self._ip_addresses]
|
||||
LOG.info("Base local networks to scan are: %r", self._ranges)
|
||||
|
||||
def get_victim_machines(self, scan_type, max_find=5):
|
||||
def get_victim_machines(self, scan_type, max_find=5, stop_callback=None):
|
||||
assert issubclass(scan_type, HostScanner)
|
||||
|
||||
scanner = scan_type()
|
||||
|
@ -42,6 +42,10 @@ class NetworkScanner(object):
|
|||
for range in self._ranges:
|
||||
LOG.debug("Scanning for potential victims in the network %r", range)
|
||||
for victim in range:
|
||||
if stop_callback and stop_callback():
|
||||
LOG.debug("Got stop signal")
|
||||
break
|
||||
|
||||
# skip self IP address
|
||||
if victim.ip_addr in self._ip_addresses:
|
||||
continue
|
||||
|
|
|
@ -123,6 +123,34 @@
|
|||
<div id="selectionInfo">
|
||||
<label>No selection</label>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="#mconfig" data-toggle="collapse">Monkey Config</a>
|
||||
</div>
|
||||
<div id="mconfig" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true">
|
||||
<span class="input-group-btn">
|
||||
<button id="btnConfigLoad" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="loadMonkeyConfig()" style="margin-top:-4px">
|
||||
Refresh
|
||||
</button>
|
||||
<button id="btnConfigUpdate" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="updateMonkeyConfig()" style="margin-top:-4px">
|
||||
Update
|
||||
</button>
|
||||
<button id="btnKillMonkey" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="killMonkey()" style="margin-top:-4px">
|
||||
Mark for Kill
|
||||
</button>
|
||||
<button id="btnReviveMonkey" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="reviveMonkey()" style="margin-top:-4px">
|
||||
Revive Monkey
|
||||
</button>
|
||||
</span>
|
||||
<div style="display: none;" id="monkey-config">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -132,7 +160,7 @@
|
|||
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="#config" data-toggle="collapse">Config</a>
|
||||
<a href="#config" data-toggle="collapse">General Config</a>
|
||||
</div>
|
||||
<div id="config" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true">
|
||||
<span class="input-group-btn">
|
||||
|
@ -146,23 +174,11 @@
|
|||
</button>
|
||||
</span>
|
||||
<div id="new-config">
|
||||
</div>
|
||||
<span class="input-group-btn">
|
||||
<button id="btnConfigLoad" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="loadMonkeyConfig()" style="margin-top:-4px">
|
||||
Load
|
||||
</button>
|
||||
<button id="btnConfigUpdate" style="display: none;" class="btn btn-default" type="button"
|
||||
onclick="updateMonkeyConfig()" style="margin-top:-4px">
|
||||
Update
|
||||
</button>
|
||||
</span>
|
||||
<div style="display: none;" id="monkey-config">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.Config section -->
|
||||
<!-- /.Config section -->
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -108,6 +108,8 @@ function initAdmin() {
|
|||
"ordering": false,
|
||||
});
|
||||
|
||||
loadNewMonkeysConfig();
|
||||
|
||||
window.setTimeout(updateMonkeys, 10000);
|
||||
|
||||
addEventsListeners();
|
||||
|
@ -134,7 +136,15 @@ function updateMonkeys() {
|
|||
createEdges();
|
||||
createTunnels();
|
||||
|
||||
// keep old selection
|
||||
var selNode = network.getSelectedNodes();
|
||||
network.setData({nodes: nodes, edges: edges});
|
||||
if (selNode.length) {
|
||||
var monkey = getMonkey(selNode[0]);
|
||||
if (monkey) { // The selection might be no longer valid if the monkey was deleted
|
||||
selectNode(monkey.hostname, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
createScanned();
|
||||
window.setTimeout(updateMonkeys, 10000);
|
||||
|
@ -269,8 +279,16 @@ function buildMonkeyDescription(monkey) {
|
|||
var html =
|
||||
"<label>Name:</label> " + monkey.hostname + "</br>" +
|
||||
"<label>Description:</label> " + monkey.description + "</br>" +
|
||||
"<label>Internet Access:</label> " + monkey.internet_access + "</br>" +
|
||||
"<label>IP Address:</label></br>"
|
||||
"<label>Internet Access:</label> " + monkey.internet_access + "</br>";
|
||||
if (monkey.dead) {
|
||||
html += "<label>State:</label> Dead </br>";
|
||||
}
|
||||
if (!monkey.config.alive) {
|
||||
html += "<label>Note:</label> Marked to be dead</br>";
|
||||
}
|
||||
html +=
|
||||
"<label>Last Seen:</label> " + monkey.keepalive + "</br>" +
|
||||
"<label>IP Address:</label></br>";
|
||||
|
||||
for (var i = 0; i < monkey.ip_addresses.length; i++) {
|
||||
html += monkey.ip_addresses[i] + "</br>"
|
||||
|
@ -352,7 +370,7 @@ function onSelect(properties) {
|
|||
var content = "<b>No selection</b>"
|
||||
$("#selectionInfo").html(content);
|
||||
$('#monkey-config').hide()
|
||||
$('#btnConfigLoad, #btnConfigUpdate').hide();
|
||||
$('#btnConfigLoad, #btnConfigUpdate, #btnKillMonkey, #btnReviveMonkey').hide();
|
||||
telemTable.clear();
|
||||
telemTable.draw();
|
||||
}
|
||||
|
@ -382,6 +400,17 @@ function onNodeSelect(nodeId) {
|
|||
$('#monkey-config').show()
|
||||
$('#btnConfigLoad, #btnConfigUpdate').show();
|
||||
|
||||
loadMonkeyConfig();
|
||||
|
||||
if (monkey.config.alive) {
|
||||
$('#btnKillMonkey').show();
|
||||
$('#btnReviveMonkey').hide();
|
||||
}
|
||||
else {
|
||||
$('#btnKillMonkey').hide();
|
||||
$('#btnReviveMonkey').show();
|
||||
}
|
||||
|
||||
|
||||
$.getJSON('/api/telemetry/' + monkey.guid, function(json) {
|
||||
telemTable.clear();
|
||||
|
@ -394,7 +423,6 @@ function onNodeSelect(nodeId) {
|
|||
telemTable.draw();
|
||||
});
|
||||
|
||||
|
||||
network.selectNodes([nodeId]);
|
||||
}
|
||||
|
||||
|
@ -406,6 +434,19 @@ function onEdgeSelect(edge) {
|
|||
|
||||
}
|
||||
|
||||
function killMonkey() {
|
||||
var curr_config = monkeyCfg.getValue();
|
||||
curr_config.alive = false;
|
||||
monkeyCfg.setValue(curr_config);
|
||||
updateMonkeyConfig();
|
||||
}
|
||||
|
||||
function reviveMonkey() {
|
||||
var curr_config = monkeyCfg.getValue();
|
||||
curr_config.alive = true;
|
||||
monkeyCfg.setValue(curr_config);
|
||||
updateMonkeyConfig();
|
||||
}
|
||||
|
||||
function toggleFocusOnNode() {
|
||||
if (focusedOnNode) {
|
||||
|
@ -413,7 +454,7 @@ function toggleFocusOnNode() {
|
|||
focusedOnNode = false;
|
||||
}
|
||||
else {
|
||||
selectNode(undefined, zoom=true);
|
||||
selectNode(undefined, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,26 +501,26 @@ function updateNewMonkeysConfig() {
|
|||
}
|
||||
|
||||
function loadMonkeyConfig() {
|
||||
nodes = network.getSelectedNodes();
|
||||
var node = network.getSelectedNodes();
|
||||
|
||||
if(nodes.length != 1) {
|
||||
if(node.length != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var monkey = getMonkey(nodes[0]);
|
||||
var monkey = getMonkey(node[0]);
|
||||
|
||||
monkeyCfg.setValue(monkey.config);
|
||||
}
|
||||
|
||||
function updateMonkeyConfig() {
|
||||
nodes = network.getSelectedNodes();
|
||||
if(nodes.length != 1) {
|
||||
var node = network.getSelectedNodes();
|
||||
if(node.length != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var monkey = getMonkey(nodes[0]);
|
||||
var monkey = getMonkey(node[0]);
|
||||
|
||||
var curr_config = monkeyCfg.getValue()
|
||||
var curr_config = monkeyCfg.getValue();
|
||||
|
||||
$.ajax({
|
||||
headers : {
|
||||
|
@ -491,7 +532,8 @@ function updateMonkeyConfig() {
|
|||
data : JSON.stringify({config: curr_config}),
|
||||
success : function(response, textStatus, jqXhr) {
|
||||
monkey.config = curr_config;
|
||||
console.log("Monkey config successfully updated!");
|
||||
console.log("Monkey config successfully updated! (" + monkey.hostname + ")");
|
||||
selectNode(monkey.hostname, false);
|
||||
},
|
||||
error : function(jqXHR, textStatus, errorThrown) {
|
||||
// log the error to the console
|
||||
|
|
|
@ -167,7 +167,15 @@ class Telemetry(restful.Resource):
|
|||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$unset': {'tunnel_guid':''}},
|
||||
upsert=True)
|
||||
|
||||
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)
|
||||
else:
|
||||
mongo.db.monkey.update({"guid": telemetry_json['monkey_guid']},
|
||||
{'$set': {'dead': False}},
|
||||
upsert=True)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue