From 6a824efab346cef4e64a4a0e45b1ed6980a3e632 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 3 Jul 2020 17:41:41 +0300 Subject: [PATCH] Finished AdvancedMultiSelect component --- .../cc/services/config_schema.py | 53 +++++++-- .../configuration-components/UiSchema.js | 15 +-- .../ui-components/AdvancedMultiSelect.js | 111 ++++++++++++++++++ .../ui-components/AdvancedMultipleSelect.js | 50 -------- .../src/components/ui-components/InfoPane.js | 52 ++++++++ .../ui-components/utils/HeightCalculator.js | 16 +++ .../ui-components/utils/ObjectPathResolver.js | 11 ++ .../components/AdvancedMultiSelect.scss | 47 ++++++++ .../cc/ui/src/styles/components/InfoPane.scss | 29 +++++ 9 files changed, 315 insertions(+), 69 deletions(-) create mode 100644 monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js delete mode 100644 monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultipleSelect.js create mode 100644 monkey/monkey_island/cc/ui/src/components/ui-components/InfoPane.js create mode 100644 monkey/monkey_island/cc/ui/src/components/ui-components/utils/HeightCalculator.js create mode 100644 monkey/monkey_island/cc/ui/src/components/ui-components/utils/ObjectPathResolver.js create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/AdvancedMultiSelect.scss create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/InfoPane.scss diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 30425dc1d..b8f2701c0 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -17,7 +17,10 @@ SCHEMA = { "SmbExploiter" ], "title": "SMB Exploiter", - "attack_techniques": ["T1110", "T1075", "T1035"] + "attack_techniques": ["T1110", "T1075", "T1035"], + "info": "Brute forces using credentials provided by user and" + " hashes gathered by mimikatz.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", @@ -25,7 +28,10 @@ SCHEMA = { "WmiExploiter" ], "title": "WMI Exploiter", - "attack_techniques": ["T1110", "T1106"] + "attack_techniques": ["T1110", "T1106"], + "info": "Brute forces WMI (Windows Management Instrumentation) " + "using credentials provided by user and hashes gathered by mimikatz.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", @@ -33,7 +39,10 @@ SCHEMA = { "MSSQLExploiter" ], "title": "MSSQL Exploiter", - "attack_techniques": ["T1110"] + "attack_techniques": ["T1110"], + "info": "Tries to brute force into MsSQL server and uses insecure " + "configuration to execute commands on server.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", @@ -41,7 +50,9 @@ SCHEMA = { "Ms08_067_Exploiter" ], "title": "MS08-067 Exploiter (UNSAFE)", - "attack_techniques": [] + "info": "Unsafe exploiter, that might cause system crash due to the use of buffer overflow. " + "Uses MS08-067 vulnerability.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", @@ -49,56 +60,74 @@ SCHEMA = { "SSHExploiter" ], "title": "SSH Exploiter", - "attack_techniques": ["T1110", "T1145", "T1106"] + "attack_techniques": ["T1110", "T1145", "T1106"], + "info": "Brute forces using credentials provided by user and SSH keys gathered from systems.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "ShellShockExploiter" ], - "title": "ShellShock Exploiter" + "title": "ShellShock Exploiter", + "info": "CVE-2014-6271, based on logic in NCC group's github.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "SambaCryExploiter" ], - "title": "SambaCry Exploiter" + "title": "SambaCry Exploiter", + "info": "Bruteforces and searches for anonymous shares. Uses Impacket.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "ElasticGroovyExploiter" ], - "title": "ElasticGroovy Exploiter" + "title": "ElasticGroovy Exploiter", + "info": "CVE-2015-1427. Logic is based on Metasploit module.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "Struts2Exploiter" ], - "title": "Struts2 Exploiter" + "title": "Struts2 Exploiter", + "info": "Exploits struts2 java web framework. CVE-2017-5638. Logic based on this PoC.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "WebLogicExploiter" ], - "title": "WebLogic Exploiter" + "title": "WebLogic Exploiter", + "info": "Exploits CVE-2017-10271 and CVE-2019-2725 vulnerabilities on WebLogic server.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "HadoopExploiter" ], - "title": "Hadoop/Yarn Exploiter" + "title": "Hadoop/Yarn Exploiter", + "info": "Remote code execution on HADOOP server with YARN and default settings. " + "Logic based on https://github.com/vulhub/vulhub/tree/master/hadoop/unauthorized-yarn.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" }, { "type": "string", "enum": [ "VSFTPDExploiter" ], - "title": "VSFTPD Exploiter" + "title": "VSFTPD Exploiter", + "info": "Exploits a malicious backdoor that was added to the VSFTPD download archive. " + "Logic based on Metasploit module.", + "link": "https://github.com/guardicore/monkey/wiki/Exploiters" } ] }, diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js index a9c592d7c..7b7d2bfcb 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js @@ -1,4 +1,4 @@ -import ArrayFieldTemplate from "../ui-components/AdvancedMultipleSelect"; +import AdvancedMultiSelect from "../ui-components/AdvancedMultiSelect"; import PbaInput from "./PbaInput"; import {API_PBA_LINUX, API_PBA_WINDOWS} from '../pages/ConfigurePage'; @@ -6,11 +6,6 @@ export default function UiSchema(props) { const UiSchema = { basic: { 'ui:order': ['general', 'credentials'], - credentials: { - exploit_password_list: { - "ui:ArrayFieldTemplate": ArrayFieldTemplate - } - } }, basic_network: {}, monkey: { @@ -54,7 +49,13 @@ export default function UiSchema(props) { exploits: { general: { exploiter_classes: { - "ui:ArrayFieldTemplate": ArrayFieldTemplate + 'ui:widget': AdvancedMultiSelect, + 'ui:options': { + defaultPaneParams: { + title: 'Exploiters', + content: 'Click on exploiter to get more information about it.' + } + } } } }, diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js new file mode 100644 index 000000000..f8083060b --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js @@ -0,0 +1,111 @@ +import React, {useState} from 'react'; + +import {Card, Button, Form} from 'react-bootstrap'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faSquare, faCheckSquare} from '@fortawesome/free-solid-svg-icons'; +import {cloneDeep} from 'lodash'; + +import {getComponentHeight} from './utils/HeightCalculator'; +import {resolveObjectPath} from './utils/ObjectPathResolver'; +import InfoPane from './InfoPane'; + + +function getSelectValuesAfterClick(valueArray, clickedValue) { + if (valueArray.includes(clickedValue)) { + return valueArray.filter((e) => { + return e !== clickedValue; + }); + } else { + valueArray.push(clickedValue); + return valueArray; + } +} + +function onMasterCheckboxClick(checkboxValue, defaultArray, onChangeFnc) { + if (checkboxValue) { + onChangeFnc([]); + } else { + onChangeFnc(defaultArray); + } +} + +// Definitions passed to components only contains value and label, +// custom fields like "info" or "links" must be pulled from registry object using this function +function getFullDefinitionsFromRegistry(refString, registry) { + let refArray = refString.replace('#', '').split('/'); + let definitionObject = resolveObjectPath(refArray, registry); + return definitionObject.anyOf; +} + +function getFullDefinitionByKey(refString, registry, itemKey) { + let fullArray = getFullDefinitionsFromRegistry(refString, registry); + return fullArray.filter(e => (e.enum[0] === itemKey))[0]; +} + +function setPaneInfo(refString, registry, itemKey, setPaneInfoFnc) { + let definitionObj = getFullDefinitionByKey(refString, registry, itemKey); + setPaneInfoFnc({title: definitionObj.title, content: definitionObj.info, link: definitionObj.link}); +} + +function AdvancedMultiSelect(props) { + const [masterCheckbox, setMasterCheckbox] = useState(true); + const { + schema, + id, + options, + value, + required, + disabled, + readonly, + multiple, + autofocus, + onChange, + registry + } = props; + const {enumOptions, defaultPaneParams} = options; + const [infoPaneParams, setInfoPaneParams] = useState(defaultPaneParams); + const selectValue = cloneDeep(value); + return ( +
+ + + {props.schema.title} + + + {enumOptions.map(({value, label}, i) => { + return ( + setPaneInfo(schema.items.$ref, registry, value, setInfoPaneParams)}> + + + {label} + + + ); + })} + + +
+ ); +} + +export default AdvancedMultiSelect; diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultipleSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultipleSelect.js deleted file mode 100644 index 70e0953a0..000000000 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultipleSelect.js +++ /dev/null @@ -1,50 +0,0 @@ -import React from "react"; -import Button from 'react-bootstrap/Button'; - - -function ArrayFieldTemplate(props) { - return ( -
- {props.items && - props.items.map(element => ( -
-
{element.children}
- {element.hasMoveDown && ( - - )} - {element.hasMoveUp && ( - - )} - -
-
- ))} - - {props.canAdd && ( -
-

- -

-
- )} -
- ); -} - -export default ArrayFieldTemplate; diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/InfoPane.js b/monkey/monkey_island/cc/ui/src/components/ui-components/InfoPane.js new file mode 100644 index 000000000..cd3315428 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/InfoPane.js @@ -0,0 +1,52 @@ +import {Card, Button} from 'react-bootstrap'; +import React from 'react'; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {faQuestionCircle} from "@fortawesome/free-solid-svg-icons"; + + +function InfoPane(props) { + return ( + + {getTitle(props)} + {getSubtitle(props)} + {getBody(props)} + ); +} + +function getTitle(props) { + if (typeof (props.title) == 'string') { + return ( + + {props.title} + {getLinkButton(props)} + ) + } +} + +function getLinkButton(props) { + if (typeof (props.link) == 'string') { + return ( + ) + } +} + +function getSubtitle(props) { + if (typeof (props.subtitle) == 'string') { + return ( + + {props.subtitle} + ) + } +} + +function getBody(props) { + return ( + + {props.body} + + ) +} + +export default InfoPane diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/utils/HeightCalculator.js b/monkey/monkey_island/cc/ui/src/components/ui-components/utils/HeightCalculator.js new file mode 100644 index 000000000..208fc5398 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/utils/HeightCalculator.js @@ -0,0 +1,16 @@ +const defaultMinHeight = 50 +const defaultMaxHeight = 300 +const defaultSubcomponentHeight = 15 + +export function getComponentHeight(subcomponentCount, + subcomponentHeight = defaultSubcomponentHeight, + minHeight = defaultMinHeight, + maxHeight = defaultMaxHeight) { + let height = subcomponentHeight * subcomponentCount; + if (height > maxHeight) + height = maxHeight + else if (height < minHeight) + height = minHeight + + return height +} diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/utils/ObjectPathResolver.js b/monkey/monkey_island/cc/ui/src/components/ui-components/utils/ObjectPathResolver.js new file mode 100644 index 000000000..9fef26c7a --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/utils/ObjectPathResolver.js @@ -0,0 +1,11 @@ + +// Resolves object's path if it's specified in a dot notation. +// (e.g. params: "firstLevel.secondLevel.property", myObject) +export function resolveObjectPath(pathArray, obj) { + return pathArray.reduce(function(prev, curr) { + if(curr === '') + return prev; + else + return prev ? prev[curr] : null; + }, obj || self) +} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/AdvancedMultiSelect.scss b/monkey/monkey_island/cc/ui/src/styles/components/AdvancedMultiSelect.scss new file mode 100644 index 000000000..5cde76e3b --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/AdvancedMultiSelect.scss @@ -0,0 +1,47 @@ +.advanced-multi-select .choice-block.form-control { + overflow: scroll; + overflow-x: hidden; + padding: 0; + margin-left: 0; +} + +.advanced-multi-select svg { + font-size: 1.15em; +} + +.advanced-multi-select .card-header { + border: 1px solid $gray-300; + border-bottom: none; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-left: 0; + padding-bottom: 5px; +} + +.advanced-multi-select .card-header button { + padding-top: 0; +} + +.advanced-multi-select .card-header .header-title { + font-size: 1.2em; +} + +.advanced-multi-select .choice-block .form-group { + margin: 0; + padding: 3px 0 0 0; + height: 30px; +} + +.advanced-multi-select .choice-block .form-group:hover { + background-color: $gray-300; + cursor: pointer; +} + +.advanced-multi-select .choice-block .form-group button { + margin: 0 5px 3px 10px; + padding: 0; +} + +.advanced-multi-select .option-text { + margin-left: 10px; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/InfoPane.scss b/monkey/monkey_island/cc/ui/src/styles/components/InfoPane.scss new file mode 100644 index 000000000..8c61d873f --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/InfoPane.scss @@ -0,0 +1,29 @@ +.info-pane, .card { + margin-top: 5px; +} + +.info-pane svg { + font-size: 1.1em; +} + +.info-pane .pane-title { + margin: 10px 15px 3px 15px; + color: $monkey-alt; +} + +.info-pane .pane-link { + position: absolute; + right: 0; + top: 0; +} + +.info-pane .pane-subtitle { + margin: 0 15px; + color: $gray-600; +} + + +.info-pane .pane-body { + margin: 10px 15px; + padding: 0; +}