Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/lint-scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
line1=$(sed -n '1p' "$script")
line2=$(sed -n '2p' "$script")
line3=$(sed -n '3p' "$script")
line4=$(sed -n '4p' "$script")

if ! echo "$line1" | grep -qE '^#!'; then
echo "FAIL: $name: line 1 is not a shebang (got: $line1)"
Expand All @@ -38,8 +39,12 @@ jobs:
echo "FAIL: $name: line 2 missing '# Shortname: <name>' (got: $line2)"
failed=1
fi
if ! echo "$line3" | grep -qE '^# Description: .+'; then
echo "FAIL: $name: line 3 missing '# Description: <text>' (got: $line3)"
if ! echo "$line3" | grep -qE '^# Severity: (Critical|High|Medium|Low)$'; then
echo "FAIL: $name: line 3 missing '# Severity: <Critical|High|Medium|Low>' (got: $line3)"
failed=1
fi
if ! echo "$line4" | grep -qE '^# Description: .+'; then
echo "FAIL: $name: line 4 missing '# Description: <text>' (got: $line4)"
failed=1
fi
done
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ For Docker, use the following command to run the detection container interactive
sudo docker run --rm -it quay.io/crowdstrike/detection-container
```

For Kubernetes environments, refer to the [vulnapp project](https://github.com/CrowdStrike/vulnapp) for running the detection container interactively.
For a graphical, browser-based experience, see [Web Frontend (VulnApp)](#web-frontend-vulnapp) below.

### Web Frontend (VulnApp)

[VulnApp](https://github.com/CrowdStrike/vulnapp) wraps this detection container in a Go web application, giving you a graphical, browser-based way to trigger detections instead of the TUI. It ships deployment manifests for both generic Kubernetes and OpenShift. See the [vulnapp project](https://github.com/CrowdStrike/vulnapp) for setup and deployment instructions.

### Non-interactive Mode

Expand Down
1 change: 1 addition & 0 deletions bin/Collection_via_Automated_Collection.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: credentials_dumping_collection
# Severity: High
# Description: Attempts to dump credentials from /etc/passwd to /tmp/passwords.

echo -e "\e[92mExecuting Collection via Automated Collection script. Trying to dump information from etc/passwd"
Expand Down
1 change: 1 addition & 0 deletions bin/Command_Control_via_Remote_Access-obfuscated.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: reverse_shell-obfuscated
# Severity: High
# Description: Attempts to connect to a remote IP address and will exit at
# fork. Falcon Prevent will kill the attempt. (obfuscated version)

Expand Down
1 change: 1 addition & 0 deletions bin/Command_Control_via_Remote_Access.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: reverse_shell
# Severity: High
# Description: Attempts to connect to a remote IP address and will exit at fork. Falcon Prevent will kill the attempt.

echo -e "\e[92mExecuting Command and Control via Remote Access Tools using Ruby script. This script will try to connect to 192.168.1.222 and will exit at fork. A Falcon Prevent action can kill the attempt"
Expand Down
1 change: 1 addition & 0 deletions bin/ContainerDrift_Via_File_Creation_and_Execution.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: container_drift
# Severity: Medium
# Description: Container Drift via file creation script. Creating a file and then executing it.

echo -e "\e[92mExecuting Container Drift via file creation script. Creating a file and then executing it."
Expand Down
1 change: 1 addition & 0 deletions bin/Credential_Access_via_Credential_Dumping.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: credentials_dumping
# Severity: High
# Description: Runs mimipenguin and tries to dump passwords from inside the container environment.

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
Expand Down
1 change: 1 addition & 0 deletions bin/Defense_Evasion_via_Rootkit.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: rootkit
# Severity: Critical
# Description: This script will change the group owner of /etc/ld.so.preload to 0, indicative of a Jynx Rootkit.

echo -e "\e[92mExecuting Defense Evasion via Rootkit. This script will change the group owner to '0' of /etc/ld.so.preload indicative for a Jynx Rootkit"
Expand Down
1 change: 1 addition & 0 deletions bin/Execution_via_Command-Line_Interface.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: suspicious_commands
# Severity: High
# Description: Emulate malicious activity related to suspicious CLI commands. Runs the command sh -c whoami '[S];pwd;echo [E]'.

echo -e "\e[92mExecuting Execution via Command-Line Interface. This script is causing malicious activity related suspicious CLI commands."
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/bash
# Shortname: data_exfiltration-alternate_protocol
# Severity: High
# Description: Attempts to exfiltrate data using DNS dig requests that contain system data in the hostname.

echo -e "\e[92mExecuting Exfiltration Over Alternative Protocol using a DNS tool sending requests to large domain names. This will take a moment to execute..."
Expand Down
1 change: 1 addition & 0 deletions bin/Impact_via_Data_Encrypted_for_Impact.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: ransomware
# Severity: High
# Description: Simulates LockBit file encryption by renaming files with the
# .lockbit extension
#
Expand Down
1 change: 1 addition & 0 deletions bin/Persistence_via_External_Remote_Services.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: remote_service_persistence
# Severity: High
# Description: Attempts to create persistence to 192.168.1.222 via External Remote Services via Python script. Falcon Prevent will kill the attempt.

echo -e "\e[92mExecuting Persistence via External Remote Services via Python script. This script will try creating persistence to 192.168.1.222. A Falcon Prevent action can kill the attempt."
Expand Down
1 change: 1 addition & 0 deletions bin/Reverse_Shell_Trojan.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: reverse_shell_trojan
# Severity: High
# Description: Executes an inert trojan that will attempt to connect to 192.168.0.1 on TCP port 444. Aggressive Machine Learning prevention policy settings will kill the attempt.

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
Expand Down
1 change: 1 addition & 0 deletions bin/Webserver_Bash_Reverse_Shell.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: data_exfiltration-reverse_shell
# Severity: High
# Description: Attempts Command Injection to execute reverse shell.

echo -e "\e[92mExecuting Command Injection to execute reverse shell."
Expand Down
1 change: 1 addition & 0 deletions bin/Webserver_Suspicious_Terminal_Spawn.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: command_injection-suspicious_terminal
# Severity: High
# Description: Executes a command injection to Spawn a Suspicious Terminal using PHP.

echo -e "\e[92mExecuting Command Injection to Spawn a Suspicious Terminal. This script executes a command injection, which writes a file to http://webserver/uploads/test.php, then executes that script"
Expand Down
1 change: 1 addition & 0 deletions bin/Webserver_Unexpected_Child_of_Web_Service.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/sh
# Shortname: data_exfiltration-mysql
# Severity: High
# Description: Executing Command Injection to dump MySQL Server tables.

echo -e "\e[92mExecuting Command Injection to dump MySQL Server tables."
Expand Down
1 change: 1 addition & 0 deletions bin/metasploit/Webserver_Trigger_Metasploit_Payload.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#/bin/sh
# Severity: Medium

echo -e "\e[92mSimulate a malicious file upload, which executes a reverse TCP meterpreter to Kali on port 4444\n"
echo -e "This scenario is multi-step, please follow these actions before confirming the Kali IP address:\n"
Expand Down
133 changes: 128 additions & 5 deletions menu/auto
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,136 @@ controlc()
# Function to handle interrupts
{
echo "User abort request..."
exit
exit
}

trap controlc 2

# Get available tests
flist=($(cd ./bin && ls -1 *.sh))
# Scenario scripts live here; override SCENARIO_DIR for local testing.
SCENARIO_DIR="${SCENARIO_DIR:-/home/eval/scenarios}"
# Detection scenarios provided by the upstream base image.
DETECTIONS_DIR="${DETECTIONS_DIR:-/home/eval/bin}"

# scenario_field FILE FIELD — echo the value of a "# Field:" header comment,
# read from the first lines of a scenario script. Case-insensitive field match.
# Mirrors the helper in menu/run so both derive the scenario list the same way.
scenario_field(){
local file="$1" field="$2"
grep -iE "^# ${field}:" "$file" 2>/dev/null | head -1 | cut -d: -f2- | sed -E 's/^[[:space:]]+//'
}

# discover FILE... — emit one "display_name<US>shortname<US>script_path" line
# per existing script (US = ASCII unit separator \037), ordered by each script's
# "# Order:" header (ascending; missing order defaults to 9999, then
# alphabetical). Name falls back to the filename; shortname comes from
# "# Shortname:" (may be empty). A non-whitespace separator is required: with a
# tab separator, `read` collapses the two tabs around an empty shortname and
# shifts the path into the wrong field. Same helper as menu/run.
discover(){
local sorted f order
sorted=$(
for f in "$@"; do
[ -e "$f" ] || continue
order=$(scenario_field "$f" "Order")
[[ "$order" =~ ^[0-9]+$ ]] || order=9999
printf '%s\t%s\n' "$order" "$f"
done | sort -k1,1n -k2,2
)
[ -z "$sorted" ] && return

local path name shortname
while IFS=$'\t' read -r _ path; do
name=$(scenario_field "$path" "Name")
if [ -z "$name" ]; then
name=$(basename "$path" .sh | tr '_' ' ')
fi
shortname=$(scenario_field "$path" "Shortname")
printf '%s\037%s\037%s\n' "$name" "$shortname" "$path"
done <<< "$sorted"
}

# run_scenarios SELECTION — non-interactive driver for the RUN_SCENARIOS env var.
# SELECTION is "all" or a comma-separated list of scenario numbers and/or
# "# Shortname:" slugs (e.g. "1,supply_chain_attack,3"). Numbers and shortnames
# resolve against the SCENARIO_DIR scenarios, ordered by "# Order:" — the
# base-image detections in DETECTIONS_DIR are NOT included. Runs each selection
# once, in the order given, and exits non-zero if any token could not be resolved.
run_scenarios(){
local selection="$1"

# Scenario list only — RUN_SCENARIOS covers SCENARIO_DIR scripts, not the
# base-image detections. Parallel arrays of shortname + path, indexed 1..N by
# position (number == index + 1), matching the numbers menu/run shows.
local shorts=() paths=()
while IFS=$'\037' read -r name short path; do
[ -z "$name" ] && continue
shorts+=("$short"); paths+=("$path")
done < <(discover "$SCENARIO_DIR"/*.sh)

# Build the ordered list of scripts to run.
local to_run=() rc=0 tok i found

if [ "$selection" = "all" ]; then
to_run=("${paths[@]}")
else
IFS=',' read -ra tokens <<< "$selection"
for tok in "${tokens[@]}"; do
tok="${tok#"${tok%%[![:space:]]*}"}" # trim leading space
tok="${tok%"${tok##*[![:space:]]}"}" # trim trailing space
[ -z "$tok" ] && continue

if [[ "$tok" =~ ^[0-9]+$ ]]; then
if [ "$tok" -ge 1 ] && [ "$tok" -le "${#paths[@]}" ]; then
to_run+=("${paths[$((tok-1))]}")
else
echo "[ERROR] Invalid scenario number: '$tok' (valid: 1-${#paths[@]})" >&2
rc=1
fi
continue
fi

# Shortname match (case-insensitive) against the combined list.
found=""
for i in "${!shorts[@]}"; do
if [ "$(echo "${shorts[$i]}" | tr '[:upper:]' '[:lower:]')" = "$(echo "$tok" | tr '[:upper:]' '[:lower:]')" ]; then
found="${paths[$i]}"; break
fi
done

if [ -n "$found" ]; then
to_run+=("$found")
else
echo "[ERROR] Unknown scenario: '$tok' (use a number 1-${#paths[@]} or a # Shortname: slug)" >&2
rc=1
fi
done
fi

# Execute the resolved scripts once each, in order.
local script
for script in "${to_run[@]}"; do
echo ""
echo "=== Running $(basename "$script") ==="
sh -c 'echo CS_testcontainer'
"$script" || echo "[WARN] $(basename "$script") exited $?"
done

return $rc
}

# Non-interactive entry: if RUN_SCENARIOS is set, resolve and run it, then exit.
if [ -n "${RUN_SCENARIOS:-}" ]; then
run_scenarios "$RUN_SCENARIOS"
exit $?
fi

# Default (no RUN_SCENARIOS): random-interval loop over scenarios + detections.
# Get available tests: scenarios first, then base-image detections. Full paths so
# both directories can be drawn from a single list.
flist=()
for f in "$SCENARIO_DIR"/*.sh "$DETECTIONS_DIR"/*.sh; do
[ -e "$f" ] && flist+=("$f")
done
length=${#flist[@]}

# Set interval randomization limits
Expand All @@ -23,7 +146,7 @@ difftime=$((maxtime-mintime+1))
# Show what tests will be run
for i in "${flist[@]}"
do
tname=`echo $i|cut -d'.' -f1| tr '_' ' '`
tname=`basename "$i" | cut -d'.' -f1 | tr '_' ' '`
echo "Adding test $tname"
done

Expand All @@ -34,7 +157,7 @@ while true; do
sleep $timeout
testtorun=$(($RANDOM%$length))
sh -c echo CS_testcontainer
./bin/${flist[$testtorun]}
"${flist[$testtorun]}"
timeout=$(($(($RANDOM%$difftime))+mintime))
echo "Sleeping $timeout seconds"
done
Loading
Loading