ATT&CK fields can be mapped together, ATT&CK configuration gets translated to monkey's configuration

This commit is contained in:
VakarisZ 2019-03-27 19:02:33 +02:00
parent cce76f37df
commit b3f7b29640
10 changed files with 177 additions and 85 deletions

View File

@ -29,7 +29,7 @@ from cc.resources.telemetry import Telemetry
from cc.resources.telemetry_feed import TelemetryFeed
from cc.resources.pba_file_download import PBAFileDownload
from cc.resources.pba_file_upload import FileUpload
from cc.resources.attack import AttackConfiguration
from cc.resources.attack_config import AttackConfiguration
from cc.services.config import ConfigService
__author__ = 'Barak'

View File

@ -1,23 +0,0 @@
import flask_restful
import json
from flask import jsonify, request
from cc.auth import jwt_required
from cc.services.attack.attack import AttackService
class AttackConfiguration(flask_restful.Resource):
@jwt_required()
def get(self):
return jsonify(configuration=AttackService.get_config()['properties'])
@jwt_required()
def post(self):
config_json = json.loads(request.data)
if 'reset_attack_matrix' in config_json:
AttackService.reset_config()
return jsonify(configuration=AttackService.get_config()['properties'])
else:
AttackService.update_config({'properties': json.loads(request.data)})
return {}

View File

@ -0,0 +1,28 @@
import flask_restful
import json
from flask import jsonify, request
from cc.auth import jwt_required
from cc.services.attack.attack_config import *
class AttackConfiguration(flask_restful.Resource):
@jwt_required()
def get(self):
return jsonify(configuration=get_config()['properties'])
@jwt_required()
def post(self):
"""
Based on request content this endpoint either resets ATT&CK configuration or updates it.
:return: Technique types dict with techniques on reset and nothing on update
"""
config_json = json.loads(request.data)
if 'reset_attack_matrix' in config_json:
reset_config()
return jsonify(configuration=get_config()['properties'])
else:
update_config({'properties': json.loads(request.data)})
apply_to_monkey_config()
return {}

View File

@ -7,7 +7,7 @@ from flask import request, make_response, jsonify
from cc.auth import jwt_required
from cc.database import mongo
from cc.services.config import ConfigService
from cc.services.attack.attack import AttackService
from cc.services.attack.attack_config import reset_config as reset_attack_config
from cc.services.node import NodeService
from cc.services.report import ReportService
from cc.utils import local_ip_addresses
@ -48,7 +48,7 @@ class Root(flask_restful.Resource):
# We can't drop system collections.
[mongo.db[x].drop() for x in mongo.db.collection_names() if not x.startswith('system.')]
ConfigService.init_config()
AttackService.reset_config()
reset_attack_config()
logger.info('DB was reset')
return jsonify(status='OK')

View File

@ -1,3 +1,3 @@
{
"server_config": "standard"
}
}

View File

@ -1,44 +0,0 @@
import logging
from cc.database import mongo
from attack_schema import SCHEMA
__author__ = "VakarisZ"
logger = logging.getLogger(__name__)
class AttackService:
default_config = None
def __init__(self):
pass
@staticmethod
def get_config():
config = mongo.db.attack.find_one({'name': 'newconfig'}) or AttackService.get_default_config()
return config
@staticmethod
def get_config_schema():
return SCHEMA
@staticmethod
def reset_config():
config = AttackService.get_default_config()
AttackService.update_config(config)
@staticmethod
def update_config(config_json):
mongo.db.attack.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True)
return True
@staticmethod
def parse_users_matrix(data):
pass
@staticmethod
def get_default_config():
if not AttackService.default_config:
AttackService.update_config(SCHEMA)
AttackService.default_config = SCHEMA
return AttackService.default_config

View File

@ -0,0 +1,86 @@
import logging
from cc.database import mongo
from attack_schema import SCHEMA
from cc.services.config import ConfigService
__author__ = "VakarisZ"
logger = logging.getLogger(__name__)
def get_config():
config = mongo.db.attack.find_one({'name': 'newconfig'}) or reset_config()
return config
def get_config_schema():
return SCHEMA
def reset_config():
update_config(SCHEMA)
def update_config(config_json):
mongo.db.attack.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True)
return True
def apply_to_monkey_config():
"""
Applies ATT&CK matrix in the database to the monkey configuration
:return:
"""
attack_techniques = get_techniques()
monkey_config = ConfigService.get_config(False, True, True)
monkey_schema = ConfigService.get_config_schema()
set_exploiters(attack_techniques, monkey_config, monkey_schema)
ConfigService.update_config(monkey_config, True)
def set_exploiters(attack_techniques, monkey_config, monkey_schema):
"""
Sets exploiters according to ATT&CK matrix
:param attack_techniques: ATT&CK techniques dict. Format: {'T1110': True, ...}
:param monkey_config: Monkey island's configuration
:param monkey_schema: Monkey configuration schema
"""
for exploiter in monkey_schema['definitions']['exploiter_classes']['anyOf']:
# Go trough each attack technique used by exploiter
for attack_technique in exploiter['attack_techniques']:
# If exploiter's attack technique is disabled, disable the exploiter
if not attack_techniques[attack_technique]:
remove_exploiter(exploiter['enum'][0], monkey_config)
break
# If exploiter's attack technique is enabled, enable the exploiter
else:
add_exploiter(exploiter['enum'][0], monkey_config)
def remove_exploiter(exploiter, monkey_config):
"""
Removes exploiter from monkey's configuration
:param exploiter: Exploiter class name found in SCHEMA->definitions->exploiter_classes -> anyOf -> enum
:param monkey_config: Monkey's configuration
"""
if exploiter in monkey_config['exploits']['general']['exploiter_classes']:
monkey_config['exploits']['general']['exploiter_classes'].remove(exploiter)
def add_exploiter(exploiter, monkey_config):
"""
Adds exploiter to monkey's configuration
:param exploiter: Exploiter class name found in SCHEMA->definitions->exploiter_classes -> anyOf -> enum
:param monkey_config: Monkey's configuration
"""
if not exploiter in monkey_config['exploits']['general']['exploiter_classes']:
monkey_config['exploits']['general']['exploiter_classes'].append(exploiter)
def get_techniques():
attack_config = get_config()
techniques = {}
for key, attack_type in attack_config['properties'].items():
for key, technique in attack_type['properties'].items():
techniques[key] = technique['value']
return techniques

