By Dieter Reuter
As we talked about before in this blog, containers are just vulnerable to be attacked as non-container workloads. Hackers can use many of their old tricks on new containers, such as application exploits, network attacks, or phishing scams. In this post and demo, I’ll show how to hack a Kubernetes container using the well-publicized Apache Struts vulnerability which was used in the Equifax data breach.
In order to show how to hack a Kubernetes container, I’ll first install a K8s cluster, then install the NeuVector container security console so we can monitor what’s going on. Then I’ll install a simple java webserver using Apache struts before showing how to hack a Kubernetes container.
You can follow the summary below, or watch the full demo video. We also have a 5-minute quick overview for those of you short on time.
Watch the Demo Webinar
Deploy a Kubernetes Cluster
First, I’ll deploy a 3 node K8s cluster. For this demo I’ll use the Microsoft Azure K8s service AKS. It’s easy to deploy, like below.
Wait a few minutes then the cluster is up and running and ready to go!
Next, I’ll deploy the NeuVector containers from the sample yaml file available from NeuVector. Contact us at [email protected] to request it.
In seconds, the NeuVector containers are deployed and baselining all the network, process and file system activity. Since I haven’t deployed any app containers yet I’ll wait to show you the console.
Deploy App Container
Next I’ll deploy the Apache Struts app on an Alpine Linux distribution. Here are the dockerfile details.
FROM alpine:3.7 AS BUILD RUN apk update RUN apk add wget unzip RUN wget http://archive.apache.org/dist/struts/2.5.12/struts-2.5.12-all.zip RUN unzip -x struts-2.5.12-all.zip FROM tomcat:alpine COPY --from=BUILD /struts-2.5.12/apps/struts2-rest-showcase.war /usr/local/tomcat/webapps/super-app.war
Build the image:
$ docker build -t dieterreuter/struts .
Next, I’ve prepared a yaml file for deploying the Apache struts app on Kubernetes.
apiVersion: v1 kind: Service metadata: name: kube-struts-svc spec: type: LoadBalancer ports: - port: 8080 selector: app: kube-struts-pod --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube-struts-pod spec: replicas: 1 template: metadata: labels: app: kube-struts-pod spec: containers: - name: kube-struts-pod image: dieterreuter/struts securityContext: privileged: true volumeMounts: - mountPath: /var/run/docker.sock name: docker-sock readOnly: false restartPolicy: Always volumes: - name: docker-sock hostPath: path: /var/run/docker.sock
You can also use docker-compose if you want.
struts: image: dieterreuter/struts container_name: struts privileged: true ports: - 8080:8080 volumes: - /var/run/docker.sock:/var/run/docker.sock
Deploy the container on Kubernetes.
$ kubectl create -f kube-struts.yaml
Now let’s take a look at the NeuVector console.
We can see above that normal behavior has been discovered and whitelisted by NeuVector.
Hack a Kubernetes Container
In order to hack a Kubernetes container I’m going to exploit the Apache Struts vulnerability. This part starts at the 5:45 minute mark of the video by the way. I’ve prepared an attacker server which will be used to initiate the attack, and will listen on 12345.
Now I’ll run a small python script that will exploit the vulnerability. The script runs an http command that contains a malformed header, in order to take control of the target. I’ll target the url of my demo application, and inject this command which will then start a process inside the container, in this case with a Tomcat user.
And now that I’ve got a reverse shell running, I can do any number of bad things from my attacker host, such as break out to my ubuntu host from my alpine based container. In my example I first install a simple docker client, then start a special container since I’m running as root.
I do other things like injecting my ssh keys by mounting the host file system so I can ssh in without needing the container hack any longer.
Of course, there are some basic security precautions you can take to avoid these simple actions:
- Don’t mount the docker socket (docker.sock) in the container
- Don’t run a application container in privileged mode
- Never use a root user inside a container
Detect the Hack
Now let’s see what’s showing in the NeuVector console. Remember we deployed NeuVector, discovered the containers, and put NeuVector in a monitor mode to detect threats and violations.
We can see above that there are red lines showing suspicious connections, and clicking on them see the connections that are generating these alerts. In this case it’s the reverse shell connections and http Apache Struts exploit.
If we examine these closer below in the security Threats Notifications, we can see that NeuVector actually detected that these were Apache Struts remote code executions, and the packet in the attack was automatically captured.
In the Incidents Notifications we also see that suspicious process ssh and wget were detected which violated the whitelist baselined processes allowed in the container, as seen below.
So the NeuVector container security platform was able to detect multiple threat vectors, including network, container processes, container file system, and host activity.
Prevent the Hack
Now, we’re going to put NeuVector into the Protect mode, where it runs like an inline firewall, inspecting all network traffic between and into containers/pods, and can block attacks by dropping connections. Then we’ll redo our hack steps, and see what’s in NeuVector.
Above, the new notifications show that the attack was detected as before, but the action is ‘Block’ which means the threat was averted.
And the best thing is that our application is still up and running taking legitimate, good traffic!
Of course, NeuVector has other container security features like end-to-end vulnerability scanning, process/file system monitoring, CIS benchmarks and so on, but this is a good demonstration of the type of attacks which can be detected and prevented with a layer 7 container firewall.