Skip to content

Latest commit

 

History

History
104 lines (80 loc) · 3.85 KB

File metadata and controls

104 lines (80 loc) · 3.85 KB

Scanning for secrets in container images

Container images are also a well-known source for secrets in the wild. There should not be any secrets baked into container images. Secrets should be mounted on runtime (or by other mechanisms). A few notes:

  • Container images are layers, which if not understood properly will give you challenges (similar to the git history)
  • Adding a secret at build time, using it and then deleting it may give you problems if not handled properly!

Let's explore a typical example.

-- Now You --

  • Assuming you have a terminal open in the folder ex-06

  • Explore the Dockerfile

  • Build the Docker image for your app. Run it afterwards

    docker build -t myapp . --progress=plain --no-cache
    docker run myapp
  • The image is build, no secrets are exposed in build output

  • Let's build again and now pass a secret

  • (A free hint; if you start commands in bash with a space the command will not be saved in the history)

     export MY_SECRET="ghp_6GdlOSDwyZKlhSyuuuEEEJJ8yLxRNQ3UnVAj"
    docker build -t myapp . --progress=plain --no-cache --build-arg MY_SECRET=$MY_SECRET
  • The image is build, the secret is emitted to the console and then deleted.

  • We will explore a bit further using our local file system (as opposed to a container registry)

  • First we do the build but store the result, that would end up in an container image, into the file system

    mkdir myapp
    docker build --build-arg MY_SECRET=${MY_SECRET} -t myapp --progress=plain --no-cache -o type=local,dest=./myapp .
  • The image is build, but the results are stored in the my-app folder. Explore

  • Let's scan the my-app for any secrets

    trufflehog filesystem ./myapp --no-update --no-verification
    echo $? # will show the status code for the last command (0 is ran to completion)
    ls myapp/tmp 
  • The scan gives some errors we can ignore, but finds no secrets (exit code 0). There is no /tmp/secret.txt, it's deleted ...

  • The previous build was not a real container image. Let's build a real image, save it to a tar file and investigate

    mkdir myapp-tar
    docker build --build-arg MY_SECRET=${MY_SECRET} -t myapp --progress=plain --no-cache .
    docker save -o myapp.tar myapp
    tar -xvf myapp.tar -C myapp-tar
    ls -la ./myapp-tar
  • The content of myapp-tar looks different than what's in myapp. It represents what ends up in the container image, all layers.

  • Let us scan the result with Trufflehog

    trufflehog filesystem ./myapp-tar --no-update --no-verification
  • We found a secret, the same one 2 places?

  • Explore the files reported (layers) and identify the secret.

    • Hint: cat (json file) | jq .
    • Hint: tar -tvf (tar file)
  • Looking at the layers with docker history

    docker history myapp
    
  • This command will show the all the layers that make up an image - and the commands that were used to create each layer.

-- Discussions --

  • In many cases, using the tool to scan images directly (local or registry, but as early as possible), is the better approach, we took a longer route to explain
  • Be aware of layers and use them "properly" with multi-stage builds
  • The better pattern for using secrets in Docker build may be to use the "--secret" option or mount a secret file using the "--mount=type=secret,id=MY_SECRET" option
  • The Docker Security Best Practices provide some guidance. Always search product documentation for security best practices.