Merge pull request #377 from VakarisZ/attack_proxy

T1188 Multi-hop proxy and T1090 Connection proxy
This commit is contained in:
Itay Mizeretz 2019-08-20 19:17:47 +03:00 committed by GitHub
commit 10b2c2e6cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 212 additions and 8 deletions

View File

@ -80,6 +80,17 @@ class Monkey(Document):
os = "windows"
return os
def get_network_info(self):
"""
Formats network info from monkey's model
:return: dictionary with an array of IP's and a hostname
"""
return {'ips': self.ip_addresses, 'hostname': self.hostname}
@staticmethod
def get_tunneled_monkeys():
return Monkey.objects(tunnel__exists=True)
def renew_ttl(self, duration=DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS):
self.ttl_ref = create_monkey_ttl_document(duration)
self.save()

View File

@ -9,11 +9,11 @@ from monkey_ttl import MonkeyTtl
class TestMonkey(IslandTestCase):
"""
Make sure to set server environment to `testing` in server.json! Otherwise this will mess up your mongo instance and
Make sure to set server environment to `testing` in server_config.json! Otherwise this will mess up your mongo instance and
won't work.
Also, the working directory needs to be the working directory from which you usually run the island so the
server.json file is found and loaded.
server_config.json file is found and loaded.
"""
def test_is_dead(self):
@ -90,3 +90,25 @@ class TestMonkey(IslandTestCase):
self.assertEquals(1, len(filter(lambda m: m.get_os() == "windows", Monkey.objects())))
self.assertEquals(1, len(filter(lambda m: m.get_os() == "linux", Monkey.objects())))
self.assertEquals(1, len(filter(lambda m: m.get_os() == "unknown", Monkey.objects())))
def test_get_tunneled_monkeys(self):
self.fail_if_not_testing_env()
self.clean_monkey_db()
linux_monkey = Monkey(guid=str(uuid.uuid4()),
description="Linux shay-Virtual-Machine")
windows_monkey = Monkey(guid=str(uuid.uuid4()),
description="Windows bla bla bla",
tunnel=linux_monkey)
unknown_monkey = Monkey(guid=str(uuid.uuid4()),
description="bla bla bla",
tunnel=windows_monkey)
linux_monkey.save()
windows_monkey.save()
unknown_monkey.save()
tunneled_monkeys = Monkey.get_tunneled_monkeys()
test = bool(windows_monkey in tunneled_monkeys
and unknown_monkey in tunneled_monkeys
and linux_monkey not in tunneled_monkeys
and len(tunneled_monkeys) == 2)
self.assertTrue(test, "Tunneling test")

View File

@ -1,7 +1,8 @@
import logging
from monkey_island.cc.models import Monkey
from monkey_island.cc.services.attack.technique_reports import T1210, T1197, T1110, T1075, T1003, T1059, T1086, T1082
from monkey_island.cc.services.attack.technique_reports import T1145, T1105, T1065, T1035, T1129, T1106, T1107
from monkey_island.cc.services.attack.technique_reports import T1145, T1105, T1065, T1035, T1129, T1106, T1107, T1188
from monkey_island.cc.services.attack.technique_reports import T1090
from monkey_island.cc.services.attack.attack_config import AttackConfig
from monkey_island.cc.database import mongo
@ -24,7 +25,9 @@ TECHNIQUES = {'T1210': T1210.T1210,
'T1035': T1035.T1035,
'T1129': T1129.T1129,
'T1106': T1106.T1106,
'T1107': T1107.T1107}
'T1107': T1107.T1107,
'T1188': T1188.T1188,
'T1090': T1090.T1090}
REPORT_NAME = 'new_report'

View File

@ -186,6 +186,22 @@ SCHEMA = {
"necessary": True,
"description": "Adversaries may conduct C2 communications over a non-standard "
"port to bypass proxies and firewalls that have been improperly configured."
},
"T1090": {
"title": "T1090 Connection proxy",
"type": "bool",
"value": True,
"necessary": True,
"description": "A connection proxy is used to direct network traffic between systems "
"or act as an intermediary for network communications."
},
"T1188": {
"title": "T1188 Multi-hop proxy",
"type": "bool",
"value": True,
"necessary": True,
"description": "To disguise the source of malicious traffic, "
"adversaries may chain together multiple proxies."
}
}
},

View File

@ -0,0 +1,24 @@
from monkey_island.cc.services.attack.technique_reports import AttackTechnique
from common.utils.attack_utils import ScanStatus
from monkey_island.cc.models import Monkey
__author__ = "VakarisZ"
class T1090(AttackTechnique):
tech_id = "T1090"
unscanned_msg = "Monkey didn't use connection proxy."
scanned_msg = ""
used_msg = "Monkey used connection proxy."
@staticmethod
def get_report_data():
monkeys = Monkey.get_tunneled_monkeys()
monkeys = [monkey.get_network_info() for monkey in monkeys]
status = ScanStatus.USED.value if monkeys else ScanStatus.UNSCANNED.value
data = T1090.get_base_data_by_status(status)
data.update({'proxies': monkeys})
return data

