diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/RansomwareReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/RansomwareReport.js index 94a4f331e..25bc3876d 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/RansomwareReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/RansomwareReport.js @@ -2,7 +2,7 @@ import React from 'react'; import ReportHeader, {ReportTypes} from './common/ReportHeader'; import ReportLoader from './common/ReportLoader'; -import FileEncryptionTable from './ransomware/FileEncryptionTable'; +import Attack from './ransomware/Attack'; import LateralMovement from './ransomware/LateralMovement'; import '../../styles/pages/report/RansomwareReport.scss'; @@ -19,7 +19,7 @@ class RansomwareReport extends React.Component {
- +
) } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/Attack.tsx b/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/Attack.tsx new file mode 100644 index 000000000..d2e2d7e38 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/Attack.tsx @@ -0,0 +1,87 @@ +import React, {ReactElement} from 'react'; +import {FileEncryptionTable, TableRow} from './FileEncryptionTable'; +import NumberedReportSection from './NumberedReportSection'; + +const ATTACK_DESCRIPTION = 'After the attacker or malware has propagated through your network, \ + your data is at risk on any machine the attacker can access. It can be \ + encrypted and held for ransomware, exfiltrated, or manipulated in \ + whatever way the attacker chooses.' +const HOSTNAME_REGEX = /^(.* - )?(\S+) :.*$/; + +function Attack({telemetry}: {telemetry: object}): ReactElement { + let tableData = processTelemetry(telemetry); + let body = ( + <> +

Infection Monkey has encrypted {tableData.length} files on your network:

+ + + ); + + return ( + + ); +} + +function processTelemetry(telemetry): Array { + // Sort ascending so that newer telemetry records overwrite older ones. + sortTelemetry(telemetry); + + let latestTelemetry = getLatestTelemetry(telemetry); + let tableData = getDataForTable(latestTelemetry); + + return tableData; +} + +function sortTelemetry(telemetry): void { + telemetry.objects.sort((a, b) => { + if (a.timestamp > b.timestamp) { + return 1; + } else if (a.timestamp < b.timestamp) { + return -1; + } + + return 0; + }); +} + +function getLatestTelemetry(telemetry) { + let latestTelemetry = {}; + for (let i = 0; i < telemetry.objects.length; i++) { + let monkey = telemetry.objects[i].monkey + + if (! (monkey in latestTelemetry)) { + latestTelemetry[monkey] = {}; + } + + telemetry.objects[i].data.files.forEach((file_encryption_telemetry) => { + latestTelemetry[monkey][file_encryption_telemetry.path] = file_encryption_telemetry.success + }); + } + + return latestTelemetry; +} + +function getDataForTable(telemetry): Array { + let tableData = []; + + for (const monkey in telemetry) { + for (const path in telemetry[monkey]) { + if (telemetry[monkey][path]) { + tableData.push({'hostname': parseHostname(monkey), 'file_path': path}); + } + } + } + + return tableData; +} + +function parseHostname(monkey: string): string { + return monkey.match(HOSTNAME_REGEX)[2]; +} + +export default Attack; diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/FileEncryptionTable.tsx b/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/FileEncryptionTable.tsx index 891fdfd87..0b4406ab6 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/FileEncryptionTable.tsx +++ b/monkey/monkey_island/cc/ui/src/components/report-components/ransomware/FileEncryptionTable.tsx @@ -2,17 +2,12 @@ import React from 'react'; import ReactTable from 'react-table'; -type Props = { - telemetry: object, -} - type TableRow = { hostname: string, file_path: number, } const PAGE_SIZE = 10; -const HOSTNAME_REGEX = /^(.* - )?(\S+) :.*$/ const columns = [ { Header: 'Encrypted Files', @@ -26,8 +21,7 @@ const columns = [ } ]; -const FileEncryptionTable = (props: Props) => { - let tableData = processTelemetry(props.telemetry); +const FileEncryptionTable = ({tableData}: {tableData: Array}) => { let defaultPageSize = tableData.length > PAGE_SIZE ? PAGE_SIZE : tableData.length; let showPagination = tableData.length > PAGE_SIZE; @@ -48,61 +42,4 @@ const FileEncryptionTable = (props: Props) => { ); } -function processTelemetry(telemetry): Array { - // Sort ascending so that newer telemetry records overwrite older ones. - sortTelemetry(telemetry); - - let latestTelemetry = getLatestTelemetry(telemetry); - let tableData = getDataForTable(latestTelemetry); - - return tableData; -} - -function sortTelemetry(telemetry): void { - telemetry.objects.sort((a, b) => { - if (a.timestamp > b.timestamp) { - return 1; - } else if (a.timestamp > b.timestamp) { - return -1; - } - - return 0; - }); -} - -function getLatestTelemetry(telemetry) { - let latestTelemetry = {}; - for (let i = 0; i < telemetry.objects.length; i++) { - let monkey = telemetry.objects[i].monkey - - if (! (monkey in latestTelemetry)) { - latestTelemetry[monkey] = {}; - } - - telemetry.objects[i].data.files.forEach((file_encryption_telemetry) => { - latestTelemetry[monkey][file_encryption_telemetry.path] = file_encryption_telemetry.success - }); - } - - return latestTelemetry -} - -function getDataForTable(telemetry): Array { - let tableData = []; - - for (const monkey in telemetry) { - for (const path in telemetry[monkey]) { - if (telemetry[monkey][path]) { - tableData.push({'hostname': parseHostname(monkey), 'file_path': path}); - } - } - } - - return tableData; -} - -function parseHostname(monkey) { - return monkey.match(HOSTNAME_REGEX)[2] -} - -export default FileEncryptionTable; +export {FileEncryptionTable, TableRow};