diff --git a/k8s/challenge49docker-compose.yml b/k8s/challenge49docker-compose.yml new file mode 100644 index 000000000..40e984efa --- /dev/null +++ b/k8s/challenge49docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.8' + +services: + db: + image: postgres:latest + environment: + POSTGRES_USER: wrongsecrets + POSTGRES_PASSWORD: sdfjklhjUYYkghjv;-jhkf + POSTGRES_DB: Acme + ports: + - "5432:5432" + volumes: + - ./postgres_data:/var/lib/postgresql/data diff --git a/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge49.java b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge49.java new file mode 100644 index 000000000..139c08532 --- /dev/null +++ b/src/main/java/org/owasp/wrongsecrets/challenges/docker/Challenge49.java @@ -0,0 +1,20 @@ +package org.owasp.wrongsecrets.challenges.docker; + +import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Challenge49 extends FixedAnswerChallenge { + + private final String dockerSecret; + + public Challenge49(@Value("${DOCKER_SECRET_CHALLENGE49}") String dockerSecret) { + this.dockerSecret = dockerSecret; + } + + @Override + public String getAnswer() { + return this.dockerSecret; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4043278b1..f92bb1072 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -72,6 +72,7 @@ challenge26ciphertext=gbU5thfgy8nwzF/qc1Pq59PrJzLB+bfAdTOrx969JZx1CKeG4Sq7v1uUpz DEFAULT37=DEFAULT37 challenge27ciphertext=gYPQPfb0TUgWK630tHCWGwwME6IWtPWA51eU0Qpb9H7/lMlZPdLGZWmYE83YmEDmaEvFr2hX challenge41password=UEBzc3dvcmQxMjM= +DOCKER_SECRET_CHALLENGE49=sdfjklhjUYYkghjv;-jhkf management.endpoint.health.probes.enabled=true management.health.livenessState.enabled=true management.health.readinessState.enabled=true diff --git a/src/main/resources/explanations/challenge49.adoc b/src/main/resources/explanations/challenge49.adoc new file mode 100644 index 000000000..fea19571e --- /dev/null +++ b/src/main/resources/explanations/challenge49.adoc @@ -0,0 +1,7 @@ +=== Exposed Docker Secrets Challenge + +In this challenge, you will explore the importance of securely managing sensitive information using Docker secrets. Docker secrets are intended to safely transmit and store sensitive data like passwords, API keys, and certificates within Docker services. However, improper handling or misconfigurations can inadvertently expose these secrets, leading to potential security risks. + +*Acme Inc.*, a rapidly growing e-commerce platform, has recently experienced suspicious activities suggesting that sensitive customer data might have been compromised. An internal audit reveals that a developer inadvertently exposed database credentials by hardcoding them into the `challenge49docker-compose.yml` file and pushing it to a public Git repository. Additionally, the application was not utilizing Docker secrets effectively, leading to plaintext exposure of sensitive information within running containers. + +You have been hired as Technical Security Consultant, your job is to secure the exposed secrets to protect the sensitive information? For now identify the misconfigurations and report the database password to fix the situation. diff --git a/src/main/resources/explanations/challenge49_hint.adoc b/src/main/resources/explanations/challenge49_hint.adoc new file mode 100644 index 000000000..7eb68d6fe --- /dev/null +++ b/src/main/resources/explanations/challenge49_hint.adoc @@ -0,0 +1,17 @@ +This challenge can be solved using the following ways: + +- *Acme Inc*. has a misconfigured `docker-compose.yml` file where sensitive information is exposed. Your task is to find these vulnerabilities. + + 1. Clone the repository containing the challenge files. + 2. Locate the `challenge49docker-compose.yml` file in the repository. + 3. Inspect the environment variables. + 4. Identify hardcoded credentials: + Within the environment section, check for variables like: + + * `POSTGRES_USER` + * `POSTGRES_PASSWORD` + * `POSTGRES_DB` + + 5. Extract the database password: + + - The value assigned to `POSTGRES_PASSWORD` is the database password. diff --git a/src/main/resources/explanations/challenge49_reason.adoc b/src/main/resources/explanations/challenge49_reason.adoc new file mode 100644 index 000000000..da94b5bd3 --- /dev/null +++ b/src/main/resources/explanations/challenge49_reason.adoc @@ -0,0 +1,25 @@ +*Why Proper Handling of Docker Secrets is Important?* + +Docker secrets provide a secure way to manage sensitive information such as passwords, API keys, and certificates within Docker services. However, improper handling and misconfiguration can lead to serious security vulnerabilities. + +If sensitive data like database credentials are hardcoded into files like docker-compose.yml and pushed to public repositories, it nullifies the security provided by Docker secrets. Anyone with access to the repository can access the credentials, leading to potential data breaches and unauthorized access. + +Let's consider an example: + +. Imagine a scenario where a developer hardcodes database credentials directly into the challenge49docker-compose.yml file and pushes it to a public Git repository: +* The file contains plaintext environment variables such as POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB. +. This situation is analogous to writing down your passwords on a sticky note and leaving it on your computer monitor: +* An attacker can easily find the credentials and gain unauthorized access to the database. + +To prevent such issues, it is crucial to ensure that sensitive information is managed securely and not exposed in version-controlled files. Always follow best practices for secret management and avoid hardcoding sensitive information in your repositories. + +*Food for thought on Docker secrets* + +Even when you keep secrets out of version control, Docker secrets have some considerations: + +. Access Control Misconfigurations: If you don't configure access controls correctly, unauthorized users may still access the secrets when they have access to the Docker environment. +. Storage of Secrets on Disk: Docker secrets are stored on the manager node's filesystem (in Swarm mode). If the node is compromised, secrets stored in /var/lib/docker/swarm/secrets/ could be exposed. +. Secret Rotation Challenges: Rotating secrets requires careful orchestration to update running services without downtime. How will you ensure all services receive the updated secrets seamlessly? +. Potential for Offline Attacks: If secrets are not encrypted properly during storage or transmission, attackers could capture and attempt to decrypt them offline. Can you think of scenarios where weak encryption schemes might be exploited? + +Always ensure that you're using robust encryption methods and following best practices for secret management to mitigate these risks. diff --git a/src/main/resources/wrong-secrets-configuration.yaml b/src/main/resources/wrong-secrets-configuration.yaml index cf71de4c9..1c4f2de9d 100644 --- a/src/main/resources/wrong-secrets-configuration.yaml +++ b/src/main/resources/wrong-secrets-configuration.yaml @@ -775,3 +775,16 @@ configurations: category: *secrets ctf: enabled: false + + - name: Challenge 49 + short-name: "challenge-49" + sources: + - class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge49" + explanation: "explanations/challenge49.adoc" + hint: "explanations/challenge49_hint.adoc" + reason: "explanations/challenge49_reason.adoc" + environments: *all_envs + difficulty: *easy + category: *secrets + ctf: + enabled: true diff --git a/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge49Test.java b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge49Test.java new file mode 100644 index 000000000..ed03da140 --- /dev/null +++ b/src/test/java/org/owasp/wrongsecrets/challenges/docker/Challenge49Test.java @@ -0,0 +1,30 @@ +package org.owasp.wrongsecrets.challenges.docker; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.owasp.wrongsecrets.challenges.Spoiler; + +class Challenge49Test { + + @Test + void spoilerShouldGiveAnswer() { + var challenge = new Challenge49("test"); + + assertThat(challenge.spoiler()).isEqualTo(new Spoiler("test")); + } + + @Test + void rightAnswerShouldSolveChallenge() { + var challenge = new Challenge49("test"); + + assertThat(challenge.answerCorrect("test")).isTrue(); + } + + @Test + void incorrectAnswerShouldNotSolveChallenge() { + var challenge = new Challenge49("test"); + + assertThat(challenge.answerCorrect("wrong answer")).isFalse(); + } +}