Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add misconfiguration for mounting in secret in during build #1790

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions .github/scripts/docker-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -352,34 +352,35 @@ build_update_pom() {

create_containers() {
echo "Creating containers"
export SECRET_VALUE="youCantHandleThisSecret"
if [[ "$script_mode" == "publish" ]]; then
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/addo-example:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets:latest-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --secret id=mysecret,env=SECRET_VALUE --push ./../../.
cd ../..
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:$tag -f Dockerfile_webdesktop --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:latest -f Dockerfile_webdesktop --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:$tag -f Dockerfile_webdesktopk8s --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:latest -f Dockerfile_webdesktopk8s --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:$tag -f Dockerfile_webdesktop --secret id=mysecret,env=SECRET_VALUE --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop:latest -f Dockerfile_webdesktop --secret id=mysecret,env=SECRET_VALUE --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:$tag -f Dockerfile_webdesktopk8s --secret id=mysecret,env=SECRET_VALUE --push .
docker buildx build --platform linux/amd64,linux/arm64 -t jeroenwillemsen/wrongsecrets-desktop-k8s:latest -f Dockerfile_webdesktopk8s --secret id=mysecret,env=SECRET_VALUE --push .
cd .github/scripts
elif [[ "$script_mode" == "test" ]]; then
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --load ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --load --secret id=mysecret,env=SECRET_VALUE ./../../.
else
if [[ "$springProfile" != "All" ]]; then
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-$springProfile --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=$springProfile" --load ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-$springProfile --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=$springProfile" --load --secret id=mysecret,env=SECRET_VALUE ./../../.
else
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --load ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --load ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --load ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-no-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=without-vault" --load --secret id=mysecret,env=SECRET_VALUE ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-local-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=local-vault" --load --secret id=mysecret,env=SECRET_VALUE ./../../.
docker buildx build -t jeroenwillemsen/wrongsecrets:$tag-k8s-vault --build-arg "$buildarg" --build-arg "PORT=8081" --build-arg "argBasedVersion=$tag" --build-arg "spring_profile=kubernetes-vault" --load --secret id=mysecret,env=SECRET_VALUE ./../../.
fi
fi
}
Expand Down
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ RUN echo "$argBasedPassword"

RUN apk add --no-cache libstdc++ icu-libs


# Create the /app directory
RUN mkdir -p /app

# Use a separate RUN command for --mount
RUN --mount=type=secret,id=mysecret \
export SECRET_VALUE=$(cat /run/secrets/mysecret) && \
echo $SECRET_VALUE >> /app/secret.txt

RUN adduser -u 2000 -D wrongsecrets
USER wrongsecrets

Expand Down
9 changes: 9 additions & 0 deletions Dockerfile_webdesktop
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ RUN \
export PATH="$PATH:/config/.dotnet/tools" &&\
dotnet tool install ilspycmd --version 9.0.0.7660-preview2 --tool-path /etc/dotnet/tools

# Add secret handling for Kubernetes-specific Docker builds
# Create the /app directory to store the secret
RUN mkdir -p /app

# Use a separate RUN command for --mount
RUN --mount=type=secret,id=mysecret \
export SECRET_VALUE=$(cat /run/secrets/mysecret) && \
echo $SECRET_VALUE >> /app/secret.txt

WORKDIR /config/Desktop

COPY src/main/resources/executables/*linux-mus* /var/tmp/wrongsecrets/
Expand Down
9 changes: 9 additions & 0 deletions Dockerfile_webdesktopk8s
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ RUN \
export PATH="$PATH:/config/.dotnet/tools" &&\
dotnet tool install ilspycmd --version 9.0.0.7660-preview2 --tool-path /etc/dotnet/tools

# Add a secret using --mount and write it to a specific file path for the challenge
# Create the /app directory to store the secret
RUN mkdir -p /app

# Use a separate RUN command for --mount
RUN --mount=type=secret,id=mysecret \
export SECRET_VALUE=$(cat /run/secrets/mysecret) && \
echo $SECRET_VALUE >> /app/secret.txt

WORKDIR /config/Desktop

COPY src/main/resources/executables/*linux-mus* /var/tmp/wrongsecrets/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.owasp.wrongsecrets.challenges.docker;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import groovy.util.logging.Slf4j;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.owasp.wrongsecrets.Challenges;
import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class Challenge52 extends FixedAnswerChallenge {

private static final Logger log = LoggerFactory.getLogger(Challenge52.class);
private final String dockerMountsecret;

public Challenge52(@Value("$challengedockermtsecret") String dockerMountsecret) {
this.dockerMountsecret = dockerMountsecret;
}

@Override
public String getAnswer() {
return getActualSecret();
}

@SuppressFBWarnings(
value = "PATH_TRAVERSAL_IN",
justification = "The location of the dockerMountPath is based on an Env Var")
private String getActualSecret() {
try {
return Files.readString(Paths.get(dockerMountsecret, "secret.txt"), StandardCharsets.UTF_8);
} catch (Exception e) {
log.warn("Exception during file reading, defaulting to default without cloud environment", e);
return Challenges.ErrorResponses.FILE_MOUNT_ERROR;
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ management.endpoint.health.probes.enabled=true
management.health.livenessState.enabled=true
management.health.readinessState.enabled=true
management.endpoints.web.exposure.include=auditevents,info,health
challengedockermtsecret=/app
#---
spring.config.activate.on-profile=kubernetes-vault
wrongsecretvalue=wrongsecret
Expand Down
7 changes: 7 additions & 0 deletions src/main/resources/explanations/challenge52.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
=== Exposed Buildx Secrets Challenge

Acme Inc., a rising star in the SaaS industry, prides itself on delivering cutting-edge AI analytics to its global clientele. However, amidst their rapid deployment cycles and growing customer base, a critical security oversight has come to light.

During their Docker Buildx process, a sensitive secret, meant to remain temporary and secure during the build phase, was accidentally embedded into the container's filesystem due to a misconfiguration. This secret, now accessible within the running container, poses a significant security risk if exploited.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bendehaan and @Shubham-Patel07 : should we be more explicit that it is about the WrongSecrets container? Instead of acme.inc we might want to make it more explicit so people know what to look for?


As Acme Inc.'s newly hired Security Consultant, your task is clear: investigate the container, identify the exposed secret, and report it to the team. By uncovering this vulnerability, you will help Acme Inc. understand the risks and implement better practices to secure their deployment pipeline.
30 changes: 30 additions & 0 deletions src/main/resources/explanations/challenge52_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
This challenge can be solved using the following steps:

- *Acme Inc.* has misconfigured their Docker Buildx process, leading to sensitive secrets being embedded in the container's filesystem. Your task is to uncover these vulnerabilities.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we maybe show 2 different paths for solutions:

  1. Show the secret from the docker-create script
  2. Show how to get the secret by an exec into the container (using source code and env var to find the location)


1. Clone the repository containing the challenge files:
```
git clone https://github.com/OWASP/wrongsecrets.git
cd wrongsecrets
```

2. Locate the `docker-create.sh` file in the repository. This file contains the build logic used by Acme Inc. to create the Docker container.

3. Build the Docker image by running the `docker-create.sh` script:
```
./docker-create.sh
```

4. Start the Docker container using the built image to access its environment:
```
docker run -it jeroenwillemsen/wrongsecrets:local-test-no-vault sh
```

5. Investigate the container filesystem to locate the secret file:
```
/ $ cat /app/secret.txt
```

6. The content of the `secret.txt` file is your answer.

The misconfiguration demonstrates how secrets, passed securely during the Docker build process using `--secret`, can become exposed when improperly stored in the container. Your findings will help Acme Inc. understand and fix this critical issue.
30 changes: 30 additions & 0 deletions src/main/resources/explanations/challenge52_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
= Docker Buildx Secrets Misconfiguration Challenge

*Why Improper Secret Management in Docker Build Processes Can Lead to Vulnerabilities*

In modern DevOps workflows, Docker Buildx is a powerful tool for building multi-platform Docker images efficiently. It provides a secure way to pass sensitive information like API keys, database credentials, and certificates during the build process using the `--secret` flag. However, improper handling or storage of these secrets during or after the build process can introduce critical vulnerabilities.

A common mistake is to write these secrets into the container filesystem or to expose them in build scripts. This approach is flawed because:

1. **Secrets become part of the container image**: If secrets are written to the container's filesystem during the build phase, they are included in the final image. Anyone with access to the image can extract these secrets by inspecting the container layers or accessing the filesystem.
2. **Hardcoding secrets in build scripts**: Developers may hardcode secrets in scripts used to build images. When these scripts are stored in version control systems, the secrets are exposed to anyone with access to the repository.
3. **Lack of cleanup during the build process**: Even if secrets are used temporarily, failing to securely clean up or remove these secrets before finalizing the image can leave them exposed.

*Why This Challenge?*

The purpose of this challenge is to demonstrate the risks of improperly handling secrets in Docker Buildx workflows. Specifically, it showcases how secrets intended to be temporary during the build process can end up being permanently stored in the container's filesystem due to misconfiguration.

This challenge simulates a scenario where:

- A sensitive secret is passed to the Docker build process using the `--secret` flag.
- Due to misconfiguration, the secret is written to a file in the container's filesystem (`/app/secret.txt`) during the build phase.
- The resulting image contains this secret, making it accessible to anyone who can run or inspect the container.

*Key Learning Points:*

- **Avoid embedding secrets in container images**: Secrets should never be baked into Docker images. Use mechanisms like runtime environment variables or external secret management tools to provide secrets dynamically.
- **Secure the build process**: Even with tools like `--secret`, ensure secrets are not permanently stored in intermediate or final image layers.
- **Do not hardcode secrets in build scripts**: Build scripts should not contain sensitive information. Store sensitive values securely and reference them dynamically during the build process.
- **Implement cleanup mechanisms**: If secrets must be written to temporary files during the build process, ensure they are securely removed before the image is finalized.

By completing this challenge, you will understand the implications of improper secret handling during Docker builds and learn best practices for managing secrets securely in containerized environments.
13 changes: 13 additions & 0 deletions src/main/resources/wrong-secrets-configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -814,3 +814,16 @@ configurations:
category: *secrets
ctf:
enabled: true

- name: Challenge 52
short-name: "challenge-52"
sources:
- class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge52"
explanation: "explanations/challenge52.adoc"
hint: "explanations/challenge52_hint.adoc"
reason: "explanations/challenge52_reason.adoc"
environments: *all_envs
difficulty: *normal
category: *secrets
ctf:
enabled: true
Loading