forked from p15670423/monkey
Auto reformat all code
This commit is contained in:
parent
d69976f4b5
commit
40494d3c3c
|
@ -17,7 +17,6 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class MSSQLExploiter(HostExploiter):
|
||||
|
||||
_EXPLOITED_SERVICE = 'MSSQL'
|
||||
_TARGET_OS_TYPE = ['windows']
|
||||
EXPLOIT_TYPE = ExploitType.BRUTE_FORCE
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
class ExploitingVulnerableMachineError(Exception):
|
||||
""" Raise when exploiter failed, but machine is vulnerable"""
|
||||
pass
|
||||
|
|
|
@ -12,6 +12,7 @@ from common.utils.attack_utils import ScanStatus
|
|||
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
|
||||
from infection_monkey.exploit.tools.helpers import get_interface_to_target
|
||||
from infection_monkey.config import Configuration
|
||||
|
||||
__author__ = 'itamar'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import threading
|
||||
import logging
|
||||
import time
|
||||
|
@ -13,7 +12,6 @@ from infection_monkey.exploit.tools.helpers import get_interface_to_target
|
|||
from infection_monkey.network.info import get_free_tcp_port
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
|
||||
__author__ = "VakarisZ"
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -34,7 +32,6 @@ HEADERS = {
|
|||
|
||||
|
||||
class WebLogicExploiter(HostExploiter):
|
||||
|
||||
_TARGET_OS_TYPE = ['linux', 'windows']
|
||||
_EXPLOITED_SERVICE = 'Weblogic'
|
||||
|
||||
|
|
|
@ -122,4 +122,3 @@ class WmiExploiter(HostExploiter):
|
|||
return success
|
||||
|
||||
return False
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ from requests import ConnectionError
|
|||
from common.network.network_range import CidrRange
|
||||
from infection_monkey.utils.environment import is_windows_os
|
||||
|
||||
|
||||
# Timeout for monkey connections
|
||||
TIMEOUT = 15
|
||||
LOOPBACK_NAME = b"lo"
|
||||
|
|
|
@ -12,7 +12,6 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class MSSQLFinger(HostFinger):
|
||||
|
||||
# Class related consts
|
||||
SQL_BROWSER_DEFAULT_PORT = 1434
|
||||
BUFFER_SIZE = 4096
|
||||
|
|
|
@ -11,7 +11,6 @@ BANNER_READ = 1024
|
|||
|
||||
|
||||
class TcpScanner(HostScanner, HostFinger):
|
||||
|
||||
_SCANNED_SERVICE = 'unknown(TCP)'
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
@ -27,6 +27,7 @@ class UsersPBA(PBA):
|
|||
"""
|
||||
Defines user's configured post breach action.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(UsersPBA, self).__init__(POST_BREACH_FILE_EXECUTION)
|
||||
self.filename = ''
|
||||
|
|
|
@ -7,7 +7,6 @@ from infection_monkey.utils.environment import is_windows_os
|
|||
from infection_monkey.config import WormConfiguration
|
||||
from infection_monkey.telemetry.attack.t1064_telem import T1064Telem
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
__author__ = 'VakarisZ'
|
||||
|
@ -19,6 +18,7 @@ class PBA(object):
|
|||
"""
|
||||
Post breach action object. Can be extended to support more than command execution on target machine.
|
||||
"""
|
||||
|
||||
def __init__(self, name="unknown", linux_cmd="", windows_cmd=""):
|
||||
"""
|
||||
:param name: Name of post breach action.
|
||||
|
|
|
@ -16,6 +16,7 @@ class PostBreach(object):
|
|||
"""
|
||||
This class handles post breach actions execution
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.os_is_linux = not is_windows_os()
|
||||
self.pba_list = self.config_to_pba_list()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
|
||||
__author__ = 'itay.mizeretz'
|
||||
|
||||
|
||||
|
|
|
@ -26,4 +26,3 @@ class LinuxInfoCollector(InfoCollector):
|
|||
super(LinuxInfoCollector, self).get_info()
|
||||
self.info['ssh_info'] = SSHCollector.get_info()
|
||||
return self.info
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import logging
|
||||
import sys
|
||||
|
||||
sys.coinit_flags = 0 # needed for proper destruction of the wmi python module
|
||||
|
||||
import infection_monkey.config
|
||||
|
|
|
@ -29,4 +29,3 @@ WMI_LDAP_CLASSES = {"ds_user": ("DS_sAMAccountName", "DS_userPrincipalName",
|
|||
"DS_sAMAccountType", "DS_servicePrincipalName", "DS_userAccountControl",
|
||||
"DS_whenChanged", "DS_whenCreated"),
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ from abc import ABCMeta, abstractmethod
|
|||
|
||||
from infection_monkey.config import WormConfiguration
|
||||
|
||||
|
||||
__author__ = 'itamar'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from infection_monkey.transport.http import HTTPServer, LockedHTTPServer
|
||||
|
||||
|
||||
__author__ = 'hoffer'
|
||||
|
|
|
@ -39,7 +39,6 @@ from monkey_island.cc.resources.test.log_test import LogTest
|
|||
|
||||
__author__ = 'Barak'
|
||||
|
||||
|
||||
HOME_FILE = 'index.html'
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import os
|
|||
import json
|
||||
import logging.config
|
||||
|
||||
|
||||
__author__ = 'Maor.Rayzin'
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
"format": "%(asctime)s - %(filename)s:%(lineno)s - %(funcName)10s() - %(levelname)s - %(message)s"
|
||||
}
|
||||
},
|
||||
|
||||
"handlers": {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
|
@ -14,7 +13,6 @@
|
|||
"formatter": "simple",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
|
||||
"info_file_handler": {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"level": "INFO",
|
||||
|
@ -25,9 +23,11 @@
|
|||
"encoding": "utf8"
|
||||
}
|
||||
},
|
||||
|
||||
"root": {
|
||||
"level": "DEBUG",
|
||||
"handlers": ["console", "info_file_handler"]
|
||||
"handlers": [
|
||||
"console",
|
||||
"info_file_handler"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ if BASE_PATH not in sys.path:
|
|||
|
||||
from monkey_island.cc.island_logger import json_setup_logging
|
||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
||||
|
||||
# This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top.
|
||||
json_setup_logging(default_path=os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'island_logger_default_config.json'),
|
||||
default_level=logging.DEBUG)
|
||||
|
|
|
@ -43,6 +43,7 @@ class Monkey(Document):
|
|||
tunnel = ReferenceField("self")
|
||||
command_control_channel = EmbeddedDocumentField(CommandControlChannel)
|
||||
aws_instance_id = StringField(required=False) # This field only exists when the monkey is running on an AWS
|
||||
|
||||
# instance. See https://github.com/guardicore/monkey/issues/426.
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -188,4 +188,3 @@ class TestMonkey(IslandTestCase):
|
|||
|
||||
cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info()
|
||||
self.assertEqual(cache_info_after_query.hits, 2)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ class TestFinding(IslandTestCase):
|
|||
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.
|
||||
"""
|
||||
|
||||
def test_save_finding_validation(self):
|
||||
self.fail_if_not_testing_env()
|
||||
self.clean_finding_db()
|
||||
|
|
|
@ -27,4 +27,3 @@ class AttackConfiguration(flask_restful.Resource):
|
|||
AttackConfig.update_config({'properties': json.loads(request.data)})
|
||||
AttackConfig.apply_to_monkey_config()
|
||||
return {}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
|||
__author__ = 'Barak'
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ from monkey_island.cc.services.node import NodeService
|
|||
|
||||
__author__ = 'Barak'
|
||||
|
||||
|
||||
# TODO: separate logic from interface
|
||||
|
||||
|
||||
|
|
|
@ -27,5 +27,3 @@ class NetMap(flask_restful.Resource):
|
|||
"nodes": monkeys + nodes + monkey_island,
|
||||
"edges": edges
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ class PBAFileDownload(flask_restful.Resource):
|
|||
"""
|
||||
File download endpoint used by monkey to download user's PBA file
|
||||
"""
|
||||
|
||||
# Used by monkey. can't secure.
|
||||
def get(self, path):
|
||||
return send_from_directory(GET_FILE_DIR, path)
|
||||
|
|
|
@ -21,6 +21,7 @@ class FileUpload(flask_restful.Resource):
|
|||
"""
|
||||
File upload endpoint used to exchange files with filepond component on the front-end
|
||||
"""
|
||||
|
||||
@jwt_required()
|
||||
def get(self, file_type):
|
||||
"""
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import http.client
|
||||
|
||||
|
||||
import flask_restful
|
||||
from flask import jsonify
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class TelemetryFeed(flask_restful.Resource):
|
|||
telemetries = mongo.db.telemetry.find({})
|
||||
else:
|
||||
telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}}) \
|
||||
|
||||
\
|
||||
telemetries = telemetries.sort([('timestamp', flask_pymongo.ASCENDING)])
|
||||
|
||||
try:
|
||||
|
|
|
@ -2,7 +2,6 @@ from bson import json_util
|
|||
import flask_restful
|
||||
from flask import request
|
||||
|
||||
|
||||
from monkey_island.cc.auth import jwt_required
|
||||
from monkey_island.cc.database import mongo, database
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ from monkey_island.cc.services.reporting.report_generation_synchronisation impor
|
|||
|
||||
__author__ = "VakarisZ"
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TECHNIQUES = {'T1210': T1210.T1210,
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1003(AttackTechnique):
|
||||
|
||||
tech_id = "T1003"
|
||||
unscanned_msg = "Monkey tried to obtain credentials from systems in the network but didn't find any or failed."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -5,7 +5,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1005(AttackTechnique):
|
||||
|
||||
tech_id = "T1005"
|
||||
unscanned_msg = "Monkey didn't gather any sensitive data from local system."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1016(AttackTechnique):
|
||||
|
||||
tech_id = "T1016"
|
||||
unscanned_msg = "Monkey didn't gather network configurations."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1018(AttackTechnique):
|
||||
|
||||
tech_id = "T1018"
|
||||
unscanned_msg = "Monkey didn't find any machines on the network."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -3,7 +3,6 @@ from monkey_island.cc.services.attack.technique_reports import AttackTechnique
|
|||
from common.utils.attack_utils import ScanStatus
|
||||
from monkey_island.cc.services.attack.technique_reports.technique_report_tools import parse_creds
|
||||
|
||||
|
||||
__author__ = "VakarisZ"
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1041(AttackTechnique):
|
||||
|
||||
tech_id = "T1041"
|
||||
unscanned_msg = "Monkey didn't exfiltrate any info trough command and control channel."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1059(AttackTechnique):
|
||||
|
||||
tech_id = "T1059"
|
||||
unscanned_msg = "Monkey didn't exploit any machines to run commands at."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1065(AttackTechnique):
|
||||
|
||||
tech_id = "T1065"
|
||||
unscanned_msg = ""
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1075(AttackTechnique):
|
||||
|
||||
tech_id = "T1075"
|
||||
unscanned_msg = "Monkey didn't try to use pass the hash attack."
|
||||
scanned_msg = "Monkey tried to use hashes while logging in but didn't succeed."
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1082(AttackTechnique):
|
||||
|
||||
tech_id = "T1082"
|
||||
unscanned_msg = "Monkey didn't gather any system info on the network."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1086(AttackTechnique):
|
||||
|
||||
tech_id = "T1086"
|
||||
unscanned_msg = "Monkey didn't run powershell."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1090(AttackTechnique):
|
||||
|
||||
tech_id = "T1090"
|
||||
unscanned_msg = "Monkey didn't use connection proxy."
|
||||
scanned_msg = ""
|
||||
|
@ -20,5 +19,3 @@ class T1090(AttackTechnique):
|
|||
data = T1090.get_base_data_by_status(status)
|
||||
data.update({'proxies': monkeys})
|
||||
return data
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1105(AttackTechnique):
|
||||
|
||||
tech_id = "T1105"
|
||||
unscanned_msg = "Monkey didn't try to copy files to any systems."
|
||||
scanned_msg = "Monkey tried to copy files, but failed."
|
||||
|
|
|
@ -46,5 +46,3 @@ class T1110(AttackTechnique):
|
|||
|
||||
data.update({'services': attempts})
|
||||
return data
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1188(AttackTechnique):
|
||||
|
||||
tech_id = "T1188"
|
||||
unscanned_msg = "Monkey didn't use multi-hop proxy."
|
||||
scanned_msg = ""
|
||||
|
|
|
@ -6,7 +6,6 @@ __author__ = "VakarisZ"
|
|||
|
||||
|
||||
class T1210(AttackTechnique):
|
||||
|
||||
tech_id = "T1210"
|
||||
unscanned_msg = "Monkey didn't scan any remote services. Maybe it didn't find any machines on the network?"
|
||||
scanned_msg = "Monkey scanned for remote services on the network, but couldn't exploit any of them."
|
||||
|
|
|
@ -15,7 +15,6 @@ __author__ = "itay.mizeretz"
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# This should be used for config values of array type (array of strings only)
|
||||
ENCRYPTED_CONFIG_ARRAYS = \
|
||||
[
|
||||
|
|
|
@ -6,7 +6,6 @@ from monkey_island.cc.services.post_breach_files import remove_PBA_files
|
|||
from flask import jsonify
|
||||
from monkey_island.cc.database import mongo
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -28,4 +27,3 @@ class Database(object):
|
|||
def init_db():
|
||||
if not mongo.db.collection_names():
|
||||
Database.reset_db()
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
|
||||
__author__ = "Maor.Rayzin"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
__author__ = 'maor.rayzin'
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from monkey_island.cc.services.reporting.report_exporter_manager import ReportEx
|
|||
from monkey_island.cc.services.reporting.aws_exporter import AWSExporter
|
||||
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
|
||||
from monkey_island.cc.environment.environment import env
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -64,6 +64,3 @@ class TestPTHReportServiceGenerateMapNodes(IslandTestCase):
|
|||
self.assertEqual(map_nodes[0]["group"], "critical")
|
||||
self.assertEqual(len(map_nodes[0]["services"]), 2)
|
||||
self.assertEqual(map_nodes[0]["hostname"], hostname)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -24,4 +24,3 @@ def process_post_breach_telemetry(telemetry_json):
|
|||
post_breach_action_name = telemetry_json["data"]["name"]
|
||||
if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS:
|
||||
POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json)
|
||||
|
||||
|
|
|
@ -54,4 +54,3 @@ class VersionUpdateService:
|
|||
@staticmethod
|
||||
def get_download_link():
|
||||
return VersionUpdateService.VERSION_SERVER_DOWNLOAD_URL % (env.get_deployment(), env.get_version())
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ __author__ = 'maor.rayzin'
|
|||
|
||||
|
||||
class WMIHandler(object):
|
||||
|
||||
ADMINISTRATORS_GROUP_KNOWN_SID = '1-5-32-544'
|
||||
|
||||
def __init__(self, monkey_id, wmi_info, user_secrets):
|
||||
|
@ -160,4 +159,3 @@ class WMIHandler(object):
|
|||
{'type': USERTYPE, 'entities_list': 1})
|
||||
if entity_details.get('type') == GROUPTYPE:
|
||||
self.add_admin(entity_details, machine_id)
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
{
|
||||
"presets": ["es2015", "stage-0", "react"],
|
||||
"plugins": ["emotion"]
|
||||
"presets": [
|
||||
"es2015",
|
||||
"stage-0",
|
||||
"react"
|
||||
],
|
||||
"plugins": [
|
||||
"emotion"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -19,14 +19,22 @@
|
|||
},
|
||||
"rules": {
|
||||
"comma-dangle": 1,
|
||||
"quotes": [ 1, "single" ],
|
||||
"quotes": [
|
||||
1,
|
||||
"single"
|
||||
],
|
||||
"no-undef": 1,
|
||||
"global-strict": 0,
|
||||
"no-extra-semi": 1,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-console": 1,
|
||||
"no-unused-vars": 1,
|
||||
"no-trailing-spaces": [1, { "skipBlankLines": true }],
|
||||
"no-trailing-spaces": [
|
||||
1,
|
||||
{
|
||||
"skipBlankLines": true
|
||||
}
|
||||
],
|
||||
"no-unreachable": 1,
|
||||
"no-alert": 0,
|
||||
"react/jsx-uses-react": 1,
|
||||
|
|
|
@ -26,16 +26,21 @@ export function renderMachineFromSystemData(data) {
|
|||
export function getUsageColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine',
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: {'whiteSpace': 'unset'},
|
||||
width: 300},
|
||||
{Header: 'Usage',
|
||||
width: 300
|
||||
},
|
||||
{
|
||||
Header: 'Usage',
|
||||
id: 'usage',
|
||||
accessor: x => x.usage,
|
||||
style: { 'whiteSpace': 'unset' }}]
|
||||
}])}
|
||||
style: {'whiteSpace': 'unset'}
|
||||
}]
|
||||
}])
|
||||
}
|
||||
|
||||
/* Renders table fields that contains 'used' boolean value and 'name' string value.
|
||||
'Used' value determines if 'name' value will be shown.
|
||||
|
|
|
@ -17,7 +17,8 @@ class T1003 extends React.Component {
|
|||
<div>{this.props.data.message}</div>
|
||||
<br/>
|
||||
{this.props.data.status === ScanStatus.USED ?
|
||||
<StolenPasswordsComponent data={this.props.reportData.glance.stolen_creds.concat(this.props.reportData.glance.ssh_keys)}/>
|
||||
<StolenPasswordsComponent
|
||||
data={this.props.reportData.glance.stolen_creds.concat(this.props.reportData.glance.ssh_keys)}/>
|
||||
: ""}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -13,10 +13,17 @@ class T1005 extends React.Component {
|
|||
return ([{
|
||||
Header: "Sensitive data",
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{Header: 'Type', id: 'type', accessor: x => x.gathered_data_type, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Info', id: 'info', accessor: x => x.info, style: {'whiteSpace': 'unset'}},
|
||||
]}])};
|
||||
]
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -14,10 +14,16 @@ class T1016 extends React.Component {
|
|||
return ([{
|
||||
Header: "Network configuration info gathered",
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{Header: 'Network info', id: 'info', accessor: x => renderUsageFields(x.info), style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -21,12 +21,23 @@ class T1018 extends React.Component {
|
|||
static getScanInfoColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.monkey), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.monkey),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{Header: 'First scan', id: 'started', accessor: x => x.started, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Last scan', id: 'finished', accessor: x => x.finished, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Systems found', id: 'systems', accessor: x => T1018.renderMachines(x.machines), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Systems found',
|
||||
id: 'systems',
|
||||
accessor: x => T1018.renderMachines(x.machines),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -13,12 +13,20 @@ class T1021 extends React.Component {
|
|||
static getServiceColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: { 'whiteSpace': 'unset' }, width: 160},
|
||||
{
|
||||
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: {'whiteSpace': 'unset'}, width: 160
|
||||
},
|
||||
{Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: {'whiteSpace': 'unset'}, width: 100},
|
||||
{Header: 'Valid account used', id: 'credentials', accessor: x => this.renderCreds(x.successful_creds), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Valid account used',
|
||||
id: 'credentials',
|
||||
accessor: x => this.renderCreds(x.successful_creds),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
static renderCreds(creds) {
|
||||
return <span>{creds.map(cred => <div key={cred}>{cred}</div>)}</span>
|
||||
|
|
|
@ -15,7 +15,9 @@ class T1041 extends React.Component {
|
|||
columns: [
|
||||
{Header: 'Source', id: 'src', accessor: x => x.src, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Destination', id: 'dst', accessor: x => x.dst, style: {'whiteSpace': 'unset'}}
|
||||
]}])};
|
||||
]
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -14,11 +14,18 @@ class T1059 extends React.Component {
|
|||
return ([{
|
||||
Header: 'Example commands used',
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.data.machine), style: { 'whiteSpace': 'unset'}, width: 160 },
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachine(x.data.machine),
|
||||
style: {'whiteSpace': 'unset'},
|
||||
width: 160
|
||||
},
|
||||
{Header: 'Approx. Time', id: 'time', accessor: x => x.data.info.finished, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Command', id: 'command', accessor: x => x.data.info.executed_cmds.cmd, style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -27,7 +27,8 @@ class T1075 extends React.Component {
|
|||
{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'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -13,10 +13,16 @@ class T1082 extends React.Component {
|
|||
static getSystemInfoColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{Header: 'Gathered info', id: 'info', accessor: x => renderUsageFields(x.collections), style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -14,11 +14,18 @@ class T1086 extends React.Component {
|
|||
return ([{
|
||||
Header: 'Example Powershell commands used',
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.data[0].machine), style: { 'whiteSpace': 'unset'}, width: 160 },
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachine(x.data[0].machine),
|
||||
style: {'whiteSpace': 'unset'},
|
||||
width: 160
|
||||
},
|
||||
{Header: 'Approx. Time', id: 'time', accessor: x => x.data[0].info.finished, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Command', id: 'command', accessor: x => x.data[0].info.executed_cmds[0].cmd, style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -13,10 +13,13 @@ class T1090 extends React.Component {
|
|||
static getProxyColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machines',
|
||||
{
|
||||
Header: 'Machines',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x),
|
||||
style: { 'whiteSpace': 'unset', textAlign: 'center' }}]}])
|
||||
style: {'whiteSpace': 'unset', textAlign: 'center'}
|
||||
}]
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -18,7 +18,8 @@ class T1105 extends React.Component {
|
|||
{Header: 'Dst. Machine', id: 'dstMachine', accessor: x => x.dst, style: {'whiteSpace': 'unset'}, width: 170},
|
||||
{Header: 'Filename', id: 'filename', accessor: x => x.filename, style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -21,11 +21,19 @@ class T1107 extends React.Component {
|
|||
static getDeletedFileColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x._id.machine), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x._id.machine),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{Header: 'Path', id: 'path', accessor: x => x._id.path, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Deleted?', id: 'deleted', accessor: x => this.renderDelete(x._id.status),
|
||||
style: { 'whiteSpace': 'unset' }, width: 160}]
|
||||
}])};
|
||||
{
|
||||
Header: 'Deleted?', id: 'deleted', accessor: x => this.renderDelete(x._id.status),
|
||||
style: {'whiteSpace': 'unset'}, width: 160
|
||||
}]
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -13,15 +13,23 @@ class T1110 extends React.Component {
|
|||
static getServiceColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: { 'whiteSpace': 'unset' }, width: 160},
|
||||
{
|
||||
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: {'whiteSpace': 'unset'}, width: 160
|
||||
},
|
||||
{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: 'Finished', id: 'finished', accessor: x => x.info.finished, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Attempts', id: 'attempts', accessor: x => x.attempt_cnt, style: {'whiteSpace': 'unset'}, width: 160},
|
||||
{Header: 'Successful credentials', id: 'credentials', accessor: x => this.renderCreds(x.successful_creds), style: { 'whiteSpace': 'unset' }},
|
||||
{
|
||||
Header: 'Successful credentials',
|
||||
id: 'credentials',
|
||||
accessor: x => this.renderCreds(x.successful_creds),
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
static renderCreds(creds) {
|
||||
return <span>{creds.map(cred => <div key={cred}>{cred}</div>)}</span>
|
||||
|
|
|
@ -22,16 +22,21 @@ class T1145 extends React.Component {
|
|||
static getKeysInfoColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{Header: 'Machine',
|
||||
{
|
||||
Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: { 'whiteSpace': 'unset' }},
|
||||
{Header: 'Keys found',
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{
|
||||
Header: 'Keys found',
|
||||
id: 'keys',
|
||||
accessor: x => T1145.renderSSHKeys(x.ssh_info),
|
||||
style: { 'whiteSpace': 'unset' }},
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -14,20 +14,27 @@ class T1188 extends React.Component {
|
|||
return ([{
|
||||
Header: "Communications through multi-hop proxies",
|
||||
columns: [
|
||||
{Header: 'From',
|
||||
{
|
||||
Header: 'From',
|
||||
id: 'from',
|
||||
accessor: x => renderMachineFromSystemData(x.from),
|
||||
style: { 'whiteSpace': 'unset' }},
|
||||
{Header: 'To',
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{
|
||||
Header: 'To',
|
||||
id: 'to',
|
||||
accessor: x => renderMachineFromSystemData(x.to),
|
||||
style: { 'whiteSpace': 'unset' }},
|
||||
{Header: 'Hops',
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
{
|
||||
Header: 'Hops',
|
||||
id: 'hops',
|
||||
accessor: x => x.count,
|
||||
style: { 'whiteSpace': 'unset' }},
|
||||
style: {'whiteSpace': 'unset'}
|
||||
},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -8,17 +8,23 @@ class T1210 extends React.Component {
|
|||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.columns = [ {Header: 'Machine',
|
||||
this.columns = [{
|
||||
Header: 'Machine',
|
||||
id: 'machine', accessor: x => renderMachine(x),
|
||||
style: {'whiteSpace': 'unset'},
|
||||
width: 200},
|
||||
{Header: 'Time',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
Header: 'Time',
|
||||
id: 'time', accessor: x => x.time,
|
||||
style: {'whiteSpace': 'unset'},
|
||||
width: 170},
|
||||
{Header: 'Usage',
|
||||
width: 170
|
||||
},
|
||||
{
|
||||
Header: 'Usage',
|
||||
id: 'usage', accessor: x => x.usage,
|
||||
style: { 'whiteSpace': 'unset' }}
|
||||
style: {'whiteSpace': 'unset'}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -14,26 +14,34 @@ class T1210 extends React.Component {
|
|||
return ([{
|
||||
Header: "Found services",
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: { 'whiteSpace': 'unset' }, width: 200},
|
||||
{
|
||||
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: {'whiteSpace': 'unset'}, width: 200
|
||||
},
|
||||
{Header: 'Time', id: 'time', accessor: x => x.time, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Port', id: 'port', accessor: x => x.service.port, style: {'whiteSpace': 'unset'}, width: 100},
|
||||
{Header: 'Service', id: 'service', accessor: x => x.service.display_name, style: {'whiteSpace': 'unset'}}
|
||||
]
|
||||
}])}
|
||||
}])
|
||||
}
|
||||
|
||||
static getExploitColumns() {
|
||||
return ([{
|
||||
Header: "Exploited services",
|
||||
columns: [
|
||||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: { 'whiteSpace': 'unset' }, width: 200},
|
||||
{
|
||||
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||
style: {'whiteSpace': 'unset'}, width: 200
|
||||
},
|
||||
{Header: 'Time', id: 'time', accessor: x => x.time, style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Port/url', id: 'port', accessor: x =>this.renderEndpoint(x.service), style: { 'whiteSpace': 'unset' },
|
||||
width: 170},
|
||||
{
|
||||
Header: 'Port/url', id: 'port', accessor: x => this.renderEndpoint(x.service), style: {'whiteSpace': 'unset'},
|
||||
width: 170
|
||||
},
|
||||
{Header: 'Service', id: 'service', accessor: x => x.service.display_name, style: {'whiteSpace': 'unset'}}
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
static renderEndpoint(val) {
|
||||
return (
|
||||
|
@ -44,10 +52,14 @@ class T1210 extends React.Component {
|
|||
static formatScanned(data) {
|
||||
let result = [];
|
||||
for (let service in data.machine.services) {
|
||||
let scanned_service = {'machine': data.machine,
|
||||
let scanned_service = {
|
||||
'machine': data.machine,
|
||||
'time': data.time,
|
||||
'service': {'port': [data.machine.services[service].port],
|
||||
'display_name': data.machine.services[service].display_name}};
|
||||
'service': {
|
||||
'port': [data.machine.services[service].port],
|
||||
'display_name': data.machine.services[service].display_name
|
||||
}
|
||||
};
|
||||
result.push(scanned_service)
|
||||
}
|
||||
return result
|
||||
|
|
|
@ -17,7 +17,8 @@ class T1222 extends React.Component {
|
|||
{Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine), style: {'whiteSpace': 'unset'}},
|
||||
{Header: 'Command', id: 'command', accessor: x => x.command, style: {'whiteSpace': 'unset'}},
|
||||
]
|
||||
}])};
|
||||
}])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -94,8 +94,11 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
this.setInitialConfig(monkeyConfig.configuration);
|
||||
this.setInitialAttackConfig(attackConfig.configuration);
|
||||
for (let sectionKey of this.sectionsOrder) {
|
||||
if (sectionKey === 'attack') {sections.push({key:sectionKey, title: "ATT&CK"})}
|
||||
else {sections.push({key: sectionKey, title: monkeyConfig.schema.properties[sectionKey].title});}
|
||||
if (sectionKey === 'attack') {
|
||||
sections.push({key: sectionKey, title: "ATT&CK"})
|
||||
} else {
|
||||
sections.push({key: sectionKey, title: monkeyConfig.schema.properties[sectionKey].title});
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
schema: monkeyConfig.schema,
|
||||
|
@ -134,13 +137,14 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
body: JSON.stringify(this.state.attackConfig)
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok)
|
||||
{
|
||||
if (!res.ok) {
|
||||
throw Error()
|
||||
}
|
||||
return res;
|
||||
})
|
||||
.then(() => {this.setInitialAttackConfig(this.state.attackConfig);})
|
||||
.then(() => {
|
||||
this.setInitialAttackConfig(this.state.attackConfig);
|
||||
})
|
||||
.then(this.updateConfig())
|
||||
.then(this.setState({lastAction: 'saved'}))
|
||||
.catch(error => {
|
||||
|
@ -207,9 +211,13 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
};
|
||||
|
||||
renderAttackAlertModal = () => {
|
||||
return (<Modal show={this.state.showAttackAlert} onHide={() => {this.setState({showAttackAlert: false})}}>
|
||||
return (<Modal show={this.state.showAttackAlert} onHide={() => {
|
||||
this.setState({showAttackAlert: false})
|
||||
}}>
|
||||
<Modal.Body>
|
||||
<h2><div className="text-center">Warning</div></h2>
|
||||
<h2>
|
||||
<div className="text-center">Warning</div>
|
||||
</h2>
|
||||
<p className="text-center" style={{'fontSize': '1.2em', 'marginBottom': '2em'}}>
|
||||
You have unsubmitted changes. Submit them before proceeding.
|
||||
</p>
|
||||
|
@ -217,7 +225,9 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
<button type="button"
|
||||
className="btn btn-success btn-lg"
|
||||
style={{margin: '5px'}}
|
||||
onClick={() => {this.setState({showAttackAlert: false})}} >
|
||||
onClick={() => {
|
||||
this.setState({showAttackAlert: false})
|
||||
}}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
|
@ -270,9 +280,11 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
this.setInitialConfig(res.configuration);
|
||||
this.props.onStatusChange();
|
||||
});
|
||||
this.authFetch(ATTACK_URL,{ method: 'POST',
|
||||
this.authFetch(ATTACK_URL, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify('reset_attack_matrix')})
|
||||
body: JSON.stringify('reset_attack_matrix')
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.setState({attackConfig: res.configuration});
|
||||
|
@ -288,8 +300,10 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
if (this.PBAlinuxPond !== null) {
|
||||
this.PBAlinuxPond.removeFile();
|
||||
}
|
||||
let request_options = {method: 'DELETE',
|
||||
headers: {'Content-Type': 'text/plain'}};
|
||||
let request_options = {
|
||||
method: 'DELETE',
|
||||
headers: {'Content-Type': 'text/plain'}
|
||||
};
|
||||
this.authFetch('/api/fileUpload/PBAlinux', request_options);
|
||||
this.authFetch('/api/fileUpload/PBAwindows', request_options);
|
||||
this.setState({PBAlinuxFile: [], PBAwinFile: []});
|
||||
|
@ -300,7 +314,10 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
this.setState({
|
||||
configuration: JSON.parse(event.target.result),
|
||||
lastAction: 'import_success'
|
||||
}, () => {this.sendConfig(); this.setInitialConfig(JSON.parse(event.target.result))});
|
||||
}, () => {
|
||||
this.sendConfig();
|
||||
this.setInitialConfig(JSON.parse(event.target.result))
|
||||
});
|
||||
this.currentFormData = {};
|
||||
} catch (SyntaxError) {
|
||||
this.setState({lastAction: 'import_failure'});
|
||||
|
@ -321,8 +338,7 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
body: JSON.stringify(this.state.configuration)
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok)
|
||||
{
|
||||
if (!res.ok) {
|
||||
throw Error()
|
||||
}
|
||||
return res;
|
||||
|
@ -355,7 +371,8 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
|
||||
PBAwindows = () => {
|
||||
return (<FilePond
|
||||
server={{ url:'/api/fileUpload/PBAwindows',
|
||||
server={{
|
||||
url: '/api/fileUpload/PBAwindows',
|
||||
process: {headers: {'Authorization': this.jwtHeader}},
|
||||
revert: {headers: {'Authorization': this.jwtHeader}},
|
||||
restore: {headers: {'Authorization': this.jwtHeader}},
|
||||
|
@ -374,7 +391,8 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
|
||||
PBAlinux = () => {
|
||||
return (<FilePond
|
||||
server={{ url:'/api/fileUpload/PBAlinux',
|
||||
server={{
|
||||
url: '/api/fileUpload/PBAlinux',
|
||||
process: {headers: {'Authorization': this.jwtHeader}},
|
||||
revert: {headers: {'Authorization': this.jwtHeader}},
|
||||
restore: {headers: {'Authorization': this.jwtHeader}},
|
||||
|
|
|
@ -71,8 +71,7 @@ class MapPageComponent extends AuthComponent {
|
|||
this.authFetch('/api/netmap/node?id=' + event.nodes[0])
|
||||
.then(res => res.json())
|
||||
.then(res => this.setState({selected: res, selectedType: 'node'}));
|
||||
}
|
||||
else if (event.edges.length === 1) {
|
||||
} else if (event.edges.length === 1) {
|
||||
let displayedEdge = this.state.graph.edges.find(
|
||||
function (edge) {
|
||||
return edge['id'] === event.edges[0];
|
||||
|
@ -84,8 +83,7 @@ class MapPageComponent extends AuthComponent {
|
|||
.then(res => res.json())
|
||||
.then(res => this.setState({selected: res.edge, selectedType: 'edge'}));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.setState({selected: null, selectedType: null});
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +98,9 @@ class MapPageComponent extends AuthComponent {
|
|||
return (
|
||||
<Modal show={this.state.showKillDialog} onHide={() => this.setState({showKillDialog: false})}>
|
||||
<Modal.Body>
|
||||
<h2><div className="text-center">Are you sure you want to kill all monkeys?</div></h2>
|
||||
<h2>
|
||||
<div className="text-center">Are you sure you want to kill all monkeys?</div>
|
||||
</h2>
|
||||
<p style={{'fontSize': '1.2em', 'marginBottom': '2em'}}>
|
||||
This might take a few moments...
|
||||
</p>
|
||||
|
@ -174,7 +174,8 @@ class MapPageComponent extends AuthComponent {
|
|||
<div style={{'overflow': 'auto', 'marginBottom': '1em'}}>
|
||||
<Link to="/infection/telemetry" className="btn btn-default pull-left" style={{'width': '48%'}}>Monkey
|
||||
Telemetry</Link>
|
||||
<button onClick={() => this.setState({showKillDialog: true})} className="btn btn-danger pull-right" style={{'width': '48%'}}>
|
||||
<button onClick={() => this.setState({showKillDialog: true})} className="btn btn-danger pull-right"
|
||||
style={{'width': '48%'}}>
|
||||
<Icon name="stop-circle" style={{'marginRight': '0.5em'}}/>
|
||||
Kill All Monkeys
|
||||
</button>
|
||||
|
|
|
@ -29,15 +29,13 @@ class PassTheHashMapPageComponent extends AuthComponent {
|
|||
return node['id'] === event.nodes[0];
|
||||
});
|
||||
this.setState({selected: displayedNode, selectedType: 'node'})
|
||||
}
|
||||
else if (event.edges.length === 1) {
|
||||
} else if (event.edges.length === 1) {
|
||||
let displayedEdge = this.state.graph.edges.find(
|
||||
function (edge) {
|
||||
return edge['id'] === event.edges[0];
|
||||
});
|
||||
this.setState({selected: displayedEdge, selectedType: 'edge'});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.setState({selected: null, selectedType: null});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,9 @@ class ReportPageComponent extends AuthComponent {
|
|||
return (
|
||||
<Fragment>
|
||||
<div style={{marginBottom: '20px'}}>
|
||||
<PrintReportButton onClick={() => {print();}} />
|
||||
<PrintReportButton onClick={() => {
|
||||
print();
|
||||
}}/>
|
||||
</div>
|
||||
<div className="report-page">
|
||||
<ReportHeader report_type={ReportTypes.security}/>
|
||||
|
@ -155,7 +157,9 @@ class ReportPageComponent extends AuthComponent {
|
|||
{content}
|
||||
</div>
|
||||
<div style={{marginTop: '20px'}}>
|
||||
<PrintReportButton onClick={() => {print();}} />
|
||||
<PrintReportButton onClick={() => {
|
||||
print();
|
||||
}}/>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -315,7 +319,8 @@ class ReportPageComponent extends AuthComponent {
|
|||
{this.state.report.overview.issues[this.Issue.HADOOP] ?
|
||||
<li>Hadoop/Yarn servers are vulnerable to remote code execution.</li> : null}
|
||||
{this.state.report.overview.issues[this.Issue.PTH_CRIT_SERVICES_ACCESS] ?
|
||||
<li>Mimikatz found login credentials of a user who has admin access to a server defined as critical.</li>: null }
|
||||
<li>Mimikatz found login credentials of a user who has admin access to a server defined as
|
||||
critical.</li> : null}
|
||||
{this.state.report.overview.issues[this.Issue.MSSQL] ?
|
||||
<li>MS-SQL servers are vulnerable to remote code execution via xp_cmdshell command.</li> : null}
|
||||
</ul>
|
||||
|
@ -344,7 +349,8 @@ class ReportPageComponent extends AuthComponent {
|
|||
{this.state.report.overview.warnings[this.Warning.TUNNEL] ?
|
||||
<li>Weak segmentation - Machines were able to communicate over unused ports.</li> : null}
|
||||
{this.state.report.overview.warnings[this.Warning.SHARED_LOCAL_ADMIN] ?
|
||||
<li>Shared local administrator account - Different machines have the same account as a local administrator.</li> : null}
|
||||
<li>Shared local administrator account - Different machines have the same account as a local
|
||||
administrator.</li> : null}
|
||||
{this.state.report.overview.warnings[this.Warning.SHARED_PASSWORDS] ?
|
||||
<li>Multiple users have the same password</li> : null}
|
||||
</ul>
|
||||
|
@ -463,11 +469,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
Credentials Map
|
||||
</h3>
|
||||
<p>
|
||||
This map visualizes possible attack paths through the network using credential compromise. Paths represent lateral movement opportunities by attackers.
|
||||
This map visualizes possible attack paths through the network using credential compromise. Paths represent lateral
|
||||
movement opportunities by attackers.
|
||||
</p>
|
||||
<div className="map-legend">
|
||||
<b>Legend: </b>
|
||||
<span>Access credentials <i className="fa fa-lg fa-minus" style={{color: '#0158aa'}}/></span> <b style={{color: '#aeaeae'}}> | </b>
|
||||
<span>Access credentials <i className="fa fa-lg fa-minus" style={{color: '#0158aa'}}/></span> <b
|
||||
style={{color: '#aeaeae'}}> | </b>
|
||||
</div>
|
||||
<div>
|
||||
<PassTheHashMapPageComponent graph={this.state.report.glance.pth_map}/>
|
||||
|
@ -664,10 +672,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
className="label label-danger">6200</span>.
|
||||
<br/>
|
||||
The attack was made possible because the VSFTPD server was not patched against CVE-2011-2523.
|
||||
<br/><br/>In July 2011, it was discovered that vsftpd version 2.3.4 downloadable from the master site had been compromised.
|
||||
Users logging into a compromised vsftpd-2.3.4 server may issue a ":)" smileyface as the username and gain a command shell on port 6200.
|
||||
<br/><br/>In July 2011, it was discovered that vsftpd version 2.3.4 downloadable from the master site had been
|
||||
compromised.
|
||||
Users logging into a compromised vsftpd-2.3.4 server may issue a ":)" smileyface as the username and gain a command
|
||||
shell on port 6200.
|
||||
<br/><br/>
|
||||
The Monkey executed commands by first logging in with ":)" in the username and then sending commands to the backdoor at port 6200.
|
||||
The Monkey executed commands by first logging in with ":)" in the username and then sending commands to the backdoor
|
||||
at port 6200.
|
||||
<br/><br/>Read more about the security issue and remediation <a
|
||||
href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2523"
|
||||
>here</a>.
|
||||
|
@ -781,7 +792,8 @@ class ReportPageComponent extends AuthComponent {
|
|||
generateSharedLocalAdminsIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
Make sure the right administrator accounts are managing the right machines, and that there isn’t an unintentional local admin sharing.
|
||||
Make sure the right administrator accounts are managing the right machines, and that there isn’t an unintentional local
|
||||
admin sharing.
|
||||
<CollapsibleWellComponent>
|
||||
Here is a list of machines which the account <span
|
||||
className="label label-primary">{issue.username}</span> is defined as an administrator:
|
||||
|
@ -856,7 +868,8 @@ class ReportPageComponent extends AuthComponent {
|
|||
generateHadoopIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
Run Hadoop in secure mode (<a href="http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/SecureMode.html">
|
||||
Run Hadoop in secure mode (<a
|
||||
href="http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/SecureMode.html">
|
||||
add Kerberos authentication</a>).
|
||||
<CollapsibleWellComponent>
|
||||
The Hadoop server at <span className="label label-primary">{issue.machine}</span> (<span
|
||||
|
|
|
@ -83,7 +83,12 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
let is_error_while_collecting_aws_machines = (res['error'] != null);
|
||||
if (is_error_while_collecting_aws_machines) {
|
||||
// There was an error. Finish loading, and display error message.
|
||||
this.setState({isOnAws: true, isErrorWhileCollectingAwsMachines: true, awsMachineCollectionErrorMsg: res['error'], isLoadingAws: false});
|
||||
this.setState({
|
||||
isOnAws: true,
|
||||
isErrorWhileCollectingAwsMachines: true,
|
||||
awsMachineCollectionErrorMsg: res['error'],
|
||||
isLoadingAws: false
|
||||
});
|
||||
} else {
|
||||
// No error! Finish loading and display machines for user
|
||||
this.setState({isOnAws: true, awsMachines: res['instances'], isLoadingAws: false});
|
||||
|
@ -219,6 +224,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
});
|
||||
});
|
||||
};
|
||||
|
||||
fetchConfig() {
|
||||
return this.authFetch('/api/configuration/island')
|
||||
.then(res => res.json())
|
||||
|
@ -226,6 +232,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
return res.configuration;
|
||||
})
|
||||
}
|
||||
|
||||
instanceIdToInstance = (instance_id) => {
|
||||
let instance = this.state.awsMachines.find(
|
||||
function (inst) {
|
||||
|
@ -241,7 +248,9 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
<div style={{'marginTop': '1em', 'marginBottom': '1em'}}>
|
||||
<p className="alert alert-info">
|
||||
<i className="glyphicon glyphicon-info-sign" style={{'marginRight': '5px'}}/>
|
||||
Not sure what this is? Not seeing your AWS EC2 instances? <a href="https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances" target="_blank">Read the documentation</a>!
|
||||
Not sure what this is? Not seeing your AWS EC2 instances? <a
|
||||
href="https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances"
|
||||
target="_blank">Read the documentation</a>!
|
||||
</p>
|
||||
</div>
|
||||
{
|
||||
|
@ -269,6 +278,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Col xs={12} lg={8}>
|
||||
|
@ -302,7 +312,8 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
OR
|
||||
</p>
|
||||
<p style={this.state.showManual || !this.state.isOnAws ? {'marginBottom': '2em'} : {}}>
|
||||
<button onClick={this.toggleManual} className={'btn btn-default btn-lg center-block' + (this.state.showManual ? ' active' : '')}>
|
||||
<button onClick={this.toggleManual}
|
||||
className={'btn btn-default btn-lg center-block' + (this.state.showManual ? ' active' : '')}>
|
||||
Run on machine of your choice
|
||||
</button>
|
||||
</p>
|
||||
|
@ -357,7 +368,8 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
{
|
||||
this.state.isOnAws ?
|
||||
<p style={{'marginBottom': '2em'}}>
|
||||
<button onClick={this.toggleAws} className={'btn btn-default btn-lg center-block' + (this.state.showAws ? ' active' : '')}>
|
||||
<button onClick={this.toggleAws}
|
||||
className={'btn btn-default btn-lg center-block' + (this.state.showAws ? ' active' : '')}>
|
||||
Run on AWS machine of your choice
|
||||
</button>
|
||||
</p>
|
||||
|
@ -370,9 +382,12 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
<div style={{'marginTop': '1em'}}>
|
||||
<p class="alert alert-danger">
|
||||
<i className="glyphicon glyphicon-warning-sign" style={{'marginRight': '5px'}}/>
|
||||
Error while collecting AWS machine data. Error message: <code>{this.state.awsMachineCollectionErrorMsg}</code><br/>
|
||||
Error while collecting AWS machine data. Error
|
||||
message: <code>{this.state.awsMachineCollectionErrorMsg}</code><br/>
|
||||
Are you sure you've set the correct role on your Island AWS machine?<br/>
|
||||
Not sure what this is? <a href="https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances">Read the documentation</a>!
|
||||
Not sure what this is? <a
|
||||
href="https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances">Read
|
||||
the documentation</a>!
|
||||
</p>
|
||||
</div>
|
||||
:
|
||||
|
|
|
@ -29,7 +29,9 @@ class StartOverPageComponent extends AuthComponent {
|
|||
return (
|
||||
<Modal show={this.state.showCleanDialog} onHide={() => this.setState({showCleanDialog: false})}>
|
||||
<Modal.Body>
|
||||
<h2><div className="text-center">Reset environment</div></h2>
|
||||
<h2>
|
||||
<div className="text-center">Reset environment</div>
|
||||
</h2>
|
||||
<p style={{'fontSize': '1.2em', 'marginBottom': '2em'}}>
|
||||
Are you sure you want to reset the environment?
|
||||
</p>
|
||||
|
@ -75,7 +77,8 @@ class StartOverPageComponent extends AuthComponent {
|
|||
<button className="btn btn-danger btn-lg center-block"
|
||||
onClick={() => {
|
||||
this.setState({showCleanDialog: true});
|
||||
this.updateMonkeysRunning();}
|
||||
this.updateMonkeysRunning();
|
||||
}
|
||||
}>
|
||||
Reset the Environment
|
||||
</button>
|
||||
|
|
|
@ -18,8 +18,7 @@ class PaginatedTable extends Component {
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (
|
||||
<div/>
|
||||
);
|
||||
|
|
|
@ -177,8 +177,7 @@ class AttackReportPageComponent extends AuthComponent {
|
|||
|
||||
render() {
|
||||
let content;
|
||||
if (! this.state.runStarted)
|
||||
{
|
||||
if (!this.state.runStarted) {
|
||||
content =
|
||||
<p className="alert alert-warning">
|
||||
<i className="glyphicon glyphicon-warning-sign" style={{'marginRight': '5px'}}/>
|
||||
|
|
|
@ -14,8 +14,10 @@ const columns = [
|
|||
Header: 'Breached Servers',
|
||||
columns: [
|
||||
{Header: 'Machine', accessor: 'label'},
|
||||
{Header: 'IP Addresses', id: 'ip_addresses',
|
||||
accessor: x => renderIpAddresses(x)},
|
||||
{
|
||||
Header: 'IP Addresses', id: 'ip_addresses',
|
||||
accessor: x => renderIpAddresses(x)
|
||||
},
|
||||
{Header: 'Exploits', id: 'exploits', accessor: x => renderArray(x.exploits)}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -14,8 +14,10 @@ const columns = [
|
|||
Header: 'Scanned Servers',
|
||||
columns: [
|
||||
{Header: 'Machine', accessor: 'label'},
|
||||
{ Header: 'IP Addresses', id: 'ip_addresses',
|
||||
accessor: x => renderIpAddresses(x)},
|
||||
{
|
||||
Header: 'IP Addresses', id: 'ip_addresses',
|
||||
accessor: x => renderIpAddresses(x)
|
||||
},
|
||||
{Header: 'Accessible From', id: 'accessible_from_nodes', accessor: x => renderArray(x.accessible_from_nodes)},
|
||||
{Header: 'Services', id: 'services', accessor: x => renderArray(x.services)}
|
||||
]
|
||||
|
|
|
@ -22,7 +22,9 @@ export default class EventsModal extends Component {
|
|||
</h3>
|
||||
<hr/>
|
||||
<p>
|
||||
There {Pluralize('is', this.props.events.length)} {<div className={"label label-primary"}>{this.props.events.length}</div>} {Pluralize('event', this.props.events.length)} associated with this finding.
|
||||
There {Pluralize('is', this.props.events.length)} {<div
|
||||
className={"label label-primary"}>{this.props.events.length}</div>} {Pluralize('event', this.props.events.length)} associated
|
||||
with this finding.
|
||||
</p>
|
||||
{this.props.events.length > 5 ? this.renderButtons() : null}
|
||||
<EventsTimeline events={this.props.events}/>
|
||||
|
|
|
@ -15,7 +15,8 @@ const pillarToIcon = {
|
|||
export default class PillarLabel extends Component {
|
||||
render() {
|
||||
const className = "label " + statusToLabelType[this.props.status];
|
||||
return <div className={className} style={{margin: '2px', display: 'inline-block'}}><i className={pillarToIcon[this.props.pillar]}/> {this.props.pillar}</div>
|
||||
return <div className={className} style={{margin: '2px', display: 'inline-block'}}><i
|
||||
className={pillarToIcon[this.props.pillar]}/> {this.props.pillar}</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,16 +10,19 @@ const MAX_WIDTH_STATUS_COLUMN = 80;
|
|||
const columns = [
|
||||
{
|
||||
columns: [
|
||||
{ Header: 'Status', id: 'status',
|
||||
{
|
||||
Header: 'Status', id: 'status',
|
||||
accessor: x => {
|
||||
return <StatusLabel status={x.status} size="fa-3x" showText={false}/>;
|
||||
},
|
||||
maxWidth: MAX_WIDTH_STATUS_COLUMN
|
||||
},
|
||||
{ Header: 'Zero Trust Principle', accessor: 'principle',
|
||||
{
|
||||
Header: 'Zero Trust Principle', accessor: 'principle',
|
||||
style: {'whiteSpace': 'unset'} // This enables word wrap
|
||||
},
|
||||
{ Header: 'Monkey Tests', id: 'tests',
|
||||
{
|
||||
Header: 'Monkey Tests', id: 'tests',
|
||||
style: {'whiteSpace': 'unset'}, // This enables word wrap
|
||||
accessor: x => {
|
||||
return <TestsStatus tests={x.tests}/>;
|
||||
|
|
|
@ -32,7 +32,8 @@ class ZeroTrustReportLegend extends Component {
|
|||
<div style={{display: "inline-block"}}>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.failed}/>
|
||||
</div>
|
||||
{"\t"}At least one of the tests related to this component failed. This means that the Infection Monkey detected an unmet Zero Trust requirement.
|
||||
{"\t"}At least one of the tests related to this component failed. This means that the Infection Monkey detected an
|
||||
unmet Zero Trust requirement.
|
||||
</li>
|
||||
<li>
|
||||
<div style={{display: "inline-block"}}>
|
||||
|
@ -50,7 +51,8 @@ class ZeroTrustReportLegend extends Component {
|
|||
<div style={{display: "inline-block"}}>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.unexecuted}/>
|
||||
</div>
|
||||
{"\t"}This status means the test wasn't executed.To activate more tests, refer to the Monkey <NavLink to="/configuration"><u>configuration</u></NavLink> page.
|
||||
{"\t"}This status means the test wasn't executed.To activate more tests, refer to the Monkey <NavLink
|
||||
to="/configuration"><u>configuration</u></NavLink> page.
|
||||
</li>
|
||||
</ul>
|
||||
</div>;
|
||||
|
|
|
@ -9,14 +9,14 @@ export default class SinglePillarPrinciplesStatus extends AuthComponent {
|
|||
render() {
|
||||
if (this.props.principlesStatus.length === 0) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (
|
||||
<Panel>
|
||||
<Panel.Heading>
|
||||
<Panel.Title toggle>
|
||||
<h3 style={{textAlign: "center", marginTop: "1px", marginBottom: "1px"}}>
|
||||
<i className="fa fa-chevron-down" /> <PillarLabel pillar={this.props.pillar} status={this.props.pillarsToStatuses[this.props.pillar]} />
|
||||
<i className="fa fa-chevron-down"/> <PillarLabel pillar={this.props.pillar}
|
||||
status={this.props.pillarsToStatuses[this.props.pillar]}/>
|
||||
</h3>
|
||||
</Panel.Title>
|
||||
</Panel.Heading>
|
||||
|
|
|
@ -14,7 +14,8 @@ export default class SummarySection extends Component {
|
|||
<Col xs={12} sm={12} md={12} lg={12}>
|
||||
<MonkeysStillAliveWarning allMonkeysAreDead={this.props.allMonkeysAreDead}/>
|
||||
<p>
|
||||
Get a quick glance at how your network aligns with the <a href="https://www.forrester.com/report/The+Zero+Trust+eXtended+ZTX+Ecosystem/-/E-RES137210">
|
||||
Get a quick glance at how your network aligns with the <a
|
||||
href="https://www.forrester.com/report/The+Zero+Trust+eXtended+ZTX+Ecosystem/-/E-RES137210">
|
||||
Zero Trust eXtended (ZTX) framework
|
||||
</a>.
|
||||
</p>
|
||||
|
|
|
@ -29,11 +29,15 @@ class CheckboxComponent extends React.PureComponent {
|
|||
|
||||
//Toggles component.
|
||||
toggleChecked() {
|
||||
if (this.state.isAnimating) {return false;}
|
||||
if (this.state.isAnimating) {
|
||||
return false;
|
||||
}
|
||||
this.setState({
|
||||
checked: !this.state.checked,
|
||||
isAnimating: true,
|
||||
}, () => { this.props.changeHandler ? this.props.changeHandler(this.props.name, this.state.checked) : null});
|
||||
}, () => {
|
||||
this.props.changeHandler ? this.props.changeHandler(this.props.name, this.state.checked) : null
|
||||
});
|
||||
}
|
||||
|
||||
// Stops ping animation on checkbox after click
|
||||
|
@ -47,10 +51,15 @@ class CheckboxComponent extends React.PureComponent {
|
|||
if (this.state.necessary) {
|
||||
return result + ' blocked'
|
||||
}
|
||||
if (this.state.checked) { result += ' is-checked'; }
|
||||
else { result += ' is-unchecked' }
|
||||
if (this.state.checked) {
|
||||
result += ' is-checked';
|
||||
} else {
|
||||
result += ' is-unchecked'
|
||||
}
|
||||
|
||||
if (this.state.isAnimating) { result += ' do-ping'; }
|
||||
if (this.state.isAnimating) {
|
||||
result += ' do-ping';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
// Settings configured here will be merged into the final config object.
|
||||
export default {
|
||||
}
|
||||
export default {}
|
||||
|
|
|
@ -8,24 +8,39 @@
|
|||
</defs>
|
||||
<title>14cbedff-3eed-4f8f-abb7-fffe92867ded</title>
|
||||
<g>
|
||||
<path class="cls-1" d="M89.22,6.874l1.819-.159a3.153,3.153,0,1,1,.124-1.065,2.306,2.306,0,0,1-.005.492l-4.489.393a1.257,1.257,0,0,0,1.414.989,1.417,1.417,0,0,0,1.06-.56A.6.6,0,0,1,89.22,6.874Zm.087-1.767a1.311,1.311,0,0,0-1.443-.916,1.282,1.282,0,0,0-1.249,1.151Z"/>
|
||||
<path class="cls-1" d="M67.715,4.191a1.622,1.622,0,1,1-1.622,1.622,1.624,1.624,0,0,1,1.622-1.622m0-1.542a3.164,3.164,0,1,0,3.164,3.164A3.164,3.164,0,0,0,67.715,2.65Z"/>
|
||||
<path class="cls-1" d="M54.893,8.808,55.53.648A6.958,6.958,0,0,1,56.736.564a6.743,6.743,0,0,1,1.193.084L58.7,3.7q.324,1.332.456,2.148h.071q.132-.816.456-2.148L60.45.648a6.914,6.914,0,0,1,1.2-.084,6.7,6.7,0,0,1,1.188.084l.636,8.16a3.218,3.218,0,0,1-.863.1,5.125,5.125,0,0,1-.864-.06l-.192-3.48q-.1-1.656-.1-2.724h-.084L60.126,7.62a5.447,5.447,0,0,1-.93.06,5.9,5.9,0,0,1-.954-.06L57.006,2.64h-.084q-.023,1.464-.1,2.724l-.192,3.48a5.125,5.125,0,0,1-.864.06A3.366,3.366,0,0,1,54.893,8.808Z"/>
|
||||
<path class="cls-1" d="M77.094,4.86v2.5a2.089,2.089,0,0,0,.288,1.188,1.611,1.611,0,0,1-1.05.384.983.983,0,0,1-.8-.276,1.321,1.321,0,0,1-.223-.84V5.2a1.33,1.33,0,0,0-.12-.648.446.446,0,0,0-.42-.2,1.386,1.386,0,0,0-.983.468v4.02A4.716,4.716,0,0,1,72.9,8.9a5.113,5.113,0,0,1-.906-.072V2.856l.084-.084h.672a.9.9,0,0,1,.948.72,2.669,2.669,0,0,1,1.7-.744,1.477,1.477,0,0,1,1.26.576A2.5,2.5,0,0,1,77.094,4.86Z"/>
|
||||
<path class="cls-1" d="M81.3,6.408l-.4.012V8.832a4.606,4.606,0,0,1-.864.072,5,5,0,0,1-.888-.072V.084L79.241,0h.7a.973.973,0,0,1,.75.246,1.243,1.243,0,0,1,.222.834V4.944h.216a.369.369,0,0,0,.336-.216l.685-1.26a1.062,1.062,0,0,1,1.008-.66q.347,0,1,.024l.071.1-.972,1.824a1.885,1.885,0,0,1-.6.672,1.7,1.7,0,0,1,1.02,1.044l.3.888a4.932,4.932,0,0,0,.307.708.941.941,0,0,0,.27.3,1.512,1.512,0,0,1-1.2.564.839.839,0,0,1-.582-.18,1.534,1.534,0,0,1-.354-.636l-.36-1.056a1.225,1.225,0,0,0-.306-.516A.675.675,0,0,0,81.3,6.408Z"/>
|
||||
<path class="cls-1" d="M97.577,3.036l-1.5,5.628a5.042,5.042,0,0,1-1,2.1,2.437,2.437,0,0,1-1.9.7,4.322,4.322,0,0,1-1.416-.24V11a2.268,2.268,0,0,1,.09-.51,1.213,1.213,0,0,1,.27-.54,3.946,3.946,0,0,0,1.057.18,1.231,1.231,0,0,0,1.212-1.044l.048-.168q-1.008-.024-1.2-.744L91.805,2.988a2.4,2.4,0,0,1,.989-.24,1.049,1.049,0,0,1,.666.168,1.108,1.108,0,0,1,.313.6l.6,2.376q.1.348.288,1.6a.094.094,0,0,0,.108.084l1.08-4.716a3.485,3.485,0,0,1,.786-.072,2.786,2.786,0,0,1,.882.132Z"/>
|
||||
<path class="cls-1"
|
||||
d="M89.22,6.874l1.819-.159a3.153,3.153,0,1,1,.124-1.065,2.306,2.306,0,0,1-.005.492l-4.489.393a1.257,1.257,0,0,0,1.414.989,1.417,1.417,0,0,0,1.06-.56A.6.6,0,0,1,89.22,6.874Zm.087-1.767a1.311,1.311,0,0,0-1.443-.916,1.282,1.282,0,0,0-1.249,1.151Z"/>
|
||||
<path class="cls-1"
|
||||
d="M67.715,4.191a1.622,1.622,0,1,1-1.622,1.622,1.624,1.624,0,0,1,1.622-1.622m0-1.542a3.164,3.164,0,1,0,3.164,3.164A3.164,3.164,0,0,0,67.715,2.65Z"/>
|
||||
<path class="cls-1"
|
||||
d="M54.893,8.808,55.53.648A6.958,6.958,0,0,1,56.736.564a6.743,6.743,0,0,1,1.193.084L58.7,3.7q.324,1.332.456,2.148h.071q.132-.816.456-2.148L60.45.648a6.914,6.914,0,0,1,1.2-.084,6.7,6.7,0,0,1,1.188.084l.636,8.16a3.218,3.218,0,0,1-.863.1,5.125,5.125,0,0,1-.864-.06l-.192-3.48q-.1-1.656-.1-2.724h-.084L60.126,7.62a5.447,5.447,0,0,1-.93.06,5.9,5.9,0,0,1-.954-.06L57.006,2.64h-.084q-.023,1.464-.1,2.724l-.192,3.48a5.125,5.125,0,0,1-.864.06A3.366,3.366,0,0,1,54.893,8.808Z"/>
|
||||
<path class="cls-1"
|
||||
d="M77.094,4.86v2.5a2.089,2.089,0,0,0,.288,1.188,1.611,1.611,0,0,1-1.05.384.983.983,0,0,1-.8-.276,1.321,1.321,0,0,1-.223-.84V5.2a1.33,1.33,0,0,0-.12-.648.446.446,0,0,0-.42-.2,1.386,1.386,0,0,0-.983.468v4.02A4.716,4.716,0,0,1,72.9,8.9a5.113,5.113,0,0,1-.906-.072V2.856l.084-.084h.672a.9.9,0,0,1,.948.72,2.669,2.669,0,0,1,1.7-.744,1.477,1.477,0,0,1,1.26.576A2.5,2.5,0,0,1,77.094,4.86Z"/>
|
||||
<path class="cls-1"
|
||||
d="M81.3,6.408l-.4.012V8.832a4.606,4.606,0,0,1-.864.072,5,5,0,0,1-.888-.072V.084L79.241,0h.7a.973.973,0,0,1,.75.246,1.243,1.243,0,0,1,.222.834V4.944h.216a.369.369,0,0,0,.336-.216l.685-1.26a1.062,1.062,0,0,1,1.008-.66q.347,0,1,.024l.071.1-.972,1.824a1.885,1.885,0,0,1-.6.672,1.7,1.7,0,0,1,1.02,1.044l.3.888a4.932,4.932,0,0,0,.307.708.941.941,0,0,0,.27.3,1.512,1.512,0,0,1-1.2.564.839.839,0,0,1-.582-.18,1.534,1.534,0,0,1-.354-.636l-.36-1.056a1.225,1.225,0,0,0-.306-.516A.675.675,0,0,0,81.3,6.408Z"/>
|
||||
<path class="cls-1"
|
||||
d="M97.577,3.036l-1.5,5.628a5.042,5.042,0,0,1-1,2.1,2.437,2.437,0,0,1-1.9.7,4.322,4.322,0,0,1-1.416-.24V11a2.268,2.268,0,0,1,.09-.51,1.213,1.213,0,0,1,.27-.54,3.946,3.946,0,0,0,1.057.18,1.231,1.231,0,0,0,1.212-1.044l.048-.168q-1.008-.024-1.2-.744L91.805,2.988a2.4,2.4,0,0,1,.989-.24,1.049,1.049,0,0,1,.666.168,1.108,1.108,0,0,1,.313.6l.6,2.376q.1.348.288,1.6a.094.094,0,0,0,.108.084l1.08-4.716a3.485,3.485,0,0,1,.786-.072,2.786,2.786,0,0,1,.882.132Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-1" d="M0,8.937V.741A1.882,1.882,0,0,1,.414.705,2.229,2.229,0,0,1,.852.741v8.2a2.231,2.231,0,0,1-.432.036A2.056,2.056,0,0,1,0,8.937Z"/>
|
||||
<path class="cls-1" d="M8.232,4.809V7.833a2.871,2.871,0,0,0,.12,1,.7.7,0,0,1-.517.18q-.42,0-.42-.54V5.085a2.2,2.2,0,0,0-.191-1.074.747.747,0,0,0-.7-.318,2.332,2.332,0,0,0-1.044.27,2.7,2.7,0,0,0-.888.69V8.937a1.994,1.994,0,0,1-.408.036,1.987,1.987,0,0,1-.408-.036V3.093l.072-.072h.312a.384.384,0,0,1,.348.132.831.831,0,0,1,.085.432v.24a2.983,2.983,0,0,1,.966-.636A2.908,2.908,0,0,1,6.7,2.949a1.335,1.335,0,0,1,1.17.516A2.272,2.272,0,0,1,8.232,4.809Z"/>
|
||||
<path class="cls-1" d="M11.147,8.937V3.669l-1.031.012a1.473,1.473,0,0,1-.036-.312,1.639,1.639,0,0,1,.036-.324l1,.024q-.085-1.115-.084-1.272A1.769,1.769,0,0,1,11.472.555,1.538,1.538,0,0,1,12.666.069a3.728,3.728,0,0,1,1.386.252.818.818,0,0,1-.2.564A3.881,3.881,0,0,0,12.756.693a.883.883,0,0,0-.708.294,1.226,1.226,0,0,0-.252.822,9.977,9.977,0,0,0,.1,1.26l1.776-.024a1.716,1.716,0,0,1,.036.324,1.54,1.54,0,0,1-.036.312l-1.716-.012V8.937a2.258,2.258,0,0,1-.8,0Z"/>
|
||||
<path class="cls-1" d="M32.352,3.045a1.716,1.716,0,0,1,.036.324,1.54,1.54,0,0,1-.036.312l-1.524-.012v4.14q0,.492.468.492h.925a1,1,0,0,1,.071.372,1.405,1.405,0,0,1-.012.24,8.879,8.879,0,0,1-1.122.072,1.268,1.268,0,0,1-.846-.246.87.87,0,0,1-.288-.7V3.669l-.828.012a1.336,1.336,0,0,1-.036-.306,1.664,1.664,0,0,1,.036-.33l.828.012v-1.3a.794.794,0,0,1,.09-.432.4.4,0,0,1,.354-.132h.288l.072.072v1.8Z"/>
|
||||
<path class="cls-1" d="M35.472,3.837v5.1a2.324,2.324,0,0,1-.816,0V4.257a.7.7,0,0,0-.108-.456.5.5,0,0,0-.384-.12h-.107a1.288,1.288,0,0,1-.036-.294,1.616,1.616,0,0,1,.036-.318,4.4,4.4,0,0,1,.575-.048h.1a.7.7,0,0,1,.546.216A.856.856,0,0,1,35.472,3.837ZM34.379,1.881a.986.986,0,0,1-.084-.438.837.837,0,0,1,.084-.414.853.853,0,0,1,.511-.12.8.8,0,0,1,.5.12.837.837,0,0,1,.084.414.986.986,0,0,1-.084.438A.707.707,0,0,1,34.9,2,.874.874,0,0,1,34.379,1.881Z"/>
|
||||
<path class="cls-1" d="M49.139,4.809V7.833a2.871,2.871,0,0,0,.12,1,.7.7,0,0,1-.517.18q-.42,0-.42-.54V5.085a2.2,2.2,0,0,0-.191-1.074.747.747,0,0,0-.7-.318,2.332,2.332,0,0,0-1.044.27,2.7,2.7,0,0,0-.888.69V8.937a2.324,2.324,0,0,1-.816,0V3.093l.072-.072h.312a.384.384,0,0,1,.348.132.831.831,0,0,1,.085.432v.24a2.983,2.983,0,0,1,.966-.636,2.908,2.908,0,0,1,1.134-.24,1.335,1.335,0,0,1,1.17.516A2.272,2.272,0,0,1,49.139,4.809Z"/>
|
||||
<path class="cls-1" d="M40.075,3.555a2.364,2.364,0,1,1-2.364,2.364,2.367,2.367,0,0,1,2.364-2.364m0-.8a3.164,3.164,0,1,0,3.164,3.164,3.164,3.164,0,0,0-3.164-3.164Z"/>
|
||||
<path class="cls-1" d="M25.315,8.285a2.349,2.349,0,0,1-2.04-1.18,2.335,2.335,0,0,1,0-2.36,2.344,2.344,0,0,1,4.08,0l.7-.4a3.16,3.16,0,1,0,0,3.16l-.7-.4A2.35,2.35,0,0,1,25.315,8.285Z"/>
|
||||
<path class="cls-1"
|
||||
d="M0,8.937V.741A1.882,1.882,0,0,1,.414.705,2.229,2.229,0,0,1,.852.741v8.2a2.231,2.231,0,0,1-.432.036A2.056,2.056,0,0,1,0,8.937Z"/>
|
||||
<path class="cls-1"
|
||||
d="M8.232,4.809V7.833a2.871,2.871,0,0,0,.12,1,.7.7,0,0,1-.517.18q-.42,0-.42-.54V5.085a2.2,2.2,0,0,0-.191-1.074.747.747,0,0,0-.7-.318,2.332,2.332,0,0,0-1.044.27,2.7,2.7,0,0,0-.888.69V8.937a1.994,1.994,0,0,1-.408.036,1.987,1.987,0,0,1-.408-.036V3.093l.072-.072h.312a.384.384,0,0,1,.348.132.831.831,0,0,1,.085.432v.24a2.983,2.983,0,0,1,.966-.636A2.908,2.908,0,0,1,6.7,2.949a1.335,1.335,0,0,1,1.17.516A2.272,2.272,0,0,1,8.232,4.809Z"/>
|
||||
<path class="cls-1"
|
||||
d="M11.147,8.937V3.669l-1.031.012a1.473,1.473,0,0,1-.036-.312,1.639,1.639,0,0,1,.036-.324l1,.024q-.085-1.115-.084-1.272A1.769,1.769,0,0,1,11.472.555,1.538,1.538,0,0,1,12.666.069a3.728,3.728,0,0,1,1.386.252.818.818,0,0,1-.2.564A3.881,3.881,0,0,0,12.756.693a.883.883,0,0,0-.708.294,1.226,1.226,0,0,0-.252.822,9.977,9.977,0,0,0,.1,1.26l1.776-.024a1.716,1.716,0,0,1,.036.324,1.54,1.54,0,0,1-.036.312l-1.716-.012V8.937a2.258,2.258,0,0,1-.8,0Z"/>
|
||||
<path class="cls-1"
|
||||
d="M32.352,3.045a1.716,1.716,0,0,1,.036.324,1.54,1.54,0,0,1-.036.312l-1.524-.012v4.14q0,.492.468.492h.925a1,1,0,0,1,.071.372,1.405,1.405,0,0,1-.012.24,8.879,8.879,0,0,1-1.122.072,1.268,1.268,0,0,1-.846-.246.87.87,0,0,1-.288-.7V3.669l-.828.012a1.336,1.336,0,0,1-.036-.306,1.664,1.664,0,0,1,.036-.33l.828.012v-1.3a.794.794,0,0,1,.09-.432.4.4,0,0,1,.354-.132h.288l.072.072v1.8Z"/>
|
||||
<path class="cls-1"
|
||||
d="M35.472,3.837v5.1a2.324,2.324,0,0,1-.816,0V4.257a.7.7,0,0,0-.108-.456.5.5,0,0,0-.384-.12h-.107a1.288,1.288,0,0,1-.036-.294,1.616,1.616,0,0,1,.036-.318,4.4,4.4,0,0,1,.575-.048h.1a.7.7,0,0,1,.546.216A.856.856,0,0,1,35.472,3.837ZM34.379,1.881a.986.986,0,0,1-.084-.438.837.837,0,0,1,.084-.414.853.853,0,0,1,.511-.12.8.8,0,0,1,.5.12.837.837,0,0,1,.084.414.986.986,0,0,1-.084.438A.707.707,0,0,1,34.9,2,.874.874,0,0,1,34.379,1.881Z"/>
|
||||
<path class="cls-1"
|
||||
d="M49.139,4.809V7.833a2.871,2.871,0,0,0,.12,1,.7.7,0,0,1-.517.18q-.42,0-.42-.54V5.085a2.2,2.2,0,0,0-.191-1.074.747.747,0,0,0-.7-.318,2.332,2.332,0,0,0-1.044.27,2.7,2.7,0,0,0-.888.69V8.937a2.324,2.324,0,0,1-.816,0V3.093l.072-.072h.312a.384.384,0,0,1,.348.132.831.831,0,0,1,.085.432v.24a2.983,2.983,0,0,1,.966-.636,2.908,2.908,0,0,1,1.134-.24,1.335,1.335,0,0,1,1.17.516A2.272,2.272,0,0,1,49.139,4.809Z"/>
|
||||
<path class="cls-1"
|
||||
d="M40.075,3.555a2.364,2.364,0,1,1-2.364,2.364,2.367,2.367,0,0,1,2.364-2.364m0-.8a3.164,3.164,0,1,0,3.164,3.164,3.164,3.164,0,0,0-3.164-3.164Z"/>
|
||||
<path class="cls-1"
|
||||
d="M25.315,8.285a2.349,2.349,0,0,1-2.04-1.18,2.335,2.335,0,0,1,0-2.36,2.344,2.344,0,0,1,4.08,0l.7-.4a3.16,3.16,0,1,0,0,3.16l-.7-.4A2.35,2.35,0,0,1,25.315,8.285Z"/>
|
||||
<g>
|
||||
<path class="cls-1" d="M17.87,8.285a2.365,2.365,0,1,1,2.36-2.37h.8a3.162,3.162,0,0,0-5.9-1.58,3.018,3.018,0,0,0-.43,1.58,3.165,3.165,0,0,0,5.91,1.58l-.69-.39A2.378,2.378,0,0,1,17.87,8.285Z"/>
|
||||
<path class="cls-1"
|
||||
d="M17.87,8.285a2.365,2.365,0,1,1,2.36-2.37h.8a3.162,3.162,0,0,0-5.9-1.58,3.018,3.018,0,0,0-.43,1.58,3.165,3.165,0,0,0,5.91,1.58l-.69-.39A2.378,2.378,0,0,1,17.87,8.285Z"/>
|
||||
<polygon class="cls-1" points="15.286 5.718 20.514 5.261 21.03 5.915 15.347 6.412 15.286 5.718"/>
|
||||
</g>
|
||||
</g>
|
||||
|
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.7 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue