Design thoughts with the Docker container implementation and its deamon writeable binaries

Continuing the conversation started by @zem from issue #419 on the WriteFreely repo. Please feel free to jump in!


Describe the bug

When I investigated the Docker container I found some design flaws that could lead to security impacts.

Steps to reproduce (if necessary)

Steps to reproduce the behavior:

  1. podman image pull docker.io/writeas/writefreely:latest
  2. podman run -it --entrypoint sh docker.io/writeas/writefreely:latest
  3. have a look around
/go $ whoami
daemon
/go $ ls -l bin 
total 2856
-rwxr-xr-x    1 daemon   daemon     2924460 Apr 23  2020 go-bindata
/go $ ls -l cmd/writefreely/
total 106368
-rw-r--r--    1 daemon   daemon        1503 Apr 23  2020 config.go
-rw-r--r--    1 daemon   daemon        1024 Apr 23  2020 db.go
-rw-r--r--    1 daemon   daemon         842 Apr 23  2020 keys.go
-rw-r--r--    1 daemon   daemon        4543 Apr 23  2020 main.go
-rw-r--r--    1 daemon   daemon        2223 Apr 23  2020 user.go
-rw-r--r--    1 daemon   daemon        1035 Apr 23  2020 web.go
-rwxr-xr-x    1 daemon   daemon    51867592 Apr 23  2020 writefreely
-rwxr-xr-x    1 daemon   daemon    57023488 Apr 23  2020 writefreely.exe
/go $ 

Having the application run as regular user is a good idea in general, however, in this case, the user who runs the container is owning its binaries and therefore the rights to modify them. This might not be a big issue if you throw away the container on restart, however there are container orchestrator’s that don’t do that.

The next thing you might realize is that windows binary. This is not executable on Linux based systems. It might be nothing but I would guess that this binary should not be there at all.

        "Config": {
            "User": "daemon",
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Entrypoint": [
                "cmd/writefreely/writefreely"
            ],
            "Volumes": {
                "/go/keys": {}
            },
            "WorkingDir": "/go"
        },

I am not sure if the idea to start writefreely as entrypoint is a good idea, this is far more minor I usually tend to run some configuration scripts as root, that can also be extended by higher layers of the image, and then exec su to an unprivileged

user to run the daemon of the software. One thing you could do with such an entrypoint script is to do writefreely --gen-keys if the keys in the keys volume don’t exist, so the user does not have to care about that.