diff --git a/README-K8S.md b/README-K8S.md new file mode 100644 index 0000000000..47ef645e6f --- /dev/null +++ b/README-K8S.md @@ -0,0 +1,47 @@ +# Kubernetes based Todolist + Log4Shell exploit +To deploy Todolist on Kubernetes along with the needed ldap backend for exploiting the Log4shell +vulnerability: + +## Prerequisites +1. A kubernetes cluster where you have permissions to create namespaces, deployments and services +2. The `kubectl` client and credenials configuration +3. Docker Desktop or docker-ce (for building and pushing images) +4. A DockerHub account that you are logged in with at the command prompt (via `docker login`) + +## Quickstart +Assuming you have your kubernetes cluster up and ready, from the top level of this repo you can run `./k8s-quickstart.sh` which will do the following: +1. Builds todolist-goof image and pushes it to Docker Hub. _(see below for account/tagging info)_ +2. Deploys the todolist to the `default` namespace in your kubernetes cluster along with a LoadBalancer type service +3. Builds the log4shell-server image and pushes to Docker Hub. _(see below for account/tagging info)_ +4. Deploys the log4shell-server and a pair of ClusterIP type services into a new namespace named `darkweb` in your Kubernetes cluster. + +NOTE: You will be prompted for your DockerHub account in order for the scripts to tag, push and pull the images. +If you set and environmental variable named `DOCKER_ACCOUNT` to that account name, the script will pre-populate that prompt with it. +```bash +export DOCKER_ACCOUNT="yourdockeraccount" +``` +## Accessing the application +Once complete, run `kubectl get svc` and note the IP Address or hostname of the `goof` service. + +You should be able to open a browser to http://{svc-ip-addr}/todolist and see the app + +#### EKS cluster notes +* In order to perform NetworkPolicy egress examples, you will need to deploy the Calico CNI plugin as EKS does not implement NetworkPolicy by default. + The `eks-calico.sh` script in `todolist-goof/k8s` will deploy this for you. (that script is sym-linked to the top level here too) +* You should log into the AWS console and change inbound access for the good service's ELB to only allow your home IP, otherwise you *will* have audience members trying to mess with it. + +#### Docker Desktop Kubernetes notes +* Docker Desktop automatically serves the goof service loadblancer external IP to your workstation's localhost so the app will be available at http://localhost/todolist +* Docker Desktop Kubernetes CNI does not implement Network Policy so you will not be able to demonstrate any mitigation techniques that use that. + +#### Kind (Kubernetes on Docker) notes +* Kind's default CNI does not currently support Network Policy so you should deploy your own using the instructions on their website. +* If running Kind on top of Docker Desktop, you will need to run a port-forward to access the app. For example, use something like this: `kubectl port-forward service/goof 8000:80` and then access it via browser at http://localhost:8000/todolist + +## Quick cleanup +Run the `/.k8s-quickstop.sh` script at the top level of this repo which will do the following: +1. Deletes the todolist deployment and associated service in the `default` namespace +2. Deletes the log4shell deployment and associated services in the `darkweb` namespace and deltes the namespace as well + **Note:** This will not delete any additional objects you may have deployed such as NetworkPolicies. + +It is up to you to shut down your Kubernetes cluster as appropriate. \ No newline at end of file diff --git a/README.md b/README.md index b9e44272f0..9e47442aab 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,4 @@ It's divided into modules, each one having its own README: * [Todolist Goof](todolist-goof/README.md) * [Log4Shell Goof](log4shell-goof/README.md) +* [Quickstart for running both Todolist with Log4Shell in Kubernetes](README-K8S.md) \ No newline at end of file diff --git a/eks-calico.sh b/eks-calico.sh new file mode 120000 index 0000000000..3ba949bb63 --- /dev/null +++ b/eks-calico.sh @@ -0,0 +1 @@ +todolist-goof/k8s/eks-calico.sh \ No newline at end of file diff --git a/k8s-quickstart.sh b/k8s-quickstart.sh new file mode 100755 index 0000000000..99ba928435 --- /dev/null +++ b/k8s-quickstart.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +TOP_LEVEL_MYDIR=$(dirname $0) +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi +$TOP_LEVEL_MYDIR/todolist-goof/k8s/quickstart.sh $DOCKER_ACCOUNT +$TOP_LEVEL_MYDIR/log4shell-goof/log4shell-server/k8s/quickstart.sh $DOCKER_ACCOUNT diff --git a/k8s-quickstop.sh b/k8s-quickstop.sh new file mode 100755 index 0000000000..8d53f88879 --- /dev/null +++ b/k8s-quickstop.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +TOP_LEVEL_MYDIR=$(dirname $0) +$TOP_LEVEL_MYDIR/todolist-goof/k8s/shutdown.sh +$TOP_LEVEL_MYDIR/log4shell-goof/log4shell-server/k8s/shutdown.sh diff --git a/log4shell-goof/log4shell-server/k8s/imagebuild.sh b/log4shell-goof/log4shell-server/k8s/imagebuild.sh index 141fba743a..15e7d8e146 100755 --- a/log4shell-goof/log4shell-server/k8s/imagebuild.sh +++ b/log4shell-goof/log4shell-server/k8s/imagebuild.sh @@ -1,6 +1,10 @@ #!/usr/bin/env bash -read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input -name="${input:-$DOCKER_ACCOUNT}" +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi echo "📦 Building image ${DOCKER_ACCOUNT}/log4shell-server:latest ..." docker build -t ${DOCKER_ACCOUNT}/log4shell-server:latest . diff --git a/log4shell-goof/log4shell-server/k8s/quickstart.sh b/log4shell-goof/log4shell-server/k8s/quickstart.sh new file mode 100755 index 0000000000..73dc31e4f8 --- /dev/null +++ b/log4shell-goof/log4shell-server/k8s/quickstart.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +LOG4SHELL_MYDIR=$(dirname $0) +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi + +$LOG4SHELL_MYDIR/imagebuild.sh $DOCKER_ACCOUNT +$LOG4SHELL_MYDIR/startup.sh $DOCKER_ACCOUNT + + diff --git a/log4shell-goof/log4shell-server/k8s/startup.sh b/log4shell-goof/log4shell-server/k8s/startup.sh index 55fd3d0bc7..b15aab4f4e 100755 --- a/log4shell-goof/log4shell-server/k8s/startup.sh +++ b/log4shell-goof/log4shell-server/k8s/startup.sh @@ -1,7 +1,11 @@ #!/usr/bin/env bash MYDIR=$(dirname $0) -read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input -name="${input:-$DOCKER_ACCOUNT}" +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi cat $MYDIR/deploy.yaml | envsubst | kubectl apply -f - diff --git a/todolist-goof/Dockerfile b/todolist-goof/Dockerfile index d37dfaeafa..399722f197 100644 --- a/todolist-goof/Dockerfile +++ b/todolist-goof/Dockerfile @@ -12,3 +12,11 @@ COPY --chown=tomcat:tomcat web.xml /usr/local/tomcat/conf/web.xml COPY --from=build /usr/src/goof/todolist-web-struts/target/todolist /usr/local/tomcat/webapps/todolist COPY --from=build /usr/local/openjdk-8/bin/native2ascii /docker-java-home/jre/bin/native2ascii COPY --from=build /usr/local/openjdk-8/lib/tools.jar /docker-java-home/jre/lib/tools.jar + + + + + + +#Uncomment the next line for log4shell vulnerability if using base tomcat image > 8.5.33 +#ENV JAVA_OPTS="-Dcom.sun.jndi.ldap.object.trustURLCodebase=true" diff --git a/todolist-goof/k8s/eks-calico.sh b/todolist-goof/k8s/eks-calico.sh new file mode 100755 index 0000000000..833d8df66f --- /dev/null +++ b/todolist-goof/k8s/eks-calico.sh @@ -0,0 +1,3 @@ +#!/bin/bash +kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-operator.yaml +kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-crs.yaml diff --git a/todolist-goof/k8s/imagebuild.sh b/todolist-goof/k8s/imagebuild.sh index c2c0c778e8..f5086c5acc 100755 --- a/todolist-goof/k8s/imagebuild.sh +++ b/todolist-goof/k8s/imagebuild.sh @@ -1,9 +1,14 @@ #!/usr/bin/env bash -read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input -name="${input:-$DOCKER_ACCOUNT}" +MYDIR=$(dirname $0) +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi echo "📦 Building image ${DOCKER_ACCOUNT}/java-goof:latest ..." -docker build -t ${DOCKER_ACCOUNT}/java-goof:latest . +docker build -t ${DOCKER_ACCOUNT}/java-goof:latest $MYDIR/.. echo echo "🚚 Pushing image to DockerHub..." docker push ${DOCKER_ACCOUNT}/java-goof:latest diff --git a/todolist-goof/k8s/java-goof2.yaml b/todolist-goof/k8s/java-goof2.yaml new file mode 100644 index 0000000000..a375365181 --- /dev/null +++ b/todolist-goof/k8s/java-goof2.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: goof + name: goof + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: goof + template: + metadata: + labels: + app: goof + spec: + containers: + - image: ${DOCKER_ACCOUNT}/java-goof:latest + imagePullPolicy: Always + name: java-goof + securityContext: + runAsNonRoot: true + runAsUser: 65534 #nobody + runAsGroup: 65534 #nobody + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: goof + name: goof +spec: + type: LoadBalancer + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: goof diff --git a/todolist-goof/k8s/quickstart.sh b/todolist-goof/k8s/quickstart.sh new file mode 100755 index 0000000000..84dc7ef367 --- /dev/null +++ b/todolist-goof/k8s/quickstart.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +TODO_MYDIR=$(dirname $0) +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi + +$TODO_MYDIR/imagebuild.sh $DOCKER_ACCOUNT +$TODO_MYDIR/startup.sh $DOCKER_ACCOUNT + + diff --git a/todolist-goof/k8s/startup.sh b/todolist-goof/k8s/startup.sh index ce97ea83cc..dc679ceb15 100755 --- a/todolist-goof/k8s/startup.sh +++ b/todolist-goof/k8s/startup.sh @@ -1,7 +1,12 @@ #!/usr/bin/env bash MYDIR=$(dirname $0) -read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input -name="${input:-$DOCKER_ACCOUNT}" + +if [[ "$1" == "" ]]; then + read -e -i "${DOCKER_ACCOUNT}" -p "Please enter your DockerHub user/account name: " input + name="${input:-$DOCKER_ACCOUNT}" +else + DOCKER_ACCOUNT=$1 +fi cat $MYDIR/java-goof.yaml | envsubst | kubectl apply -f -