forked from p15670423/monkey
Merge branch 'develop' into snyk-upgrade-1d178c687faf134440c71413f44c538d
This commit is contained in:
commit
35a665b831
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: "Adding Zero Trust Tests"
|
||||
date: 2020-07-14T10:19:08+03:00
|
||||
draft: false
|
||||
weight: 100
|
||||
---
|
||||
|
||||
## How to add a new Zero Trust test to the Monkey?
|
||||
|
||||
Assuming the Monkey agent is already sending the relevant telemetry, you'll need to add the test in two places.
|
||||
|
||||
### `zero_trust_consts.py`
|
||||
|
||||
In the file `/monkey/common/data/zero_trust_consts.py`,
|
||||
|
||||
1. Add the test name to the TESTS set
|
||||
2. Add a relevant recommendation if exists
|
||||
3. Add the test to the TESTS_MAP dict. Make sure that all statuses (except `STATUS_UNEXECUTED`) have finding explanations.
|
||||
|
||||
### `telemetry/processing.py`
|
||||
|
||||
Find the relevant telemetry type you wish to test the finding in. This can be found in `/monkey/monkey_island/cc/services/telemetry/processing.py`. In the relevant `process_*_telemetry` function, add your Zero Trust testing code. Please put the zero trust tests under the `/monkey/monkey_island/cc/services/telemetry/zero_trust_tests` directory. There you can find examples of existing tests as well, so you'll know pretty much what you need to write.
|
||||
|
||||
## How to test the new Zero Trust test I've implemented?
|
||||
|
||||
Test ALL possible finding statuses you've defined in a fake network. Observe the events as well and see they were formatted correctly. If there's an algorithmic part to your Zero Trust test, please cover it using a Unit Test.
|
|
@ -2,4 +2,6 @@
|
|||
title: "Adding Exploits"
|
||||
date: 2020-06-08T19:53:00+03:00
|
||||
draft: true
|
||||
tags: ["contribute"]
|
||||
weight: 50
|
||||
---
|
||||
|
|
|
@ -1,6 +1,76 @@
|
|||
---
|
||||
title: "Adding Post Breach Actions"
|
||||
date: 2020-06-08T19:53:13+03:00
|
||||
draft: true
|
||||
draft: false
|
||||
tags: ["contribute"]
|
||||
weight: 90
|
||||
---
|
||||
|
||||
## What's this?
|
||||
|
||||
This guide will show you how to create a new _Post Breach action_ for the Infection Monkey. _Post Breach actions_ are "extra" actions that the Monkey can perform on the victim machines after it propagated to them.
|
||||
|
||||
## Do I need a new PBA?
|
||||
|
||||
If all you want is to execute shell commands, then there's no need to add a new PBA - just configure the required commands in the Monkey Island configuration! If you think that those specific commands have reuse value in all deployments and not just your own, you can add a new PBA. If you need to run actual Python code, you must add a new PBA.
|
||||
|
||||
## How to add a new PBA
|
||||
|
||||
### Monkey side
|
||||
|
||||
#### Framework
|
||||
|
||||
1. Create your new action in the following directory: `monkey/infection_monkey/post_breach/actions` by first creating a new file with the name of your action.
|
||||
2. In that file, create a class that inherits from the `PBA` class:
|
||||
|
||||
```python
|
||||
from infection_monkey.post_breach.pba import PBA
|
||||
|
||||
class MyNewPba(PBA):
|
||||
```
|
||||
|
||||
3. Set the action name in the constructor, like so:
|
||||
|
||||
```python
|
||||
class MyNewPba(PBA):
|
||||
def __init__(self):
|
||||
super(MyNewPba, self).__init__(name="MyNewPba")
|
||||
```
|
||||
|
||||
#### Implementation
|
||||
|
||||
If your PBA consists only of simple shell commands, you can reuse the generic PBA by passing the commands into the constructor. See the `add_user.py` PBA for reference.
|
||||
|
||||
Otherwise, you'll need to override the `run` method with your own implementation. See the `communicate_as_new_user.py` PBA for reference. Make sure to send the relevant PostBreachTelem upon success/failure. You can log during the PBA as well.
|
||||
|
||||
### Island side
|
||||
|
||||
#### Configuration
|
||||
|
||||
You'll need to add your PBA to the `config_schema.py` file, under `post_breach_acts`, like so:
|
||||
|
||||
```json
|
||||
"post_breach_acts": {
|
||||
"title": "Post breach actions",
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
# ...
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"MyNewPba"
|
||||
],
|
||||
"title": "My new PBA",
|
||||
"attack_techniques": []
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
Now you can choose your PBA when configuring the Monkey on the Monkey island:
|
||||
|
||||
![PBA in configuration](https://i.imgur.com/9PrcWr0.png)
|
||||
|
||||
#### Telemetry processing
|
||||
|
||||
If you wish to process your Post Breach action telemetry (for example, to analyze it for report data), add a processing function to the `POST_BREACH_TELEMETRY_PROCESSING_FUNCS` which can be found at `monkey/monkey_island/cc/services/telemetry/processing/post_breach.py`. You can look at the `process_communicate_as_new_user_telemetry` method as an example.
|
||||
|
|
|
@ -1,6 +1,101 @@
|
|||
---
|
||||
title: "Adding System Info Collectors"
|
||||
date: 2020-06-09T11:03:42+03:00
|
||||
draft: true
|
||||
draft: false
|
||||
tags: ["contribute"]
|
||||
weight: 80
|
||||
---
|
||||
|
||||
## What's this?
|
||||
|
||||
This guide will show you how to create a new _System Info Collector_ for the Infection Monkey. _System Info Collectors_ are modules which each Monkey runs, that collect specific information and sends it back to the Island as part of the System Info Telemetry.
|
||||
|
||||
### Do I need a new System Info Controller?
|
||||
|
||||
If all you want is to execute a shell command, then there's no need to add a new collector - just configure the required commands in the Monkey Island configuration in the PBA section! Also, if there is a relevant collector and you only need to add more information to it, expand the existing one. Otherwise, you must add a new Collector.
|
||||
|
||||
## How to add a new System Info Collector
|
||||
|
||||
### Monkey side
|
||||
|
||||
#### Framework
|
||||
|
||||
1. Create your new collector in the following directory: `monkey/infection_monkey/system_info/collectors` by first creating a new file with the name of your collector.
|
||||
2. In that file, create a class that inherits from the `SystemInfoCollector` class:
|
||||
|
||||
```py
|
||||
from infection_monkey.system_info.system_info_collector import SystemInfoCollector
|
||||
|
||||
class MyNewCollector(SystemInfoCollector):
|
||||
```
|
||||
|
||||
3. Set the Collector name in the constructor, like so:
|
||||
|
||||
```py
|
||||
class MyNewCollector(SystemInfoCollector):
|
||||
def __init__(self):
|
||||
super(MyNewCollector, self).__init__(name="MyNewCollector")
|
||||
```
|
||||
|
||||
#### Implementation
|
||||
|
||||
Override the `collect` method with your own implementation. See the `EnvironmentCollector.py` Collector for reference. You can log during collection as well.
|
||||
|
||||
### Island side
|
||||
|
||||
#### Island Configuration
|
||||
|
||||
##### Definitions
|
||||
|
||||
You'll need to add your Collector to the `monkey_island/cc/services/config_schema.py` file, under `definitions/system_info_collectors_classes/anyOf`, like so:
|
||||
|
||||
```json
|
||||
"system_info_collectors_classes": {
|
||||
"title": "System Information Collectors",
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"EnvironmentCollector"
|
||||
],
|
||||
"title": "Which Environment this machine is on (on prem/cloud)",
|
||||
"attack_techniques": []
|
||||
},
|
||||
{ <=================================
|
||||
"type": "string", <=================================
|
||||
"enum": [ <=================================
|
||||
"MyNewCollector" <=================================
|
||||
], <=================================
|
||||
"title": "My new title", <=================================
|
||||
"attack_techniques": [] <=================================
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
##### properties
|
||||
|
||||
Also, you can add the Collector to be used by default by adding it to the `default` key under `properties/monkey/system_info/system_info_collectors_classes`:
|
||||
|
||||
```json
|
||||
"system_info_collectors_classes": {
|
||||
"title": "System info collectors",
|
||||
"type": "array",
|
||||
"uniqueItems": True,
|
||||
"items": {
|
||||
"$ref": "#/definitions/system_info_collectors_classes"
|
||||
},
|
||||
"default": [
|
||||
"EnvironmentCollector",
|
||||
"MyNewCollector" <=================================
|
||||
],
|
||||
"description": "Determines which system information collectors will collect information."
|
||||
},
|
||||
```
|
||||
|
||||
#### Telemetry processing
|
||||
|
||||
1. Add a process function under `monkey_island/cc/telemetry/processing/system_info_collectors/{DATA_NAME_HERE}.py`. The function should parse the collector's result. See `processing/system_info_collectors/environment.py` for example.
|
||||
|
||||
2. Add that function to `SYSTEM_INFO_COLLECTOR_TO_TELEMETRY_PROCESSORS` under `monkey_island/cc/services/telemetry/processing/system_info_collectors/system_info_telemetry_dispatcher.py`.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
title: "Contribute Documentation"
|
||||
date: 2020-06-17T17:31:54+03:00
|
||||
draft: false
|
||||
weight: 1
|
||||
tags: ["contribute"]
|
||||
---
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
title: "Setting up a development environment"
|
||||
title: "Development setup"
|
||||
date: 2020-06-08T19:53:00+03:00
|
||||
draft: false
|
||||
weight: 5
|
||||
tags: ["contribute"]
|
||||
---
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
+++
|
||||
title = "Reference"
|
||||
date = 2020-05-26T20:55:04+03:00
|
||||
weight = 30
|
||||
chapter = true
|
||||
pre = '<i class="fas fa-layer-group"></i> '
|
||||
tags = ["reference"]
|
||||
+++
|
||||
|
||||
# Reference
|
||||
|
||||
Find detailed information about Infection Monkey.
|
||||
|
||||
{{% children %}}
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: "ElasticGroovy"
|
||||
date: 2020-07-14T08:41:40+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "windows", "linux"]
|
||||
---
|
||||
|
||||
CVE-2015-1427.
|
||||
|
||||
> The Groovy scripting engine in Elasticsearch before 1.3.8 and 1.4.x before 1.4.3 allows remote attackers to bypass the sandbox protection mechanism and execute arbitrary shell commands via a crafted script.
|
||||
|
||||
Logic is based on [Metasploit module](https://github.com/rapid7/metasploit-framework/blob/12198a088132f047e0a86724bc5ebba92a73ac66/modules/exploits/multi/elasticsearch/search_groovy_script.rb).
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Hadoop"
|
||||
date: 2020-07-14T08:41:49+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux", "windows"]
|
||||
---
|
||||
|
||||
Remote code execution on HADOOP server with YARN and default settings. Logic based on [this vulhub module](https://github.com/vulhub/vulhub/tree/master/hadoop/unauthorized-yarn).
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: "MS08 067"
|
||||
date: 2020-07-14T08:42:54+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "windows"]
|
||||
---
|
||||
|
||||
[MS08-067](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2008/ms08-067) is a remote code execution vulnerability.
|
||||
|
||||
This exploiter is unsafe. If an exploit attempt fails, this could also lead to a crash in Svchost.exe. If the crash in Svchost.exe occurs, the Server service will be affected. That might cause system crash due to the use of buffer overflow. It's therefore **not** enabled by default.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "MsSQL"
|
||||
date: 2020-07-14T08:41:56+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "windows"]
|
||||
---
|
||||
|
||||
The Monkey will try to brute force into MsSQL server and uses insecure configuration to execute commands on server.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "SMBExec"
|
||||
date: 2020-07-14T08:42:16+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "windows"]
|
||||
---
|
||||
|
||||
Brute forces using credentials provided by user (see ["Configuration"](../usage/configuration)) and hashes gathered by Mimikatz.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "SSHExec"
|
||||
date: 2020-07-14T08:42:21+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux"]
|
||||
---
|
||||
|
||||
Brute forces using credentials provided by user (see ["Configuration"](../usage/configuration))and SSH keys gathered from systems.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Sambacry"
|
||||
date: 2020-07-14T08:42:02+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux"]
|
||||
---
|
||||
|
||||
Bruteforces and searches for anonymous shares. Partially based on [the following implementation](https://github.com/CoreSecurity/impacket/blob/master/examples/sambaPipe.py) by CORE Security Technologies' impacket.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Struts2"
|
||||
date: 2020-07-14T08:42:30+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux", "windows"]
|
||||
---
|
||||
|
||||
Exploits struts2 java web framework. CVE-2017-5638. Logic based on [VEX WOO's PoC](https://www.exploit-db.com/exploits/41570).
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "VSFTPD"
|
||||
date: 2020-07-14T08:42:39+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux"]
|
||||
---
|
||||
|
||||
Exploits a malicious backdoor that was added to the VSFTPD download archive. Logic based on [this MetaSploit module](https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb).
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "WMIExec"
|
||||
date: 2020-07-14T08:43:12+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "windows"]
|
||||
---
|
||||
|
||||
Brute forces WMI (Windows Management Instrumentation) using credentials provided by user ((see ["Configuration"](../usage/configuration))) and hashes gathered by mimikatz.
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "WebLogic"
|
||||
date: 2020-07-14T08:42:46+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux", "windows"]
|
||||
---
|
||||
|
||||
Exploits CVE-2017-10271 and CVE-2019-2725 vulnerabilities on a vulnerable WebLogic server.
|
|
@ -0,0 +1,16 @@
|
|||
+++
|
||||
title = "Exploiters"
|
||||
date = 2020-05-26T20:55:04+03:00
|
||||
weight = 100
|
||||
chapter = true
|
||||
pre = '<i class="fas fa-ethernet"></i> '
|
||||
tags = ["reference", "exploit"]
|
||||
+++
|
||||
|
||||
# Exploiters
|
||||
|
||||
Infection Monkey uses various RCE exploiters. Most of these, in our knowledge, pose no risk to performance or services on victim machines. This documentation serves as a quick introduction to the exploiters currently implemented and vulnerabilities used by them.
|
||||
|
||||
{{% children %}}
|
||||
|
||||
You can check out the Exploiters' implementation yourself [in the Monkey's GitHub repository](https://github.com/guardicore/monkey/tree/develop/monkey/infection_monkey/exploit).
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: "ShellShock"
|
||||
date: 2020-07-14T08:41:32+03:00
|
||||
draft: false
|
||||
tags: ["exploit", "linux"]
|
||||
---
|
||||
|
||||
CVE-2014-6271, based on [logic in NCC group's GitHub](https://github.com/nccgroup/shocker/blob/master/shocker.py).
|
||||
|
||||
> GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables, which allows remote attackers to execute arbitrary code via a crafted environment, as demonstrated by vectors involving the ForceCommand feature in OpenSSH sshd, the mod_cgi and mod_cgid modules in the Apache HTTP Server, scripts executed by unspecified DHCP clients, and other situations in which setting the environment occurs across a privilege boundary from Bash execution, aka "ShellShock."
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
title: "Operating systems"
|
||||
date: 2020-07-14T08:09:53+03:00
|
||||
draft: false
|
||||
pre: '<i class="fas fa-laptop"></i> '
|
||||
weight: 10
|
||||
tags: ["setup", "reference", "windows", "linux"]
|
||||
---
|
||||
|
||||
The Infection Monkey project supports many popular OSes (but we can always do more).
|
||||
|
||||
The Monkey itself (the agent) has been tested to run on the following operating systems (on x64 architecture)
|
||||
|
||||
### Monkey support
|
||||
|
||||
#### Linux
|
||||
|
||||
Compatibility depends on GLIBC version (2.14+)[^1]. By default these distributions are supported:
|
||||
|
||||
- Centos 7+
|
||||
- Debian 7+
|
||||
- Kali 2019+
|
||||
- Oracle 7+
|
||||
- Rhel 7+
|
||||
- Suse 12+
|
||||
- Ubuntu 14+
|
||||
|
||||
#### Windows
|
||||
|
||||
- Windows 2012+
|
||||
- Windows 2012_R2+
|
||||
- Windows 7/Server 2008_R2 if [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows) is installed.
|
||||
- Windows vista/Server 2008 should also work if the same update is installed, but this wasn't tested.
|
||||
|
||||
### Island support
|
||||
|
||||
**The Monkey Island (control server)** runs out of the box on:
|
||||
|
||||
- Ubuntu 18.04
|
||||
- Debian 9
|
||||
- Windows Server 2012
|
||||
- Windows Server 2012 R2
|
||||
- Windows Server 2016
|
||||
|
||||
We provide a dockerfile from our [website](http://infectionmonkey.com/) that lets the Monkey Island run inside a container.
|
||||
|
||||
### Old machine bootloader
|
||||
|
||||
Some **Older machines** still get a partial compatibility as in they get exploited and reported, but monkey can't run on them. So instead of monkey, old machine bootloader (small c program) is ran, which reports some minor info like network interface configuration, GLIBC version, OS and so on.
|
||||
|
||||
**Old machine bootloader** also has a GLIBC 2.14+ requirement for linux, because bootloader is included into pyinstaller bootloader which uses python3.7, which in turn requires GLIBC 2.14+. If you think partial support for older machines is important, don't hesitate to open a new issue about it.
|
||||
|
||||
**Old machine bootloader** runs on machines with:
|
||||
|
||||
- Centos 7+
|
||||
- Debian 7+
|
||||
- Kali 2019+
|
||||
- Oracle 7+
|
||||
- Rhel 7+
|
||||
- Suse 12+
|
||||
- Ubuntu 14+
|
||||
- **Windows XP/Server 2003+**
|
||||
|
||||
[^1]: GLIBC >= 2.14 requirement comes from the fact that monkey is built using this GLIBC version and GLIBC is not backwards compatible. We are also limited to the oldest GLIBC version compatible with ptyhon3.7
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
title: "Scanners"
|
||||
date: 2020-07-14T08:43:12+03:00
|
||||
draft: false
|
||||
weight: 20
|
||||
pre: '<i class="fas fa-network-wired"></i> '
|
||||
tags: ["reference"]
|
||||
---
|
||||
|
||||
The Infection Monkey agent has two steps before attempting to exploit a victim, scanning and fingerprinting, it's possible to customize both steps in the configuration files.
|
||||
|
||||
## Scanning
|
||||
|
||||
Currently there are two scanners, [`PingScanner`][ping-scanner] and [`TcpScanner`][tcp-scanner] both inheriting from [`HostScanner`][host-scanner].
|
||||
|
||||
The sole interface required is the `is_host_alive` interface, which needs to return True/False.
|
||||
|
||||
[`TcpScanner`][tcp-scanner] is the default scanner and it checks for open ports based on the `tcp_target_ports` configuration setting.
|
||||
|
||||
[`PingScanner`][ping-scanner] sends a ping message using the host OS utility `ping`.
|
||||
|
||||
## Fingerprinting
|
||||
|
||||
Fingerprinters are modules that collect server information from a specific victim. They inherit from the [`HostFinger`][host-finger] class and are listed under `finger_classes` configuration option.
|
||||
|
||||
Currently implemented Fingerprint modules are:
|
||||
|
||||
1. [`SMBFinger`][smb-finger] - Fingerprints target machines over SMB. Extracts computer name and OS version.
|
||||
2. [`SSHFinger`][ssh-finger] - Fingerprints target machines over SSH (port 22). Extracts the computer version and SSH banner.
|
||||
3. [`PingScanner`][ping-scanner] - Fingerprints using the machines TTL, to differentiate between Linux and Windows hosts.
|
||||
4. [`HTTPFinger`][http-finger] - Fingerprints over HTTP/HTTPS, using the ports listed in `HTTP_PORTS` in the configuration. Returns the server type and if it supports SSL.
|
||||
5. [`MySQLFinger`][mysql-finger] - Fingerprints over MySQL (port 3306). Extracts MySQL banner info - Version, Major/Minor/Build and capabilities.
|
||||
6. [`ElasticFinger`][elastic-finger] - Fingerprints over ElasticSearch (port 9200). Extracts the cluster name, node name and node version.
|
||||
|
||||
## Adding a scanner/fingerprinter
|
||||
|
||||
To add a new scanner/fingerprinter, create a new class that inherits from [`HostScanner`][host-scanner] or [`HostFinger`][host-finger] (depending on the interface). The class should be under the network module and should be imported under [`network/__init__.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/network/__init__.py).
|
||||
|
||||
To be used by default, two files need to be changed - [`infection_monkey/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/config.py) and [`infection_monkey/example.conf`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/example.conf) to add references to the new class.
|
||||
|
||||
At this point, the Monkey knows how to use the new scanner/fingerprinter but to make it easy to use, the UI needs to be updated. The relevant UI file is [`monkey_island/cc/services/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/monkey_island/cc/services/config.py).
|
||||
|
||||
[elastic-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/elasticfinger.py
|
||||
[http-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/httpfinger.py
|
||||
[host-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/__init__.py
|
||||
[host-scanner]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/__init__.py
|
||||
[mysql-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/mysqlfinger.py
|
||||
[ping-scanner]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/ping_scanner.py
|
||||
[smb-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/smbfinger.py
|
||||
[ssh-finger]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/sshfinger.py
|
||||
[tcp-scanner]: https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/network/tcp_scanner.py
|
|
@ -16,3 +16,7 @@ Once you've downloaded an installer, you can follow the relevant guide for your
|
|||
{{% children %}}
|
||||
|
||||
Once you're done setting the Monkey up, check out our [Getting Started](../usage/getting-started) guide!
|
||||
|
||||
{{% notice tip %}}
|
||||
You can find information about [operating system compatibility and support here](../reference/operating_systems_support).
|
||||
{{% /notice %}}
|
||||
|
|
|
@ -5,7 +5,7 @@ draft: false
|
|||
pre: '<i class="fab fa-linux"></i> '
|
||||
weight: 1
|
||||
disableToc: false
|
||||
tags: ["setup", "debian"]
|
||||
tags: ["setup", "debian", "linux"]
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
|
|
@ -4,7 +4,7 @@ date: 2020-05-26T20:57:28+03:00
|
|||
draft: false
|
||||
pre: '<i class="fab fa-docker"></i> '
|
||||
weight: 4
|
||||
tags: ["setup", "docker"]
|
||||
tags: ["setup", "docker", "linux", "windows"]
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
|
|
@ -7,7 +7,6 @@ from infection_monkey.utils.environment import is_windows_os
|
|||
|
||||
class ChangeSetuidSetgid(PBA):
|
||||
def __init__(self):
|
||||
if not is_windows_os():
|
||||
linux_cmds = get_commands_to_change_setuid_setgid()
|
||||
super(ChangeSetuidSetgid, self).__init__(POST_BREACH_SETUID_SETGID,
|
||||
linux_cmd=' '.join(linux_cmds))
|
||||
linux_cmds = get_commands_to_change_setuid_setgid()
|
||||
super(ChangeSetuidSetgid, self).__init__(POST_BREACH_SETUID_SETGID,
|
||||
linux_cmd=' '.join(linux_cmds))
|
||||
|
|
|
@ -7,7 +7,6 @@ from infection_monkey.utils.environment import is_windows_os
|
|||
|
||||
class TrapCommand(PBA):
|
||||
def __init__(self):
|
||||
if not is_windows_os():
|
||||
linux_cmds = get_trap_commands()
|
||||
super(TrapCommand, self).__init__(POST_BREACH_TRAP_COMMAND,
|
||||
linux_cmd=linux_cmds)
|
||||
linux_cmds = get_trap_commands()
|
||||
super(TrapCommand, self).__init__(POST_BREACH_TRAP_COMMAND,
|
||||
linux_cmd=linux_cmds)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import flask_restful
|
||||
from flask import send_from_directory
|
||||
|
||||
from monkey_island.cc.resources.pba_file_upload import GET_FILE_DIR
|
||||
from monkey_island.cc.services.post_breach_files import UPLOADS_DIR
|
||||
|
||||
__author__ = 'VakarisZ'
|
||||
|
||||
|
@ -13,4 +13,4 @@ class PBAFileDownload(flask_restful.Resource):
|
|||
|
||||
# Used by monkey. can't secure.
|
||||
def get(self, path):
|
||||
return send_from_directory(GET_FILE_DIR, path)
|
||||
return send_from_directory(UPLOADS_DIR, path)
|
||||
|
|
|
@ -14,7 +14,6 @@ from monkey_island.cc.services.post_breach_files import (
|
|||
__author__ = 'VakarisZ'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
GET_FILE_DIR = "./userUploads"
|
||||
# Front end uses these strings to identify which files to work with (linux of windows)
|
||||
LINUX_PBA_TYPE = 'PBAlinux'
|
||||
WINDOWS_PBA_TYPE = 'PBAwindows'
|
||||
|
@ -24,6 +23,9 @@ class FileUpload(flask_restful.Resource):
|
|||
"""
|
||||
File upload endpoint used to exchange files with filepond component on the front-end
|
||||
"""
|
||||
def __init__(self):
|
||||
# Create all directories on the way if they don't exist
|
||||
UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@jwt_required()
|
||||
def get(self, file_type):
|
||||
|
@ -37,7 +39,7 @@ class FileUpload(flask_restful.Resource):
|
|||
filename = ConfigService.get_config_value(copy.deepcopy(PBA_LINUX_FILENAME_PATH))
|
||||
else:
|
||||
filename = ConfigService.get_config_value(copy.deepcopy(PBA_WINDOWS_FILENAME_PATH))
|
||||
return send_from_directory(GET_FILE_DIR, filename)
|
||||
return send_from_directory(UPLOADS_DIR, filename)
|
||||
|
||||
@jwt_required()
|
||||
def post(self, file_type):
|
||||
|
@ -62,7 +64,7 @@ class FileUpload(flask_restful.Resource):
|
|||
"""
|
||||
filename_path = PBA_LINUX_FILENAME_PATH if file_type == 'PBAlinux' else PBA_WINDOWS_FILENAME_PATH
|
||||
filename = ConfigService.get_config_value(filename_path)
|
||||
file_path = os.path.join(UPLOADS_DIR, filename)
|
||||
file_path = UPLOADS_DIR.joinpath(filename)
|
||||
try:
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
|
@ -81,7 +83,7 @@ class FileUpload(flask_restful.Resource):
|
|||
:return: filename string
|
||||
"""
|
||||
filename = secure_filename(request_.files['filepond'].filename)
|
||||
file_path = os.path.join(UPLOADS_DIR, filename)
|
||||
request_.files['filepond'].save(file_path)
|
||||
file_path = UPLOADS_DIR.joinpath(filename).absolute()
|
||||
request_.files['filepond'].save(str(file_path))
|
||||
ConfigService.set_config_value((PBA_LINUX_FILENAME_PATH if is_linux else PBA_WINDOWS_FILENAME_PATH), filename)
|
||||
return filename
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import monkey_island.cc.services.config
|
||||
|
||||
|
@ -10,7 +11,7 @@ logger = logging.getLogger(__name__)
|
|||
# Where to find file names in config
|
||||
PBA_WINDOWS_FILENAME_PATH = ['monkey', 'behaviour', 'PBA_windows_filename']
|
||||
PBA_LINUX_FILENAME_PATH = ['monkey', 'behaviour', 'PBA_linux_filename']
|
||||
UPLOADS_DIR = 'monkey_island/cc/userUploads'
|
||||
UPLOADS_DIR = Path('monkey_island', 'cc', 'userUploads')
|
||||
|
||||
|
||||
def remove_PBA_files():
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "entry"
|
||||
"useBuiltIns": "entry",
|
||||
"corejs": 3
|
||||
}
|
||||
],
|
||||
"@babel/preset-react"
|
||||
|
|
|
@ -952,15 +952,6 @@
|
|||
"@babel/helper-plugin-utils": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/polyfill": {
|
||||
"version": "7.8.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.8.7.tgz",
|
||||
"integrity": "sha512-LeSfP9bNZH2UOZgcGcZ0PIHUt1ZuHub1L3CVmEyqLxCeDLm4C5Gi8jRH8ZX2PNpDhQCo0z6y/+DIs2JlliXW8w==",
|
||||
"requires": {
|
||||
"core-js": "^2.6.5",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@babel/preset-env": {
|
||||
"version": "7.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz",
|
||||
|
@ -1071,6 +1062,13 @@
|
|||
"requires": {
|
||||
"core-js": "^2.6.5",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/runtime-corejs3": {
|
||||
|
@ -2896,6 +2894,11 @@
|
|||
"regenerator-runtime": "^0.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
|
@ -4017,9 +4020,9 @@
|
|||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
|
||||
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.6.5",
|
||||
|
@ -6017,9 +6020,9 @@
|
|||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||
},
|
||||
"filepond": {
|
||||
"version": "4.13.5",
|
||||
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.13.5.tgz",
|
||||
"integrity": "sha512-WZi8kMGZNh6hH6qsUdvCQcQOF5uPaTV1PdPC4PiAZauRyepDxtAnkK4OHRW+UXIkA2CW2IdHFrqlKvDR4Dk24A=="
|
||||
"version": "4.18.0",
|
||||
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.18.0.tgz",
|
||||
"integrity": "sha512-lIRv27uYU0DQjUNa0G+aGsdmkhxdEzk9k2gbOsWLQdO+4u6FGNPjA1lUfy5vkF4ifx2GEeO1X+xP6Kqyb6tWaw=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "4.0.0",
|
||||
|
@ -13659,6 +13662,13 @@
|
|||
"react-is": "^16.8.4",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"shortid": "^2.2.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-jsonschema-form-bs4": {
|
||||
|
@ -13678,6 +13688,13 @@
|
|||
"react-is": "^16.8.4",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"shortid": "^2.2.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
"webpack-dev-server": "^3.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.8.0",
|
||||
"@emotion/core": "^10.0.22",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.29",
|
||||
"@fortawesome/free-regular-svg-icons": "^5.13.1",
|
||||
|
@ -68,12 +67,12 @@
|
|||
"@kunukn/react-collapse": "^1.2.7",
|
||||
"bootstrap": "^4.5.0",
|
||||
"classnames": "^2.2.6",
|
||||
"core-js": "^2.6.10",
|
||||
"core-js": "^3.6.5",
|
||||
"d3": "^5.14.1",
|
||||
"downloadjs": "^1.4.7",
|
||||
"fetch": "^1.1.0",
|
||||
"file-saver": "^2.0.2",
|
||||
"filepond": "^4.7.3",
|
||||
"filepond": "^4.18.0",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"marked": "^0.8.2",
|
||||
"normalize.css": "^8.0.0",
|
||||
|
|
|
@ -121,7 +121,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
|
||||
renderNavButton = (section) => {
|
||||
return (
|
||||
<Nav.Item>
|
||||
<Nav.Item key={section.key}>
|
||||
<Nav.Link key={section.key}
|
||||
eventKey={section.key}
|
||||
onSelect={() => {
|
||||
|
|
|
@ -277,7 +277,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
this.state.ips.length > 1 ?
|
||||
<Nav variant="pills" activeKey={this.state.selectedIp} onSelect={this.setSelectedIp}
|
||||
style={{'marginBottom': '2em'}}>
|
||||
{this.state.ips.map(ip => <Nav.Item><Nav.Link eventKey={ip}>{ip}</Nav.Link></Nav.Item>)}
|
||||
{this.state.ips.map(ip => <Nav.Item key={ip}><Nav.Link eventKey={ip}>{ip}</Nav.Link></Nav.Item>)}
|
||||
</Nav>
|
||||
: <div style={{'marginBottom': '2em'}}/>
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ class RunMonkeyPageComponent extends AuthComponent {
|
|||
<Col>
|
||||
<Nav variant="pills" fill activeKey={this.state.selectedIp} onSelect={this.setSelectedIp}
|
||||
className={'run-on-os-buttons'}>
|
||||
{this.state.ips.map(ip => <Nav.Item>
|
||||
{this.state.ips.map(ip => <Nav.Item key={ip}>
|
||||
<Nav.Link eventKey={ip}>{ip}</Nav.Link></Nav.Item>)}
|
||||
</Nav>
|
||||
</Col>
|
||||
|
|
|
@ -161,25 +161,29 @@ class ReportPageComponent extends AuthComponent {
|
|||
</p>
|
||||
<p>
|
||||
The monkey started propagating from the following machines where it was manually installed:
|
||||
<ul>
|
||||
{this.state.report.overview.manual_monkeys.map(x => <li>{x}</li>)}
|
||||
</ul>
|
||||
</p>
|
||||
<ul>
|
||||
{this.state.report.overview.manual_monkeys.map(x => <li key={x}>{x}</li>)}
|
||||
</ul>
|
||||
<p>
|
||||
The monkeys were run with the following configuration:
|
||||
</p>
|
||||
{
|
||||
this.state.report.overview.config_users.length > 0 ?
|
||||
<p>
|
||||
Usernames used for brute-forcing:
|
||||
<>
|
||||
<p>
|
||||
Usernames used for brute-forcing:
|
||||
</p>
|
||||
<ul>
|
||||
{this.state.report.overview.config_users.map(x => <li>{x}</li>)}
|
||||
{this.state.report.overview.config_users.map(x => <li key={x}>{x}</li>)}
|
||||
</ul>
|
||||
Passwords used for brute-forcing:
|
||||
<p>
|
||||
Passwords used for brute-forcing:
|
||||
</p>
|
||||
<ul>
|
||||
{this.state.report.overview.config_passwords.map(x => <li>{x.substr(0, 3) + '******'}</li>)}
|
||||
{this.state.report.overview.config_passwords.map(x => <li key={x}>{x.substr(0, 3) + '******'}</li>)}
|
||||
</ul>
|
||||
</p>
|
||||
</>
|
||||
:
|
||||
<p>
|
||||
Brute forcing uses stolen credentials only. No credentials were supplied during Monkey’s
|
||||
|
@ -195,7 +199,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
<p>
|
||||
The Monkey uses the following exploit methods:
|
||||
<ul>
|
||||
{this.state.report.overview.config_exploits.map(x => <li>{x}</li>)}
|
||||
{this.state.report.overview.config_exploits.map(x => <li key={x}>{x}</li>)}
|
||||
</ul>
|
||||
</p>
|
||||
)
|
||||
|
@ -209,7 +213,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
<p>
|
||||
The Monkey scans the following IPs:
|
||||
<ul>
|
||||
{this.state.report.overview.config_ips.map(x => <li>{x}</li>)}
|
||||
{this.state.report.overview.config_ips.map(x => <li key={x}>{x}</li>)}
|
||||
</ul>
|
||||
</p>
|
||||
:
|
||||
|
@ -313,15 +317,15 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey uncovered the following possible set of issues:
|
||||
<ul>
|
||||
{this.state.report.overview.warnings[this.Warning.CROSS_SEGMENT] ?
|
||||
<li>Weak segmentation - Machines from different segments are able to
|
||||
<li key={this.Warning.CROSS_SEGMENT}>Weak segmentation - Machines from different segments are able to
|
||||
communicate.</li> : null}
|
||||
{this.state.report.overview.warnings[this.Warning.TUNNEL] ?
|
||||
<li>Weak segmentation - Machines were able to communicate over unused ports.</li> : null}
|
||||
<li key={this.Warning.TUNNEL}>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
|
||||
<li key={this.Warning.SHARED_LOCAL_ADMIN}>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}
|
||||
<li key={this.Warning.SHARED_PASSWORDS}>Multiple users have the same password</li> : null}
|
||||
</ul>
|
||||
</div>
|
||||
:
|
||||
|
@ -443,21 +447,22 @@ class ReportPageComponent extends AuthComponent {
|
|||
}
|
||||
|
||||
generateInfoBadges(data_array) {
|
||||
return data_array.map(badge_data => <span className="badge badge-info" style={{margin: '2px'}}>{badge_data}</span>);
|
||||
return data_array.map(badge_data => <span key={badge_data} className="badge badge-info" style={{margin: '2px'}}>{badge_data}</span>);
|
||||
}
|
||||
|
||||
generateCrossSegmentIssue(crossSegmentIssue) {
|
||||
return <li>
|
||||
{'Communication possible from ' + crossSegmentIssue['source_subnet'] + ' to ' + crossSegmentIssue['target_subnet']}
|
||||
let crossSegmentIssueOverview = 'Communication possible from ' + crossSegmentIssue['source_subnet'] + ' to ' + crossSegmentIssue['target_subnet']
|
||||
return <li key={crossSegmentIssueOverview}>
|
||||
{crossSegmentIssueOverview}
|
||||
<CollapsibleWellComponent>
|
||||
<ul>
|
||||
{crossSegmentIssue['issues'].map(x =>
|
||||
x['is_self'] ?
|
||||
<li>
|
||||
<li key={x['hostname']}>
|
||||
{'Machine ' + x['hostname'] + ' has both ips: ' + x['source'] + ' and ' + x['target']}
|
||||
</li>
|
||||
:
|
||||
<li>
|
||||
<li key={x['source'] + x['target']}>
|
||||
{'IP ' + x['source'] + ' (' + x['hostname'] + ') connected to IP ' + x['target']
|
||||
+ ' using the services: ' + Object.keys(x['services']).join(', ')}
|
||||
</li>
|
||||
|
@ -473,7 +478,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
|
||||
generateSmbPasswordIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -484,13 +489,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey authenticated over the SMB protocol with user <span
|
||||
className="badge badge-success">{issue.username}</span> and its password.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateSmbPthIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -501,13 +506,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey used a pass-the-hash attack over SMB protocol with user <span
|
||||
className="badge badge-success">{issue.username}</span>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateWmiPasswordIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -518,13 +523,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey authenticated over the WMI protocol with user <span
|
||||
className="badge badge-success">{issue.username}</span> and its password.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateWmiPthIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -535,13 +540,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey used a pass-the-hash attack over WMI protocol with user <span
|
||||
className="badge badge-success">{issue.username}</span>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateSshIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -552,13 +557,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey authenticated over the SSH protocol with user <span
|
||||
className="badge badge-success">{issue.username}</span> and its password.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateSshKeysIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Protect <span className="badge badge-success">{issue.ssh_key}</span> private key with a pass phrase.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -568,14 +573,14 @@ class ReportPageComponent extends AuthComponent {
|
|||
The Monkey authenticated over the SSH protocol with private key <span
|
||||
className="badge badge-success">{issue.ssh_key}</span>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
generateSambaCryIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Change <span className="badge badge-success">{issue.username}</span>'s password to a complex one-use password
|
||||
that is not shared with other computers on the network.
|
||||
<br/>
|
||||
|
@ -589,13 +594,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
className="badge badge-success">{issue.username}</span> and its password, and used the SambaCry
|
||||
vulnerability.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateVsftpdBackdoorIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Update your VSFTPD server to the latest version vsftpd-3.0.3.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -614,13 +619,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2523"
|
||||
>here</a>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateElasticIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Update your Elastic Search server to version 1.4.3 and up.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -629,13 +634,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
<br/>
|
||||
The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateShellshockIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Update your Bash to a ShellShock-patched version.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -646,13 +651,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
className="badge badge-info">{issue.port}</span> was vulnerable to a shell injection attack on the
|
||||
paths: {this.generateShellshockPathListBadges(issue.paths)}.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateAzureIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Delete VM Access plugin configuration files.
|
||||
<CollapsibleWellComponent>
|
||||
Credentials could be stolen from <span
|
||||
|
@ -661,13 +666,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
href="https://www.guardicore.com/2018/03/recovering-plaintext-passwords-azure/"
|
||||
>here</a>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateConfickerIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Install the latest Windows updates or upgrade to a newer operating system.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -677,13 +682,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
The attack was made possible because the target machine used an outdated and unpatched operating system
|
||||
vulnerable to Conficker.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateIslandCrossSegmentIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Segment your network and make sure there is no communication between machines from different segments.
|
||||
<CollapsibleWellComponent>
|
||||
The network can probably be segmented. A monkey instance on <span
|
||||
|
@ -692,37 +697,37 @@ class ReportPageComponent extends AuthComponent {
|
|||
could directly access the Monkey Island server in the
|
||||
networks {this.generateInfoBadges(issue.server_networks)}.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateSharedCredsDomainIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Some domain users are sharing passwords, this should be fixed by changing passwords.
|
||||
<CollapsibleWellComponent>
|
||||
These users are sharing access password:
|
||||
{this.generateInfoBadges(issue.shared_with)}.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateSharedCredsIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Some users are sharing passwords, this should be fixed by changing passwords.
|
||||
<CollapsibleWellComponent>
|
||||
These users are sharing access password:
|
||||
{this.generateInfoBadges(issue.shared_with)}.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
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.
|
||||
<CollapsibleWellComponent>
|
||||
|
@ -730,13 +735,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
className="badge badge-primary">{issue.username}</span> is defined as an administrator:
|
||||
{this.generateInfoBadges(issue.shared_machines)}
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateStrongUsersOnCritIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
This critical machine is open to attacks via strong users with access to it.
|
||||
<CollapsibleWellComponent>
|
||||
The services: {this.generateInfoBadges(issue.services)} have been found on the machine
|
||||
|
@ -744,26 +749,26 @@ class ReportPageComponent extends AuthComponent {
|
|||
These users has access to it:
|
||||
{this.generateInfoBadges(issue.threatening_users)}.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateTunnelIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Use micro-segmentation policies to disable communication other than the required.
|
||||
<CollapsibleWellComponent>
|
||||
Machines are not locked down at port level. Network tunnel was set up from <span
|
||||
className="badge badge-primary">{issue.machine}</span> to <span
|
||||
className="badge badge-primary">{issue.dest}</span>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateStruts2Issue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions.
|
||||
<CollapsibleWellComponent>
|
||||
Struts2 server at <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -775,13 +780,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
href="https://cwiki.apache.org/confluence/display/WW/S2-045"
|
||||
>here</a>.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateWebLogicIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Update Oracle WebLogic server to the latest supported version.
|
||||
<CollapsibleWellComponent>
|
||||
Oracle WebLogic server at <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -792,13 +797,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
<a href={'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-10271'}> CVE-2017-10271</a> or
|
||||
<a href={'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-2725'}> CVE-2019-2725</a>
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateHadoopIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Run Hadoop in secure mode (<a
|
||||
href="http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/SecureMode.html">
|
||||
add Kerberos authentication</a>).
|
||||
|
@ -809,13 +814,13 @@ class ReportPageComponent extends AuthComponent {
|
|||
<br/>
|
||||
The attack was made possible due to default Hadoop/Yarn configuration being insecure.
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateMSSQLIssue(issue) {
|
||||
return (
|
||||
<li>
|
||||
<>
|
||||
Disable the xp_cmdshell option.
|
||||
<CollapsibleWellComponent>
|
||||
The machine <span className="badge badge-primary">{issue.machine}</span> (<span
|
||||
|
@ -827,88 +832,88 @@ class ReportPageComponent extends AuthComponent {
|
|||
href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option?view=sql-server-2017">
|
||||
Microsoft's documentation. </a>
|
||||
</CollapsibleWellComponent>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
generateIssue = (issue) => {
|
||||
let data;
|
||||
let issueData;
|
||||
switch (issue.type) {
|
||||
case 'vsftp':
|
||||
data = this.generateVsftpdBackdoorIssue(issue);
|
||||
issueData = this.generateVsftpdBackdoorIssue(issue);
|
||||
break;
|
||||
case 'smb_password':
|
||||
data = this.generateSmbPasswordIssue(issue);
|
||||
issueData = this.generateSmbPasswordIssue(issue);
|
||||
break;
|
||||
case 'smb_pth':
|
||||
data = this.generateSmbPthIssue(issue);
|
||||
issueData = this.generateSmbPthIssue(issue);
|
||||
break;
|
||||
case 'wmi_password':
|
||||
data = this.generateWmiPasswordIssue(issue);
|
||||
issueData = this.generateWmiPasswordIssue(issue);
|
||||
break;
|
||||
case 'wmi_pth':
|
||||
data = this.generateWmiPthIssue(issue);
|
||||
issueData = this.generateWmiPthIssue(issue);
|
||||
break;
|
||||
case 'ssh':
|
||||
data = this.generateSshIssue(issue);
|
||||
issueData = this.generateSshIssue(issue);
|
||||
break;
|
||||
case 'ssh_key':
|
||||
data = this.generateSshKeysIssue(issue);
|
||||
issueData = this.generateSshKeysIssue(issue);
|
||||
break;
|
||||
case 'sambacry':
|
||||
data = this.generateSambaCryIssue(issue);
|
||||
issueData = this.generateSambaCryIssue(issue);
|
||||
break;
|
||||
case 'elastic':
|
||||
data = this.generateElasticIssue(issue);
|
||||
issueData = this.generateElasticIssue(issue);
|
||||
break;
|
||||
case 'shellshock':
|
||||
data = this.generateShellshockIssue(issue);
|
||||
issueData = this.generateShellshockIssue(issue);
|
||||
break;
|
||||
case 'conficker':
|
||||
data = this.generateConfickerIssue(issue);
|
||||
issueData = this.generateConfickerIssue(issue);
|
||||
break;
|
||||
case 'island_cross_segment':
|
||||
data = this.generateIslandCrossSegmentIssue(issue);
|
||||
issueData = this.generateIslandCrossSegmentIssue(issue);
|
||||
break;
|
||||
case 'shared_passwords':
|
||||
data = this.generateSharedCredsIssue(issue);
|
||||
issueData = this.generateSharedCredsIssue(issue);
|
||||
break;
|
||||
case 'shared_passwords_domain':
|
||||
data = this.generateSharedCredsDomainIssue(issue);
|
||||
issueData = this.generateSharedCredsDomainIssue(issue);
|
||||
break;
|
||||
case 'shared_admins_domain':
|
||||
data = this.generateSharedLocalAdminsIssue(issue);
|
||||
issueData = this.generateSharedLocalAdminsIssue(issue);
|
||||
break;
|
||||
case 'strong_users_on_crit':
|
||||
data = this.generateStrongUsersOnCritIssue(issue);
|
||||
issueData = this.generateStrongUsersOnCritIssue(issue);
|
||||
break;
|
||||
case 'tunnel':
|
||||
data = this.generateTunnelIssue(issue);
|
||||
issueData = this.generateTunnelIssue(issue);
|
||||
break;
|
||||
case 'azure_password':
|
||||
data = this.generateAzureIssue(issue);
|
||||
issueData = this.generateAzureIssue(issue);
|
||||
break;
|
||||
case 'struts2':
|
||||
data = this.generateStruts2Issue(issue);
|
||||
issueData = this.generateStruts2Issue(issue);
|
||||
break;
|
||||
case 'weblogic':
|
||||
data = this.generateWebLogicIssue(issue);
|
||||
issueData = this.generateWebLogicIssue(issue);
|
||||
break;
|
||||
case 'hadoop':
|
||||
data = this.generateHadoopIssue(issue);
|
||||
issueData = this.generateHadoopIssue(issue);
|
||||
break;
|
||||
case 'mssql':
|
||||
data = this.generateMSSQLIssue(issue);
|
||||
issueData = this.generateMSSQLIssue(issue);
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
return <li key={JSON.stringify(issue)}>{issueData}</li>;
|
||||
};
|
||||
|
||||
generateIssues = (issues) => {
|
||||
let issuesDivArray = [];
|
||||
for (let machine of Object.keys(issues)) {
|
||||
issuesDivArray.push(
|
||||
<li>
|
||||
<li key={JSON.stringify(machine)}>
|
||||
<h4><b>{machine}</b></h4>
|
||||
<ol>
|
||||
{issues[machine].map(this.generateIssue)}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import React from "react";
|
||||
|
||||
export let renderArray = function (val) {
|
||||
return <>{val.map(x => <div key={x}>{x}</div>)}</>;
|
||||
};
|
||||
export let renderIpAddresses = function (val) {
|
||||
return <div>{renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')} </div>;
|
||||
};
|
|
@ -1,14 +1,8 @@
|
|||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import Pluralize from 'pluralize';
|
||||
import {renderArray, renderIpAddresses} from "../common/RenderArrays";
|
||||
|
||||
let renderArray = function (val) {
|
||||
return <div>{val.map(x => <div>{x}</div>)}</div>;
|
||||
};
|
||||
|
||||
let renderIpAddresses = function (val) {
|
||||
return <div>{renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')} </div>;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import Pluralize from 'pluralize';
|
||||
|
||||
let renderArray = function (val) {
|
||||
return <span>{val.map(x => <span key={x}> {x}</span>)}</span>;
|
||||
};
|
||||
|
||||
let renderIpAddresses = function (val) {
|
||||
return <span> {renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')} </span>;
|
||||
};
|
||||
import {renderIpAddresses} from "../common/RenderArrays";
|
||||
|
||||
let renderMachine = function (data) {
|
||||
return <div>{data.label} ( {renderIpAddresses(data)} )</div>
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import Pluralize from 'pluralize';
|
||||
import {renderArray, renderIpAddresses} from "../common/RenderArrays";
|
||||
|
||||
let renderArray = function (val) {
|
||||
return <div>{val.map(x => <div>{x}</div>)}</div>;
|
||||
};
|
||||
|
||||
let renderIpAddresses = function (val) {
|
||||
return <div>{renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')} </div>;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import React from 'react';
|
||||
import ReactTable from 'react-table'
|
||||
import {renderArray} from "../common/RenderArrays";
|
||||
|
||||
let renderArray = function (val) {
|
||||
console.log(val);
|
||||
return <div>{val.map(x => <div>{x}</div>)}</div>;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import '@babel/polyfill';
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
import 'core-js/fn/object/assign';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
|
Loading…
Reference in New Issue