View File

@ -0,0 +1,32 @@
from monkey_island.cc.services.attack.technique_reports import AttackTechnique
from monkey_island.cc.models.monkey import Monkey
from common.utils.attack_utils import ScanStatus
__author__ = "VakarisZ"
class T1188(AttackTechnique):
tech_id = "T1188"
unscanned_msg = "Monkey didn't use multi-hop proxy."
scanned_msg = ""
used_msg = "Monkey used multi-hop proxy."
@staticmethod
def get_report_data():
monkeys = Monkey.get_tunneled_monkeys()
hops = []
for monkey in monkeys:
proxy_count = 0
proxy = initial = monkey
while proxy.tunnel:
proxy_count += 1
proxy = proxy.tunnel
if proxy_count > 1:
hops.append({'from': initial.get_network_info(),
'to': proxy.get_network_info(),
'count': proxy_count})
status = ScanStatus.USED.value if hops else ScanStatus.UNSCANNED.value
data = T1188.get_base_data_by_status(status)
data.update({'hops': hops})
return data

View File

@ -12,12 +12,13 @@ export function renderMachineFromSystemData(data) {
let machineStr = data['hostname'] + " ( ";
data['ips'].forEach(function(ipInfo){
if(typeof ipInfo === "object"){
machineStr += ipInfo['addr'] + " ";
machineStr += ipInfo['addr'] + ", ";
} else {
machineStr += ipInfo + " ";
machineStr += ipInfo + ", ";
}
});
return machineStr + ")"
// Replaces " ," with " )" to finish a list of IP's
return machineStr.slice(0, -2) + " )"
}
/* Formats telemetry data that contains _id.machine and _id.usage fields into columns

View File

@ -0,0 +1,42 @@
import React from 'react';
import '../../../styles/Collapse.scss'
import ReactTable from "react-table";
import { renderMachineFromSystemData, scanStatus } from "./Helpers"
class T1090 extends React.Component {
constructor(props) {
super(props);
}
static getProxyColumns() {
return ([{
columns: [
{Header: 'Machines',
id: 'machine',
accessor: x => renderMachineFromSystemData(x),
style: { 'whiteSpace': 'unset', textAlign: 'center' }}]}])
};
render() {
return (
<div>
<div>{this.props.data.message}</div>
<br/>
{this.props.data.status === scanStatus.USED ?
<div>
<p>Proxies were used to communicate with:</p>
<ReactTable
columns={T1090.getProxyColumns()}
data={this.props.data.proxies}
showPagination={false}
defaultPageSize={this.props.data.proxies.length}
/>
</div>: ""}
</div>
);
}
}
export default T1090;

View File

@ -0,0 +1,49 @@
import React from 'react';
import '../../../styles/Collapse.scss'
import ReactTable from "react-table";
import { renderMachineFromSystemData, scanStatus } from "./Helpers"
class T1188 extends React.Component {
constructor(props) {
super(props);
}
static getHopColumns() {
return ([{
Header: "Communications through multi-hop proxies",
columns: [
{Header: 'From',
id: 'from',
accessor: x => renderMachineFromSystemData(x.from),
style: { 'whiteSpace': 'unset' }},
{Header: 'To',
id: 'to',
accessor: x => renderMachineFromSystemData(x.to),
style: { 'whiteSpace': 'unset' }},
{Header: 'Hops',
id: 'hops',
accessor: x => x.count,
style: { 'whiteSpace': 'unset' }},
]
}])};
render() {
return (
<div>
<div>{this.props.data.message}</div>
<br/>
{this.props.data.status === scanStatus.USED ?
<ReactTable
columns={T1188.getHopColumns()}
data={this.props.data.hops}
showPagination={false}
defaultPageSize={this.props.data.hops.length}
/> : ""}
</div>
);
}
}
export default T1188;

View File

@ -21,6 +21,8 @@ import T1065 from "../attack/techniques/T1065";
import T1035 from "../attack/techniques/T1035";
import T1129 from "../attack/techniques/T1129";
import T1106 from "../attack/techniques/T1106";
import T1188 from "../attack/techniques/T1188";
import T1090 from "../attack/techniques/T1090";
const tech_components = {
'T1210': T1210,
@ -37,7 +39,9 @@ const tech_components = {
'T1035': T1035,
'T1129': T1129,
'T1106': T1106,
'T1107': T1107
'T1107': T1107,
'T1188': T1188,
'T1090': T1090
};
const classNames = require('classnames');