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