forked from p15670423/monkey
Merge pull request #628 from guardicore/release/1.8.0
Release/1.8.0 to develop
This commit is contained in:
commit
aa21e864fe
Binary file not shown.
After Width: | Height: | Size: 198 KiB |
Binary file not shown.
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 162 KiB |
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
[submodule "monkey/monkey_island/cc/services/attack/attack_data"]
|
[submodule "monkey/monkey_island/cc/services/attack/attack_data"]
|
||||||
path = monkey/monkey_island/cc/services/attack/attack_data
|
path = monkey/monkey_island/cc/services/attack/attack_data
|
||||||
url = https://github.com/mitre/cti
|
url = https://github.com/guardicore/cti
|
||||||
|
|
20
README.md
20
README.md
|
@ -13,10 +13,6 @@ Welcome to the Infection Monkey!
|
||||||
|
|
||||||
The Infection Monkey is an open source security tool for testing a data center's resiliency to perimeter breaches and internal server infection. The Monkey uses various methods to self propagate across a data center and reports success to a centralized Monkey Island server.
|
The Infection Monkey is an open source security tool for testing a data center's resiliency to perimeter breaches and internal server infection. The Monkey uses various methods to self propagate across a data center and reports success to a centralized Monkey Island server.
|
||||||
|
|
||||||
<img src=".github/map-full.png" >
|
|
||||||
|
|
||||||
<img src=".github/Security-overview.png" width="800" height="500">
|
|
||||||
|
|
||||||
The Infection Monkey is comprised of two parts:
|
The Infection Monkey is comprised of two parts:
|
||||||
|
|
||||||
* **Monkey** - A tool which infects other machines and propagates to them.
|
* **Monkey** - A tool which infects other machines and propagates to them.
|
||||||
|
@ -24,6 +20,20 @@ The Infection Monkey is comprised of two parts:
|
||||||
|
|
||||||
To read more about the Monkey, visit [infectionmonkey.com](https://infectionmonkey.com).
|
To read more about the Monkey, visit [infectionmonkey.com](https://infectionmonkey.com).
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
### Map
|
||||||
|
<img src=".github/map-full.png" width="800" height="600">
|
||||||
|
|
||||||
|
### Security report
|
||||||
|
<img src=".github/security-report.png" width="800" height="500">
|
||||||
|
|
||||||
|
### Zero trust report
|
||||||
|
<img src=".github/zero-trust-report.png" width="800" height="500">
|
||||||
|
|
||||||
|
### ATT&CK report
|
||||||
|
<img src=".github/attack-report.png" width="900" height="500">
|
||||||
|
|
||||||
## Main Features
|
## Main Features
|
||||||
|
|
||||||
The Infection Monkey uses the following techniques and exploits to propagate to other machines.
|
The Infection Monkey uses the following techniques and exploits to propagate to other machines.
|
||||||
|
@ -40,6 +50,8 @@ The Infection Monkey uses the following techniques and exploits to propagate to
|
||||||
* Conficker
|
* Conficker
|
||||||
* SambaCry
|
* SambaCry
|
||||||
* Elastic Search (CVE-2015-1427)
|
* Elastic Search (CVE-2015-1427)
|
||||||
|
* Weblogic server
|
||||||
|
* and more
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
Check out the [Setup](https://github.com/guardicore/monkey/wiki/setup) page in the Wiki or a quick getting [started guide](https://www.guardicore.com/infectionmonkey/wt/).
|
Check out the [Setup](https://github.com/guardicore/monkey/wiki/setup) page in the Wiki or a quick getting [started guide](https://www.guardicore.com/infectionmonkey/wt/).
|
||||||
|
|
|
@ -2,7 +2,7 @@ FROM debian:stretch-slim
|
||||||
|
|
||||||
LABEL MAINTAINER="theonlydoo <theonlydoo@gmail.com>"
|
LABEL MAINTAINER="theonlydoo <theonlydoo@gmail.com>"
|
||||||
|
|
||||||
ARG RELEASE=1.6
|
ARG RELEASE=1.8.0
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|
|
@ -129,7 +129,7 @@ class VSFTPDExploiter(HostExploiter):
|
||||||
change_permission = str.encode(str(change_permission) + '\n')
|
change_permission = str.encode(str(change_permission) + '\n')
|
||||||
LOG.info("change_permission command is %s", change_permission)
|
LOG.info("change_permission command is %s", change_permission)
|
||||||
backdoor_socket.send(change_permission)
|
backdoor_socket.send(change_permission)
|
||||||
T1222Telem(ScanStatus.USED, change_permission, self.host).send()
|
T1222Telem(ScanStatus.USED, change_permission.decode(), self.host).send()
|
||||||
|
|
||||||
# Run monkey on the machine
|
# Run monkey on the machine
|
||||||
parameters = build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
parameters = build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
||||||
|
@ -143,7 +143,7 @@ class VSFTPDExploiter(HostExploiter):
|
||||||
if backdoor_socket.send(run_monkey):
|
if backdoor_socket.send(run_monkey):
|
||||||
LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", self._config.dropper_target_path_linux,
|
LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", self._config.dropper_target_path_linux,
|
||||||
self.host, run_monkey)
|
self.host, run_monkey)
|
||||||
self.add_executed_cmd(run_monkey)
|
self.add_executed_cmd(run_monkey.decode())
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -9,7 +9,11 @@ git+https://github.com/guardicore/pyinstaller
|
||||||
ecdsa
|
ecdsa
|
||||||
netifaces
|
netifaces
|
||||||
ipaddress
|
ipaddress
|
||||||
wmi
|
# Locking WMI since version 1.5 introduced breaking change on Linux agent compilation.
|
||||||
|
# See breaking change here: https://github.com/tjguk/wmi/commit/dcf8e3eca79bb8c0101ffb83e25c066b0ba9e16d
|
||||||
|
# Causes pip to error with:
|
||||||
|
# Could not find a version that satisfies the requirement pywin32 (from wmi->-r /src/infection_monkey/requirements.txt (line 12)) (from versions: none)
|
||||||
|
wmi==1.4.9
|
||||||
pywin32 ; sys_platform == 'win32'
|
pywin32 ; sys_platform == 'win32'
|
||||||
pymssql<3.0
|
pymssql<3.0
|
||||||
pyftpdlib
|
pyftpdlib
|
||||||
|
|
|
@ -17,12 +17,16 @@ class BaseTelem(object, metaclass=abc.ABCMeta):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def send(self):
|
def send(self, log_data=True):
|
||||||
"""
|
"""
|
||||||
Sends telemetry to island
|
Sends telemetry to island
|
||||||
"""
|
"""
|
||||||
data = self.get_data()
|
data = self.get_data()
|
||||||
logger.debug("Sending {} telemetry. Data: {}".format(self.telem_category, json.dumps(data)))
|
if log_data:
|
||||||
|
data_to_log = json.dumps(data)
|
||||||
|
else:
|
||||||
|
data_to_log = 'redacted'
|
||||||
|
logger.debug("Sending {} telemetry. Data: {}".format(self.telem_category, data_to_log))
|
||||||
ControlClient.send_telemetry(self.telem_category, data)
|
ControlClient.send_telemetry(self.telem_category, data)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -17,3 +17,6 @@ class SystemInfoTelem(BaseTelem):
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
return self.system_info
|
return self.system_info
|
||||||
|
|
||||||
|
def send(self, log_data=False):
|
||||||
|
super(SystemInfoTelem, self).send(log_data)
|
||||||
|
|
|
@ -31,7 +31,7 @@ from monkey_island.cc.bootloader_server import BootloaderHttpServer
|
||||||
from monkey_island.cc.setup import setup
|
from monkey_island.cc.setup import setup
|
||||||
|
|
||||||
|
|
||||||
def main(should_setup_only):
|
def main(should_setup_only=False):
|
||||||
logger.info("Starting bootloader server")
|
logger.info("Starting bootloader server")
|
||||||
mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url())
|
mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url())
|
||||||
bootloader_server_thread = Thread(target=BootloaderHttpServer(mongo_url).serve_forever, daemon=True)
|
bootloader_server_thread = Thread(target=BootloaderHttpServer(mongo_url).serve_forever, daemon=True)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c139e37bdc51acbc7d0488a5be48553caffdbbd7
|
Subproject commit fb8942b1a10f4e734ed75542f2ccae7cbd72c46d
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
from stix2 import FileSystemSource, Filter, CourseOfAction, AttackPattern, v20
|
from stix2 import FileSystemSource, Filter, CourseOfAction, AttackPattern
|
||||||
|
|
||||||
|
|
||||||
class MitreApiInterface:
|
class MitreApiInterface:
|
||||||
|
@ -32,14 +32,14 @@ class MitreApiInterface:
|
||||||
return all_techniques
|
return all_techniques
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_stix2_external_reference_id(stix2_data: v20._DomainObject) -> str:
|
def get_stix2_external_reference_id(stix2_data) -> str:
|
||||||
for reference in stix2_data['external_references']:
|
for reference in stix2_data['external_references']:
|
||||||
if reference['source_name'] == "mitre-attack" and 'external_id' in reference:
|
if reference['source_name'] == "mitre-attack" and 'external_id' in reference:
|
||||||
return reference['external_id']
|
return reference['external_id']
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_stix2_external_reference_url(stix2_data: v20._DomainObject) -> str:
|
def get_stix2_external_reference_url(stix2_data) -> str:
|
||||||
for reference in stix2_data['external_references']:
|
for reference in stix2_data['external_references']:
|
||||||
if 'url' in reference:
|
if 'url' in reference:
|
||||||
return reference['url']
|
return reference['url']
|
||||||
|
|
|
@ -5,7 +5,7 @@ from monkey_island.cc.database import mongo
|
||||||
from common.utils.attack_utils import ScanStatus
|
from common.utils.attack_utils import ScanStatus
|
||||||
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
||||||
from common.utils.code_utils import abstractstatic
|
from common.utils.code_utils import abstractstatic
|
||||||
from cc.models.attack.attack_mitigations import AttackMitigations
|
from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,4 @@ Homepage: https://www.infectionmonkey.com
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Version: 1.0
|
Version: 1.0
|
||||||
Description: Guardicore Infection Monkey Island installation package
|
Description: Guardicore Infection Monkey Island installation package
|
||||||
Depends: openssl, python3-pip, python3-dev
|
Depends: openssl, python3.7-dev, python3.7-venv, python3-venv, build-essential
|
||||||
|
|
|
@ -1,20 +1,42 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# See the "Depends" field of the control file for what packages this scripts depends on.
|
||||||
|
# Here are the explanations for the current deps:
|
||||||
|
# Dependency - Why is it required
|
||||||
|
## openssl - Server certificate generation
|
||||||
|
## python3.7-dev - Server runtime
|
||||||
|
## python3.7-venv - For creating virtual env to install all the server pip deps (don't want to pollute system python)
|
||||||
|
## python3-venv - python3.7-venv doesn't work without it since you need ensure-pip
|
||||||
|
## build-essential - for compiling python dependencies that don't come in a pre-compiled wheel, like `netifaces`
|
||||||
|
|
||||||
|
echo "Installing Monkey Island (Infection Monkey server)..."
|
||||||
|
|
||||||
MONKEY_FOLDER=/var/monkey
|
MONKEY_FOLDER=/var/monkey
|
||||||
INSTALLATION_FOLDER=/var/monkey/monkey_island/installation
|
INSTALLATION_FOLDER=/var/monkey/monkey_island/installation
|
||||||
PYTHON_FOLDER=/var/monkey/monkey_island/bin/python
|
PYTHON_FOLDER=/var/monkey/monkey_island/bin/python
|
||||||
|
PYTHON_VERSION=python3.7
|
||||||
|
|
||||||
# Prepare python virtualenv
|
# Prepare python virtualenv
|
||||||
pip3 install virtualenv --no-index --find-links file://$INSTALLATION_FOLDER
|
# This is using the apt package `python3.7-venv` which is listed in the `control` file as a dependency.
|
||||||
python3 -m virtualenv -p python3 ${PYTHON_FOLDER}
|
# See https://packages.debian.org/stable/python/python3.7-venv
|
||||||
|
echo "Using $(command -v $PYTHON_VERSION) as the base for virtualenv creation"
|
||||||
|
$PYTHON_VERSION -m venv ${PYTHON_FOLDER}
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source ${PYTHON_FOLDER}/bin/activate
|
||||||
|
|
||||||
# install pip requirements
|
echo "Installing Python dependencies using $(command -v python) and $(command -v pip)..."
|
||||||
${PYTHON_FOLDER}/bin/python -m pip install -r $MONKEY_FOLDER/monkey_island/requirements.txt --no-index --find-links file://$INSTALLATION_FOLDER
|
# First, make sure that pip is updated
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
# Then install the dependecies from the pre-downloaded whl and tar.gz file
|
||||||
|
python -m pip install -r $MONKEY_FOLDER/monkey_island/requirements.txt --no-index --find-links file://$INSTALLATION_FOLDER
|
||||||
|
|
||||||
|
deactivate
|
||||||
|
|
||||||
# remove installation folder and unnecessary files
|
# remove installation folder and unnecessary files
|
||||||
rm -rf ${INSTALLATION_FOLDER}
|
rm -rf ${INSTALLATION_FOLDER}
|
||||||
rm -f ${MONKEY_FOLDER}/monkey_island/requirements.txt
|
rm -f ${MONKEY_FOLDER}/monkey_island/requirements.txt
|
||||||
|
|
||||||
|
echo "Installing mongodb..."
|
||||||
${MONKEY_FOLDER}/monkey_island/install_mongo.sh ${MONKEY_FOLDER}/monkey_island/bin/mongodb
|
${MONKEY_FOLDER}/monkey_island/install_mongo.sh ${MONKEY_FOLDER}/monkey_island/bin/mongodb
|
||||||
|
|
||||||
if [ -d "/etc/systemd/network" ]; then
|
if [ -d "/etc/systemd/network" ]; then
|
||||||
|
@ -25,11 +47,17 @@ if [ -d "/etc/systemd/network" ]; then
|
||||||
systemctl enable monkey-island
|
systemctl enable monkey-island
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${MONKEY_FOLDER}/monkey_island/create_certificate.sh ${MONKEY_FOLDER}/monkey_island/
|
echo "Creating server certificate..."
|
||||||
|
${MONKEY_FOLDER}/monkey_island/create_certificate.sh ${MONKEY_FOLDER}/monkey_island/cc
|
||||||
|
|
||||||
|
echo "Starting services..."
|
||||||
service monkey-island start
|
service monkey-island start
|
||||||
service monkey-mongo start
|
service monkey-mongo start
|
||||||
|
|
||||||
echo Monkey Island installation ended
|
echo ""
|
||||||
|
echo "Monkey Island installation ended."
|
||||||
|
echo "The server should be accessible soon via https://<server_ip>:5000/"
|
||||||
|
echo "To check the Island's status, run 'sudo service monkey-island status'"
|
||||||
|
echo ""
|
||||||
|
|
||||||
exit 0
|
exit 0
|
|
@ -2,8 +2,29 @@
|
||||||
|
|
||||||
server_root=${1:-"./cc"}
|
server_root=${1:-"./cc"}
|
||||||
|
|
||||||
|
echo "Creating server cetificate. Server root: $server_root"
|
||||||
|
# We override the RANDFILE determined by default openssl.cnf, if it doesn't exist.
|
||||||
|
# This is a known issue with the current version of openssl on Ubuntu 18.04 - once they release
|
||||||
|
# a new version, we can delete this command. See
|
||||||
|
# https://github.com/openssl/openssl/commit/0f58220973a02248ca5c69db59e615378467b9c8#diff-8ce6aaad88b10ed2b3b4592fd5c8e03a
|
||||||
|
# for more details.
|
||||||
|
DEFAULT_RND_FILE_PATH=~/.rnd
|
||||||
|
CREATED_RND_FILE=false
|
||||||
|
if [ ! -f /tmp/foo.txt ]; then # If the file already exists, assume that the contents are fine, and don't change them.
|
||||||
|
echo "Creating rand seed file in $DEFAULT_RND_FILE_PATH"
|
||||||
|
dd bs=1024 count=2 </dev/urandom >"$DEFAULT_RND_FILE_PATH"
|
||||||
|
chmod 666 "$DEFAULT_RND_FILE_PATH"
|
||||||
|
CREATED_RND_FILE=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Generating key in $server_root/server.key..."
|
||||||
openssl genrsa -out "$server_root"/server.key 2048
|
openssl genrsa -out "$server_root"/server.key 2048
|
||||||
|
echo "Generating csr in $server_root/server.csr..."
|
||||||
openssl req -new -key "$server_root"/server.key -out "$server_root"/server.csr -subj "/C=GB/ST=London/L=London/O=Global Security/OU=Monkey Department/CN=monkey.com"
|
openssl req -new -key "$server_root"/server.key -out "$server_root"/server.csr -subj "/C=GB/ST=London/L=London/O=Global Security/OU=Monkey Department/CN=monkey.com"
|
||||||
openssl x509 -req -days 366 -in "$server_root"/server.csr -signkey "$server_root"/server.key -out $server_root/server.crt
|
echo "Generating certificate in $server_root/server.crt..."
|
||||||
|
openssl x509 -req -days 366 -in "$server_root"/server.csr -signkey "$server_root"/server.key -out "$server_root"/server.crt
|
||||||
|
|
||||||
|
# Shove some new random data into the file to override the original seed we put in.
|
||||||
|
if [ "$CREATED_RND_FILE" = true ] ; then
|
||||||
|
dd bs=1024 count=2 </dev/urandom >"$DEFAULT_RND_FILE_PATH"
|
||||||
|
fi
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import sys
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
@ -9,15 +9,20 @@ block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
# These data files and folders will be included in the bundle.
|
||||||
|
# The format of the tuples is (src, dest_dir). See https://pythonhosted.org/PyInstaller/spec-files.html#adding-data-files
|
||||||
|
added_datas = [
|
||||||
|
("../common/BUILD", "/common"),
|
||||||
|
("../monkey_island/cc/services/attack/attack_data", "/monkey_island/cc/services/attack/attack_data")
|
||||||
|
]
|
||||||
|
|
||||||
a = Analysis(['cc/main.py'],
|
a = Analysis(['cc/main.py'],
|
||||||
pathex=['..'],
|
pathex=['..'],
|
||||||
hiddenimports=get_hidden_imports(),
|
hiddenimports=get_hidden_imports(),
|
||||||
hookspath=None,
|
hookspath=[os.path.join(".", "pyinstaller_hooks")],
|
||||||
runtime_hooks=None,
|
runtime_hooks=None,
|
||||||
binaries=None,
|
binaries=None,
|
||||||
datas=[
|
datas=added_datas,
|
||||||
("../common/BUILD", "/common")
|
|
||||||
],
|
|
||||||
excludes=None,
|
excludes=None,
|
||||||
win_no_prefer_redirects=None,
|
win_no_prefer_redirects=None,
|
||||||
win_private_assemblies=None,
|
win_private_assemblies=None,
|
||||||
|
@ -36,8 +41,7 @@ def main():
|
||||||
name=get_monkey_filename(),
|
name=get_monkey_filename(),
|
||||||
debug=False,
|
debug=False,
|
||||||
strip=get_exe_strip(),
|
strip=get_exe_strip(),
|
||||||
upx=True,
|
upx=False,
|
||||||
upx_exclude=['vcruntime140.dll'],
|
|
||||||
console=True,
|
console=True,
|
||||||
icon=get_exe_icon())
|
icon=get_exe_icon())
|
||||||
|
|
||||||
|
@ -74,7 +78,7 @@ def get_linux_only_binaries():
|
||||||
|
|
||||||
|
|
||||||
def get_hidden_imports():
|
def get_hidden_imports():
|
||||||
return ['_cffi_backend', 'queue'] if is_windows() else ['_cffi_backend']
|
return ['_cffi_backend', 'queue', 'pkg_resources.py2_warn'] if is_windows() else ['_cffi_backend']
|
||||||
|
|
||||||
|
|
||||||
def get_msvcr():
|
def get_msvcr():
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Workaround for packaging Monkey Island using PyInstaller. See https://github.com/oasis-open/cti-python-stix2/issues/218
|
||||||
|
|
||||||
|
import os
|
||||||
|
from PyInstaller.utils.hooks import get_module_file_attribute
|
||||||
|
|
||||||
|
stix2_dir = os.path.dirname(get_module_file_attribute('stix2'))
|
||||||
|
datas = [(stix2_dir, 'stix2')]
|
|
@ -1,5 +1,4 @@
|
||||||
pytest
|
pytest
|
||||||
bson
|
|
||||||
python-dateutil
|
python-dateutil
|
||||||
tornado
|
tornado
|
||||||
werkzeug
|
werkzeug
|
||||||
|
|
Loading…
Reference in New Issue