Merge branch 'attack_pass_the_hash' into attack_comand_line_interface

# Conflicts:
#	monkey/monkey_island/cc/services/attack/attack_report.py
This commit is contained in:
VakarisZ 2019-06-19 12:12:20 +03:00
commit b1f13155bb
10 changed files with 72 additions and 57 deletions

View File

@ -16,7 +16,7 @@ class T1075(AttackTechnique):
{'lm_hash': {'$ne': ''}}]}}} {'lm_hash': {'$ne': ''}}]}}}
# Gets data about successful PTH logins # Gets data about successful PTH logins
query = [{'$match': {'telem_type': 'exploit', query = [{'$match': {'telem_category': 'exploit',
'data.attempts': {'$not': {'$size': 0}, 'data.attempts': {'$not': {'$size': 0},
'$elemMatch': {'$and': [{'$or': [{'ntlm_hash': {'$ne': ''}}, '$elemMatch': {'$and': [{'$or': [{'ntlm_hash': {'$ne': ''}},
{'lm_hash': {'$ne': ''}}]}, {'lm_hash': {'$ne': ''}}]},
@ -35,9 +35,10 @@ class T1075(AttackTechnique):
successful_logins = list(mongo.db.telemetry.aggregate(T1075.query)) successful_logins = list(mongo.db.telemetry.aggregate(T1075.query))
data.update({'successful_logins': successful_logins}) data.update({'successful_logins': successful_logins})
if successful_logins: if successful_logins:
data.update({'message': T1075.used_msg, 'status': ScanStatus.USED.name}) status = ScanStatus.USED
elif mongo.db.telemetry.count_documents(T1075.login_attempt_query): elif mongo.db.telemetry.count_documents(T1075.login_attempt_query):
data.update({'message': T1075.scanned_msg, 'status': ScanStatus.SCANNED.name}) status = ScanStatus.SCANNED
else: else:
data.update({'message': T1075.unscanned_msg, 'status': ScanStatus.UNSCANNED.name}) status = ScanStatus.UNSCANNED
data.update(T1075.get_message_and_status(status))
return data return data

View File

@ -35,12 +35,12 @@ class T1110(AttackTechnique):
result['successful_creds'].append(T1110.parse_creds(attempt)) result['successful_creds'].append(T1110.parse_creds(attempt))
if succeeded: if succeeded:
data = T1110.get_message_and_status(T1110, ScanStatus.USED) status = ScanStatus.USED
elif attempts: elif attempts:
data = T1110.get_message_and_status(T1110, ScanStatus.SCANNED) status = ScanStatus.SCANNED
else: else:
data = T1110.get_message_and_status(T1110, ScanStatus.UNSCANNED) status = ScanStatus.UNSCANNED
data = T1110.get_message_and_status(status)
# Remove data with no successful brute force attempts # Remove data with no successful brute force attempts
attempts = [attempt for attempt in attempts if attempt['attempts']] attempts = [attempt for attempt in attempts if attempt['attempts']]

View File

@ -12,7 +12,7 @@ class T1197(AttackTechnique):
@staticmethod @staticmethod
def get_report_data(): def get_report_data():
data = T1197.get_tech_base_data(T1197) data = T1197.get_tech_base_data()
bits_results = mongo.db.telemetry.aggregate([{'$match': {'telem_catagory': 'attack', 'data.technique': T1197.tech_id}}, bits_results = mongo.db.telemetry.aggregate([{'$match': {'telem_catagory': 'attack', 'data.technique': T1197.tech_id}},
{'$group': {'_id': {'ip_addr': '$data.machine.ip_addr', 'usage': '$data.usage'}, {'$group': {'_id': {'ip_addr': '$data.machine.ip_addr', 'usage': '$data.usage'},
'ip_addr': {'$first': '$data.machine.ip_addr'}, 'ip_addr': {'$first': '$data.machine.ip_addr'},

View File

@ -18,11 +18,12 @@ class T1210(AttackTechnique):
scanned_services = T1210.get_scanned_services() scanned_services = T1210.get_scanned_services()
exploited_services = T1210.get_exploited_services() exploited_services = T1210.get_exploited_services()
if exploited_services: if exploited_services:
data.update({'status': ScanStatus.USED.name, 'message': T1210.used_msg}) status = ScanStatus.USED
elif scanned_services: elif scanned_services:
data.update({'status': ScanStatus.SCANNED.name, 'message': T1210.scanned_msg}) status = ScanStatus.SCANNED
else: else:
data.update({'status': ScanStatus.UNSCANNED.name, 'message': T1210.unscanned_msg}) status = ScanStatus.UNSCANNED.name
data.update(T1210.get_message_and_status(status))
data.update({'scanned_services': scanned_services, 'exploited_services': exploited_services}) data.update({'scanned_services': scanned_services, 'exploited_services': exploited_services})
return data return data

View File

@ -46,52 +46,63 @@ class AttackTechnique(object):
""" """
pass pass
@staticmethod @classmethod
def technique_status(technique): def technique_status(cls):
""" """
Gets the status of a certain attack technique. Gets the status of a certain attack technique.
:param technique: technique's id.
:return: ScanStatus Enum object :return: ScanStatus Enum object
""" """
if mongo.db.telemetry.find_one({'telem_catagory': 'attack', 'data.status': ScanStatus.USED.value, 'data.technique': technique}): if mongo.db.attack_results.find_one({'telem_catagory': 'attack',
'status': ScanStatus.USED.value,
'technique': cls.tech_id}):
return ScanStatus.USED return ScanStatus.USED
elif mongo.db.telemetry.find_one({'telem_catagory': 'attack', 'data.status': ScanStatus.SCANNED.value, 'data.technique': technique}): elif mongo.db.attack_results.find_one({'telem_catagory': 'attack',
'status': ScanStatus.SCANNED.value,
'technique': cls.tech_id}):
return ScanStatus.SCANNED return ScanStatus.SCANNED
else: else:
return ScanStatus.UNSCANNED return ScanStatus.UNSCANNED
@staticmethod @classmethod
def get_message_and_status(technique, status): def get_message_and_status(cls, status):
return {'message': technique.get_message_by_status(technique, status), 'status': status.name} """
Returns a dict with attack technique's message and status.
@staticmethod :param status: Enum type value from common/attack_utils.py
def get_message_by_status(technique, status): :return: Dict with message and status
if status == ScanStatus.UNSCANNED: """
return technique.unscanned_msg return {'message': cls.get_message_by_status(status), 'status': status.name}
elif status == ScanStatus.SCANNED:
return technique.scanned_msg @classmethod
else: def get_message_by_status(cls, status):
return technique.used_msg """
Picks a message to return based on status.
@staticmethod :param status: Enum type value from common/attack_utils.py
def technique_title(technique): :return: message string
"""
if status == ScanStatus.UNSCANNED:
return cls.unscanned_msg
elif status == ScanStatus.SCANNED:
return cls.scanned_msg
else:
return cls.used_msg
@classmethod
def technique_title(cls):
""" """
:param technique: Technique's id. E.g. T1110
:return: techniques title. E.g. "T1110 Brute force" :return: techniques title. E.g. "T1110 Brute force"
""" """
return AttackConfig.get_technique(technique)['title'] return AttackConfig.get_technique(cls.tech_id)['title']
@staticmethod @classmethod
def get_tech_base_data(technique): def get_tech_base_data(cls):
""" """
Gathers basic attack technique data into a dict. Gathers basic attack technique data into a dict.
:param technique: Technique's id. E.g. T1110
:return: dict E.g. {'message': 'Brute force used', 'status': 'Used', 'title': 'T1110 Brute force'} :return: dict E.g. {'message': 'Brute force used', 'status': 'Used', 'title': 'T1110 Brute force'}
""" """
data = {} data = {}
status = AttackTechnique.technique_status(technique.tech_id) status = cls.technique_status()
title = AttackTechnique.technique_title(technique.tech_id) title = cls.technique_title()
data.update({'status': status.name, data.update({'status': status.name,
'title': title, 'title': title,
'message': technique.get_message_by_status(technique, status)}) 'message': cls.get_message_by_status(status)})
return data return data

View File

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
export function RenderMachine(val){ export function renderMachine(val){
return ( return (
<span>{val.ip_addr} {(val.domain_name ? " (".concat(val.domain_name, ")") : "")}</span> <span>{val.ip_addr} {(val.domain_name ? " (".concat(val.domain_name, ")") : "")}</span>
) )

View File

@ -1,26 +1,28 @@
import React from 'react'; import React from 'react';
import '../../../styles/Collapse.scss' import '../../../styles/Collapse.scss'
import ReactTable from "react-table"; import ReactTable from "react-table";
import { RenderMachine } from "./Helpers" import { renderMachine } from "./Helpers"
class T1075 extends React.Component { class T1075 extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.props.data.successful_logins.forEach((login) => { this.props.data.successful_logins.forEach((login) => this.setLoginHashType(login))
}
setLoginHashType(login){
if(login.attempts[0].ntlm_hash !== ""){ if(login.attempts[0].ntlm_hash !== ""){
login.attempts[0].hashType = 'NTLM'; login.attempts[0].hashType = 'NTLM';
} else if(login.attempts[0].lm_hash !== ""){ } else if(login.attempts[0].lm_hash !== ""){
login.attempts[0].hashType = 'LM'; login.attempts[0].hashType = 'LM';
} }
})
} }
static getHashColumns() { static getHashColumns() {
return ([{ return ([{
columns: [ columns: [
{Header: 'Machine', id: 'machine', accessor: x => RenderMachine(x.machine), style: { 'whiteSpace': 'unset' }}, {Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine), style: { 'whiteSpace': 'unset' }},
{Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: { 'whiteSpace': 'unset' }}, {Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: { 'whiteSpace': 'unset' }},
{Header: 'Username', id: 'username', accessor: x => x.attempts[0].user, style: { 'whiteSpace': 'unset' }}, {Header: 'Username', id: 'username', accessor: x => x.attempts[0].user, style: { 'whiteSpace': 'unset' }},
{Header: 'Hash type', id: 'hash', accessor: x => x.attempts[0].hashType, style: { 'whiteSpace': 'unset' }}, {Header: 'Hash type', id: 'hash', accessor: x => x.attempts[0].hashType, style: { 'whiteSpace': 'unset' }},

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import '../../../styles/Collapse.scss' import '../../../styles/Collapse.scss'
import ReactTable from "react-table"; import ReactTable from "react-table";
import { RenderMachine } from "./Helpers" import { renderMachine } from "./Helpers"
class T1110 extends React.Component { class T1110 extends React.Component {
@ -13,7 +13,7 @@ class T1110 extends React.Component {
static getServiceColumns() { static getServiceColumns() {
return ([{ return ([{
columns: [ columns: [
{Header: 'Machine', id: 'machine', accessor: x => RenderMachine(x.machine), {Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
style: { 'whiteSpace': 'unset' }, width: 160}, style: { 'whiteSpace': 'unset' }, width: 160},
{Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: { 'whiteSpace': 'unset' }, width: 100}, {Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: { 'whiteSpace': 'unset' }, width: 100},
{Header: 'Started', id: 'started', accessor: x => x.info.started, style: { 'whiteSpace': 'unset' }}, {Header: 'Started', id: 'started', accessor: x => x.info.started, style: { 'whiteSpace': 'unset' }},

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import '../../../styles/Collapse.scss' import '../../../styles/Collapse.scss'
import ReactTable from "react-table"; import ReactTable from "react-table";
import { RenderMachine } from "./Helpers" import { renderMachine } from "./Helpers"
class T1210 extends React.Component { class T1210 extends React.Component {
@ -9,7 +9,7 @@ class T1210 extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.columns = [ {Header: 'Machine', this.columns = [ {Header: 'Machine',
id: 'machine', accessor: x => RenderMachine(x), id: 'machine', accessor: x => renderMachine(x),
style: { 'whiteSpace': 'unset' }, style: { 'whiteSpace': 'unset' },
width: 200}, width: 200},
{Header: 'Time', {Header: 'Time',

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import '../../../styles/Collapse.scss' import '../../../styles/Collapse.scss'
import ReactTable from "react-table"; import ReactTable from "react-table";
import { RenderMachine } from "./Helpers" import { renderMachine } from "./Helpers"
class T1210 extends React.Component { class T1210 extends React.Component {
@ -13,7 +13,7 @@ class T1210 extends React.Component {
static getScanColumns() { static getScanColumns() {
return ([{ return ([{
columns: [ columns: [
{Header: 'Machine', id: 'machine', accessor: x => RenderMachine(x.machine), {Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
style: { 'whiteSpace': 'unset' }, width: 200}, style: { 'whiteSpace': 'unset' }, width: 200},
{Header: 'Time', id: 'time', accessor: x => x.time, style: { 'whiteSpace': 'unset' }, width: 170}, {Header: 'Time', id: 'time', accessor: x => x.time, style: { 'whiteSpace': 'unset' }, width: 170},
{Header: 'Port', id: 'port', accessor: x =>x.service.port, style: { 'whiteSpace': 'unset' }}, {Header: 'Port', id: 'port', accessor: x =>x.service.port, style: { 'whiteSpace': 'unset' }},
@ -24,7 +24,7 @@ class T1210 extends React.Component {
static getExploitColumns() { static getExploitColumns() {
return ([{ return ([{
columns: [ columns: [
{Header: 'Machine', id: 'machine', accessor: x => RenderMachine(x.machine), {Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
style: { 'whiteSpace': 'unset' }, width: 200}, style: { 'whiteSpace': 'unset' }, width: 200},
{Header: 'Time', id: 'time', accessor: x => x.time, style: { 'whiteSpace': 'unset' }, width: 170}, {Header: 'Time', id: 'time', accessor: x => x.time, style: { 'whiteSpace': 'unset' }, width: 170},
{Header: 'Port/url', id: 'port', accessor: x =>this.renderEndpoint(x.service), style: { 'whiteSpace': 'unset' }}, {Header: 'Port/url', id: 'port', accessor: x =>this.renderEndpoint(x.service), style: { 'whiteSpace': 'unset' }},