Skip to content

Latest commit

 

History

History
329 lines (276 loc) · 22.6 KB

README.md

File metadata and controls

329 lines (276 loc) · 22.6 KB

Container image with malware and crypto miner for testing purposes

Container build Artifact Hub Docker Image Size (latest semver) GitHub release (latest SemVer)

Ransomware Malware Threat Actor

I decided to build minimal nginx based container image which contains malware / ransomware / crypto miner / ...

Security tools should be able to scan the image and discover harmful files.

Running/starting the container image do not "activate" / "execute" the malware.

The malware files inside container image were downloaded from:

The malware/crypto miner files are located in the /usr/share/nginx/html directory:

/usr/share/nginx/html
├── eicar
│   ├── eicar.com                        [EICAR virus test files]
│   ├── eicar.com.txt                    [EICAR virus test files]
│   └── eicarcom2.zip                    [Zip archive data, at least v1.0 to extract]
├── malware
│   ├── ILOVEYOU.vbs                     [C source, ASCII text]
│   ├── Invoke-ConPtyShell.ps1           [ASCII text, with very long lines (361)]
│   ├── L0Lz.bat                         [DOS batch file, ASCII text]
│   ├── Linux.Trojan.Multiverze.elf.x86  [ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, with debug_info, not stripped]
│   ├── MadMan.exe                       [MS-DOS executable, MZ for MS-DOS]
│   ├── Melissa.doc                      [Composite Document File V2 Document, Little Endian, Os: Windows, Version 4.10, Code page: 1252, Title: Password List for March 26th 1999, Subject: Adult Website Passwords, Author: John Holmes, Keywords: 73 sites in this list, Comments: Password List for March 26th 1999, Template: Normal.dot, Last Saved By: Him, Revision Number: 2, Name of Creating Application: Microsoft Word 8.0, Create Time/Date: Fri Mar 26 11:39:00 1999, Last Saved Time/Date: Fri Mar 26 11:39:00 1999, Number of Pages: 2, Number of Words: 745, Number of Characters: 4249, Security: 0]
│   ├── Py.Trojan.NecroBot.py            [Python script, ASCII text executable, with very long lines (4330), with CRLF line terminators]
│   ├── Trojan.Java.Fractureiser.MTB.jar [Java archive data (JAR)]
│   ├── TrojanSpy.MacOS.XCSSET.A.bin     [Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>]
│   ├── Txt.Malware.Sustes.sh            [Bourne-Again shell script, ASCII text executable]
│   ├── Unix.Downloader.Rocke.sh         [POSIX shell script, ASCII text executable]
│   ├── Unix.Malware.Kaiji.elf.arm       [ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, Go, stripped]
│   ├── Unix.Trojan.Mirai.elf.m68k       [ELF 32-bit MSB executable, Motorola m68k, 68020, version 1 (SYSV), statically linked, stripped]
│   ├── Unix.Trojan.Mirai.elf.mips       [ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, not stripped]
│   ├── Unix.Trojan.Mirai.elf.ppc        [ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), statically linked, not stripped]
│   ├── Unix.Trojan.Mirai.elf.sparc      [ELF 32-bit MSB executable, SPARC, version 1 (SYSV), statically linked, not stripped]
│   ├── Unix.Trojan.Mirai.elf.x86_64     [ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped]
│   ├── Unix.Trojan.Spike.elf.arm        [ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, with debug_info, not stripped]
│   ├── Walker.com                       [DOS executable (COM), start instruction 0xe9cd04e8 5400e871]
│   ├── WannaCry.exe                     [PE32 executable (GUI) Intel 80386, for MS Windows, 4 sections]
│   ├── Win.Trojan.Perl.perl             [Perl script text executable]
│   └── Zloader.xlsm                     [Microsoft Excel 2007+]
└── xmrig
    ├── my-xmrig                         [ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped]
    ├── xmrig                            [ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped]
    └── xmrig-linux-static-x64.tar.gz    [gzip compressed data, from Unix, original size modulo 2^32 8291840]

List of malware/ransomware/crypto miner files:

Deployment of the vulnerable image

There are several ways how to run the "malware container image" and there are few of them.

Note: Running the container image is not harmful for the host system.

CloudFormation - EC2 instance

Run the EC2 instance with docker and the quay.io/petr_ruzicka/malware-cryptominer-container container with SSM enabled (only console access):

export AWS_DEFAULT_REGION="eu-central-1"

aws cloudformation deploy --capabilities CAPABILITY_IAM \
  --stack-name "${USER}-malware-cryptominer-container-ec2" \
  --parameter-overrides "ContainerImage=quay.io/petr_ruzicka/malware-cryptominer-container:3" \
  --template-file EC2InstanceWithDockerSample.yaml \
  --tags "Name=${USER}-malware-cryptominer-container-ec2"

# aws cloudformation delete-stack --stack-name ${USER}-malware-cryptominer-container-ec2

Amazon ECS

Copilot example:

export AWS_DEFAULT_REGION="eu-central-1"

copilot init --app "${USER}-malware-cryptominer-app" --name "${USER}-malware-cryptominer" \
  --image quay.io/petr_ruzicka/malware-cryptominer-container:3 \
  --type 'Load Balanced Web Service' --port 8080 --deploy