View File

@ -2,6 +2,22 @@ SCHEMA = {
"title": "ATT&CK configuration",
"type": "object",
"properties": {
"initial_access": {
"title": "Initial access",
"type": "object",
"properties": {
"T1078": {
"title": "T1078 Valid accounts",
"type": "bool",
"value": True,
"necessary": False,
"description": "Adversaries may steal the credentials of a specific user or service account using "
"Credential Access techniques or capture credentials earlier in their "
"reconnaissance process.",
"mapped_to": ["T1003"]
}
}
},
"lateral_movement": {
"title": "Lateral movement",
"type": "object",
@ -36,6 +52,16 @@ SCHEMA = {
"necessary": False,
"description": "Adversaries may use brute force techniques to attempt access to accounts "
"when passwords are unknown or when password hashes are obtained."
},
"T1003": {
"title": "T1003 Credential dumping",
"type": "bool",
"value": True,
"necessary": False,
"description": "Credential dumping is the process of obtaining account login and password "
"information, normally in the form of a hash or a clear text password, "
"from the operating system and software.",
"mapped_to": ["T1078"]
}
}
},

View File

@ -13,84 +13,96 @@ SCHEMA = {
"enum": [
"SmbExploiter"
],
"title": "SMB Exploiter"
"title": "SMB Exploiter",
"attack_techniques": ["T1110", "T1210", "T1021", "T1035", "T1075"]
},
{
"type": "string",
"enum": [
"WmiExploiter"
],
"title": "WMI Exploiter"
"title": "WMI Exploiter",
"attack_techniques": ["T1110"]
},
{
"type": "string",
"enum": [
"MSSQLExploiter"
],
"title": "MSSQL Exploiter"
"title": "MSSQL Exploiter",
"attack_techniques": ["T1110"]
},
{
"type": "string",
"enum": [
"RdpExploiter"
],
"title": "RDP Exploiter (UNSAFE)"
"title": "RDP Exploiter (UNSAFE)",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"Ms08_067_Exploiter"
],
"title": "MS08-067 Exploiter (UNSAFE)"
"title": "MS08-067 Exploiter (UNSAFE)",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"SSHExploiter"
],
"title": "SSH Exploiter"
"title": "SSH Exploiter",
"attack_techniques": ["T1110"]
},
{
"type": "string",
"enum": [
"ShellShockExploiter"
],
"title": "ShellShock Exploiter"
"title": "ShellShock Exploiter",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"SambaCryExploiter"
],
"title": "SambaCry Exploiter"
"title": "SambaCry Exploiter",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"ElasticGroovyExploiter"
],
"title": "ElasticGroovy Exploiter"
"title": "ElasticGroovy Exploiter",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"Struts2Exploiter"
],
"title": "Struts2 Exploiter"
"title": "Struts2 Exploiter",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"WebLogicExploiter"
],
"title": "Oracle Web Logic Exploiter"
"title": "Oracle Web Logic Exploiter",
"attack_techniques": []
},
{
"type": "string",
"enum": [
"HadoopExploiter"
],
"title": "Hadoop/Yarn Exploiter"
"title": "Hadoop/Yarn Exploiter",
"attack_techniques": []
}
]
},

View File

@ -55,7 +55,6 @@ class MatrixComponent extends AuthComponent {
this.state.columns = this.getColumns(this.state.matrixTableData)
};
getColumns(matrixData) {
return Object.keys(matrixData[0]).map((key)=>{
return {
@ -132,12 +131,20 @@ class MatrixComponent extends AuthComponent {
});
};
handleTechniqueChange = (technique, value) => {
handleTechniqueChange = (technique, value, mapped=false) => {
// Change value on configuration
Object.entries(this.state.configData).forEach(techType => {
if(techType[1].properties.hasOwnProperty(technique)){
let tempMatrix = this.state.configData;
tempMatrix[techType[0]].properties[technique].value = value;
// Toggle all mapped techniques
if (! mapped && tempMatrix[techType[0]].properties[technique].hasOwnProperty('mapped_to')){
console.log("Triggered");
tempMatrix[techType[0]].properties[technique].mapped_to.forEach(mappedTechnique => {
console.log(mappedTechnique)
this.handleTechniqueChange(mappedTechnique, value, true)
})
}
this.updateStateFromConfig(tempMatrix);
}
});