In this guide, I want to show how you can modify any docker image so that file permissions of file inside a volume can be modified ad-hoc.
Problem: Almost all docker containers have the default file permission of 644
(-rw-r--r--)
Solution: With the help of the deb package inotify-tools
(https://github.com/inotify-tools/inotify-tools/wiki) we can monitor filesystem events. With the integrated inotifywait
(https://www.man7.org/linux/man-pages/man1/inotifywait.1.html) shell-command we can build a small script that is watching the connected volume inside the container and if files gets "moved in" or "created" inside this folder a chmod 666
is applyed the these files.
Thus, the privileges of the "moved in" or "created" files can be effectively escalated.
In the following example I am using the docker base image: php:apache
version: "3.7"
services:
web-server:
build:
context: .
dockerfile_inline: "FROM php:apache\nRUN apt-get update && apt-get install -qqy inotify-tools && apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/\nRUN echo '#!/bin/sh' > /perm.sh && echo 'inotifywait -q -m -e create --format \"%f\" /var/www/test | while read FILENAME' >> /perm.sh && echo 'do' >> /perm.sh && echo ' chmod 666 /var/www/test/$$FILENAME' >> /perm.sh && echo 'done' >> /perm.sh && chmod +x /perm.sh"
command: sh -c "/bin/sh /perm.sh | apache2-foreground"
restart: always
volumes:
- "/host/test-folder:/var/www/test/"
ports:
- "9999:80"
The magic happens inside the long docker_inline
command inside the docker-compose.yml
.
FROM php:apache\n
:
With this command we are setting the docker base image
RUN apt-get update && apt-get install -qqy inotify-tools && apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/\n
:
With this part of the command we are installing inotify-tools
inside the docker base image (php:apache
)
RUN echo '#!/bin/sh' > /perm.sh && echo 'inotifywait -q -m -e create --format \"%f\" /var/www/test | while read FILENAME' >> /perm.sh && echo 'do' >> /perm.sh && echo ' chmod 666 /var/www/test/$$FILENAME' >> /perm.sh && echo 'done' >> /perm.sh && chmod +x /perm.sh
:
With the last part of the docker_inline
command we are creating a small sh script (/perm.sh
) with the following content:
#!/bin/sh
inotifywait -q -m -e create --format "%f" /var/www/test | while read FILENAME
do
chmod 666 /var/www/test/$FILENAME
done
Please edit the path /var/www/test
inside the docker_inline
command if you have mounted the volume to another place inside the docker container.
Now with the command: sh -c "/bin/sh /perm.sh | apache2-foreground"
command we are starting the /perm.sh
script and the apache
-webserver at the same time inside the docker container.
If you are not using the base image php:apache
you need to change apache2-foreground
command with the last command inside the docker base image.
You can find a list of all layers inside of a docker base image if you search the docker hub
If you have found your image click on the "Tags"-View and click on the tag you are using (In my example apache
https://hub.docker.com/layers/library/php/apache/images/sha256-3dd4df7bdf81a042b2f93bf582c7a98f54fd14b7ab7976e3d6e7fef03af73a8c?context=explore
Now you see all layers of the specific base image. In my example the last layer command is CMD ["apache2-foreground"]
and so I have used apache2-foreground
command inside the docker-compose.yml
If the last layer in the docker base image is a ENTRYPOINT
command please replace command: sh -c "/bin/sh /perm.sh | ........"
with entrypont: sh -c "/bin/sh /perm.sh | ........"
in the docker-compose.yml