# copilot app delete --name "${USER}-malware-cryptominer-app"

Amazon EKS

Run simple Amazon EKS cluster with "malware pod":

export AWS_DEFAULT_REGION="eu-central-1"
export CLUSTER_NAME="${USER}-malware-cryptominer-eks"
export KUBECONFIG="/tmp/kubeconfig-${CLUSTER_NAME}.conf"

eksctl create cluster --name "${CLUSTER_NAME}" --instance-types t3a.small --kubeconfig "${KUBECONFIG}"
kubectl run malware-cryptominer --image=quay.io/petr_ruzicka/malware-cryptominer-container:3

# eksctl delete cluster --name "${CLUSTER_NAME}"

Scanner tests

Details from various scanner tests (Aqua, Trivy, Prisma Cloud, Wiz.io, Grype, Snyk) can be found in Scanner tests

Verify image integrity

CONTAINER_REGISTRY_IMAGE_NAME="quay.io/petr_ruzicka/malware-cryptominer-container"
CONTAINER_IMAGE_TAG="3"
CONTAINER_IMAGE_DIGEST=$(regctl image digest "${CONTAINER_REGISTRY_IMAGE_NAME}:${CONTAINER_IMAGE_TAG}")
CONTAINER_REGISTRY_IMAGE="${CONTAINER_REGISTRY_IMAGE_NAME}@${CONTAINER_IMAGE_DIGEST}"
COSIGN_CERTIFICATE_IDENTITY_REGEXP="https://github.com/ruzickap/malware-cryptominer-container/.github/workflows"
COSIGN_CERTIFICATE_OIDC_ISSUER="https://token.actions.githubusercontent.com"
COSIGN_ATTESTATION_TYPE="https://cyclonedx.org/bom"
CONTAINER_IMAGE_PLATFORMS="linux/amd64,linux/arm64"

# Verify the manifest list is signed
cosign verify \
  --certificate-identity-regexp="${COSIGN_CERTIFICATE_IDENTITY_REGEXP}" \
  --certificate-oidc-issuer="${COSIGN_CERTIFICATE_OIDC_ISSUER}" \
  "${CONTAINER_REGISTRY_IMAGE}" | jq --color-output

# Verify if every platfrom image manifest is signed
while read -r MANIFEST_DIGESTS; do
  cosign verify \
    --certificate-identity-regexp="${COSIGN_CERTIFICATE_IDENTITY_REGEXP}" \
    --certificate-oidc-issuer="${COSIGN_CERTIFICATE_OIDC_ISSUER}" \
    "${CONTAINER_REGISTRY_IMAGE_NAME}@${MANIFEST_DIGESTS}" | jq --color-output
done <<< "$(regctl manifest get "${CONTAINER_REGISTRY_IMAGE}" --format '{{jsonPretty .}}' | jq -r '.manifests[].digest')"

cosign verify-attestation --type="${COSIGN_ATTESTATION_TYPE}" \
  --certificate-oidc-issuer="${COSIGN_CERTIFICATE_OIDC_ISSUER}" \
  --certificate-identity-regexp="${COSIGN_CERTIFICATE_IDENTITY_REGEXP}" \
  "${CONTAINER_REGISTRY_IMAGE}" | jq --color-output '.payload |= .[:2000] + "...<rest_is_removed>..."' --color-output

cosign verify-attestation --type="${COSIGN_ATTESTATION_TYPE}" \
  --certificate-oidc-issuer="${COSIGN_CERTIFICATE_OIDC_ISSUER}" \
  --certificate-identity-regexp="${COSIGN_CERTIFICATE_IDENTITY_REGEXP}" \
  "${CONTAINER_REGISTRY_IMAGE}" | jq '.payload | @base64d | fromjson | .predicate' | grype

for PLATFORM in ${CONTAINER_IMAGE_PLATFORMS//,/ }; do
  cosign download attestation --platform="${PLATFORM}" --predicate-type="${COSIGN_ATTESTATION_TYPE}" \
    "${CONTAINER_REGISTRY_IMAGE}" | jq -r .payload | base64 -d | jq .predicate | grype --add-cpes-if-none
done

cosign verify-attestation --type="slsaprovenance" \
  --certificate-oidc-issuer="${COSIGN_CERTIFICATE_OIDC_ISSUER}" \
  --certificate-identity-regexp='^https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+$' \
  "${CONTAINER_REGISTRY_IMAGE}" | jq --color-output

slsa-verifier verify-image --print-provenance --source-uri "github.com/ruzickap/malware-cryptominer-container" \
  "${CONTAINER_REGISTRY_IMAGE}" | jq --color-output

cosign tree "${CONTAINER_REGISTRY_IMAGE}"

Local tests

Container build:

docker build . -t malware-cryptominer-container

Run container and download the malware file:

docker run -it --rm -p 8080:8080 malware-cryptominer-container

curl http://localhost:8080/eicar/

Debug container:

docker run -it --rm --entrypoint=/bin/sh --user root malware-cryptominer-container

Run in Kubernetes:

kubectl run malware-cryptominer --image=quay.io/petr_ruzicka/malware-cryptominer-container:3