Merge pull request #1887 from guardicore/agent-refactor

This commit is contained in:
Mike Salvatore 2022-04-14 11:13:45 -04:00
commit 16e887a94a
600 changed files with 32435 additions and 19004 deletions

2
.gitattributes vendored
View File

@ -1,4 +1,4 @@
monkey/tests/data_for_tests/ransomware_targets/** -text
monkey/tests/data_for_tests/test_readme.txt -text
monkey/tests/data_for_tests/stable_file.txt -text
monkey/infection_monkey/ransomware/ransomware_readme.txt -text
monkey/infection_monkey/payload/ransomware/ransomware_readme.txt -text

View File

@ -1,7 +1,7 @@
default_stages: [commit]
repos:
- repo: https://github.com/pycqa/isort
rev: 5.8.0
rev: 5.10.1
hooks:
- id: isort
name: isort (python)
@ -12,16 +12,16 @@ repos:
name: isort (pyi)
types: [pyi]
- repo: https://github.com/psf/black
rev: 20.8b1
rev: 22.3.0
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.1
rev: 4.0.1
hooks:
- id: flake8
additional_dependencies: [dlint]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.1.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
@ -31,7 +31,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/eslint/eslint
rev: v7.24.0
rev: v8.12.0
hooks:
- id: eslint
args: ["monkey/monkey_island/cc/ui/src/", "--fix", "--max-warnings=0"]
@ -45,7 +45,7 @@ repos:
exclude: "monkey/monkey_island/cc/ui"
stages: [push]
- repo: https://github.com/swimmio/pre-commit
rev: v0.2
rev: v0.7
hooks:
- id: swimm-verify
- repo: https://github.com/jendrikseipp/vulture

View File

@ -1,86 +0,0 @@
{
"id": "AzD8XysWg1BBXCjCDkfq",
"name": "Add a new configuration setting to the Agent ⚙",
"task": {
"dod": "Make the max victim number that Monkey will find before stopping configurable by the user instead of constant.",
"tests": [],
"hints": [
"Look for `victims_max_exploit` - it's rather similar."
]
},
"content": [
{
"type": "text",
"text": "# Make something configurable\n\nIn this unit, you will learn how to add a configuration option to Monkey and how to use it in the Monkey Agent code. \n\n![computer fire](https://media.giphy.com/media/7J4P7cUur2DlErijp3/giphy.gif \"computer fire\")\n\n## Why is this important?\n\nEnabling users to configure the Monkey's behaviour gives them a lot more freedom in how they want to use the Monkey and enables more use cases.\n\n## What is \"Max victims to find\"?\n\nThe Monkey has a function which finds \"victim\" machines on the network for the Monkey to try and exploit. It's called `get_victim_machines`. This function accepts an argument which limits how many machines the Monkey should find.\n\nWe want to make that value editable by the user instead of constant in the code.\n\n## Manual testing\n\n1. After you've performed the required changes, reload the Server and check your value exists in the Internal tab of the config (see image).\n\n![](https://i.imgur.com/e0XAxuV.png)\n\n2. Set the new value to 1, and run Monkey locally (from source). See that the Monkey only scans one machine."
},
{
"type": "snippet",
"path": "monkey/infection_monkey/config.py",
"comments": [],
"firstLineNumber": 103,
"lines": [
" exploiter_classes = []",
" system_info_collector_classes = []",
" ",
"* # how many victims to look for in a single scan iteration",
"* victims_max_find = 100",
" ",
" # how many victims to exploit before stopping",
" victims_max_exploit = 100"
]
},
{
"type": "snippet",
"path": "monkey/infection_monkey/monkey.py",
"comments": [],
"firstLineNumber": 220,
"lines": [
" if not WormConfiguration.alive:",
" logger.info(\"Marked not alive from configuration\")",
" ",
"* machines = self._network.get_victim_machines(",
"* max_find=WormConfiguration.victims_max_find,",
"* stop_callback=ControlClient.check_for_stop,",
"* )",
" for machine in machines:",
" if ControlClient.check_for_stop():",
" break"
]
},
{
"type": "snippet",
"path": "monkey/monkey_island/cc/services/config_schema/internal.py",
"comments": [],
"firstLineNumber": 28,
"lines": [
" \"title\": \"Monkey\",",
" \"type\": \"object\",",
" \"properties\": {",
"* \"victims_max_find\": {",
"* \"title\": \"Max victims to find\",",
"* \"type\": \"integer\",",
"* \"default\": 100,",
"* \"description\": \"Determines the maximum number of machines the monkey is \"",
"* \"allowed to scan\",",
"* },",
" \"victims_max_exploit\": {",
" \"title\": \"Max victims to exploit\",",
" \"type\": \"integer\","
]
},
{
"type": "text",
"text": "* When changing config schema by adding or deleting keys, you need to update the Blackbox Test configurations as well [here](https://github.com/guardicore/monkey/tree/develop/envs/monkey_zoo/blackbox/config_templates)."
}
],
"symbols": {},
"file_version": "2.0.3",
"meta": {
"app_version": "0.6.6-2",
"file_blobs": {
"monkey/infection_monkey/config.py": "8f4984ba6563564343282765ab498efca5d89ba8",
"monkey/infection_monkey/monkey.py": "4160a36e0e624404d77526472d51dd07bba49e5a",
"monkey/monkey_island/cc/services/config_schema/internal.py": "86318eaf19b9991a8af5de861a3eb085238e17a4"
}
}
}

View File

@ -18,23 +18,24 @@
"type": "snippet",
"path": "monkey/infection_monkey/post_breach/actions/schedule_jobs.py",
"comments": [],
"firstLineNumber": 12,
"firstLineNumber": 15,
"lines": [
" \"\"\"",
" ",
" def __init__(self):",
" def __init__(self, telemetry_messenger: ITelemetryMessenger):",
"* linux_cmds, windows_cmds = get_commands_to_schedule_jobs()",
"+ pass",
"*",
"+ # Swimmer: IMPLEMENT HERE!",
"* super(ScheduleJobs, self).__init__(",
"* telemetry_messenger,",
"* name=POST_BREACH_JOB_SCHEDULING,",
"* linux_cmd=\" \".join(linux_cmds),",
"* windows_cmd=windows_cmds,",
"* )",
"*",
"* def run(self):",
"* super(ScheduleJobs, self).run()",
"* def run(self, options: Dict):",
"* super(ScheduleJobs, self).run(options)",
"* remove_scheduled_jobs()"
]
},
@ -44,11 +45,11 @@
}
],
"symbols": {},
"file_version": "2.0.1",
"file_version": "2.0.3",
"meta": {
"app_version": "0.4.1-1",
"app_version": "0.6.6-2",
"file_blobs": {
"monkey/infection_monkey/post_breach/actions/schedule_jobs.py": "e7845968a0c27d2eba71a8889645fe88491cb2a8"
"monkey/infection_monkey/post_breach/actions/schedule_jobs.py": "4ab023e35fa4424f0c6583233f5b056c7b1cad51"
}
}
}

View File

@ -34,15 +34,18 @@
"lines": [
" ",
" class AccountDiscovery(PBA):",
" def __init__(self):",
" def __init__(self, telemetry_messenger: ITelemetryMessenger):",
"* linux_cmds, windows_cmds = get_commands_to_discover_accounts()",
"+ # SWIMMER: Implement here!",
"* super().__init__(",
"+ pass",
"* POST_BREACH_ACCOUNT_DISCOVERY, linux_cmd=\" \".join(linux_cmds), windows_cmd=windows_cmds",
"* telemetry_messenger,",
"* POST_BREACH_ACCOUNT_DISCOVERY,",
"* linux_cmd=\" \".join(linux_cmds),",
"* windows_cmd=windows_cmds,",
"* )"
],
"firstLineNumber": 7,
"firstLineNumber": 8,
"path": "monkey/infection_monkey/post_breach/actions/discover_accounts.py",
"comments": []
},
@ -65,7 +68,7 @@
" \"type\": \"string\",",
" \"enum\": [\"ClearCommandHistory\"],"
],
"firstLineNumber": 80,
"firstLineNumber": 78,
"path": "monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py",
"comments": []
},
@ -77,11 +80,11 @@
"symbols": {},
"file_version": "2.0.3",
"meta": {
"app_version": "0.5.7-0",
"app_version": "0.6.6-2",
"file_blobs": {
"monkey/common/common_consts/post_breach_consts.py": "01d31448269e5581dbe0176c289f7dd36cc5854f",
"monkey/infection_monkey/post_breach/actions/discover_accounts.py": "8fdebd0df97655e4cba3aebcdcf3c5ed1d1b6cbd",
"monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py": "88a3e8cb59fb0d1c07c9487bcb4eaab7b8087d84"
"monkey/common/common_consts/post_breach_consts.py": "19b6c4f19b7223f115976a0050ca04ab97e52f8e",
"monkey/infection_monkey/post_breach/actions/discover_accounts.py": "a153cf5b6185c9771414fc5ae49d441efc7294b6",
"monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py": "d6831ed63b17f327d719a05840d7e51202fa5ccb"
}
}
}

View File

@ -7,10 +7,11 @@ group: travis_latest
language: python
env:
- PIP_CACHE_DIR=$HOME/.cache/pip PIPENV_CACHE_DIR=$HOME/.cache/pipenv
- PIP_CACHE_DIR=$HOME/.cache/pip PIPENV_CACHE_DIR=$HOME/.cache/pipenv LIBSODIUM_MAKE_ARGS=-j8
cache:
- pip
- pip: true
- npm: true
- directories:
- "$HOME/.npm"
- $PIP_CACHE_DIR
@ -20,10 +21,13 @@ python:
- 3.7
os: linux
vm:
size: x-large
install:
# Python
- nproc
- pip install pipenv --upgrade
# Install island and monkey requirements as they are needed by UT's
- pushd monkey/monkey_island
@ -37,7 +41,7 @@ install:
- node --version
- npm --version
- nvm --version
- nvm install 12
- nvm install 16
- nvm use node
- npm i -g eslint
- node --version
@ -65,7 +69,8 @@ script:
## Run unit tests and generate coverage data
- cd monkey # This is our source dir
- python -m pytest --cov=. # Have to use `python -m pytest` instead of `pytest` to add "{$builddir}/monkey/monkey" to sys.path.
- pip install pytest-xdist
- python -m pytest -n auto --cov=. # Have to use `python -m pytest` instead of `pytest` to add "{$builddir}/monkey/monkey" to sys.path.
# Check JS code. The npm install must happen AFTER the flake8 because the node_modules folder will cause a lot of errors.
- cd monkey_island/cc/ui
@ -80,7 +85,7 @@ script:
# verify swimm
- cd $TRAVIS_BUILD_DIR
- curl -L https://github.com/swimmio/SwimmReleases/releases/latest/download/packed-swimm-linux-cli --output swimm-cli
- curl -L https://releases.swimm.io/ci/latest/packed-swimm-linux-cli --output swimm-cli
- chmod u+x swimm-cli
- ./swimm-cli --version
- ./swimm-cli verify

View File

@ -8,16 +8,27 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- credentials.json file for storing Monkey Island user login information. #1206
- "GET /api/propagation-credentials/<string:guid>" endpoint for agents to
retrieve updated credentials from the Island. #1538
- SSHCollector as a configurable System info Collector. #1606
- deployment_scrips/install-infection-monkey-service.sh to install an AppImage
as a service. #1552
- The ability to download the Monkey Island logs from the Infection Map page. #1640
### Changed
- "Communicate as Backdoor User" PBA's HTTP requests to request headers only and
include a timeout. #1577
- The setup procedure for custom server_config.json files to be simpler. #1576
- The order and content of Monkey Island's initialization logging to give
clearer instructions to the user and avoid confusion. #1684
- The process list collection system info collector to now be a post-breach action. #1697
- The "/api/monkey/download" endpoint to accept an OS and return a file. #1675
- Log messages to contain human-readable thread names. #1766
- The log file name to `infection-monkey-agent-<TIMESTAMP>-<RANDOM_STRING>.log`. #1761
- "Logs" page renamed to "Telemetries". #1640
### Removed
- The VSFTPD exploiter. #1533
- VSFTPD exploiter. #1533
- Manual agent run command for CMD. #1570
- Sambacry exploiter. #1567, #1693
- "Kill file" option in the config. #1536
@ -34,6 +45,23 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- Hostname system info collector. #1535
- Max iterations and timeout between iterations config options. #1600
- MITRE ATT&CK configuration screen. #1532
- Propagation credentials from "GET /api/monkey/<string:guid>" endpoint. #1538
- "GET /api/monkey_control/check_remote_port/<string:port>" endpoint. #1635
- Max victims to find/exploit, TCP scan interval and TCP scan get banner internal options. #1597
- MySQL fingerprinter. #1648
- MS08-067 (Conficker) exploiter. #1677
- Agent bootloader. #1676
- Zero Trust integration with ScoutSuite. #1669
- ShellShock exploiter. #1733
- ElasticGroovy exploiter. #1732
- T1082 attack technique report. #1754
- 32-bit agents. #1675
- Log path config options. #1761
- "smb_service_name" option. #1741
- Struts2 exploiter. #1869
- Drupal exploiter. #1869
- WebLogic exploiter. #1869
- The /api/t1216-pba/download endpoint. #1864
- Island log download button from "Telemetries"(previously called "Logs") page. #1640
### Fixed
@ -41,9 +69,14 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- Windows "run as a user" powershell command for manual agent runs. #1570
- A bug in the "Signed Script Proxy Execution" PBA that downloaded the exe on Linux
systems as well. #1557
- A bug where T1216_random_executable.exe was copied to disk even if the signed
script proxy execution PBA was disabled. #1864
### Security
- Change SSH exploiter so that it does not set the permissions of the agent
binary in /tmp on the target system to 777, as this could allow a malicious
actor with local access to escalate their privileges. #1750
## [1.13.0] - 2022-01-25
### Added
@ -54,6 +87,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- Exploiters attempting to start servers listening on privileged ports,
resulting in failed propagation. 8f53a5c
## [1.12.0] - 2021-10-27
### Added
- A new exploiter that allows propagation via PowerShell Remoting. #1246

View File

@ -58,10 +58,8 @@ The Infection Monkey uses the following techniques and exploits to propagate to
* SSH
* SMB
* WMI
* Shellshock
* Conficker
* Elastic Search (CVE-2015-1427)
* Weblogic server
* Log4Shell
* Zerologon
* and more, see our [Documentation hub](https://www.guardicore.com/infectionmonkey/docs/reference/exploiters/) for more information about our RCE exploiters.
## Setup

View File

@ -1,7 +1,7 @@
#!/bin/bash
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
PYTHON_VERSION="3.7.12"
PYTHON_VERSION="3.7.13"
PYTHON_APPIMAGE_URL="https://github.com/niess/python-appimage/releases/download/python3.7/python${PYTHON_VERSION}-cp37-cp37m-manylinux1_x86_64.AppImage"
APPIMAGE_DIR="$(realpath $(dirname $BASH_SOURCE[0]))"
APPDIR="$APPIMAGE_DIR/squashfs-root"
@ -28,6 +28,7 @@ setup_build_dir() {
local agent_binary_dir=$1
local monkey_repo=$2
local deployment_type=$3
local is_release_build=$4
pushd $APPIMAGE_DIR
@ -44,7 +45,7 @@ setup_build_dir() {
install_mongodb
generate_ssl_cert "$BUILD_DIR"
build_frontend "$BUILD_DIR"
build_frontend "$BUILD_DIR" "$is_release_build"
remove_python_appdir_artifacts

View File

@ -1,7 +1,7 @@
WORKSPACE=${WORKSPACE:-$HOME}
DEFAULT_REPO_MONKEY_HOME=$WORKSPACE/git/monkey
MONKEY_ORIGIN_URL="https://github.com/guardicore/monkey.git"
NODE_SRC=https://deb.nodesource.com/setup_12.x
NODE_SRC=https://deb.nodesource.com/setup_16.x
BUILD_SCRIPTS_DIR="$(realpath $(dirname $BASH_SOURCE[0]))"
DIST_DIR="$BUILD_SCRIPTS_DIR/dist"
@ -196,8 +196,13 @@ fi
install_build_prereqs
install_package_specific_build_prereqs "$WORKSPACE"
is_release_build=false
# Monkey version is empty on release build
if [ ! -z "$monkey_version" ]; then
is_release_build=true
fi
setup_build_dir "$agent_binary_dir" "$monkey_repo" "$deployment_type"
setup_build_dir "$agent_binary_dir" "$monkey_repo" "$deployment_type" "$is_release_build"
commit_id=$(get_commit_id "$monkey_repo")
build_package "$monkey_version" "$commit_id" "$DIST_DIR"

View File

@ -42,9 +42,7 @@ download_monkey_agent_binaries() {
load_monkey_binary_config
mkdir -p "${island_binaries_path}" || handle_error
curl -L -o "${island_binaries_path}/${LINUX_32_BINARY_NAME}" "${LINUX_32_BINARY_URL}"
curl -L -o "${island_binaries_path}/${LINUX_64_BINARY_NAME}" "${LINUX_64_BINARY_URL}"
curl -L -o "${island_binaries_path}/${WINDOWS_32_BINARY_NAME}" "${WINDOWS_32_BINARY_URL}"
curl -L -o "${island_binaries_path}/${WINDOWS_64_BINARY_NAME}" "${WINDOWS_64_BINARY_URL}"
}
@ -76,11 +74,18 @@ generate_ssl_cert() {
build_frontend() {
local ui_dir="$1/monkey_island/cc/ui"
local is_release_build=$2
pushd "$ui_dir" || handle_error
log_message "Generating front end"
npm ci
npm run dist
if [ "$is_release_build" == true ]; then
log_message "Running production front end build"
npm run dist
else
log_message "Running development front end build"
npm run dev
fi
popd || handle_error

View File

@ -9,6 +9,7 @@ install_package_specific_build_prereqs() {
setup_build_dir() {
local agent_binary_dir=$1
local monkey_repo=$2
local is_release_build=$4
local build_dir=$DOCKER_DIR/monkey
mkdir "$build_dir"
@ -22,7 +23,7 @@ setup_build_dir() {
generate_ssl_cert "$build_dir"
build_frontend "$build_dir"
build_frontend "$build_dir" "$is_release_build"
}
copy_entrypoint_to_build_dir() {

View File

@ -22,7 +22,7 @@ The first argument is an empty directory (script can create one). The second arg
- `.\deploy_windows.ps1` (Sets up monkey in current directory under .\infection_monkey)
- `.\deploy_windows.ps1 -monkey_home "C:\test"` (Sets up monkey in C:\test)
- `.\deploy_windows.ps1 -branch "master"` (Sets up master branch instead of develop in current dir)
- `.\deploy_windows.ps1 -branch 'master'` (Sets up master branch instead of develop in current dir)
You may also pass in an optional `agents=$false` parameter to disable downloading the latest agent binaries.

View File

@ -25,15 +25,9 @@ get_latest_release() {
MONKEY_LATEST_RELEASE=$(get_latest_release "guardicore/monkey")
# Monkey binaries
export LINUX_32_BINARY_NAME="monkey-linux-32"
export LINUX_32_BINARY_URL="https://github.com/guardicore/monkey/releases/download/$MONKEY_LATEST_RELEASE/monkey-linux-32"
export LINUX_64_BINARY_NAME="monkey-linux-64"
export LINUX_64_BINARY_URL="https://github.com/guardicore/monkey/releases/download/$MONKEY_LATEST_RELEASE/monkey-linux-64"
export WINDOWS_32_BINARY_NAME="monkey-windows-32.exe"
export WINDOWS_32_BINARY_URL="https://github.com/guardicore/monkey/releases/download/$MONKEY_LATEST_RELEASE/monkey-windows-32.exe"
export WINDOWS_64_BINARY_NAME="monkey-windows-64.exe"
export WINDOWS_64_BINARY_URL="https://github.com/guardicore/monkey/releases/download/$MONKEY_LATEST_RELEASE/monkey-windows-64.exe"

View File

@ -12,12 +12,8 @@ $PYTHON_URL = "https://www.python.org/ftp/python/3.7.7/python-3.7.7-amd64.exe"
# Monkey binaries
$LINUX_32_BINARY_URL = $MONKEY_DOWNLOAD_URL + "monkey-linux-32"
$LINUX_32_BINARY_PATH = "monkey-linux-32"
$LINUX_64_BINARY_URL = $MONKEY_DOWNLOAD_URL + "monkey-linux-64"
$LINUX_64_BINARY_PATH = "monkey-linux-64"
$WINDOWS_32_BINARY_URL = $MONKEY_DOWNLOAD_URL + "monkey-windows-32.exe"
$WINDOWS_32_BINARY_PATH = "monkey-windows-32.exe"
$WINDOWS_64_BINARY_URL = $MONKEY_DOWNLOAD_URL + "monkey-windows-64.exe"
$WINDOWS_64_BINARY_PATH = "monkey-windows-64.exe"
@ -36,6 +32,6 @@ $UPX_FOLDER = "upx-3.96-win64"
$MONGODB_URL = "https://downloads.mongodb.org/win32/mongodb-win32-x86_64-2012plus-v4.2-latest.zip"
$OPEN_SSL_URL = "https://indy.fulgan.com/SSL/openssl-1.0.2u-x64_86-win64.zip"
$CPP_URL = "https://go.microsoft.com/fwlink/?LinkId=746572"
$NPM_URL = "https://nodejs.org/dist/v12.14.1/node-v12.14.1-x64.msi"
$NPM_URL = "https://nodejs.org/dist/v16.14.2/node-v16.14.2-x64.msi"
$UPX_URL = "https://github.com/upx/upx/releases/download/v3.96/upx-3.96-win64.zip"
$SWIMM_URL="https://github.com/swimmio/SwimmReleases/releases/download/v0.4.4-0/Swimm-Setup-0.4.4-0.exe"

View File

@ -93,7 +93,7 @@ log_message "Cloning files from git"
branch=${2:-"develop"}
log_message "Branch selected: ${branch}"
if [[ ! -d "$monkey_home/monkey" ]]; then # If not already cloned
git clone --single-branch --recurse-submodules -b "$branch" "${MONKEY_GIT_URL}" "${monkey_home}" 2>&1 || handle_error
git clone --recurse-submodules -b "$branch" "${MONKEY_GIT_URL}" "${monkey_home}" 2>&1 || handle_error
fi
# Create folders
@ -161,20 +161,15 @@ agents=${3:-true}
if [ "$agents" = true ] ; then
log_message "Downloading binaries"
if exists wget; then
wget -c -N -P ${ISLAND_BINARIES_PATH} ${LINUX_32_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${LINUX_64_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${WINDOWS_32_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${WINDOWS_64_BINARY_URL}
else
curl -o ${ISLAND_BINARIES_PATH}\monkey-linux-32 ${LINUX_32_BINARY_URL}
curl -o ${ISLAND_BINARIES_PATH}\monkey-linux-64 ${LINUX_64_BINARY_URL}
curl -o ${ISLAND_BINARIES_PATH}\monkey-windows-32.exe ${WINDOWS_32_BINARY_URL}
curl -o ${ISLAND_BINARIES_PATH}\monkey-windows-64.exe ${WINDOWS_64_BINARY_URL}
fi
fi
# Allow them to be executed
chmod a+x "$ISLAND_BINARIES_PATH/$LINUX_32_BINARY_NAME"
chmod a+x "$ISLAND_BINARIES_PATH/$LINUX_64_BINARY_NAME"
# If a user haven't installed mongo manually check if we can install it with our script
@ -197,7 +192,7 @@ chmod u+x "${ISLAND_PATH}"/linux/create_certificate.sh
# Update node
if ! exists npm; then
log_message "Installing nodejs"
node_src=https://deb.nodesource.com/setup_12.x
node_src=https://deb.nodesource.com/setup_16.x
if exists curl; then
curl -sL $node_src | sudo -E bash -
else
@ -207,8 +202,7 @@ if ! exists npm; then
fi
pushd "$ISLAND_PATH/cc/ui" || handle_error
npm install sass-loader node-sass webpack --save-dev
npm update
npm ci
log_message "Generating front end"
npm run dist

View File

@ -209,9 +209,7 @@ function Deploy-Windows([String] $monkey_home = (Get-Item -Path ".\").FullName,
"Adding binaries"
$binaries = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\cc\binaries")
New-Item -ItemType directory -path $binaries -ErrorAction SilentlyContinue
$webClient.DownloadFile($LINUX_32_BINARY_URL, (Join-Path -Path $binaries -ChildPath $LINUX_32_BINARY_PATH))
$webClient.DownloadFile($LINUX_64_BINARY_URL, (Join-Path -Path $binaries -ChildPath $LINUX_64_BINARY_PATH))
$webClient.DownloadFile($WINDOWS_32_BINARY_URL, (Join-Path -Path $binaries -ChildPath $WINDOWS_32_BINARY_PATH))
$webClient.DownloadFile($WINDOWS_64_BINARY_URL, (Join-Path -Path $binaries -ChildPath $WINDOWS_64_BINARY_PATH))
}

View File

@ -0,0 +1,161 @@
#!/bin/bash
set -e
SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
SYSTEMD_UNIT_FILENAME="infection-monkey.service"
SYSTEMD_DIR="/lib/systemd/system"
MONKEY_BIN="/opt/infection-monkey/bin"
APPIMAGE_NAME="InfectionMonkey.AppImage"
echo_help() {
echo "Installs the Infection Monkey service to run on boot."
echo ""
echo "Usage:"
echo " install-infection-monkey-service.sh --user <USERNAME> --appimage <PATH>"
echo " install-infection-monkey-service.sh --uninstall"
echo " install-infection-monkey-service.sh -h|--help"
echo ""
echo "Options:"
echo " --user User to run the service as"
echo " --appimage Path to AppImage"
echo " --uninstall Uninstall the Infection Monkey service"
}
install_service() {
move_appimage "$2"
cat > "${SCRIPT_DIR}/${SYSTEMD_UNIT_FILENAME}" << EOF
[Unit]
Description=Infection Monkey Runner
After=network.target
[Service]
User=$1
Type=simple
ExecStart="${MONKEY_BIN}/${APPIMAGE_NAME}"
[Install]
WantedBy=multi-user.target
EOF
umask 077
sudo mv "${SCRIPT_DIR}/${SYSTEMD_UNIT_FILENAME}" "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}"
sudo systemctl enable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null
echo -e "The Infection Monkey service has been installed and will start on boot.\n\
Run 'systemctl start infection-monkey' to start the service now."
}
uninstall_service() {
if [ -f "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then
sudo rm -f "${MONKEY_BIN}/${APPIMAGE_NAME}"
fi
if [ -f "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}" ] ; then
sudo systemctl stop "${SYSTEMD_UNIT_FILENAME}" 2>/dev/null
sudo systemctl disable "${SYSTEMD_UNIT_FILENAME}" &>/dev/null
sudo rm "${SYSTEMD_DIR}/${SYSTEMD_UNIT_FILENAME}"
sudo systemctl daemon-reload
fi
echo "The Infection Monkey service has been uninstalled"
}
move_appimage() {
sudo mkdir --mode=0755 -p "${MONKEY_BIN}"
if [ "$1" != "${MONKEY_BIN}/${APPIMAGE_NAME}" ] ; then
umask 022
sudo cp "$appimage_path" "${MONKEY_BIN}/${APPIMAGE_NAME}"
sudo chmod 755 "${MONKEY_BIN}/${APPIMAGE_NAME}"
fi
}
user_exists() {
id -u "$1" &>/dev/null
}
assert_parameter_supplied() {
if [ -z "$2" ] ; then
echo "Error: missing required parameter '$1'"
echo_help
exit 1
fi
}
has_sudo() {
# 0 true, 1 false
sudo -nv > /dev/null 2>&1
return $?
}
exit_if_missing_argument() {
if [ -z "$2" ] || [ "${2:0:1}" == "-" ]; then
echo "Error: Argument for parameter '$1' is missing" >&2
echo_help
exit 1
fi
}
do_uninstall=false
uname=""
appimage_path=""
while (( "$#" )); do
case "$1" in
--user)
exit_if_missing_argument "$1" "$2"
uname=$2
shift 2
;;
--appimage)
exit_if_missing_argument "$1" "$2"
appimage_path=$2
shift 2
;;
--uninstall)
do_uninstall=true
shift
;;
-h|--help)
echo_help
exit 0
;;
*)
echo "Error: Unsupported parameter $1" >&2
exit 1
;;
esac
done
if ! has_sudo; then
echo "Error: You need root permissions for some of this script operations. \
Run \`sudo -v\`, enter your password, and then re-run this script."
exit 1
fi
if $do_uninstall ; then
uninstall_service
exit 0
fi
assert_parameter_supplied "--user" "$uname"
assert_parameter_supplied "--appimage" "$appimage_path"
if ! user_exists "$uname" ; then
echo "Error: User '$uname' does not exist"
exit 1
fi
if [ ! -f "$appimage_path" ] ; then
if [ ! -f "${SCRIPT_DIR}/$appimage_path" ] ; then
echo "Error: AppImage '$appimage_path' does not exist"
exit 1
fi
appimage_path="${SCRIPT_DIR}/$appimage_path"
fi
install_service "$uname" "$appimage_path"

View File

@ -11,6 +11,7 @@ Below are some of the most common questions we receive about the Infection Monke
- [I updated to a new version of the Infection Monkey and I'm being asked to delete my existing data directory. Why?](#i-updated-to-a-new-version-of-the-infection-monkey-and-im-being-asked-to-delete-my-existing-data-directory-why)
- [How can I use an old data directory?](#how-can-i-use-an-old-data-directory)
- [How long does a single Infection Monkey agent run? Is there a time limit?](#how-long-does-a-single-infection-monkey-agent-run-is-there-a-time-limit)
- [How long does it take to stop all running Infection Monkey agents?](#how-long-does-it-take-to-stop-all-running-infection-monkey-agents)
- [Is the Infection Monkey a malware/virus?](#is-the-infection-monkey-a-malwarevirus)
- [Reset the Monkey Island password](#reset-the-monkey-island-password)
- [Should I run the Infection Monkey continuously?](#should-i-run-the-infection-monkey-continuously)
@ -59,6 +60,12 @@ ref "/reference/data_directory" >}}).
The Infection Monkey agent shuts off either when it can't find new victims or it has exceeded the quota of victims as defined in the configuration.
## How long does it take to stop all running Infection Monkey agents?
On the Infection Map page, when <b>Kill All Monkeys</b> is pressed, the agents
try to finish execution safely. This can take up to 2 minutes, but will be much
shorter on average.
## Is the Infection Monkey a malware/virus?
The Infection Monkey is not malware, but it uses similar techniques to safely
@ -189,10 +196,20 @@ It's also possible to change the default log level by editing `log_level` value
#### Infection Monkey agent logs
The Infection Monkey agent log file can be found in the following paths on machines where it was executed:
The Infection Monkey agent log file can be found in directories specified for
temporary files on the machines where it was executed. In most cases, this will
be `/tmp` on Linux and `%temp%` on Windows. The agent searches a standard list
of directories to find an appropriate place to store the log:
- Path on Linux: `/tmp/user-1563`
- Path on Windows: `%temp%\\~df1563.tmp`
1. The directory named by the `TMPDIR` environment variable.
2. The directory named by the `TEMP` environment variable.
3. The directory named by the `TMP` environment variable.
4. A platform-specific location:
- On Windows, the directories `C:\TEMP`, `C:\TMP`, `\TEMP`, and `\TMP`, in that order.
- On all other platforms, the directories `/tmp`, `/var/tmp`, and `/usr/tmp`, in that order.
5. As a last resort, the current working directory.
Infection Monkey log file name is constructed to the following pattern: `infection-monkey-agent-<TIMESTAMP>-<RANDOM_STRING>.log`
The logs contain information about the internals of the Infection Monkey agent's execution. The log will contain entries like these:
@ -216,9 +233,9 @@ The logs contain information about the internals of the Infection Monkey agent's
The Infection Monkey leaves hardly any trace on the target system. It will leave:
- Log files in the following locations:
- Path on Linux: `/tmp/user-1563`
- Path on Windows: `%temp%\\~df1563.tmp`
- Log files in [temporary directories]({{< ref "/faq/#infection-monkey-agent-logs">}}):
- Path on Linux: `/tmp/infection-monky-agent-<TIMESTAMP>-<RANDOM_STRING>.log`
- Path on Windows: `%temp%\\infection-monky-agent-<TIMESTAMP>-<RANDOM_STRING>.log`
### What's the Infection Monkey Agent's impact on system resources usage?

View File

@ -26,7 +26,7 @@ You can take a look at [our roadmap](https://github.com/guardicore/monkey/projec
The best way to find weak spots in a network is by attacking it. The [*Adding Exploits*](./adding-exploits/) page will help you add exploits.
It's important to note that the Infection Monkey must be absolutely reliable. Otherwise, no one will use it, so avoid memory corruption exploits unless they're rock solid and focus on the logical vulns such as Shellshock.
It's important to note that the Infection Monkey must be absolutely reliable. Otherwise, no one will use it, so avoid memory corruption exploits unless they're rock solid and focus on the logical vulns such as Hadoop.
### Analysis plugins 🔬

View File

@ -14,7 +14,7 @@ An exploit is a sequence of commands that takes advantage of a security vulnerab
### Do I need a new Exploit?
If all you want to do is execute a shell command, configure the required commands in the Monkey Island's post-breach action (PBA) configuration section or [add a new PBA](../adding-post-breach-actions/). If you would like the Infection Monkey agent to collect specific information, [add a new System Info Collector](../adding-system-info-collectors/).
If all you want to do is execute a shell command, configure the required commands in the Monkey Island's post-breach action (PBA) configuration section or [add a new PBA](../adding-post-breach-actions/).
However, if you have your eye on an interesting CVE that you would like the Infection Monkey to support, you must add a new exploit. Keep reading to learn how to add a new exploit.
@ -39,7 +39,7 @@ class MyNewExploiter(HostExploiter):
...
```
A good example of an exploiter class is the [`SSHExploiter`](https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/exploit/sshexec.py). The [Drupal exploiter is a recently added web RCE exploit](https://github.com/guardicore/monkey/pull/808) that is a good reference as well.
A good example of an exploiter class is the [`SSHExploiter`](https://github.com/guardicore/monkey/blob/develop/monkey/infection_monkey/exploit/sshexec.py). The [Log4Shell exploiter is a recently added web RCE exploit](https://github.com/guardicore/monkey/pull/1670) that is a good reference as well.
### Modify the Monkey Island
@ -83,7 +83,7 @@ A good example of an exploiter class is the [`SSHExploiter`](https://github.com/
"default": [
"SmbExploiter",
...
"DrupalExploiter",
"Log4ShellExploiter",
"MyNewExploiter", <=================================
],
}

View File

@ -1,101 +0,0 @@
---
title: "Adding System Info Collectors"
date: 2020-06-09T11:03:42+03:00
draft: false
tags: ["contribute"]
weight: 80
---
## What does this guide cover?
This guide will show you how to create a new _System Info Collector_ for the Infection Monkey. System Info Collectors are modules that each of the Infection Monkey agents runs that collect specific information and send it back to the Monkey Island as part of the System Info Telemetry.
### Do I need a new System Info Collector?
If all you want to do is execute a shell command, then there's no need to add a new System Info Collector - just configure the required commands in the Monkey Island's post-breach action (PBA) section! Also, if there is a relevant System Info Collector and you only need to add more information to it, simply expand the existing one. Otherwise, you must add a new System Info Collector.
## How to add a new System Info Collector
### Modify the Infection Monkey Agent
#### Framework
1. Create your new System Info Collector in the following directory: `monkey/infection_monkey/system_info/collectors` by first creating a new file with the name of your System Info 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 System Info 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 `process_list_collector.py` System Info Collector for reference. You can log during collection as well.
### Modify the Monkey Island
#### Configuration
##### Definitions
You'll need to add your Sytem Info 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": [
"HostnameCollector"
],
"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 System Info 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": [
"HostnameCollector",
"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 System Info 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`.

View File

@ -16,7 +16,7 @@ The agent (which we sometimes refer to as the Infection Monkey) is a single Pyth
In order to compile the Infection Monkey for distribution by the Monkey Island, you'll need to run the instructions listed in the [`readme.txt`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/readme.txt) on each supported environment.
This means setting up an environment with Linux 32/64-bit with Python installed and a Windows 64-bit machine with developer tools, along with 32/64-bit Python versions.
This means setting up an environment with Linux 64-bit with Python installed and a Windows 64-bit machine with developer tools, along with 64-bit Python versions.
## The Monkey Island

View File

@ -1,35 +0,0 @@
---
title: "Drupal"
date: 2020-09-01T08:42:46+03:00
draft: false
tags: ["exploit", "linux", "windows"]
---
The Drupal exploiter exploits [CVE-2019-6340](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6340)
on a vulnerable Drupal server.
### Description
Some field types do not properly sanitize data from non-form sources in certain versions
of Drupal server.
This can lead to arbitrary PHP code execution in some cases.
### Affected Versions
* Drupal 8.5.x (before 8.5.11) and Drupal 8.6.x (before 8.6.10).
One of the following conditions must hold:
* The site has the Drupal 8 core RESTful Web Services (rest) module enabled and allows PATCH
or POST requests; OR
* The site has another web services module enabled, like JSON:API in
Drupal 8, or Services or RESTful Web Services in Drupal 7.
### Notes
* The Infection Monkey exploiter implementation is based on an open-source
[Python implementation](https://gist.github.com/leonjza/d0ab053be9b06fa020b66f00358e3d88/f9f6a5bb6605745e292bee3a4079f261d891738a)
of the exploit by @leonjza.
* For the full attack to work, more than one vulnerable URL is required.

View File

@ -1,13 +0,0 @@
---
title: "ElasticGroovy"
date: 2020-07-14T08:41:40+03:00
draft: false
tags: ["exploit", "windows", "linux"]
---
### Description
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.
The logic is based on the [Metasploit module](https://github.com/rapid7/metasploit-framework/blob/12198a088132f047e0a86724bc5ebba92a73ac66/modules/exploits/multi/elasticsearch/search_groovy_script.rb).

View File

@ -1,14 +0,0 @@
---
title: "MS08 067"
date: 2020-07-14T08:42:54+03:00
draft: false
tags: ["exploit", "windows"]
---
### Description
[MS08-067](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2008/ms08-067) is a remote code execution vulnerability.
This exploiter is unsafe. It's therefore **not** enabled by default.
If an exploit attempt fails, this could also lead to a crash in Svchost.exe. If a crash in Svchost.exe occurs, the server service will be affected. This may cause a system crash due to the use of buffer overflow.

View File

@ -1,9 +0,0 @@
---
title: "Struts2"
date: 2020-07-14T08:42:30+03:00
draft: false
tags: ["exploit", "linux", "windows"]
---
### Description
This exploit, CVE-2017-5638, utilizes the Struts 2 Java web framework. The logic is based on [VEX WOO's PoC](https://www.exploit-db.com/exploits/41570).

View File

@ -1,9 +0,0 @@
---
title: "WebLogic"
date: 2020-07-14T08:42:46+03:00
draft: false
tags: ["exploit", "linux", "windows"]
---
### Description
This exploits CVE-2017-10271 and CVE-2019-2725 vulnerabilities on a vulnerable WebLogic server.

View File

@ -1,11 +0,0 @@
---
title: "ShellShock"
date: 2020-07-14T08:41:32+03:00
draft: false
tags: ["exploit", "linux"]
---
### Description
This exploit, CVE-2014-6271, is based on the [logic in NCC group's GitHub](https://github.com/nccgroup/shocker/blob/master/shocker.py).
> In GNU Bash (through 4.3), processes trailing strings after function definitions in the values of environment variables allow remote attackers to execute arbitrary code via a crafted environment. This is 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."

View File

@ -44,21 +44,4 @@ Compatibility depends on GLIBC version (2.14+)[^1]. By default, these distributi
We also provide a Dockerfile on our [website](http://infectionmonkey.com/) that lets the Monkey Island run inside a container.
### Old machine bootloader
Some **older machines** still have partial compatibility and will be exploited and reported, but the Infection Monkey agent can't run on them. In these cases, old machine bootloader (a small C program) will be run, which reports some minor info like network interface configuration, GLIBC version, OS, etc.
**Old machine bootloader** also has a GLIBC 2.14+ requirement for Linux because the bootloader is included in the Pyinstaller bootloader, which uses Python 3.7 that 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]: The GLIBC >= 2.14 requirement exists because the Infection Monkey was built using this GLIBC version, and GLIBC is not backward compatible. We are also limited to the oldest GLIBC version compatible with Python 3.7.

View File

@ -29,14 +29,13 @@ The currently implemented Fingerprint modules are:
2. [`SSHFinger`][ssh-finger] - Fingerprints target machines over SSH (port 22) and extracts the computer version and SSH banner.
3. [`PingScanner`][ping-scanner] - Fingerprints target machine's TTL to differentiate between Linux and Windows hosts.
4. [`HTTPFinger`][http-finger] - Detects HTTP/HTTPS services, using the ports listed in `HTTP_PORTS` in the configuration, will return the server type and if it supports SSL.
5. [`MySQLFinger`][mysql-finger] - Fingerprints MySQL (port 3306) and will extract MySQL banner info - version, major/minor/build and capabilities.
6. [`ElasticFinger`][elastic-finger] - Fingerprints ElasticSearch (port 9200) will extract the cluster name, node name and node version.
5. [`ElasticFinger`][elastic-finger] - Fingerprints ElasticSearch (port 9200) and will extract 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 imported under [`network/__init__.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/network/__init__.py).
To use the new scanner/fingerprinter 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.
To use the new scanner/fingerprinter by default, modify [`infection_monkey/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/config.py) to add references to the new class.
At this point, the Infection 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).
@ -44,7 +43,6 @@ At this point, the Infection Monkey knows how to use the new scanner/fingerprint
[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

View File

@ -52,7 +52,7 @@ You can configure the server by creating
a [server configuration file](../../reference/server_configuration) and
providing a path to it via command line parameters:
`./InfectionMonkey-v1.12.0.AppImage --server-config="/path/to/server_config.json"`
`./InfectionMonkey-v1.13.0.AppImage --server-config="/path/to/server_config.json"`
### Start Monkey Island with user-provided certificate
@ -88,7 +88,7 @@ The server configuration file should look something like:
1. Start Monkey Island by running the Infection Monkey AppImage package:
```bash
./InfectionMonkey-v1.12.0.AppImage --server-config="/path/to/server_config.json"
./InfectionMonkey-v1.13.0.AppImage --server-config="/path/to/server_config.json"
```
1. Access the Monkey Island web UI by pointing your browser at
@ -109,7 +109,7 @@ The server configuration file should look something like:
1. Start Monkey Island by running the Infection Monkey AppImage package:
```bash
./InfectionMonkey-v1.12.0.AppImage --server-config="/path/to/server_config.json"
./InfectionMonkey-v1.13.0.AppImage --server-config="/path/to/server_config.json"
```
1. Access the Monkey Island web UI by pointing your browser at

View File

@ -35,6 +35,19 @@ $ sha256sum monkey-linux-64
## Latest version checksums
| Filename | Type | Version | SHA256 |
|------------------------------------------------------|-------------------|---------|--------------------------------------------------------------------|
| monkey-windows-64.exe | Windows Agent | 1.13.0 | `3EDD20DE2247047C8A822C84145981936CE2FD0BDF843EB5CA777CA4D2478B35` |
| monkey-windows-32.exe | Windows Agent | 1.13.0 | `7497907E3CF4FFEB121A7795BFA16709800E6E0F99770F64AF7FFF684ECBA6D6` |
| monkey-linux-64 | Linux Agent | 1.13.0 | `F21E709CB7BA8DAF90B908AF5FE485BA43866C325D3C7CE1EB07E8A2323E07C1` |
| monkey-linux-32 | Linux Agent | 1.13.0 | `24C5779825F26C76A8910794836647096F4BB4B47CFD6AD213CC48116D140FAB` |
| InfectionMonkey-v1.13.0.AppImage | Linux Package | 1.13.0 | `CDED4E8394A4D2A809BA9B74B924AEA590317515B9B032BA8005A93DFCE1C861` |
| InfectionMonkey-docker-v1.13.0.tgz | Docker | 1.13.0 | `342701BA8EC5B754C59685896FC3DCDBB93362FFFAD0EC7F9E2E5B99DA26F5EC` |
| InfectionMonkey-v1.13.0.exe | Windows Installer | 1.13.0 | `D35ED6CAF21AC786D9A438510282FA07AEF812590A5E6405A01F2B06661B33B9` |
## Older checksums
| Filename | Type | Version | SHA256 |
|------------------------------------------------------|-------------------|---------|--------------------------------------------------------------------|
| monkey-windows-64.exe | Windows Agent | 1.12.0 | `02e5e051a96e2ca61ae8e661b3a5828ee53a0fc00aca6502d5c73a46754f0d07` |
@ -44,12 +57,6 @@ $ sha256sum monkey-linux-64
| InfectionMonkey-v1.12.0.AppImage | Linux Package | 1.12.0 | `1325f2aa1d0c27aec2e2f9864ed53c53c524bd208313f87ea6606f59c90ff310` |
| InfectionMonkey-docker-v1.12.0.tgz | Docker | 1.12.0 | `dcaf669411d55ea6883920597af4a35f3735a286801e08b6ef047cc91ff32769` |
| InfectionMonkey-v1.12.0.exe | Windows Installer | 1.12.0 | `4d6e0373be3615a4b97721a07d2a854f6316d1ce8c4ff6d6495aac3a8f2c6a69` |
## Older checksums
| Filename | Type | Version | SHA256 |
|------------------------------------------------------|-------------------|---------|--------------------------------------------------------------------|
| monkey-windows-64.exe | Windows Agent | 1.11.0 | `12c55377381a8fc7d8ff731db52302ef2f8bb894d8712769e5a91a140ba22b0a` |
| monkey-windows-32.exe | Windows Agent | 1.11.0 | `e006b26663f59b92bad8d49b034cd8101dd481f881e3c4839a9c1e64fd99e849` |
| monkey-linux-64 | Linux Agent | 1.11.0 | `fb4c979ce6c29bb458be50a44cc6839650826b831da849da69a05dfefdc66462` |

View File

@ -7,6 +7,9 @@ pre: "<i class='fas fa-play-circle'></i> "
tags: ["usage"]
---
<!-- TODO: Update screenshots -->
If you haven't deployed the Monkey Island yet, please [refer to our setup documentation](/setup).
## Using the Infection Monkey

View File

@ -1,67 +0,0 @@
---
title: "Scoutsuite"
date: 2021-03-02T16:23:06+02:00
draft: false
description: "Scout Suite is an open-source cloud security-auditing tool."
weight: 10
---
### About ScoutSuite
<a href="https://github.com/nccgroup/ScoutSuite" target="_blank" >Scout Suite</a> is an open-source cloud security-auditing tool.
It queries the cloud API to gather configuration data. Based on configuration
data gathered, ScoutSuite shows security issues and risks present in your infrastructure.
### Supported cloud providers
Currently, ScoutSuite integration only supports AWS environments.
### Enabling ScoutSuite
First, Infection Monkey needs access to your cloud API. You can provide access
in the following ways:
- Provide access keys:
- Create a new user with ReadOnlyAccess and SecurityAudit policies and generate keys
- Generate keys for your current user (faster but less secure)
- Configure AWS CLI:
- If the command-line interface is available on the Island, it will be used to access
the cloud API
More details about configuring ScoutSuite can be found in the tool itself, by choosing
"Cloud Security Scan" in the "Run Monkey" options.
![Cloud scan option in run page](/images/usage/integrations/scoutsuite_run_page.png
"Successful setup indicator")
After you're done with the setup, make sure that a checkmark appears next to the AWS option. This
verifies that ScoutSuite can access the API.
![Successfull setup indicator](/images/usage/integrations/scoutsuite_aws_configured.png
"Successful setup indicator")
### Running a cloud security scan
If you have successfully configured the cloud scan, Infection Monkey will scan
your cloud infrastructure when the Monkey Agent is run **on the Island**. You
can simply click on "From Island" in the run options to start the scan. The
scope of the network scan and other activities you may have configured the Agent
to perform are ignored by the ScoutSuite integration, except **Monkey
Configuration -> System info collectors -> AWS collector**, which needs to
remain **enabled**.
### Assessing scan results
After the scan is done, ScoutSuite results will be categorized according to the
ZeroTrust Extended framework and displayed as a part of the ZeroTrust report.
The main difference between Infection Monkey findings and ScoutSuite findings
is that ScoutSuite findings contain security rules. To see which rules were
checked, click on the "Rules" button next to the relevant test. You'll see a
list of rule dropdowns that are color coded according to their status. Expand a
rule to see its description, remediation and more details about resources
flagged. Each flagged resource has a path so you can easily locate it in the
cloud and remediate the issue.
![Open ScoutSuite rule](/images/usage/integrations/scoutsuite_report_rule.png
"Successful setup indicator")

View File

@ -11,8 +11,6 @@ weight: 1
Want to assess your progress in achieving a Zero Trust network? The Infection Monkey can automatically evaluate your readiness across the different
[Zero Trust Extended Framework](https://www.forrester.com/report/The+Zero+Trust+eXtended+ZTX+Ecosystem/-/E-RES137210) principles.
You can additionally scan your cloud infrastructure's compliance to ZeroTrust principles using [ScoutSuite integration.]({{< ref "/usage/integrations/scoutsuite" >}})
## Configuration
- **Exploits -> Credentials** This configuration value will be used for brute-forcing. The Infection Monkey uses the most popular default passwords and usernames, but feel free to adjust it according to the default passwords common in your network. Keep in mind a longer list means longer scanning times.

View File

@ -8,7 +8,7 @@ class BaseTemplate(ConfigTemplate):
"basic.exploiters.exploiter_classes": [],
"basic_network.scope.local_network_scan": False,
"basic_network.scope.depth": 1,
"internal.classes.finger_classes": ["PingScanner", "HTTPFinger"],
"internal.classes.finger_classes": ["HTTPFinger"],
"internal.monkey.system_info.system_info_collector_classes": [],
"monkey.post_breach.post_breach_actions": [],
"internal.general.keep_tunnel_open_time": 0,

View File

@ -1,18 +0,0 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Drupal(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
config_values.update(
{
"internal.classes.finger_classes": ["PingScanner", "HTTPFinger"],
"basic.exploiters.exploiter_classes": ["DrupalExploiter"],
"basic_network.scope.subnet_scan_list": ["10.2.2.28"],
"internal.network.tcp_scanner.HTTP_PORTS": [80],
"internal.network.tcp_scanner.tcp_target_ports": [],
}
)

View File

@ -1,20 +0,0 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Elastic(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
config_values.update(
{
"basic.exploiters.exploiter_classes": ["ElasticGroovyExploiter"],
"internal.classes.finger_classes": ["PingScanner", "HTTPFinger", "ElasticFinger"],
"basic_network.scope.subnet_scan_list": ["10.2.2.4", "10.2.2.5"],
"basic_network.scope.depth": 1,
"internal.network.tcp_scanner.HTTP_PORTS": [9200],
"internal.network.tcp_scanner.tcp_target_ports": [],
}
)

View File

@ -0,0 +1,42 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Depth1A(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
# Tests:
# Hadoop (10.2.2.2, 10.2.2.3)
# Log4shell (10.2.3.55, 10.2.3.56, 10.2.3.49, 10.2.3.50, 10.2.3.51, 10.2.3.52)
# MSSQL (10.2.2.16)
# SMB mimikatz password stealing and brute force (10.2.2.14 and 10.2.2.15)
config_values.update(
{
"basic.exploiters.exploiter_classes": [
"HadoopExploiter",
"Log4ShellExploiter",
"MSSQLExploiter",
"SmbExploiter",
"SSHExploiter",
],
"basic_network.scope.subnet_scan_list": [
"10.2.2.2",
"10.2.2.3",
"10.2.3.55",
"10.2.3.56",
"10.2.3.49",
"10.2.3.50",
"10.2.3.51",
"10.2.3.52",
"10.2.2.16",
"10.2.2.14",
"10.2.2.15",
],
"basic.credentials.exploit_password_list": ["Ivrrw5zEzs", "Xk8VDTsC"],
"basic.credentials.exploit_user_list": ["m0nk3y"],
"monkey.system_info.system_info_collector_classes": [
"MimikatzCollector",
],
}
)

View File

@ -0,0 +1,23 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Depth2A(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
# SSH password and key brute-force, key stealing (10.2.2.11, 10.2.2.12)
config_values.update(
{
"basic.exploiters.exploiter_classes": [
"SSHExploiter",
],
"basic_network.scope.subnet_scan_list": [
"10.2.2.11",
"10.2.2.12",
],
"basic_network.scope.depth": 2,
"basic.credentials.exploit_password_list": ["^NgDvY59~8"],
"basic.credentials.exploit_user_list": ["m0nk3y"],
}
)

View File

@ -0,0 +1,48 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Depth3A(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
# Tests:
# Powershell (10.2.3.45, 10.2.3.46, 10.2.3.47, 10.2.3.48)
# Tunneling (SSH brute force) (10.2.2.9, 10.2.1.10, 10.2.0.12, 10.2.0.11)
# WMI pass the hash (10.2.2.15)
config_values.update(
{
"basic.exploiters.exploiter_classes": [
"PowerShellExploiter",
"SSHExploiter",
"WmiExploiter",
],
"basic_network.scope.subnet_scan_list": [
"10.2.3.45",
"10.2.3.46",
"10.2.3.47",
"10.2.3.48",
"10.2.2.9",
"10.2.1.10",
"10.2.0.12",
"10.2.0.11",
"10.2.2.15",
],
"basic.credentials.exploit_password_list": [
"Passw0rd!",
"3Q=(Ge(+&w]*",
"`))jU7L(w}",
"t67TC5ZDmz",
],
"basic_network.scope.depth": 3,
"internal.general.keep_tunnel_open_time": 20,
"basic.credentials.exploit_user_list": ["m0nk3y", "m0nk3y-user"],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.exploits.exploit_ntlm_hash_list": [
"d0f0132b308a0c4e5d1029cc06f48692",
"5da0889ea2081aa79f6852294cba4a5e",
"50c9987a6bf1ac59398df9f911122c9b",
],
}
)

View File

@ -1,17 +0,0 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class ShellShock(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
config_values.update(
{
"basic.exploiters.exploiter_classes": ["ShellShockExploiter"],
"basic_network.scope.subnet_scan_list": ["10.2.2.8"],
"internal.network.tcp_scanner.HTTP_PORTS": [80, 8080],
"internal.network.tcp_scanner.tcp_target_ports": [],
}
)

View File

@ -10,7 +10,7 @@ class Mssql(ConfigTemplate):
config_values.update(
{
"basic.exploiters.exploiter_classes": ["MSSQLExploiter"],
"internal.classes.finger_classes": ["PingScanner"],
"internal.classes.finger_classes": [],
"basic_network.scope.subnet_scan_list": ["10.2.2.16"],
"basic.credentials.exploit_password_list": [
"Password1!",

View File

@ -16,10 +16,6 @@ class Performance(ConfigTemplate):
"SmbExploiter",
"WmiExploiter",
"SSHExploiter",
"ShellShockExploiter",
"ElasticGroovyExploiter",
"Struts2Exploiter",
"WebLogicExploiter",
"HadoopExploiter",
"MSSQLExploiter",
"PowerShellExploiter",
@ -29,8 +25,6 @@ class Performance(ConfigTemplate):
"basic_network.network_analysis.inaccessible_subnets": [
"10.2.2.0/30",
"10.2.2.8/30",
"10.2.2.24/32",
"10.2.2.23/32",
"10.2.2.21/32",
"10.2.2.19/32",
"10.2.2.18/32",
@ -55,8 +49,6 @@ class Performance(ConfigTemplate):
"10.2.2.19",
"10.2.2.20",
"10.2.2.21",
"10.2.2.23",
"10.2.2.24",
"10.2.2.25",
"10.2.3.55",
"10.2.3.56",

View File

@ -19,9 +19,9 @@ class PowerShell(ConfigTemplate):
"basic.credentials.exploit_password_list": ["Passw0rd!"],
"basic_network.scope.depth": 2,
"basic.credentials.exploit_user_list": ["m0nk3y", "m0nk3y-user"],
"internal.classes.finger_classes": ["PingScanner"],
"internal.classes.finger_classes": [],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [],
"internal.network.tcp_scanner.tcp_target_ports": [5985, 5986],
"internal.exploits.exploit_ntlm_hash_list": [
"d0f0132b308a0c4e5d1029cc06f48692",
],

View File

@ -14,8 +14,8 @@ class PowerShellCredentialsReuse(ConfigTemplate):
"10.2.3.46",
],
"basic_network.scope.depth": 2,
"internal.classes.finger_classes": ["PingScanner"],
"internal.classes.finger_classes": [],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [],
"internal.network.tcp_scanner.tcp_target_ports": [5985, 5986],
}
)

View File

@ -13,11 +13,10 @@ class SmbMimikatz(ConfigTemplate):
"basic_network.scope.subnet_scan_list": ["10.2.2.14", "10.2.2.15"],
"basic.credentials.exploit_password_list": ["Password1!", "Ivrrw5zEzs"],
"basic.credentials.exploit_user_list": ["Administrator", "m0nk3y", "user"],
"internal.classes.finger_classes": ["SMBFinger", "PingScanner", "HTTPFinger"],
"internal.classes.finger_classes": ["SMBFinger", "HTTPFinger"],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [445],
"monkey.system_info.system_info_collector_classes": [
"ProcessListCollector",
"MimikatzCollector",
],
}

View File

@ -13,7 +13,7 @@ class SmbPth(ConfigTemplate):
"basic_network.scope.subnet_scan_list": ["10.2.2.15"],
"basic.credentials.exploit_password_list": ["Password1!", "Ivrrw5zEzs"],
"basic.credentials.exploit_user_list": ["Administrator", "m0nk3y", "user"],
"internal.classes.finger_classes": ["SMBFinger", "PingScanner", "HTTPFinger"],
"internal.classes.finger_classes": ["SMBFinger", "HTTPFinger"],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [445],
"internal.classes.exploits.exploit_ntlm_hash_list": [

View File

@ -14,7 +14,7 @@ class Ssh(ConfigTemplate):
"basic.credentials.exploit_password_list": ["Password1!", "12345678", "^NgDvY59~8"],
"basic_network.scope.depth": 2,
"basic.credentials.exploit_user_list": ["Administrator", "m0nk3y", "user"],
"internal.classes.finger_classes": ["SSHFinger", "PingScanner"],
"internal.classes.finger_classes": ["SSHFinger"],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [22],
}

View File

@ -17,7 +17,7 @@ class Tunneling(ConfigTemplate):
"10.2.0.11",
],
"basic_network.scope.depth": 3,
"internal.general.keep_tunnel_open_time": 150,
"internal.general.keep_tunnel_open_time": 20,
"basic.credentials.exploit_password_list": [
"Password1!",
"3Q=(Ge(+&w]*",
@ -28,7 +28,6 @@ class Tunneling(ConfigTemplate):
"basic.credentials.exploit_user_list": ["Administrator", "m0nk3y", "user"],
"internal.classes.finger_classes": [
"SSHFinger",
"PingScanner",
"HTTPFinger",
"SMBFinger",
],

View File

@ -16,7 +16,6 @@ class WmiMimikatz(ConfigTemplate):
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [135],
"monkey.system_info.system_info_collector_classes": [
"ProcessListCollector",
"MimikatzCollector",
],
}

View File

@ -13,7 +13,7 @@ class WmiPth(ConfigTemplate):
"basic_network.scope.subnet_scan_list": ["10.2.2.15"],
"basic.credentials.exploit_password_list": ["Password1!"],
"basic.credentials.exploit_user_list": ["Administrator", "m0nk3y", "user"],
"internal.classes.finger_classes": ["PingScanner", "HTTPFinger"],
"internal.classes.finger_classes": ["HTTPFinger"],
"internal.network.tcp_scanner.HTTP_PORTS": [],
"internal.network.tcp_scanner.tcp_target_ports": [135],
"internal.exploits.exploit_ntlm_hash_list": [

View File

@ -1,19 +0,0 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Struts2(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
config_values.update(
{
"basic.exploiters.exploiter_classes": ["Struts2Exploiter"],
"basic_network.scope.depth": 2,
"basic_network.scope.subnet_scan_list": ["10.2.2.23", "10.2.2.24"],
"internal.network.tcp_scanner.HTTP_PORTS": [80, 8080],
"internal.network.tcp_scanner.tcp_target_ports": [80, 8080],
}
)

View File

@ -1,18 +0,0 @@
from copy import copy
from envs.monkey_zoo.blackbox.config_templates.base_template import BaseTemplate
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
class Weblogic(ConfigTemplate):
config_values = copy(BaseTemplate.config_values)
config_values.update(
{
"basic.exploiters.exploiter_classes": ["WebLogicExploiter"],
"basic_network.scope.subnet_scan_list": ["10.2.2.18", "10.2.2.19"],
"internal.network.tcp_scanner.HTTP_PORTS": [7001],
"internal.network.tcp_scanner.tcp_target_ports": [],
}
)

View File

@ -2,24 +2,16 @@ GCP_TEST_MACHINE_LIST = {
"europe-west3-a": [
"sshkeys-11",
"sshkeys-12",
"elastic-4",
"elastic-5",
"hadoop-2",
"hadoop-3",
"mssql-16",
"mimikatz-14",
"mimikatz-15",
"struts2-23",
"struts2-24",
"tunneling-9",
"tunneling-10",
"tunneling-11",
"tunneling-12",
"weblogic-18",
"weblogic-19",
"shellshock-8",
"zerologon-25",
"drupal-28",
],
"europe-west1-b": [
"powershell-3-45",

View File

@ -1,6 +1,6 @@
import json
import logging
from time import sleep
import time
from typing import Union
from bson import json_util
@ -15,7 +15,7 @@ LOGGER = logging.getLogger(__name__)
def avoid_race_condition(func):
sleep(SLEEP_BETWEEN_REQUESTS_SECONDS)
time.sleep(SLEEP_BETWEEN_REQUESTS_SECONDS)
return func
@ -48,10 +48,15 @@ class MonkeyIslandClient(object):
@avoid_race_condition
def kill_all_monkeys(self):
if self.requests.get("api", {"action": "killall"}).ok:
response = self.requests.post_json(
"api/monkey_control/stop-all-agents", data={"kill_time": time.time()}
)
if response.ok:
LOGGER.info("Killing all monkeys after the test.")
else:
LOGGER.error("Failed to kill all monkeys.")
LOGGER.error(response.status_code)
LOGGER.error(response.content)
assert False
@avoid_race_condition

View File

@ -8,44 +8,20 @@ from typing_extensions import Type
from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer
from envs.monkey_zoo.blackbox.analyzers.zerologon_analyzer import ZerologonAnalyzer
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
from envs.monkey_zoo.blackbox.config_templates.drupal import Drupal
from envs.monkey_zoo.blackbox.config_templates.elastic import Elastic
from envs.monkey_zoo.blackbox.config_templates.hadoop import Hadoop
from envs.monkey_zoo.blackbox.config_templates.log4j_logstash import Log4jLogstash
from envs.monkey_zoo.blackbox.config_templates.log4j_solr import Log4jSolr
from envs.monkey_zoo.blackbox.config_templates.log4j_tomcat import Log4jTomcat
from envs.monkey_zoo.blackbox.config_templates.mssql import Mssql
from envs.monkey_zoo.blackbox.config_templates.performance import Performance
from envs.monkey_zoo.blackbox.config_templates.powershell import PowerShell
from envs.monkey_zoo.blackbox.config_templates.powershell_credentials_reuse import (
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_1_a import Depth1A
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_2_a import Depth2A
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_3_a import Depth3A
from envs.monkey_zoo.blackbox.config_templates.single_tests.powershell_credentials_reuse import (
PowerShellCredentialsReuse,
)
from envs.monkey_zoo.blackbox.config_templates.shellshock import ShellShock
from envs.monkey_zoo.blackbox.config_templates.smb_mimikatz import SmbMimikatz
from envs.monkey_zoo.blackbox.config_templates.smb_pth import SmbPth
from envs.monkey_zoo.blackbox.config_templates.ssh import Ssh
from envs.monkey_zoo.blackbox.config_templates.struts2 import Struts2
from envs.monkey_zoo.blackbox.config_templates.tunneling import Tunneling
from envs.monkey_zoo.blackbox.config_templates.weblogic import Weblogic
from envs.monkey_zoo.blackbox.config_templates.wmi_mimikatz import WmiMimikatz
from envs.monkey_zoo.blackbox.config_templates.wmi_pth import WmiPth
from envs.monkey_zoo.blackbox.config_templates.zerologon import Zerologon
from envs.monkey_zoo.blackbox.config_templates.single_tests.smb_pth import SmbPth
from envs.monkey_zoo.blackbox.config_templates.single_tests.wmi_mimikatz import WmiMimikatz
from envs.monkey_zoo.blackbox.config_templates.single_tests.zerologon import Zerologon
from envs.monkey_zoo.blackbox.gcp_test_machine_list import GCP_TEST_MACHINE_LIST
from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser
from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
from envs.monkey_zoo.blackbox.tests.exploitation import ExploitationTest
from envs.monkey_zoo.blackbox.tests.performance.map_generation import MapGenerationTest
from envs.monkey_zoo.blackbox.tests.performance.map_generation_from_telemetries import (
MapGenerationFromTelemetryTest,
)
from envs.monkey_zoo.blackbox.tests.performance.report_generation import ReportGenerationTest
from envs.monkey_zoo.blackbox.tests.performance.report_generation_from_telemetries import (
ReportGenerationFromTelemetryTest,
)
from envs.monkey_zoo.blackbox.tests.performance.telemetry_performance_test import (
TelemetryPerformanceTest,
)
from envs.monkey_zoo.blackbox.utils.gcp_machine_handlers import (
initialize_gcp_client,
start_machines,
@ -53,7 +29,7 @@ from envs.monkey_zoo.blackbox.utils.gcp_machine_handlers import (
)
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
DEFAULT_TIMEOUT_SECONDS = 5 * 60
DEFAULT_TIMEOUT_SECONDS = 2 * 60 + 30
MACHINE_BOOTUP_WAIT_SECONDS = 30
LOG_DIR_PATH = "./logs"
logging.basicConfig(level=logging.INFO)
@ -130,48 +106,20 @@ class TestMonkeyBlackbox:
log_handler=log_handler,
).run()
@staticmethod
def run_performance_test(
performance_test_class,
island_client,
config_template,
timeout_in_seconds,
break_on_timeout=False,
):
raw_config = IslandConfigParser.get_raw_config(config_template, island_client)
log_handler = TestLogsHandler(
performance_test_class.TEST_NAME, island_client, TestMonkeyBlackbox.get_log_dir_path()
)
analyzers = [
CommunicationAnalyzer(island_client, IslandConfigParser.get_ips_of_targets(raw_config))
]
performance_test_class(
island_client=island_client,
raw_config=raw_config,
analyzers=analyzers,
timeout=timeout_in_seconds,
log_handler=log_handler,
break_on_timeout=break_on_timeout,
).run()
@staticmethod
def get_log_dir_path():
return os.path.abspath(LOG_DIR_PATH)
def test_ssh_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Ssh, "SSH_exploiter_and_keys")
def test_depth_1_a(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Depth1A, "Depth1A test suite")
def test_hadoop_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Hadoop, "Hadoop_exploiter", 6 * 60)
def test_depth_2_a(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Depth2A, "Depth2A test suite")
def test_mssql_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Mssql, "MSSQL_exploiter")
def test_powershell_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, PowerShell, "PowerShell_Remoting_exploiter"
)
def test_depth_3_a(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Depth3A, "Depth3A test suite")
# Not grouped because can only be ran on windows
@pytest.mark.skip_powershell_reuse
def test_powershell_exploiter_credentials_reuse(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
@ -180,57 +128,7 @@ class TestMonkeyBlackbox:
"PowerShell_Remoting_exploiter_credentials_reuse",
)
def test_smb_and_mimikatz_exploiters(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, SmbMimikatz, "SMB_exploiter_mimikatz"
)
def test_smb_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, SmbPth, "SMB_PTH")
def test_drupal_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Drupal, "Drupal_exploiter")
def test_elastic_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Elastic, "Elastic_exploiter")
def test_struts_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Struts2, "Struts2_exploiter")
def test_weblogic_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Weblogic, "Weblogic_exploiter")
def test_shellshock_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, ShellShock, "Shellshock_exploiter")
def test_log4j_solr_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jSolr, "Log4Shell_Solr_exploiter"
)
def test_log4j_tomcat_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jTomcat, "Log4Shell_tomcat_exploiter"
)
def test_log4j_logstash_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jLogstash, "Log4Shell_logstash_exploiter"
)
def test_tunneling(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Tunneling, "Tunneling_exploiter", 15 * 60
)
def test_wmi_and_mimikatz_exploiters(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, WmiMimikatz, "WMI_exploiter,_mimikatz"
)
def test_wmi_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, WmiPth, "WMI_PTH")
# Not grouped because it's slow
def test_zerologon_exploiter(self, island_client):
test_name = "Zerologon_exploiter"
expected_creds = [
@ -255,47 +153,13 @@ class TestMonkeyBlackbox:
log_handler=log_handler,
).run()
@pytest.mark.skip(
reason="Perfomance test that creates env from fake telemetries is faster, use that instead."
)
def test_report_generation_performance(self, island_client, quick_performance_tests):
"""
This test includes the SSH + Elastic + Hadoop + MSSQL machines all in one test
for a total of 8 machines including the Monkey Island.
# Not grouped because conflicts with SMB.
# Consider grouping when more depth 1 exploiters collide with group depth_1_a
def test_wmi_and_mimikatz_exploiters(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, WmiMimikatz, "WMI_exploiter,_mimikatz"
)
Is has 2 analyzers - the regular one which checks all the Monkeys
and the Timing one which checks how long the report took to execute
"""
if not quick_performance_tests:
TestMonkeyBlackbox.run_performance_test(
ReportGenerationTest, island_client, Performance, timeout_in_seconds=10 * 60
)
else:
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
assert False
@pytest.mark.skip(
reason="Perfomance test that creates env from fake telemetries is faster, use that instead."
)
def test_map_generation_performance(self, island_client, quick_performance_tests):
if not quick_performance_tests:
TestMonkeyBlackbox.run_performance_test(
MapGenerationTest, island_client, "PERFORMANCE.conf", timeout_in_seconds=10 * 60
)
else:
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
assert False
@pytest.mark.run_performance_tests
def test_report_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
ReportGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
@pytest.mark.run_performance_tests
def test_map_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
MapGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
@pytest.mark.run_performance_tests
def test_telem_performance(self, island_client, quick_performance_tests):
TelemetryPerformanceTest(
island_client, quick_performance_tests
).test_telemetry_performance()
# Not grouped because it's depth 1 but conflicts with SMB exploiter in group depth_1_a
def test_smb_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, SmbPth, "SMB_PTH")

View File

@ -0,0 +1,296 @@
import logging
import os
from time import sleep
import pytest
from typing_extensions import Type
from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer
from envs.monkey_zoo.blackbox.analyzers.zerologon_analyzer import ZerologonAnalyzer
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
from envs.monkey_zoo.blackbox.config_templates.single_tests.drupal import Drupal
from envs.monkey_zoo.blackbox.config_templates.single_tests.hadoop import Hadoop
from envs.monkey_zoo.blackbox.config_templates.single_tests.log4j_logstash import Log4jLogstash
from envs.monkey_zoo.blackbox.config_templates.single_tests.log4j_solr import Log4jSolr
from envs.monkey_zoo.blackbox.config_templates.single_tests.log4j_tomcat import Log4jTomcat
from envs.monkey_zoo.blackbox.config_templates.single_tests.mssql import Mssql
from envs.monkey_zoo.blackbox.config_templates.single_tests.performance import Performance
from envs.monkey_zoo.blackbox.config_templates.single_tests.powershell import PowerShell
from envs.monkey_zoo.blackbox.config_templates.single_tests.powershell_credentials_reuse import (
PowerShellCredentialsReuse,
)
from envs.monkey_zoo.blackbox.config_templates.single_tests.smb_mimikatz import SmbMimikatz
from envs.monkey_zoo.blackbox.config_templates.single_tests.smb_pth import SmbPth
from envs.monkey_zoo.blackbox.config_templates.single_tests.ssh import Ssh
from envs.monkey_zoo.blackbox.config_templates.single_tests.struts2 import Struts2
from envs.monkey_zoo.blackbox.config_templates.single_tests.tunneling import Tunneling
from envs.monkey_zoo.blackbox.config_templates.single_tests.weblogic import Weblogic
from envs.monkey_zoo.blackbox.config_templates.single_tests.wmi_mimikatz import WmiMimikatz
from envs.monkey_zoo.blackbox.config_templates.single_tests.wmi_pth import WmiPth
from envs.monkey_zoo.blackbox.config_templates.single_tests.zerologon import Zerologon
from envs.monkey_zoo.blackbox.gcp_test_machine_list import GCP_TEST_MACHINE_LIST
from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser
from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
from envs.monkey_zoo.blackbox.tests.exploitation import ExploitationTest
from envs.monkey_zoo.blackbox.tests.performance.map_generation import MapGenerationTest
from envs.monkey_zoo.blackbox.tests.performance.map_generation_from_telemetries import (
MapGenerationFromTelemetryTest,
)
from envs.monkey_zoo.blackbox.tests.performance.report_generation import ReportGenerationTest
from envs.monkey_zoo.blackbox.tests.performance.report_generation_from_telemetries import (
ReportGenerationFromTelemetryTest,
)
from envs.monkey_zoo.blackbox.tests.performance.telemetry_performance_test import (
TelemetryPerformanceTest,
)
from envs.monkey_zoo.blackbox.utils.gcp_machine_handlers import (
initialize_gcp_client,
start_machines,
stop_machines,
)
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
DEFAULT_TIMEOUT_SECONDS = 2 * 60
MACHINE_BOOTUP_WAIT_SECONDS = 30
LOG_DIR_PATH = "./logs"
logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger(__name__)
@pytest.fixture(autouse=True, scope="session")
def GCPHandler(request, no_gcp):
if not no_gcp:
try:
initialize_gcp_client()
start_machines(GCP_TEST_MACHINE_LIST)
except Exception as e:
LOGGER.error("GCP Handler failed to initialize: %s." % e)
pytest.exit("Encountered an error while starting GCP machines. Stopping the tests.")
wait_machine_bootup()
def fin():
stop_machines(GCP_TEST_MACHINE_LIST)
request.addfinalizer(fin)
@pytest.fixture(autouse=True, scope="session")
def delete_logs():
LOGGER.info("Deleting monkey logs before new tests.")
TestLogsHandler.delete_log_folder_contents(TestMonkeyBlackbox.get_log_dir_path())
def wait_machine_bootup():
sleep(MACHINE_BOOTUP_WAIT_SECONDS)
@pytest.fixture(scope="class")
def island_client(island, quick_performance_tests):
client_established = False
try:
island_client_object = MonkeyIslandClient(island)
client_established = island_client_object.get_api_status()
except Exception:
logging.exception("Got an exception while trying to establish connection to the Island.")
finally:
if not client_established:
pytest.exit("BB tests couldn't establish communication to the island.")
if not quick_performance_tests:
island_client_object.reset_env()
island_client_object.set_scenario(IslandModeEnum.ADVANCED.value)
yield island_client_object
@pytest.mark.usefixtures("island_client")
# noinspection PyUnresolvedReferences
class TestMonkeyBlackbox:
@staticmethod
def run_exploitation_test(
island_client: MonkeyIslandClient,
config_template: Type[ConfigTemplate],
test_name: str,
timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS,
):
raw_config = IslandConfigParser.get_raw_config(config_template, island_client)
analyzer = CommunicationAnalyzer(
island_client, IslandConfigParser.get_ips_of_targets(raw_config)
)
log_handler = TestLogsHandler(
test_name, island_client, TestMonkeyBlackbox.get_log_dir_path()
)
ExploitationTest(
name=test_name,
island_client=island_client,
raw_config=raw_config,
analyzers=[analyzer],
timeout=timeout_in_seconds,
log_handler=log_handler,
).run()
@staticmethod
def run_performance_test(
performance_test_class,
island_client,
config_template,
timeout_in_seconds,
break_on_timeout=False,
):
raw_config = IslandConfigParser.get_raw_config(config_template, island_client)
log_handler = TestLogsHandler(
performance_test_class.TEST_NAME, island_client, TestMonkeyBlackbox.get_log_dir_path()
)
analyzers = [
CommunicationAnalyzer(island_client, IslandConfigParser.get_ips_of_targets(raw_config))
]
performance_test_class(
island_client=island_client,
raw_config=raw_config,
analyzers=analyzers,
timeout=timeout_in_seconds,
log_handler=log_handler,
break_on_timeout=break_on_timeout,
).run()
@staticmethod
def get_log_dir_path():
return os.path.abspath(LOG_DIR_PATH)
def test_ssh_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Ssh, "SSH_exploiter_and_keys")
def test_hadoop_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Hadoop, "Hadoop_exploiter", 6 * 60)
def test_mssql_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Mssql, "MSSQL_exploiter")
def test_powershell_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, PowerShell, "PowerShell_Remoting_exploiter"
)
@pytest.mark.skip_powershell_reuse
def test_powershell_exploiter_credentials_reuse(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client,
PowerShellCredentialsReuse,
"PowerShell_Remoting_exploiter_credentials_reuse",
)
def test_smb_and_mimikatz_exploiters(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, SmbMimikatz, "SMB_exploiter_mimikatz"
)
def test_smb_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, SmbPth, "SMB_PTH")
@pytest.mark.skip(reason="Drupal exploiter is deprecated")
def test_drupal_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Drupal, "Drupal_exploiter")
@pytest.mark.skip(reason="Struts2 exploiter is deprecated")
def test_struts_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Struts2, "Struts2_exploiter")
@pytest.mark.skip(reason="Weblogic exploiter is deprecated")
def test_weblogic_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, Weblogic, "Weblogic_exploiter")
def test_log4j_solr_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jSolr, "Log4Shell_Solr_exploiter"
)
def test_log4j_tomcat_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jTomcat, "Log4Shell_tomcat_exploiter"
)
def test_log4j_logstash_exploiter(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Log4jLogstash, "Log4Shell_logstash_exploiter"
)
def test_tunneling(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, Tunneling, "Tunneling_exploiter", 3 * 60
)
def test_wmi_and_mimikatz_exploiters(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(
island_client, WmiMimikatz, "WMI_exploiter,_mimikatz"
)
def test_wmi_pth(self, island_client):
TestMonkeyBlackbox.run_exploitation_test(island_client, WmiPth, "WMI_PTH")
def test_zerologon_exploiter(self, island_client):
test_name = "Zerologon_exploiter"
expected_creds = [
"Administrator",
"aad3b435b51404eeaad3b435b51404ee",
"2864b62ea4496934a5d6e86f50b834a5",
]
raw_config = IslandConfigParser.get_raw_config(Zerologon, island_client)
zero_logon_analyzer = ZerologonAnalyzer(island_client, expected_creds)
communication_analyzer = CommunicationAnalyzer(
island_client, IslandConfigParser.get_ips_of_targets(raw_config)
)
log_handler = TestLogsHandler(
test_name, island_client, TestMonkeyBlackbox.get_log_dir_path()
)
ExploitationTest(
name=test_name,
island_client=island_client,
raw_config=raw_config,
analyzers=[zero_logon_analyzer, communication_analyzer],
timeout=DEFAULT_TIMEOUT_SECONDS,
log_handler=log_handler,
).run()
@pytest.mark.skip(
reason="Perfomance test that creates env from fake telemetries is faster, use that instead."
)
def test_report_generation_performance(self, island_client, quick_performance_tests):
"""
This test includes the SSH + Hadoop + MSSQL machines all in one test
for a total of 8 machines including the Monkey Island.
Is has 2 analyzers - the regular one which checks all the Monkeys
and the Timing one which checks how long the report took to execute
"""
if not quick_performance_tests:
TestMonkeyBlackbox.run_performance_test(
ReportGenerationTest, island_client, Performance, timeout_in_seconds=10 * 60
)
else:
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
assert False
@pytest.mark.skip(
reason="Perfomance test that creates env from fake telemetries is faster, use that instead."
)
def test_map_generation_performance(self, island_client, quick_performance_tests):
if not quick_performance_tests:
TestMonkeyBlackbox.run_performance_test(
MapGenerationTest, island_client, "PERFORMANCE.conf", timeout_in_seconds=10 * 60
)
else:
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
assert False
@pytest.mark.run_performance_tests
def test_report_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
ReportGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
@pytest.mark.run_performance_tests
def test_map_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
MapGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
@pytest.mark.run_performance_tests
def test_telem_performance(self, island_client, quick_performance_tests):
TelemetryPerformanceTest(
island_client, quick_performance_tests
).test_telemetry_performance()

View File

@ -5,10 +5,10 @@ from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandCo
from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest
from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer
MAX_TIME_FOR_MONKEYS_TO_DIE = 5 * 60
WAIT_TIME_BETWEEN_REQUESTS = 5
TIME_FOR_MONKEY_PROCESS_TO_FINISH = 10
DELAY_BETWEEN_ANALYSIS = 3
MAX_TIME_FOR_MONKEYS_TO_DIE = 2 * 60
WAIT_TIME_BETWEEN_REQUESTS = 1
TIME_FOR_MONKEY_PROCESS_TO_FINISH = 5
DELAY_BETWEEN_ANALYSIS = 1
LOGGER = logging.getLogger(__name__)
@ -89,6 +89,7 @@ class ExploitationTest(BasicTest):
if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE:
LOGGER.error("Some monkeys didn't die after the test, failing")
assert False
LOGGER.info(f"After {time_passed} seconds all monkeys have died")
def parse_logs(self):
LOGGER.info("Parsing test logs:")

View File

@ -3,25 +3,15 @@ import pathlib
from typing import Type
from envs.monkey_zoo.blackbox.config_templates.config_template import ConfigTemplate
from envs.monkey_zoo.blackbox.config_templates.drupal import Drupal
from envs.monkey_zoo.blackbox.config_templates.elastic import Elastic
from envs.monkey_zoo.blackbox.config_templates.hadoop import Hadoop
from envs.monkey_zoo.blackbox.config_templates.log4j_logstash import Log4jLogstash
from envs.monkey_zoo.blackbox.config_templates.log4j_solr import Log4jSolr
from envs.monkey_zoo.blackbox.config_templates.log4j_tomcat import Log4jTomcat
from envs.monkey_zoo.blackbox.config_templates.mssql import Mssql
from envs.monkey_zoo.blackbox.config_templates.performance import Performance
from envs.monkey_zoo.blackbox.config_templates.powershell import PowerShell
from envs.monkey_zoo.blackbox.config_templates.shellshock import ShellShock
from envs.monkey_zoo.blackbox.config_templates.smb_mimikatz import SmbMimikatz
from envs.monkey_zoo.blackbox.config_templates.smb_pth import SmbPth
from envs.monkey_zoo.blackbox.config_templates.ssh import Ssh
from envs.monkey_zoo.blackbox.config_templates.struts2 import Struts2
from envs.monkey_zoo.blackbox.config_templates.tunneling import Tunneling
from envs.monkey_zoo.blackbox.config_templates.weblogic import Weblogic
from envs.monkey_zoo.blackbox.config_templates.wmi_mimikatz import WmiMimikatz
from envs.monkey_zoo.blackbox.config_templates.wmi_pth import WmiPth
from envs.monkey_zoo.blackbox.config_templates.zerologon import Zerologon
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_1_a import Depth1A
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_2_a import Depth2A
from envs.monkey_zoo.blackbox.config_templates.grouped.depth_3_a import Depth3A
from envs.monkey_zoo.blackbox.config_templates.single_tests.powershell_credentials_reuse import (
PowerShellCredentialsReuse,
)
from envs.monkey_zoo.blackbox.config_templates.single_tests.smb_pth import SmbPth
from envs.monkey_zoo.blackbox.config_templates.single_tests.wmi_mimikatz import WmiMimikatz
from envs.monkey_zoo.blackbox.config_templates.single_tests.zerologon import Zerologon
from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser
from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient
@ -38,27 +28,14 @@ parser.add_argument(
args = parser.parse_args()
island_client = MonkeyIslandClient(args.island_ip)
CONFIG_TEMPLATES = [
Elastic,
Hadoop,
Mssql,
Performance,
PowerShell,
ShellShock,
SmbMimikatz,
SmbPth,
Ssh,
Struts2,
Tunneling,
Weblogic,
WmiMimikatz,
WmiPth,
Depth1A,
Depth2A,
Depth3A,
Zerologon,
Drupal,
Log4jLogstash,
Log4jTomcat,
Log4jSolr,
SmbPth,
WmiMimikatz,
PowerShellCredentialsReuse,
]

View File

@ -9,9 +9,6 @@ This document describes Infection Monkeys test network, how to deploy and use
[Machines](#machines)<br>
[Nr. 2 Hadoop](#_Toc526517182)<br>
[Nr. 3 Hadoop](#_Toc526517183)<br>
[Nr. 4 Elastic](#_Toc526517184)<br>
[Nr. 5 Elastic](#_Toc526517185)<br>
[Nr. 8 Shellshock](#_Toc536021461)<br>
[Nr. 9 Tunneling M1](#_Toc536021462)<br>
[Nr. 10 Tunneling M2](#_Toc536021463)<br>
[Nr. 11 SSH key steal](#_Toc526517190)<br>
@ -21,13 +18,8 @@ This document describes Infection Monkeys test network, how to deploy and use
[Nr. 15 Mimikatz](#_Toc536021468)<br>
[Nr. 16 MsSQL](#_Toc536021469)<br>
[Nr. 17 Upgrader](#_Toc536021470)<br>
[Nr. 18 WebLogic](#_Toc526517180)<br>
[Nr. 19 WebLogic](#_Toc526517181)<br>
[Nr. 20 SMB](#_Toc536021473)<br>
[Nr. 21 Scan](#_Toc526517196)<br>
[Nr. 22 Scan](#_Toc526517197)<br>
[Nr. 23 Struts2](#_Toc536021476)<br>
[Nr. 24 Struts2](#_Toc536021477)<br>
[Nr. 25 Zerologon](#_Toc536021478)<br>
[Nr. 3-45 Powershell](#_Toc536021479)<br>
[Nr. 3-46 Powershell](#_Toc536021480)<br>
@ -252,112 +244,6 @@ Update all requirements using deployment script:<br>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc526517184" class="anchor"></span>Nr. <strong>4</strong> Elastic</p>
<p>(10.2.2.4)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Ubuntu 16.04.05 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p><a href="https://www.elastic.co/downloads/past-releases/elasticsearch-1-4-2">Elastic 1.4.2</a></p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>9200</td>
</tr>
<tr class="even">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="odd">
<td>Scan results:</td>
<td>Machine exploited using Elastic exploiter</td>
</tr>
<tr class="even">
<td>Notes:</td>
<td><a href="https://www.elastic.co/guide/en/elasticsearch/reference/1.4/_index_and_query_a_document.html">Quick</a> tutorial on how to add entries (was useful when setting up).</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc526517185" class="anchor"></span>Nr. <strong>5</strong> Elastic</p>
<p>(10.2.2.5)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Windows 10 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p><a href="https://www.elastic.co/downloads/past-releases/elasticsearch-1-4-2">Elastic 1.4.2</a></p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>9200</td>
</tr>
<tr class="even">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="odd">
<td>Scan results:</td>
<td>Machine exploited using Elastic exploiter</td>
</tr>
<tr class="even">
<td>Notes:</td>
<td><a href="https://www.elastic.co/guide/en/elasticsearch/reference/1.4/_index_and_query_a_document.html">Quick</a> tutorial on how to add entries (was useful when setting up).</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc536021461" class="anchor"></span>Nr. <strong>8</strong> Shellshock</p>
<p>(10.2.2.8)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Ubuntu 12.04 LTS x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td>Apache2, bash 4.2.</td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>80</td>
</tr>
<tr class="even">
<td>Scan results:</td>
<td>Machine exploited using Shellshock exploiter</td>
</tr>
<tr class="odd">
<td>Notes:</td>
<td>Vulnerable app is under /cgi-bin/test.cgi</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
@ -744,116 +630,6 @@ Update all requirements using deployment script:<br>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc526517180" class="anchor"></span>Nr. <strong>18</strong> WebLogic</p>
<p>(10.2.2.18)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Ubuntu 16.04.05 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p><a href="https://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html">Oracle WebLogic server 12.2.1.2</a></p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>7001</td>
</tr>
<tr class="even">
<td>Admin domain credentials:</td>
<td>weblogic : B74Ot0c4</td>
</tr>
<tr class="odd">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="even">
<td>Notes:</td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc526517181" class="anchor"></span>Nr. <strong>19</strong> WebLogic</p>
<p>(10.2.2.19)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Windows 10 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p><a href="https://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html">Oracle WebLogic server 12.2.1.2</a></p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>7001</td>
</tr>
<tr class="even">
<td>Admin servers credentials:</td>
<td>weblogic : =ThS2d=m(`B</td>
</tr>
<tr class="odd">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="even">
<td>Notes:</td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc536021473" class="anchor"></span>Nr. <strong>20</strong> SMB</p>
<p>(10.2.2.20)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Windows 10 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td>-</td>
</tr>
<tr class="odd">
<td>Default services port:</td>
<td>445</td>
</tr>
<tr class="even">
<td>Root password:</td>
<td>YbS,&lt;tpS.2av</td>
</tr>
<tr class="odd">
<td>Servers config:</td>
<td><a href="https://social.technet.microsoft.com/Forums/windows/en-US/8160d62b-0f5d-48a3-9fe9-5cd319837917/how-te-reenable-smb1-in-windows1o?forum=win10itprogeneral">SMB</a> turned on</td>
</tr>
<tr class="even">
<td>Notes:</td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
@ -922,74 +698,6 @@ Update all requirements using deployment script:<br>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc536021476" class="anchor"></span>Nr. <strong>23</strong> Struts2</p>
<p>(10.2.2.23)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Ubuntu 16.04.05 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p>struts2 2.3.15.1,</p>
<p>tomcat 9.0.0.M9</p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>8080</td>
</tr>
<tr class="even">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="odd">
<td>Notes:</td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><p><span id="_Toc536021477" class="anchor"></span>Nr. <strong>24</strong> Struts2</p>
<p>(10.2.2.24)</p></th>
<th>(Vulnerable)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OS:</td>
<td><strong>Windows 10 x64</strong></td>
</tr>
<tr class="even">
<td>Software:</td>
<td><p>JDK,</p>
<p>struts2 2.3.15.1,</p>
<p>tomcat 9.0.0.M9</p></td>
</tr>
<tr class="odd">
<td>Default servers port:</td>
<td>8080</td>
</tr>
<tr class="even">
<td>Servers config:</td>
<td>Default</td>
</tr>
<tr class="odd">
<td>Notes:</td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
@ -1063,7 +771,9 @@ Accessibale through Island using m0nk3y-user.</td>
<tr class="even">
<td>Notes:</td>
<td>User: m0nk3y, Password: nPj8rbc3<br>
Accessiable through cached credentials (Windows Island)</td>
Accessible using the same m0nk3y user from island, in other words powershell exploiter can exploit
this machine without credentials as long as the user running the agent is the same on both
machines</td>
</tr>
</tbody>
</table>

View File

@ -7,19 +7,6 @@ data "google_compute_image" "hadoop-3" {
name = "hadoop-3"
project = local.monkeyzoo_project
}
data "google_compute_image" "elastic-4" {
name = "elastic-4"
project = local.monkeyzoo_project
}
data "google_compute_image" "elastic-5" {
name = "elastic-5"
project = local.monkeyzoo_project
}
data "google_compute_image" "shellshock-8" {
name = "shellshock-8"
project = local.monkeyzoo_project
}
data "google_compute_image" "tunneling-9" {
name = "tunneling-9"
project = local.monkeyzoo_project
@ -96,18 +83,6 @@ data "google_compute_image" "log4j-logstash-56" {
name = "log4j-logstash-56"
project = local.monkeyzoo_project
}
data "google_compute_image" "weblogic-18" {
name = "weblogic-18"
project = local.monkeyzoo_project
}
data "google_compute_image" "weblogic-19" {
name = "weblogic-19"
project = local.monkeyzoo_project
}
data "google_compute_image" "smb-20" {
name = "smb-20"
project = local.monkeyzoo_project
}
data "google_compute_image" "scan-21" {
name = "scan-21"
project = local.monkeyzoo_project
@ -116,22 +91,10 @@ data "google_compute_image" "scan-22" {
name = "scan-22"
project = local.monkeyzoo_project
}
data "google_compute_image" "struts2-23" {
name = "struts2-23"
project = local.monkeyzoo_project
}
data "google_compute_image" "struts2-24" {
name = "struts2-24"
project = local.monkeyzoo_project
}
data "google_compute_image" "zerologon-25" {
name = "zerologon-25"
project = local.monkeyzoo_project
}
data "google_compute_image" "drupal-28" {
name = "drupal-28"
project = local.monkeyzoo_project
}
data "google_compute_image" "island-linux-250" {
name = "island-linux-250"
project = local.monkeyzoo_project

View File

@ -76,51 +76,6 @@ resource "google_compute_instance_from_template" "hadoop-3" {
}
}
resource "google_compute_instance_from_template" "elastic-4" {
name = "${local.resource_prefix}elastic-4"
source_instance_template = local.default_ubuntu
boot_disk{
initialize_params {
image = data.google_compute_image.elastic-4.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.4"
}
}
resource "google_compute_instance_from_template" "elastic-5" {
name = "${local.resource_prefix}elastic-5"
source_instance_template = local.default_windows
boot_disk{
initialize_params {
image = data.google_compute_image.elastic-5.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.5"
}
}
resource "google_compute_instance_from_template" "shellshock-8" {
name = "${local.resource_prefix}shellshock-8"
source_instance_template = local.default_ubuntu
boot_disk{
initialize_params {
image = data.google_compute_image.shellshock-8.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.8"
}
}
resource "google_compute_instance_from_template" "tunneling-9" {
name = "${local.resource_prefix}tunneling-9"
source_instance_template = local.default_ubuntu
@ -445,71 +400,6 @@ resource "google_compute_instance_from_template" "log4j-logstash-56" {
}
}
/* We need to alter monkey's behavior for this to upload 32-bit monkey instead of 64-bit (not yet developed)
resource "google_compute_instance_from_template" "upgrader-17" {
name = "${local.resource_prefix}upgrader-17"
source_instance_template = "${local.default_windows}"
boot_disk{
initialize_params {
image = "${data.google_compute_image.upgrader-17.self_link}"
}
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.17"
access_config {
// Cheaper, non-premium routing
network_tier = "STANDARD"
}
}
}
*/
resource "google_compute_instance_from_template" "weblogic-18" {
name = "${local.resource_prefix}weblogic-18"
source_instance_template = local.default_ubuntu
boot_disk{
initialize_params {
image = data.google_compute_image.weblogic-18.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.18"
}
}
resource "google_compute_instance_from_template" "weblogic-19" {
name = "${local.resource_prefix}weblogic-19"
source_instance_template = local.default_windows
boot_disk{
initialize_params {
image = data.google_compute_image.weblogic-19.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.19"
}
}
resource "google_compute_instance_from_template" "smb-20" {
name = "${local.resource_prefix}smb-20"
source_instance_template = local.default_windows
boot_disk{
initialize_params {
image = data.google_compute_image.smb-20.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.20"
}
}
resource "google_compute_instance_from_template" "scan-21" {
name = "${local.resource_prefix}scan-21"
source_instance_template = local.default_ubuntu
@ -540,36 +430,6 @@ resource "google_compute_instance_from_template" "scan-22" {
}
}
resource "google_compute_instance_from_template" "struts2-23" {
name = "${local.resource_prefix}struts2-23"
source_instance_template = local.default_ubuntu
boot_disk{
initialize_params {
image = data.google_compute_image.struts2-23.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.23"
}
}
resource "google_compute_instance_from_template" "struts2-24" {
name = "${local.resource_prefix}struts2-24"
source_instance_template = local.default_windows
boot_disk{
initialize_params {
image = data.google_compute_image.struts2-24.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.24"
}
}
resource "google_compute_instance_from_template" "zerologon-25" {
name = "${local.resource_prefix}zerologon-25"
source_instance_template = local.default_windows
@ -585,21 +445,6 @@ resource "google_compute_instance_from_template" "zerologon-25" {
}
}
resource "google_compute_instance_from_template" "drupal-28" {
name = "${local.resource_prefix}drupal-28"
source_instance_template = local.default_windows
boot_disk{
initialize_params {
image = data.google_compute_image.drupal-28.self_link
}
auto_delete = true
}
network_interface {
subnetwork="${local.resource_prefix}monkeyzoo-main"
network_ip="10.2.2.28"
}
}
resource "google_compute_instance_from_template" "island-linux-250" {
name = "${local.resource_prefix}island-linux-250"
machine_type = "n1-standard-2"

View File

@ -12,6 +12,8 @@ ACCOUNT_ID_KEY = "accountId"
logger = logging.getLogger(__name__)
AWS_TIMEOUT = 2
class AwsInstance(CloudInstance):
"""
@ -28,12 +30,14 @@ class AwsInstance(CloudInstance):
try:
response = requests.get(
AWS_LATEST_METADATA_URI_PREFIX + "meta-data/instance-id", timeout=2
AWS_LATEST_METADATA_URI_PREFIX + "meta-data/instance-id",
timeout=AWS_TIMEOUT,
)
self.instance_id = response.text if response else None
self.region = self._parse_region(
requests.get(
AWS_LATEST_METADATA_URI_PREFIX + "meta-data/placement/availability-zone"
AWS_LATEST_METADATA_URI_PREFIX + "meta-data/placement/availability-zone",
timeout=AWS_TIMEOUT,
).text
)
except (requests.RequestException, IOError) as e:
@ -42,7 +46,8 @@ class AwsInstance(CloudInstance):
try:
self.account_id = self._extract_account_id(
requests.get(
AWS_LATEST_METADATA_URI_PREFIX + "dynamic/instance-identity/document", timeout=2
AWS_LATEST_METADATA_URI_PREFIX + "dynamic/instance-identity/document",
timeout=AWS_TIMEOUT,
).text
)
except (requests.RequestException, json.decoder.JSONDecodeError, IOError) as e:

View File

@ -1,5 +0,0 @@
from enum import Enum
class CloudProviders(Enum):
AWS = "aws"

View File

@ -1,4 +1,5 @@
import logging
import time
from common.cloud.aws.aws_service import AwsService
from common.cmd.aws.aws_cmd_result import AwsCmdResult
@ -20,6 +21,7 @@ class AwsCmdRunner(CmdRunner):
self.ssm = AwsService.get_client("ssm", region)
def query_command(self, command_id):
time.sleep(2)
return self.ssm.get_command_invocation(CommandId=command_id, InstanceId=self.instance_id)
def get_command_result(self, command_info):

View File

@ -1 +0,0 @@
T1216_PBA_FILE_DOWNLOAD_PATH = "/api/t1216-pba/download"

View File

@ -0,0 +1,2 @@
MIMIKATZ_COLLECTOR = "MimikatzCollector"
SSH_COLLECTOR = "SSHCollector"

View File

@ -0,0 +1,9 @@
from enum import Enum, auto
class CredentialComponentType(Enum):
USERNAME = auto()
PASSWORD = auto()
NT_HASH = auto()
LM_HASH = auto()
SSH_KEYPAIR = auto()

View File

@ -9,3 +9,4 @@ POST_BREACH_TIMESTOMPING = "Modify files' timestamps"
POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC = "Signed script proxy execution"
POST_BREACH_ACCOUNT_DISCOVERY = "Account discovery"
POST_BREACH_CLEAR_CMD_HISTORY = "Clear command history"
POST_BREACH_PROCESS_LIST_COLLECTION = "Collect running processes"

View File

@ -1,3 +0,0 @@
AWS_COLLECTOR = "AwsCollector"
PROCESS_LIST_COLLECTOR = "ProcessListCollector"
MIMIKATZ_COLLECTOR = "MimikatzCollector"

View File

@ -1,11 +1,11 @@
class TelemCategoryEnum:
ATTACK = "attack"
AWS_INFO = "aws_info"
CREDENTIALS = "credentials"
EXPLOIT = "exploit"
FILE_ENCRYPTION = "file_encryption"
POST_BREACH = "post_breach"
SCAN = "scan"
SCOUTSUITE = "scoutsuite"
STATE = "state"
SYSTEM_INFO = "system_info"
TRACE = "trace"
TUNNEL = "tunnel"
ATTACK = "attack"
FILE_ENCRYPTION = "file_encryption"

View File

@ -1,3 +1,4 @@
SHORT_REQUEST_TIMEOUT = 2.5 # Seconds. Use where we expect timeout.
SHORT_REQUEST_TIMEOUT = 2.5 # Seconds. Use where we expect timeout and for small data transactions.
MEDIUM_REQUEST_TIMEOUT = 5 # Seconds. Use where we don't expect timeout.
LONG_REQUEST_TIMEOUT = 15 # Seconds. Use where we don't expect timeout and operate heavy data.
CONNECTION_TIMEOUT = 3 # Seconds. Use for TCP, SSH and other connections that shouldn't take long.

View File

@ -41,13 +41,6 @@ TEST_MALICIOUS_ACTIVITY_TIMELINE = "malicious_activity_timeline"
TEST_SEGMENTATION = "segmentation"
TEST_TUNNELING = "tunneling"
TEST_COMMUNICATE_AS_BACKDOOR_USER = "communicate_as_backdoor_user"
TEST_SCOUTSUITE_PERMISSIVE_FIREWALL_RULES = "scoutsuite_permissive_firewall_rules"
TEST_SCOUTSUITE_UNENCRYPTED_DATA = "scoutsuite_unencrypted_data"
TEST_SCOUTSUITE_DATA_LOSS_PREVENTION = "scoutsuite_data_loss_prevention"
TEST_SCOUTSUITE_SECURE_AUTHENTICATION = "scoutsuite_secure_authentication"
TEST_SCOUTSUITE_RESTRICTIVE_POLICIES = "scoutsuite_unrestrictive_policies"
TEST_SCOUTSUITE_LOGGING = "scoutsuite_logging"
TEST_SCOUTSUITE_SERVICE_SECURITY = "scoutsuite_service_security"
TESTS = (
TEST_SEGMENTATION,
@ -59,13 +52,6 @@ TESTS = (
TEST_DATA_ENDPOINT_ELASTIC,
TEST_TUNNELING,
TEST_COMMUNICATE_AS_BACKDOOR_USER,
TEST_SCOUTSUITE_PERMISSIVE_FIREWALL_RULES,
TEST_SCOUTSUITE_UNENCRYPTED_DATA,
TEST_SCOUTSUITE_DATA_LOSS_PREVENTION,
TEST_SCOUTSUITE_SECURE_AUTHENTICATION,
TEST_SCOUTSUITE_RESTRICTIVE_POLICIES,
TEST_SCOUTSUITE_LOGGING,
TEST_SCOUTSUITE_SERVICE_SECURITY,
)
PRINCIPLE_DATA_CONFIDENTIALITY = "data_transit"
@ -219,77 +205,6 @@ TESTS_MAP = {
PILLARS_KEY: [PEOPLE, NETWORKS, VISIBILITY_ANALYTICS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_PERMISSIVE_FIREWALL_RULES: {
TEST_EXPLANATION_KEY: "ScoutSuite assessed cloud firewall rules and settings.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found overly permissive firewall rules.",
STATUS_PASSED: "ScoutSuite found no problems with cloud firewall rules.",
},
PRINCIPLE_KEY: PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES,
PILLARS_KEY: [NETWORKS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_UNENCRYPTED_DATA: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for resources containing " "unencrypted data.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found resources with unencrypted data.",
STATUS_PASSED: "ScoutSuite found no resources with unencrypted data.",
},
PRINCIPLE_KEY: PRINCIPLE_DATA_CONFIDENTIALITY,
PILLARS_KEY: [DATA],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_DATA_LOSS_PREVENTION: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for resources which are not "
"protected against data loss.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found resources not protected against data loss.",
STATUS_PASSED: "ScoutSuite found that all resources are secured against data loss.",
},
PRINCIPLE_KEY: PRINCIPLE_DISASTER_RECOVERY,
PILLARS_KEY: [DATA],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_SECURE_AUTHENTICATION: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for issues related to users' " "authentication.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found issues related to users' authentication.",
STATUS_PASSED: "ScoutSuite found no issues related to users' authentication.",
},
PRINCIPLE_KEY: PRINCIPLE_SECURE_AUTHENTICATION,
PILLARS_KEY: [PEOPLE, WORKLOADS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_RESTRICTIVE_POLICIES: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for permissive user access " "policies.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found permissive user access policies.",
STATUS_PASSED: "ScoutSuite found no issues related to user access policies.",
},
PRINCIPLE_KEY: PRINCIPLE_USERS_MAC_POLICIES,
PILLARS_KEY: [PEOPLE, WORKLOADS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_LOGGING: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for issues, related to logging.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found logging issues.",
STATUS_PASSED: "ScoutSuite found no logging issues.",
},
PRINCIPLE_KEY: PRINCIPLE_MONITORING_AND_LOGGING,
PILLARS_KEY: [AUTOMATION_ORCHESTRATION, VISIBILITY_ANALYTICS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
TEST_SCOUTSUITE_SERVICE_SECURITY: {
TEST_EXPLANATION_KEY: "ScoutSuite searched for service security issues.",
FINDING_EXPLANATION_BY_STATUS_KEY: {
STATUS_FAILED: "ScoutSuite found service security issues.",
STATUS_PASSED: "ScoutSuite found no service security issues.",
},
PRINCIPLE_KEY: PRINCIPLE_MONITORING_AND_LOGGING,
PILLARS_KEY: [DEVICES, NETWORKS],
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED],
},
}
EVENT_TYPE_MONKEY_NETWORK = "monkey_network"

View File

@ -1,5 +1,4 @@
AWS_KEYS_PATH = ["internal", "monkey", "aws_keys"]
STARTED_ON_ISLAND_PATH = ["internal", "general", "started_on_island"]
EXPORT_MONKEY_TELEMS_PATH = ["internal", "testing", "export_monkey_telems"]
CURRENT_SERVER_PATH = ["internal", "island_server", "current_server"]
SSH_KEYS_PATH = ["internal", "exploits", "exploit_ssh_keys"]

View File

@ -4,10 +4,15 @@ import random
import socket
import struct
from abc import ABCMeta, abstractmethod
from typing import List, Tuple
logger = logging.getLogger(__name__)
class InvalidNetworkRangeError(Exception):
"""Raise when invalid network range is provided"""
class NetworkRange(object, metaclass=ABCMeta):
def __init__(self, shuffle=True):
self._shuffle = shuffle
@ -44,23 +49,50 @@ class NetworkRange(object, metaclass=ABCMeta):
if not address_str: # Empty string
return None
address_str = address_str.strip()
if address_str.endswith("/32"):
address_str = address_str[:-3]
if NetworkRange.check_if_range(address_str):
return IpRange(ip_range=address_str)
if -1 != address_str.find("/"):
if "/" in address_str:
return CidrRange(cidr_range=address_str)
return SingleIpRange(ip_address=address_str)
@staticmethod
def filter_invalid_ranges(ranges: List[str], error_msg: str) -> List[str]:
valid_ranges = []
for target_range in ranges:
try:
NetworkRange.validate_range(target_range)
except InvalidNetworkRangeError as e:
logger.error(f"{error_msg} {e}")
continue
valid_ranges.append(target_range)
return valid_ranges
@staticmethod
def validate_range(address_str: str):
try:
NetworkRange.get_range_obj(address_str)
except (ValueError, OSError) as e:
raise InvalidNetworkRangeError(e)
@staticmethod
def check_if_range(address_str):
if -1 != address_str.find("-"):
ips = address_str.split("-")
try:
ipaddress.ip_address(ips[0]) and ipaddress.ip_address(ips[1])
NetworkRange._range_to_ips(address_str)
except ValueError:
return False
return True
return False
@staticmethod
def _range_to_ips(ip_range: str) -> Tuple[str, str]:
ips = ip_range.split("-")
ips = [ip.strip() for ip in ips]
ips = sorted(ips, key=lambda ip: socket.inet_aton(ip))
return ips[0], ips[1]
@staticmethod
def _ip_to_number(address):
return struct.unpack(">L", socket.inet_aton(address))[0]
@ -94,12 +126,7 @@ class IpRange(NetworkRange):
def __init__(self, ip_range=None, lower_end_ip=None, higher_end_ip=None, shuffle=True):
super(IpRange, self).__init__(shuffle=shuffle)
if ip_range is not None:
addresses = ip_range.split("-")
if len(addresses) != 2:
raise ValueError(
"Illegal IP range format: %s. Format is 192.168.0.5-192.168.0.20" % ip_range
)
self._lower_end_ip, self._higher_end_ip = [x.strip() for x in addresses]
self._lower_end_ip, self._higher_end_ip = IpRange._range_to_ips(ip_range)
elif (lower_end_ip is not None) and (higher_end_ip is not None):
self._lower_end_ip = lower_end_ip.strip()
self._higher_end_ip = higher_end_ip.strip()
@ -163,7 +190,10 @@ class SingleIpRange(NetworkRange):
:return: A tuple in format (IP, domain_name). Eg. (192.168.55.1, www.google.com)
"""
# The most common use case is to enter ip/range into "Scan IP/subnet list"
domain_name = ""
domain_name = None
if " " in string_:
raise ValueError(f'"{string_}" is not a valid IP address or domain name.')
# Try casting user's input as IP
try:
@ -174,10 +204,9 @@ class SingleIpRange(NetworkRange):
ip = socket.gethostbyname(string_)
domain_name = string_
except socket.error:
logger.error(
raise ValueError(
"Your specified host: {} is not found as a domain name and"
" it's not an IP address".format(string_)
)
return None, string_
# If a string_ was entered instead of IP we presume that it was domain name and translate it
return ip, domain_name

View File

@ -1,22 +1,9 @@
import re
from urllib.parse import urlparse
from typing import Optional, Tuple
def get_host_from_network_location(network_location: str) -> str:
"""
URL structure is "<scheme>://<net_loc>/<path>;<params>?<query>#<fragment>" (
https://tools.ietf.org/html/rfc1808.html)
And the net_loc is "<user>:<password>@<host>:<port>" (
https://tools.ietf.org/html/rfc1738#section-3.1)
:param network_location: server network location
:return: host part of the network location
"""
url = urlparse("http://" + network_location)
return str(url.hostname)
def remove_port(url):
parsed = urlparse(url)
with_port = f"{parsed.scheme}://{parsed.netloc}"
without_port = re.sub(":[0-9]+(?=$|/)", "", with_port)
return without_port
def address_to_ip_port(address: str) -> Tuple[str, Optional[str]]:
if ":" in address:
ip, port = address.split(":")
return ip, port or None
else:
return address, None

View File

@ -1,6 +1,5 @@
# abstract, static method decorator
# noinspection PyPep8Naming
from typing import List
class abstractstatic(staticmethod):
@ -11,10 +10,3 @@ class abstractstatic(staticmethod):
function.__isabstractmethod__ = True
__isabstractmethod__ = True
def get_value_from_dict(dict_data: dict, path: List[str]):
current_data = dict_data
for key in path:
current_data = current_data[key]
return current_data

View File

@ -1,58 +1,42 @@
class ExploitingVulnerableMachineError(Exception):
""" Raise when exploiter failed, but machine is vulnerable """
class FailedExploitationError(Exception):
""" Raise when exploiter fails instead of returning False """
"""Raise when exploiter fails instead of returning False"""
class InvalidRegistrationCredentialsError(Exception):
""" Raise when server config file changed and island needs to restart """
"""Raise when server config file changed and island needs to restart"""
class AlreadyRegisteredError(Exception):
""" Raise to indicate the reason why registration is not required """
"""Raise to indicate the reason why registration is not required"""
class UnknownUserError(Exception):
""" Raise to indicate that authentication failed """
"""Raise to indicate that authentication failed"""
class IncorrectCredentialsError(Exception):
""" Raise to indicate that authentication failed """
class RulePathCreatorNotFound(Exception):
""" Raise to indicate that ScoutSuite rule doesn't have a path creator"""
class InvalidAWSKeys(Exception):
""" Raise to indicate that AWS API keys are invalid"""
"""Raise to indicate that authentication failed"""
class NoInternetError(Exception):
""" Raise to indicate problems caused when no internet connection is present"""
class ScoutSuiteScanError(Exception):
""" Raise to indicate problems ScoutSuite encountered during scanning"""
"""Raise to indicate problems caused when no internet connection is present"""
class UnknownFindingError(Exception):
""" Raise when provided finding is of unknown type"""
"""Raise when provided finding is of unknown type"""
class VersionServerConnectionError(Exception):
""" Raise to indicate that connection to version update server failed """
"""Raise to indicate that connection to version update server failed"""
class FindingWithoutDetailsError(Exception):
""" Raise when pulling events for a finding, but get none """
"""Raise when pulling events for a finding, but get none"""
class DomainControllerNameFetchError(FailedExploitationError):
""" Raise on failed attempt to extract domain controller's name """
"""Raise on failed attempt to extract domain controller's name"""
class InvalidConfigurationError(Exception):
""" Raise when configuration is invalid """
"""Raise when configuration is invalid"""

View File

@ -1,6 +0,0 @@
from enum import Enum
class ExploitType(Enum):
VULNERABILITY = 1
BRUTE_FORCE = 9

View File

@ -1,30 +0,0 @@
# This code is used to obfuscate shellcode
# Usage:
# shellcode_obfuscator.py [your normal shellcode].
import sys
# PyCrypto is deprecated, but we use pycryptodome, which uses the exact same imports
from Crypto.Cipher import AES # noqa: DUO133 # nosec: B413
# We only encrypt payloads to hide them from static analysis
# it's OK to have these keys plaintext
KEY = b"1234567890123456"
NONCE = b"\x93n2\xbc\xf5\x8d:\xc2fP\xabn\x02\xb3\x17f"
# Use this manually to get obfuscated bytes of shellcode
def obfuscate(shellcode: bytes) -> bytes:
cipher = AES.new(KEY, AES.MODE_EAX, nonce=NONCE)
ciphertext, _ = cipher.encrypt_and_digest(shellcode)
return ciphertext
def clarify(shellcode: bytes) -> bytes:
cipher = AES.new(KEY, AES.MODE_EAX, nonce=NONCE)
plaintext = cipher.decrypt(shellcode)
return plaintext
if __name__ == "__main__":
print(obfuscate(sys.argv[1].encode()))

View File

@ -4,35 +4,29 @@ verify_ssl = true
name = "pypi"
[packages]
cryptography = "==2.5" # We can't build 32bit ubuntu12 binary with newer versions of cryptography
pyinstaller = {git = "git://github.com/guardicore/pyinstaller"}
pyinstaller-hooks-contrib = "==2021.1" # Required to build docker with our pyinstaller branch
pyinstaller = "==4.9"
impacket = ">=0.9"
importlib-metadata = "==4.0.1" # Required to build docker with our pyinstaller branch
ipaddress = ">=1.0.23"
netifaces = ">=0.10.9"
odict = "==1.7.0"
paramiko = ">=2.7.1"
psutil = ">=5.7.0"
pymssql = "==2.1.5"
pypykatz = "==0.3.12"
pypykatz = "==0.5.2"
requests = ">=2.24"
urllib3 = "==1.26.5"
WMI = {version = "==1.5.1", sys_platform = "== 'win32'"}
ScoutSuite = {git = "git://github.com/guardicode/ScoutSuite"}
pyopenssl = "==19.0.0" # We can't build 32bit ubuntu12 binary with newer versions of pyopenssl
pypsrp = "*"
typing-extensions = "*" # Allows us to use 3.9 typing features on 3.7 project
pycryptodome = "*" # Used in common/utils/shellcode_obfuscator.py
altgraph = "*" # Required for pyinstaller branch, without it agents fail to build
pysmb = "*"
"WinSys-3.x" = "*"
ldaptor = "*"
pywin32-ctypes = {version = "*", sys_platform = "== 'win32'"} # Pyinstaller requirement on windows
pywin32 = {version = "*", sys_platform = "== 'win32'"} # Lock file is not created with sys_platform win32 requirement if not explicitly specified
pefile = {version = "*", sys_platform = "== 'win32'"} # Pyinstaller requirement on windows
paramiko = {editable = true, ref = "2.10.3.dev1", git = "https://github.com/VakarisZ/paramiko.git"}
[dev-packages]
ldap3 = "*"
pywin32-ctypes = {version = "*", sys_platform = "== 'win32'"}
pefile = {version = "*", sys_platform = "== 'win32'"}
[requires]
python_version = "3.7"

View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "1495c89a3acf6a14a0ef9a00bf5660181b1c4bc4ff8e4f470f90cab3da424f70"
"sha256": "c1c28510b728242624129b39bd9ace9ba2629061bf64226cb43f1f857fc87212"
},
"pipfile-spec": 6,
"requires": {
@ -16,6 +16,14 @@
]
},
"default": {
"aiosmb": {
"hashes": [
"sha256:0afa901093f0ad91d0b8421dec66c80bd2e9cb237a8da405984413a5d7475398",
"sha256:0e98390ba00fdc4190e698f184dfcf72b02b592cdfe9274e03cc7316ac4ee368"
],
"markers": "python_version >= '3.7'",
"version": "==0.3.8"
},
"aiowinreg": {
"hashes": [
"sha256:6cd7f64ef002a7c6d7c27310db578fbc8992eeaca0936ebc56283d70c54573f2",
@ -29,30 +37,22 @@
"sha256:743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857",
"sha256:ebf2269361b47d97b3b88e696439f6e4cbc607c17c51feb1754f90fb79839158"
],
"index": "pypi",
"version": "==0.17.2"
},
"asn1crypto": {
"hashes": [
"sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8",
"sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"
"sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c",
"sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"
],
"version": "==1.4.0"
},
"asyncio-throttle": {
"hashes": [
"sha256:a01a56f3671e961253cf262918f3e0741e222fc50d57d981ba5c801f284eccfe"
],
"markers": "python_version >= '3.5'",
"version": "==0.1.1"
"version": "==1.5.1"
},
"asysocks": {
"hashes": [
"sha256:5ec0582252b0085d9337d13c6b03ab7fd062e487070667f9140e6972bd9db256",
"sha256:b97ac905cd4ca1e7a8e7c295f9cb22ced5dfd3f17e888e71cbf05a1d67a4d393"
"sha256:23d5fcfae71a75826c3ed787bd9b1bc3b189ec37658961bce83c9e99455e354c",
"sha256:731eda25d41783c5243153d3cb4f9357fef337c7317135488afab9ecd6b7f1a1"
],
"markers": "python_version >= '3.6'",
"version": "==0.1.6"
"version": "==0.1.7"
},
"attrs": {
"hashes": [
@ -85,22 +85,6 @@
"markers": "python_version >= '3.6'",
"version": "==3.2.0"
},
"boto3": {
"hashes": [
"sha256:26f18ca7411615f33d8d1bf60cc8efe5b331a57b3013d5f8f3587cd5350c27cb",
"sha256:4470f64e4af609ff678055338c96a6f7cbe601d1fb06a4ea7dc8d9223c2e527a"
],
"markers": "python_version >= '3.6'",
"version": "==1.20.44"
},
"botocore": {
"hashes": [
"sha256:11483a493de4a76ef218d8cd3980c63550d006a0d082c10d53c0954184ca542a",
"sha256:8e5317f84fc1118bff58fa6fa79a9b62083e75a2a9c62feb3ea73694c550b99d"
],
"markers": "python_version >= '3.6'",
"version": "==1.23.44"
},
"certifi": {
"hashes": [
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
@ -173,59 +157,28 @@
},
"charset-normalizer": {
"hashes": [
"sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd",
"sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"
"sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
"sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
],
"markers": "python_version >= '3'",
"version": "==2.0.10"
},
"cheroot": {
"hashes": [
"sha256:366adf6e7cac9555486c2d1be6297993022eff6f8c4655c1443268cca3f08e25",
"sha256:62cbced16f07e8aaf512673987cd6b1fc5ad00073345e9ed6c4e2a5cc2a3a22d"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==8.6.0"
},
"cherrypy": {
"hashes": [
"sha256:55659e6f012d374898d6d9d581e17cc1477b6a14710218e64f187b9227bea038",
"sha256:f33e87286e7b3e309e04e7225d8e49382d9d7773e6092241d7f613893c563495"
],
"markers": "python_version >= '3.5'",
"version": "==18.6.1"
},
"cherrypy-cors": {
"hashes": [
"sha256:eb512e20fa9e478abd1868b1417814a4e9240ed0c403472a2c624460e49ab0d5",
"sha256:f7fb75f6e617ce29c9ec3fdd8b1ff6ec64fec2c56371182525e22bcf4c180513"
],
"markers": "python_version >= '2.7'",
"version": "==1.6"
"version": "==2.0.12"
},
"click": {
"hashes": [
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
],
"markers": "python_version >= '3.6'",
"version": "==8.0.3"
"markers": "python_version >= '3.7'",
"version": "==8.1.2"
},
"colorama": {
"hashes": [
"sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
"sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
],
"markers": "sys_platform == 'win32'",
"markers": "platform_system == 'Windows' and platform_system == 'Windows'",
"version": "==0.4.4"
},
"coloredlogs": {
"hashes": [
"sha256:34fad2e342d5a559c31b6c889e8d14f97cb62c47d9a2ae7b5ed14ea10a79eff8",
"sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"
],
"version": "==10.0"
},
"constantly": {
"hashes": [
"sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35",
@ -235,44 +188,45 @@
},
"cryptography": {
"hashes": [
"sha256:05b3ded5e88747d28ee3ef493f2b92cbb947c1e45cf98cfef22e6d38bb67d4af",
"sha256:06826e7f72d1770e186e9c90e76b4f84d90cdb917b47ff88d8dc59a7b10e2b1e",
"sha256:08b753df3672b7066e74376f42ce8fc4683e4fd1358d34c80f502e939ee944d2",
"sha256:2cd29bd1911782baaee890544c653bb03ec7d95ebeb144d714b0f5c33deb55c7",
"sha256:31e5637e9036d966824edaa91bf0aa39dc6f525a1c599f39fd5c50340264e079",
"sha256:42fad67d7072216a49e34f923d8cbda9edacbf6633b19a79655e88a1b4857063",
"sha256:4946b67235b9d2ea7d31307be9d5ad5959d6c4a8f98f900157b47abddf698401",
"sha256:522fdb2809603ee97a4d0ef2f8d617bc791eb483313ba307cb9c0a773e5e5695",
"sha256:6f841c7272645dd7c65b07b7108adfa8af0aaea57f27b7f59e01d41f75444c85",
"sha256:7d335e35306af5b9bc0560ca39f740dfc8def72749645e193dd35be11fb323b3",
"sha256:8504661ffe324837f5c4607347eeee4cf0fcad689163c6e9c8d3b18cf1f4a4ad",
"sha256:9260b201ce584d7825d900c88700aa0bd6b40d4ebac7b213857bd2babee9dbca",
"sha256:9a30384cc402eac099210ab9b8801b2ae21e591831253883decdb4513b77a3cd",
"sha256:9e29af877c29338f0cab5f049ccc8bd3ead289a557f144376c4fbc7d1b98914f",
"sha256:ab50da871bc109b2d9389259aac269dd1b7c7413ee02d06fe4e486ed26882159",
"sha256:b13c80b877e73bcb6f012813c6f4a9334fcf4b0e96681c5a15dac578f2eedfa0",
"sha256:bfe66b577a7118e05b04141f0f1ed0959552d45672aa7ecb3d91e319d846001e",
"sha256:e091bd424567efa4b9d94287a952597c05d22155a13716bf5f9f746b9dc906d3",
"sha256:fa2b38c8519c5a3aa6e2b4e1cf1a549b54acda6adb25397ff542068e73d1ed00"
"sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b",
"sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51",
"sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7",
"sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d",
"sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6",
"sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29",
"sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9",
"sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf",
"sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815",
"sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf",
"sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85",
"sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77",
"sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86",
"sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb",
"sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e",
"sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0",
"sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3",
"sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84",
"sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2",
"sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6"
],
"index": "pypi",
"version": "==2.5"
"markers": "python_version >= '3.6'",
"version": "==36.0.2"
},
"dnspython": {
"hashes": [
"sha256:081649da27ced5e75709a1ee542136eaba9842a0fe4c03da4fb0a3d3ed1f3c44",
"sha256:e79351e032d0b606b98d38a4b0e6e2275b31a5b85c873e587cc11b73aca026d6"
"sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e",
"sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f"
],
"markers": "python_version >= '3.6' and python_version < '4.0'",
"version": "==2.2.0"
"markers": "python_version >= '3.6' and python_version < '4'",
"version": "==2.2.1"
},
"flask": {
"hashes": [
"sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2",
"sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"
"sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264",
"sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.2"
"markers": "python_version >= '3.7'",
"version": "==2.1.1"
},
"future": {
"hashes": [
@ -281,20 +235,6 @@
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.18.2"
},
"httpagentparser": {
"hashes": [
"sha256:a190dfdc5e63b2f1c87729424b19cbc49263d6a1fb585a16ac1c9d9ce127a4bf"
],
"version": "==1.9.2"
},
"humanfriendly": {
"hashes": [
"sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477",
"sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==10.0"
},
"hyperlink": {
"hashes": [
"sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b",
@ -319,19 +259,11 @@
},
"importlib-metadata": {
"hashes": [
"sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581",
"sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d"
"sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6",
"sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"
],
"index": "pypi",
"version": "==4.0.1"
},
"importlib-resources": {
"hashes": [
"sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45",
"sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"
],
"markers": "python_version < '3.9'",
"version": "==5.4.0"
"markers": "python_version < '3.10'",
"version": "==4.11.3"
},
"incremental": {
"hashes": [
@ -350,67 +282,19 @@
},
"itsdangerous": {
"hashes": [
"sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
"sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
},
"jaraco.classes": {
"hashes": [
"sha256:22ac35313cf4b145bf7b217cc51be2d98a3d2db1c8558a30ca259d9f0b9c0b7d",
"sha256:ed54b728af1937dc16b7236fbaf34ba561ba1ace572b03fffa5486ed363ecf34"
],
"markers": "python_version >= '3.6'",
"version": "==3.2.1"
},
"jaraco.collections": {
"hashes": [
"sha256:b04f00bd4b3c4fc4ba5fe1baf8042c0efd192b13e386830ea23fff77bb69dc88",
"sha256:ef7c308d6d7cadfb16b32c7e414d628151ab02b57a5702b9d9a293148c035e70"
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
],
"markers": "python_version >= '3.7'",
"version": "==3.5.1"
},
"jaraco.context": {
"hashes": [
"sha256:17b909da2fb37ad237ca7ff9523977f8665a47a25b90aec6a99a3e0959c86141",
"sha256:f0d4d82ffbbbff680384eba48a32a3167f12a91a30a7db56fd97b87e73a87241"
],
"markers": "python_version >= '3.6'",
"version": "==4.1.1"
},
"jaraco.functools": {
"hashes": [
"sha256:141f95c490a18eb8aab86caf7a2728f02f604988a26dc36652e3d9fa9e4c49fa",
"sha256:31e0e93d1027592b7b0bec6ad468db850338981ebee76ba5e212e235f4c7dda0"
],
"markers": "python_version >= '3.7'",
"version": "==3.5.0"
},
"jaraco.text": {
"hashes": [
"sha256:17b43aa0bd46e97c368ccd8a4c8fef2719ca121b6d39ce4be9d9e0143832479a",
"sha256:a7f9cc1b44a5f3096a216cbd130b650c7a6b2c9f8005b000ae97f329239a7c00"
],
"markers": "python_version >= '3.6'",
"version": "==3.7.0"
"version": "==2.1.2"
},
"jinja2": {
"hashes": [
"sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8",
"sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"
"sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119",
"sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.3"
},
"jmespath": {
"hashes": [
"sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9",
"sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.0"
"markers": "python_version >= '3.7'",
"version": "==3.1.1"
},
"ldap3": {
"hashes": [
@ -440,78 +324,49 @@
},
"markupsafe": {
"hashes": [
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
"sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194",
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
"sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
"sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
"sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
"sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a",
"sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
"sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
"sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
"sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
"sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
"sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047",
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
"sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b",
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
"sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
"sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1",
"sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
"sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
"sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee",
"sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f",
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
"sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
"sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86",
"sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6",
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
"sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
"sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e",
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
"sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f",
"sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
"sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
"sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
"sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
"sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a",
"sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207",
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
"sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
"sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd",
"sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
"sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
"sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9",
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"markers": "python_version >= '3.7'",
"version": "==2.1.1"
},
"minidump": {
"hashes": [
@ -523,34 +378,19 @@
},
"minikerberos": {
"hashes": [
"sha256:eba89d5c649241a3367839ebd1c0333b9a9e4fe514746e246a6a1f2cb7bde26e",
"sha256:f556a6015904147c3302e9038b49f766c975df6aeb1725027cd7fc68ba993864"
"sha256:3c383f67ebcf6f28105ed54f623a6a5c677a24e3f0c9ad69ed453f77e569d714",
"sha256:789f802263fa1882f701b123f6eec048b45cd731bf1b528870005daf07402047"
],
"markers": "python_version >= '3.6'",
"version": "==0.2.16"
},
"more-itertools": {
"hashes": [
"sha256:43e6dd9942dffd72661a2c4ef383ad7da1e6a3e968a927ad7a6083ab410a688b",
"sha256:7dc6ad46f05f545f900dd59e8dfb4e84a4827b97b3cfecb175ea0c7d247f6064"
],
"markers": "python_version >= '3.5'",
"version": "==8.12.0"
"version": "==0.2.20"
},
"msldap": {
"hashes": [
"sha256:37e1b1044792595ca78fc14402baf84922e0a3838b36534ecd5a75cdd81e74ee",
"sha256:7d7f96d41ab8174ffa0f2c56780eb3be8b3015009d0e94a4dbd83b9ead5c6181"
"sha256:c9e530a5e61a2a4584c3541a1e40787399b9225a4f727ad13ad0b4998bfda03a",
"sha256:cc9129f3f8cf4c06f7469cf25f249db55976b922e94a2ac690987b181ff74307"
],
"markers": "python_version >= '3.7'",
"version": "==0.3.30"
},
"netaddr": {
"hashes": [
"sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac",
"sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"
],
"version": "==0.8.0"
"version": "==0.3.38"
},
"netifaces": {
"hashes": [
@ -597,18 +437,15 @@
},
"oscrypto": {
"hashes": [
"sha256:7d2cca6235d89d1af6eb9cfcd4d2c0cb405849868157b2f7b278beb644d48694",
"sha256:988087e05b17df8bfcc7c5fac51f54595e46d3e4dffa7b3d15955cf61a633529"
"sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085",
"sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4"
],
"version": "==1.2.1"
"version": "==1.3.0"
},
"paramiko": {
"hashes": [
"sha256:04097dbd96871691cdb34c13db1883066b8a13a0df2afd4cb0a92221f51c2603",
"sha256:944a9e5dbdd413ab6c7951ea46b0ab40713235a9c4c5ca81cfe45c6f14fa677b"
],
"index": "pypi",
"version": "==2.9.2"
"editable": true,
"git": "https://github.com/VakarisZ/paramiko.git",
"ref": "d554bc53b9712e5fbb5e444750ad9d91f8c0b16f"
},
"passlib": {
"hashes": [
@ -621,31 +458,17 @@
"hashes": [
"sha256:344a49e40a94e10849f0fe34dddc80f773a12b40675bf2f7be4b8be578bdd94a"
],
"markers": "python_version >= '3.6'",
"index": "pypi",
"markers": "sys_platform == 'win32'",
"version": "==2021.9.3"
},
"policyuniverse": {
"hashes": [
"sha256:116b808554d7ea75efc97b4cb904085546db45934ef315175cb4755c7a4489de",
"sha256:7440ac520bb791e0318e3d99f9b0e76b7b2b604e7160f1d8341ded060f9ff1cd"
],
"version": "==1.4.0.20220110"
},
"portend": {
"hashes": [
"sha256:239e3116045ea823f6df87d6168107ad75ccc0590e37242af0cc1e98c5d224e4",
"sha256:9e735cee3a5c1961f09e3f3ba6dc498198c2d70b473d98d0d1504b8d1e7a3d61"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.0"
},
"prompt-toolkit": {
"hashes": [
"sha256:45f3137a16a7bb5893928f918bfcc36cfe812db49437d087201cd2a78016cbb3",
"sha256:c79f8d3fe475116a2daaed1c5c08d4450becbe7b5c1a513d50b6d45248857a67"
"sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752",
"sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7"
],
"markers": "python_full_version >= '3.6.2'",
"version": "==3.0.25"
"version": "==3.0.29"
},
"psutil": {
"hashes": [
@ -729,89 +552,63 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.21"
},
"pycryptodome": {
"hashes": [
"sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691",
"sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6",
"sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1",
"sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f",
"sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90",
"sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02",
"sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5",
"sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1",
"sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f",
"sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3",
"sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732",
"sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6",
"sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863",
"sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f",
"sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e",
"sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d",
"sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4",
"sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b",
"sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d",
"sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2",
"sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5",
"sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf",
"sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3",
"sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d",
"sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a",
"sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873",
"sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27",
"sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f",
"sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5",
"sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"
],
"index": "pypi",
"version": "==3.13.0"
},
"pycryptodomex": {
"hashes": [
"sha256:00e37d478c0f040639ab41a9d5280291ad2b3b5f25b9aad5baa1d5ecb578a3f6",
"sha256:04a38a7dc484f5e3152a69e4eab89d9340c2ad3b7c4a27d2ee256e5fb878c469",
"sha256:05e0e3b78b7ccc0b7c5f88596d51fdc8533adb91070b93e18cec12ca3b43deb3",
"sha256:0ec86fca2114e8c58fe6bfc7e04ee91568a813139dcf4334819aa44876764bcf",
"sha256:182962b3612c0d12748fa770f1ef0556ba8ba2c442834450e08acb31d9e6d2ed",
"sha256:2f2bcee2ef59597bfcb755eef2c98294094c1c9b64e9b9195cc9e71be83adb92",
"sha256:2f7db8d85294c1123e700097af407425fd4c9e6c58b688f391de7053c6a60317",
"sha256:3b7656189c259bb2b838559f0a11b533d4d18409ab6d9119c00bae436c3d3e34",
"sha256:5a2014598ceb19c34f14815a26536e5cc24167ea4d402f0aec2a52b18960c668",
"sha256:63443230247837dd03c5d4028cae5cb2e6793a9ae110e321798bee48a04ff3e9",
"sha256:68fb861b41a889c2efdf2795b0d46aa05d4748543bc4e0bca5886c929c7cbdef",
"sha256:6b3c06e6d235f475395a7e150f2e562a3e9d749fb40c6d81240596f73809346c",
"sha256:6d50723984ba802904618ef5bfe257a0f9644e76821d323f79f27be5adb9ece7",
"sha256:7fb188c9a0f69d4f7b607780641ef7aec7f02a8dad689512b17bdf04c96ce6e3",
"sha256:7fb9d1ab6a10cfc8c8c7e11f004e01c8a1beff5fd4118370d95110735cc23117",
"sha256:80eedc23c4c4d3655c6a7d315a01f0e9d460c7070c5c3af4952937b4f2c0da6f",
"sha256:9fa76261100b450e5aca2990ba982e5294ba383f653da041a71b4ac1cbaed1ff",
"sha256:b11331510cfd08ec4416f37dc8f072541d7b7240ba924c71288f7218aad36bdf",
"sha256:b4240991748ae0f57a0120b8d905b2d9f835fee02968fc11faec929ef6915ee6",
"sha256:b7b059517d84c57f25c6fd3b2e03a1b2945df2e585b96109bcd11e56f6c9e610",
"sha256:b975ce778ea2c65f399ab889a661e118bb68b85db47d93e0442eb1ba1f554794",
"sha256:c87f62de9e167031ad4179efb1fda4012bb6f7363472a61254e4426bda6bcb64",
"sha256:ccd301d2e71d243b0fad8c4642116c538d7d405d35b6026cf4dcee463a667a2e",
"sha256:dce2bfd0f285c3fcff89e4239c55f5fbe664ff435ee45abfc154aac0f222ab14",
"sha256:dfb8bcd45e504e1c26f0bfc404f3edd08f8c8057dfe04fbf6159adc8694ff97a",
"sha256:e1900d7f16a03b869be3572e7664757c14316329a4d79ecee5a0083fad8c81b0",
"sha256:e2ddfbcb2c4c7cb8f79db49e284280be468699c701b92d30fd1e46a786b39f5b",
"sha256:eb4eea028a7ad28458abf8b98ae14af2fd9baeb327a0adb6af05a488e4d9e9a1",
"sha256:f3a29bb51e5f9b46004b5be16bcbe4e1b2d2754cbe201e1a0b142c307bdf4c73",
"sha256:f553abcb3572242fed87e308a6b91a9bc5a74b801b5d093969391b0500be718b"
"sha256:1ca8e1b4c62038bb2da55451385246f51f412c5f5eabd64812c01766a5989b4a",
"sha256:298c00ea41a81a491d5b244d295d18369e5aac4b61b77b2de5b249ca61cd6659",
"sha256:2aa887683eee493e015545bd69d3d21ac8d5ad582674ec98f4af84511e353e45",
"sha256:2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2",
"sha256:3da13c2535b7aea94cc2a6d1b1b37746814c74b6e80790daddd55ca5c120a489",
"sha256:406ec8cfe0c098fadb18d597dc2ee6de4428d640c0ccafa453f3d9b2e58d29e2",
"sha256:4d0db8df9ffae36f416897ad184608d9d7a8c2b46c4612c6bc759b26c073f750",
"sha256:530756d2faa40af4c1f74123e1d889bd07feae45bac2fd32f259a35f7aa74151",
"sha256:77931df40bb5ce5e13f4de2bfc982b2ddc0198971fbd947776c8bb5050896eb2",
"sha256:797a36bd1f69df9e2798e33edb4bd04e5a30478efc08f9428c087f17f65a7045",
"sha256:8085bd0ad2034352eee4d4f3e2da985c2749cb7344b939f4d95ead38c2520859",
"sha256:8536bc08d130cae6dcba1ea689f2913dfd332d06113904d171f2f56da6228e89",
"sha256:a4d412eba5679ede84b41dbe48b1bed8f33131ab9db06c238a235334733acc5e",
"sha256:aebecde2adc4a6847094d3bd6a8a9538ef3438a5ea84ac1983fcb167db614461",
"sha256:b276cc4deb4a80f9dfd47a41ebb464b1fe91efd8b1b8620cf5ccf8b824b850d6",
"sha256:b5a185ae79f899b01ca49f365bdf15a45d78d9856f09b0de1a41b92afce1a07f",
"sha256:c4d8977ccda886d88dc3ca789de2f1adc714df912ff3934b3d0a3f3d777deafb",
"sha256:c5dd3ffa663c982d7f1be9eb494a8924f6d40e2e2f7d1d27384cfab1b2ac0662",
"sha256:ca88f2f7020002638276439a01ffbb0355634907d1aa5ca91f3dc0c2e44e8f3b",
"sha256:d2cce1c82a7845d7e2e8a0956c6b7ed3f1661c9acf18eb120fc71e098ab5c6fe",
"sha256:d709572d64825d8d59ea112e11cc7faf6007f294e9951324b7574af4251e4de8",
"sha256:da8db8374295fb532b4b0c467e66800ef17d100e4d5faa2bbbd6df35502da125",
"sha256:e36c7e3b5382cd5669cf199c4a04a0279a43b2a3bdd77627e9b89778ac9ec08c",
"sha256:e95a4a6c54d27a84a4624d2af8bb9ee178111604653194ca6880c98dcad92f48",
"sha256:ee835def05622e0c8b1435a906491760a43d0c462f065ec9143ec4b8d79f8bff",
"sha256:f75009715dcf4a3d680c2338ab19dac5498f8121173a929872950f4fb3a48fbf",
"sha256:f8524b8bc89470cec7ac51734907818d3620fb1637f8f8b542d650ebec42a126"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==3.13.0"
"version": "==3.14.1"
},
"pyinstaller": {
"git": "git://github.com/guardicore/pyinstaller",
"ref": "913259a5cd2baece06b0eed3618eb75b1bc7fad6"
"hashes": [
"sha256:24035eb9fffa2e3e288b4c1c9710043819efc7203cae5c8c573bec16f4a8e98f",
"sha256:59372b950d176fdc5ecea29719a8ab3f194b73a15b7f9875ac2a1de9a3daf5ed",
"sha256:62c97cbbdbee30974d607eb1de9afb081eb3adba787c203b00438e21027b829b",
"sha256:75a180a658871bc41f9cf94b6f90ffa54e98f5d6a7cdb02d7530f0360afe24f9",
"sha256:7f46ab11ec986e4c525b93251063144e12d432a132dbc0070e3030e34c76537a",
"sha256:a0b988cfc197d40e3d773b3aa1c7d3e918fc0933b4c15ec3fc5d156f222d82cb",
"sha256:b5f1a94150315ea75bf3501be6c8476d65a7209580bb662da06dbdbc4454f375",
"sha256:bec57b3b2b6178907255557ec0fc4b5ce5a0474013414cdadea853205c74ed26",
"sha256:e2f165cea4470ce8a8349112cd78f48a61413805adc17792a91997a11cfe1d80",
"sha256:ebeb87cdbadb2b4e8f991ffd9945ebd4fb3a7303180e63682c3e1ce01b3fdd22",
"sha256:ec3ca331d565ffca1b6470c5aaf798885a03708c3d0b15c1b19009126f84c1d4"
],
"index": "pypi",
"version": "==4.9"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:27558072021857d89524c42136feaa2ffe4f003f1bdf0278f9b24f6902c1759c",
"sha256:892310e6363655838485ee748bf1c5e5cade7963686d9af8650ee218a3e0b031"
"sha256:9765e68552803327d58f6c5eca970bb245b7cdf073e2f912a2a3cb50360bc2d8",
"sha256:9fa4ca03d058cba676c3cc16005076ce6a529f144c08b87c69998625fbd84e0a"
],
"index": "pypi",
"version": "==2021.1"
"markers": "python_version >= '3.7'",
"version": "==2022.3"
},
"pymssql": {
"hashes": [
@ -866,11 +663,11 @@
},
"pyopenssl": {
"hashes": [
"sha256:aeca66338f6de19d1aa46ed634c3b9ae519a64b458f8468aec688e7e3c20f200",
"sha256:c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6"
"sha256:660b1b1425aac4a1bea1d94168a85d99f0b3144c869dd4390d27629d0087f1bf",
"sha256:ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0"
],
"index": "pypi",
"version": "==19.0.0"
"markers": "python_version >= '3.6'",
"version": "==22.0.0"
},
"pyparsing": {
"hashes": [
@ -882,28 +679,19 @@
},
"pypsrp": {
"hashes": [
"sha256:c0912096858ff8c53a3cf22cc46c3ce20e6ec5e2deade342088e87a81dbadac8",
"sha256:d7144ad7c798a4dcded20a71c712d63eb4bfb32debe62f3a98f01481384a5558"
"sha256:0101345ceb415896fed9b056e7b77d65312089ddc73c4286247ccf1859d4bc4d",
"sha256:f5500acd11dfe742d51b7fbb61321ba721038a300d67763dc52babe709db65e7"
],
"index": "pypi",
"version": "==0.7.0"
"version": "==0.8.1"
},
"pypykatz": {
"hashes": [
"sha256:8acd8d69f7b0ab343c593490a0837871b58b5c322ad54ada2fad0fed049349f3",
"sha256:b63b19ec6ee8448bbcf7003e6ad1f9d7a2784fd8cee54aebcc5f717792a43200"
"sha256:ad397a6ca72033df70fc6655f8922f1ee16d6c5b05e0e40276899217e2f5dbd3",
"sha256:bddb2f0729856e3a0e8c481ec90b52a7e497506ee07ef20b99719496dda02b8d"
],
"index": "pypi",
"version": "==0.3.12"
},
"pyreadline": {
"hashes": [
"sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1",
"sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e",
"sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"
],
"markers": "python_version < '3.8' and sys_platform == 'win32'",
"version": "==2.1"
"version": "==0.5.2"
},
"pysmb": {
"hashes": [
@ -914,36 +702,21 @@
},
"pyspnego": {
"hashes": [
"sha256:19da2de9d55d73d05b2798d4e5bd7ee5980e573ae50dc2f2bc460df5eaffe5ea",
"sha256:27dd07b6b918c289d2820c685b346a198498354cf3a1bfe9ec19cff9fa8fce2f",
"sha256:37c4d80a0c90bd2b670c583b2efbd210c26f54b1f7661c0cbc684a954b88c1c3",
"sha256:6387b4631120205240d1be25aff7a78d41db9b99bb5803b3ac6b7b6ed80b8920",
"sha256:6df4b5233ec28358992adadfef5be76807ca1424e7c0fbf430424759edc85f8b",
"sha256:75a0d4be4236f6b7c2ded0b43fd03e942c48cdbe91c2856f45f22884b7e92ddc",
"sha256:9235a3159a4e1648d6bb4d170b8d68ecf5b1f55fa2f3157335ce74df5c192468",
"sha256:a0d41d43657cd4d4456ca734ec00b6e24c95a144499cfc429371a310c4b10d7a",
"sha256:b02c9b61f85c96f969c78f492b35915a590dddabf987687eb1256ef2fd8fbdcb",
"sha256:ccb8d9cea310f1715d5ed3d2d092db9bf50ff2762cf94a0dd9dfab7774a727fe",
"sha256:e15d16b205fbc5e945244b974312e9796467913f69736fdad262edee0c3c105f",
"sha256:f4a00cc3796d34212b391caecb3fd636cdefea798cb4ac231f893bdade674f01"
"sha256:05438a4e3e1526134bc2d72213417a06a2c3010f5b7271f3122e635e523c3790",
"sha256:12e4da1cbbbd645c0624699a1d99f734161cb9095e9f1fc1c1982ed1b7a44abe",
"sha256:185e0c576cde30d8853d9ea1d69c32cb93e98423934263d6c067bec7adc7dc4f",
"sha256:3361027e7e86de6b784791e09a7b2ba73d06c0be40f027a7be09e45fc92325a5",
"sha256:4971fb166dc9821c98d31d698722d48d0066f1bc63beff8bf3d2a2e60fe507d1",
"sha256:58d352d901baab754f63cb0da790c1f798605eb634f7f922df9bb6822d3de3c5",
"sha256:77b7c75bed737f24989aab453b9b8cd1c1512dfc5bed7a303a1cb1156fd59959",
"sha256:adf2f3e09bc4751c06fab1fedfe734af7f232d79927c753d8981f75a25f791ec",
"sha256:c6993ee6bcfe0036d6246324fcb7975daed858a476bfc7bf1d9334911d3dfca2",
"sha256:e21fc7283caa16761d46bea54e78cbfe3177c21e3b2d17d9ef213edcd86e1250",
"sha256:f05f1a6316a9baeaef243c9420d995c3dc34cfc91841f17db0c793e3fe557728",
"sha256:fe8b2a0d7468d904c61ae63275f8234eb055767aaaba66f6d58d86f47a25aa8e"
],
"markers": "python_version >= '3.6'",
"version": "==0.3.1"
},
"python-dateutil": {
"hashes": [
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.8.0"
},
"pytz": {
"hashes": [
"sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
"sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
],
"version": "==2021.3"
"version": "==0.5.1"
},
"pywin32": {
"hashes": [
@ -960,7 +733,8 @@
"sha256:d9b5d87ca944eb3aa4cd45516203ead4b37ab06b8b777c54aedc35975dec0dee",
"sha256:fcf44032f5b14fcda86028cdf49b6ebdaea091230eb0a757282aa656e4732439"
],
"markers": "python_version < '3.10' and sys_platform == 'win32' and implementation_name == 'cpython'",
"index": "pypi",
"markers": "sys_platform == 'win32'",
"version": "==303"
},
"pywin32-ctypes": {
@ -968,6 +742,8 @@
"sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942",
"sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"
],
"index": "pypi",
"markers": "sys_platform == 'win32'",
"version": "==0.2.0"
},
"requests": {
@ -978,18 +754,6 @@
"index": "pypi",
"version": "==2.27.1"
},
"s3transfer": {
"hashes": [
"sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c",
"sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803"
],
"markers": "python_version >= '3.6'",
"version": "==0.5.0"
},
"scoutsuite": {
"git": "git://github.com/guardicode/ScoutSuite",
"ref": "eac33ac5b0a84e4a2e29682cf3568271eb595003"
},
"service-identity": {
"hashes": [
"sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34",
@ -997,14 +761,6 @@
],
"version": "==21.1.0"
},
"setuptools": {
"hashes": [
"sha256:2404879cda71495fc4d5cbc445ed52fdaddf352b36e40be8dcc63147cb4edabe",
"sha256:68eb94073fc486091447fcb0501efd6560a0e5a1839ba249e5ff3c4c93f05f90"
],
"markers": "python_version >= '3.7'",
"version": "==60.5.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
@ -1013,38 +769,24 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sqlitedict": {
"hashes": [
"sha256:2affcc301aacd4da7511692601ecbde392294205af418498f7d6d3ec0dbcad56"
],
"version": "==1.7.0"
},
"tempora": {
"hashes": [
"sha256:8d743059a4ea496d925f35480c6d206a7160cacebcd6a31e147fb495dcb732af",
"sha256:aa21dd1956e29559ecb2f2f2e14fcdb950085222fbbf86e6c946b5e1a8c36b26"
],
"markers": "python_version >= '3.7'",
"version": "==5.0.0"
},
"tqdm": {
"hashes": [
"sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c",
"sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"
"sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d",
"sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==4.62.3"
"version": "==4.64.0"
},
"twisted": {
"extras": [
"tls"
],
"hashes": [
"sha256:13c1d1d2421ae556d91e81e66cf0d4f4e4e1e4a36a0486933bee4305c6a4fb9b",
"sha256:2cd652542463277378b0d349f47c62f20d9306e57d1247baabd6d1d38a109006"
"sha256:57f32b1f6838facb8c004c89467840367ad38e9e535f8252091345dba500b4f2",
"sha256:5c63c149eb6b8fe1e32a0215b1cef96fabdba04f705d8efb9174b1ccf5b49d49"
],
"markers": "python_full_version >= '3.6.7'",
"version": "==21.7.0"
"version": "==22.2.0"
},
"twisted-iocpsupport": {
"hashes": [
@ -1066,11 +808,19 @@
},
"typing-extensions": {
"hashes": [
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
"sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42",
"sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"
],
"index": "pypi",
"version": "==4.0.1"
"version": "==4.1.1"
},
"unicrypto": {
"hashes": [
"sha256:69240f260493346861e639697e2fda245f14656c7df20ae6d9e6b1bb36acb29e",
"sha256:822bbf18ca6bc17f98c3029470bd8898e51fcb6a7716f6b1c95ed0bf9e0e4da5"
],
"markers": "python_version >= '3.6'",
"version": "==0.0.5"
},
"urllib3": {
"hashes": [
@ -1089,11 +839,11 @@
},
"werkzeug": {
"hashes": [
"sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f",
"sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"
"sha256:3c5493ece8268fecdcdc9c0b112211acd006354723b280d643ec732b6d4063d6",
"sha256:f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.2"
"markers": "python_version >= '3.7'",
"version": "==2.1.1"
},
"winacl": {
"hashes": [
@ -1108,7 +858,7 @@
"sha256:a2ad9c0f6d70f6e0e0d1f54b8582054c62d8a09f346b5ccaf55da68628ca10e1",
"sha256:a64624a25fc2d3663a2c5376c5291f3c7531e9c8051571de9ca9db8bf25746c2"
],
"markers": "python_version >= '3.6'",
"markers": "platform_system == 'Windows'",
"version": "==0.0.9"
},
"winsys-3.x": {
@ -1127,20 +877,13 @@
"markers": "sys_platform == 'win32'",
"version": "==1.5.1"
},
"zc.lockfile": {
"hashes": [
"sha256:307ad78227e48be260e64896ec8886edc7eae22d8ec53e4d528ab5537a83203b",
"sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f"
],
"version": "==2.0"
},
"zipp": {
"hashes": [
"sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d",
"sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
],
"markers": "python_version >= '3.7'",
"version": "==3.7.0"
"version": "==3.8.0"
},
"zope.interface": {
"hashes": [
@ -1201,13 +944,6 @@
}
},
"develop": {
"future": {
"hashes": [
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.18.2"
},
"ldap3": {
"hashes": [
"sha256:2bc966556fc4d4fa9f445a1c31dc484ee81d44a51ab0e2d0fd05b62cac75daa6",
@ -1218,13 +954,6 @@
],
"version": "==2.9.1"
},
"pefile": {
"hashes": [
"sha256:344a49e40a94e10849f0fe34dddc80f773a12b40675bf2f7be4b8be578bdd94a"
],
"markers": "python_version >= '3.6'",
"version": "==2021.9.3"
},
"pyasn1": {
"hashes": [
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
@ -1242,13 +971,6 @@
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
],
"version": "==0.4.8"
},
"pywin32-ctypes": {
"hashes": [
"sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942",
"sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"
],
"version": "==0.2.0"
}
}
}

View File

@ -1,9 +1,7 @@
import hashlib
import os
import sys
import uuid
from abc import ABCMeta
from itertools import product
GUID = str(uuid.getnode())
@ -28,9 +26,6 @@ class Configuration(object):
continue
if key in LOCAL_CONFIG_VARS:
continue
if self._depth_from_commandline and key == "depth":
self.max_depth = value
continue
if hasattr(self, key):
setattr(self, key, value)
else:
@ -70,18 +65,6 @@ class Configuration(object):
return result
# Used to keep track of our depth if manually specified
_depth_from_commandline = False
###########################
# logging config
###########################
dropper_log_path_windows = "%temp%\\~df1562.tmp"
dropper_log_path_linux = "/tmp/user-1562"
monkey_log_path_windows = "%temp%\\~df1563.tmp"
monkey_log_path_linux = "/tmp/user-1563"
###########################
# dropper config
###########################
@ -89,151 +72,27 @@ class Configuration(object):
dropper_set_date = True
dropper_date_reference_path_windows = r"%windir%\system32\kernel32.dll"
dropper_date_reference_path_linux = "/bin/sh"
dropper_target_path_win_32 = r"C:\Windows\temp\monkey32.exe"
dropper_target_path_win_64 = r"C:\Windows\temp\monkey64.exe"
dropper_target_path_linux = "/tmp/monkey"
###########################
# monkey config
###########################
# sets whether or not the monkey is alive. if false will stop scanning and exploiting
alive = True
finger_classes = []
exploiter_classes = []
system_info_collector_classes = []
# how many victims to look for in a single scan iteration
victims_max_find = 100
# how many victims to exploit before stopping
victims_max_exploit = 100
should_stop = False
# depth of propagation
depth = 2
max_depth = None
started_on_island = False
current_server = ""
# Configuration servers to try to connect to, in this order.
command_servers = ["192.0.2.0:5000"]
command_servers = []
keep_tunnel_open_time = 60
###########################
# scanners config
###########################
# Auto detect and scan local subnets
local_network_scan = True
subnet_scan_list = []
inaccessible_subnets = []
blocked_ips = []
# TCP Scanner
HTTP_PORTS = [
80,
8080,
443,
8008, # HTTP alternate
7001, # Oracle Weblogic default server port
]
tcp_target_ports = [22, 2222, 445, 135, 3389, 80, 8080, 443, 8008, 3306, 9200]
tcp_target_ports.extend(HTTP_PORTS)
tcp_scan_timeout = 3000 # 3000 Milliseconds
tcp_scan_interval = 0 # in milliseconds
tcp_scan_get_banner = True
# Ping Scanner
ping_scan_timeout = 1000
###########################
# exploiters config
###########################
skip_exploit_if_file_exist = False
ms08_067_exploit_attempts = 5
user_to_add = "Monkey_IUSER_SUPPORT"
###########################
# ransomware config
###########################
ransomware = ""
def get_exploit_user_password_pairs(self):
"""
Returns all combinations of the configurations users and passwords
:return:
"""
return product(self.exploit_user_list, self.exploit_password_list)
def get_exploit_user_ssh_key_pairs(self):
"""
:return: All combinations of the configurations users and ssh pairs
"""
return product(self.exploit_user_list, self.exploit_ssh_keys)
def get_exploit_user_password_or_hash_product(self):
"""
Returns all combinations of the configurations users and passwords or lm/ntlm hashes
:return:
"""
cred_list = []
for cred in product(self.exploit_user_list, self.exploit_password_list, [""], [""]):
cred_list.append(cred)
for cred in product(self.exploit_user_list, [""], [""], self.exploit_ntlm_hash_list):
cred_list.append(cred)
for cred in product(self.exploit_user_list, [""], self.exploit_lm_hash_list, [""]):
cred_list.append(cred)
return cred_list
@staticmethod
def hash_sensitive_data(sensitive_data):
"""
Hash sensitive data (e.g. passwords). Used so the log won't contain sensitive data
plain-text, as the log is
saved on client machines plain-text.
:param sensitive_data: the data to hash.
:return: the hashed data.
"""
password_hashed = hashlib.sha512(sensitive_data.encode()).hexdigest()
return password_hashed
exploit_user_list = ["Administrator", "root", "user"]
exploit_password_list = ["Password1!", "1234", "password", "12345678"]
exploit_lm_hash_list = []
exploit_ntlm_hash_list = []
exploit_ssh_keys = []
aws_access_key_id = ""
aws_secret_access_key = ""
aws_session_token = ""
# smb/wmi exploiter
smb_download_timeout = 300 # timeout in seconds
smb_service_name = "InfectionMonkey"
###########################
# post breach actions
###########################
post_breach_actions = []
custom_PBA_linux_cmd = ""
custom_PBA_windows_cmd = ""
PBA_linux_filename = None
PBA_windows_filename = None
keep_tunnel_open_time = 30
###########################
# testing configuration
###########################
export_monkey_telems = False
def get_hop_distance_to_island(self):
return self.max_depth - self.depth
WormConfiguration = Configuration()

View File

@ -1,33 +1,24 @@
import json
import logging
import platform
from datetime import datetime
from pprint import pformat
from socket import gethostname
from urllib.parse import urljoin
import requests
from requests.exceptions import ConnectionError
import infection_monkey.monkeyfs as monkeyfs
import infection_monkey.tunnel as tunnel
from common.common_consts.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
from common.common_consts.time_formats import DEFAULT_TIME_FORMAT
from common.common_consts.timeouts import (
LONG_REQUEST_TIMEOUT,
MEDIUM_REQUEST_TIMEOUT,
SHORT_REQUEST_TIMEOUT,
)
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
from infection_monkey.config import GUID, WormConfiguration
from infection_monkey.network.info import local_ips
from infection_monkey.network.info import get_host_subnets, local_ips
from infection_monkey.transport.http import HTTPConnectProxy
from infection_monkey.transport.tcp import TcpProxy
from infection_monkey.utils import agent_process
from infection_monkey.utils.environment import is_windows_os
requests.packages.urllib3.disable_warnings()
logger = logging.getLogger(__name__)
DOWNLOAD_CHUNK = 1024
PBA_FILE_DOWNLOAD = "https://%s/api/pba/download/%s"
@ -53,10 +44,11 @@ class ControlClient(object):
"guid": GUID,
"hostname": hostname,
"ip_addresses": local_ips(),
"networks": get_host_subnets(),
"description": " ".join(platform.uname()),
"config": WormConfiguration.as_dict(),
"parent": parent,
"launch_time": str(datetime.now().strftime(DEFAULT_TIME_FORMAT)),
"launch_time": agent_process.get_start_time(),
}
if ControlClient.proxies:
@ -138,28 +130,6 @@ class ControlClient(object):
else:
ControlClient.proxies["https"] = f"{proxy_address}:{proxy_port}"
@staticmethod
def keepalive():
if not WormConfiguration.current_server:
return
try:
monkey = {}
if ControlClient.proxies:
monkey["tunnel"] = ControlClient.proxies.get("https")
requests.patch( # noqa: DUO123
"https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
data=json.dumps(monkey),
headers={"content-type": "application/json"},
verify=False,
proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
except Exception as exc:
logger.warning(
"Error connecting to control server %s: %s", WormConfiguration.current_server, exc
)
return {}
@staticmethod
def send_telemetry(telem_category, json_data: str):
if not WormConfiguration.current_server:
@ -208,7 +178,7 @@ class ControlClient(object):
return
try:
reply = requests.get( # noqa: DUO123
"https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
"https://%s/api/monkey/%s/legacy" % (WormConfiguration.current_server, GUID),
verify=False,
proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
@ -258,108 +228,6 @@ class ControlClient(object):
)
return {}
@staticmethod
def check_for_stop():
ControlClient.load_control_config()
return not WormConfiguration.alive
@staticmethod
def download_monkey_exe(host):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host(host)
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def download_monkey_exe_by_os(is_windows, is_32bit):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host_dict(
ControlClient.spoof_host_os_info(is_windows, is_32bit)
)
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def spoof_host_os_info(is_windows, is_32bit):
if is_windows:
os = "windows"
if is_32bit:
arch = "x86"
else:
arch = "amd64"
else:
os = "linux"
if is_32bit:
arch = "i686"
else:
arch = "x86_64"
return {"os": {"type": os, "machine": arch}}
@staticmethod
def download_monkey_exe_by_filename(filename, size):
if not WormConfiguration.current_server:
return None
try:
dest_file = monkeyfs.virtual_path(filename)
if (monkeyfs.isfile(dest_file)) and (size == monkeyfs.getsize(dest_file)):
return dest_file
else:
download = requests.get( # noqa: DUO123
"https://%s/api/monkey/download/%s"
% (WormConfiguration.current_server, filename),
verify=False,
proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
with monkeyfs.open(dest_file, "wb") as file_obj:
for chunk in download.iter_content(chunk_size=DOWNLOAD_CHUNK):
if chunk:
file_obj.write(chunk)
file_obj.flush()
if size == monkeyfs.getsize(dest_file):
return dest_file
except Exception as exc:
logger.warning(
"Error connecting to control server %s: %s", WormConfiguration.current_server, exc
)
@staticmethod
def get_monkey_exe_filename_and_size_by_host(host):
return ControlClient.get_monkey_exe_filename_and_size_by_host_dict(host.as_dict())
@staticmethod
def get_monkey_exe_filename_and_size_by_host_dict(host_dict):
if not WormConfiguration.current_server:
return None, None
try:
reply = requests.post( # noqa: DUO123
"https://%s/api/monkey/download" % (WormConfiguration.current_server,),
data=json.dumps(host_dict),
headers={"content-type": "application/json"},
verify=False,
proxies=ControlClient.proxies,
timeout=LONG_REQUEST_TIMEOUT,
)
if 200 == reply.status_code:
result_json = reply.json()
filename = result_json.get("filename")
if not filename:
return None, None
size = result_json.get("size")
return filename, size
else:
return None, None
except Exception as exc:
logger.warning(
"Error connecting to control server %s: %s", WormConfiguration.current_server, exc
)
return None, None
@staticmethod
def create_control_tunnel():
if not WormConfiguration.current_server:
@ -377,7 +245,12 @@ class ControlClient(object):
proxy_class = HTTPConnectProxy
target_addr, target_port = None, None
return tunnel.MonkeyTunnel(proxy_class, target_addr=target_addr, target_port=target_port)
return tunnel.MonkeyTunnel(
proxy_class,
keep_tunnel_open_time=WormConfiguration.keep_tunnel_open_time,
target_addr=target_addr,
target_port=target_port,
)
@staticmethod
def get_pba_file(filename):
@ -390,55 +263,3 @@ class ControlClient(object):
)
except requests.exceptions.RequestException:
return False
@staticmethod
def get_T1216_pba_file():
try:
return requests.get( # noqa: DUO123
urljoin(
f"https://{WormConfiguration.current_server}/",
T1216_PBA_FILE_DOWNLOAD_PATH,
),
verify=False,
proxies=ControlClient.proxies,
stream=True,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
except requests.exceptions.RequestException:
return False
@staticmethod
def should_monkey_run(vulnerable_port: str) -> bool:
if (
vulnerable_port
and WormConfiguration.get_hop_distance_to_island() > 1
and ControlClient.can_island_see_port(vulnerable_port)
and WormConfiguration.started_on_island
):
return False
return True
@staticmethod
def can_island_see_port(port):
try:
url = (
f"https://{WormConfiguration.current_server}/api/monkey_control"
f"/check_remote_port/{port}"
)
response = requests.get( # noqa: DUO123
url, verify=False, timeout=SHORT_REQUEST_TIMEOUT
)
response = json.loads(response.content.decode())
return response["status"] == "port_visible"
except requests.exceptions.RequestException:
return False
@staticmethod
def report_start_on_island():
requests.post( # noqa: DUO123
f"https://{WormConfiguration.current_server}/api/monkey_control/started_on_island",
data=json.dumps({"started_on_island": True}),
verify=False,
timeout=MEDIUM_REQUEST_TIMEOUT,
)

View File

@ -0,0 +1,7 @@
from .credential_components.nt_hash import NTHash
from .credential_components.lm_hash import LMHash
from .credential_components.password import Password
from .credential_components.username import Username
from .credential_components.ssh_keypair import SSHKeypair
from .mimikatz_collector import MimikatzCredentialCollector
from .ssh_collector import SSHCredentialCollector

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass, field
from common.common_consts.credential_component_type import CredentialComponentType
from infection_monkey.i_puppet import ICredentialComponent
@dataclass(frozen=True)
class LMHash(ICredentialComponent):
credential_type: CredentialComponentType = field(
default=CredentialComponentType.LM_HASH, init=False
)
lm_hash: str

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass, field
from common.common_consts.credential_component_type import CredentialComponentType
from infection_monkey.i_puppet import ICredentialComponent
@dataclass(frozen=True)
class NTHash(ICredentialComponent):
credential_type: CredentialComponentType = field(
default=CredentialComponentType.NT_HASH, init=False
)
nt_hash: str

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass, field
from common.common_consts.credential_component_type import CredentialComponentType
from infection_monkey.i_puppet import ICredentialComponent
@dataclass(frozen=True)
class Password(ICredentialComponent):
credential_type: CredentialComponentType = field(
default=CredentialComponentType.PASSWORD, init=False
)
password: str

View File

@ -0,0 +1,13 @@
from dataclasses import dataclass, field
from common.common_consts.credential_component_type import CredentialComponentType
from infection_monkey.i_puppet import ICredentialComponent
@dataclass(frozen=True)
class SSHKeypair(ICredentialComponent):
credential_type: CredentialComponentType = field(
default=CredentialComponentType.SSH_KEYPAIR, init=False
)
private_key: str
public_key: str

View File

@ -0,0 +1,12 @@
from dataclasses import dataclass, field
from common.common_consts.credential_component_type import CredentialComponentType
from infection_monkey.i_puppet import ICredentialComponent
@dataclass(frozen=True)
class Username(ICredentialComponent):
credential_type: CredentialComponentType = field(
default=CredentialComponentType.USERNAME, init=False
)
username: str

View File

@ -0,0 +1 @@
from .mimikatz_credential_collector import MimikatzCredentialCollector

Some files were not shown because too many files have changed in this diff Show More