Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ export SPRING_CLOUD_VAULT_URI='http://127.0.0.1:8200'
export SPRING_CLOUD_VAULT_TOKEN='<TOKENHERE>'
vault token create -id="00000000-0000-0000-0000-000000000000" -policy="root"
vault kv put secret/secret-challenge vaultpassword.password="$(openssl rand -base64 16)"
vault kv put secret/injected vaultinjected.value="$(openssl rand -base64 16)"
vault kv put secret/codified challenge47secret.value="debugvalue"
```

Now use the `local-vault` profile to do your development.
Expand Down
6 changes: 6 additions & 0 deletions k8s-vault-minkube-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ kubectl exec vault-0 -n vault -- vault kv put secret/secret-challenge vaultpassw
echo "Putting a challenge key in"
kubectl exec vault-0 -n vault -- vault kv put secret/injected vaultinjected.value="$(openssl rand -base64 16)"

echo "Putting a challenge key in"
kubectl exec vault-0 -n vault -- vault kv put secret/codified challenge47secret.value="debugvalue"

echo "Putting a subkey issue in"
kubectl exec vault-0 -n vault -- vault kv put secret/wrongsecret aaaauser."$(openssl rand -base64 8)"="$(openssl rand -base64 16)"

Expand Down Expand Up @@ -121,6 +124,9 @@ path "secret/data/application" {
path "secret/data/injected" {
capabilities = ["read"]
}
path "secret/data/codified" {
capabilities = ["read"]
}
EOF'

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write standard_sre - <<EOF
Expand Down
6 changes: 6 additions & 0 deletions k8s/secret-challenge-vault-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ spec:
{{ printf "%s=%s" $k $v }}
{{ end }}
{{ end }}
vault.hashicorp.com/agent-inject-secret-challenge47: "secret/data/codified"
vault.hashicorp.com/agent-inject-template-challenge47: |
{{ with secret "secret/data/codified" }}
{{ range $k, $v := .Data.data }}export challenge47secret="isthiswhatweneed?"
{{ end }}
{{ end }}
vault.hashicorp.com/role: "secret-challenge"
labels:
app: secret-challenge
Expand Down
7 changes: 4 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.owasp</groupId>
<artifactId>wrongsecrets</artifactId>
<version>1.8.5-SNAPSHOT</version>
<version>1.8.6A1-SNAPSHOT</version>

<name>OWASP WrongSecrets</name>
<description>Examples with how to not use secrets</description>
Expand Down Expand Up @@ -51,7 +51,7 @@
<com.azure.spring.version>5.11.0</com.azure.spring.version>
<cyclonedx.core.version>8.0.3</cyclonedx.core.version>
<datatables.version>2.0.3</datatables.version>
<dependency-check-maven.version>9.0.10</dependency-check-maven.version>
<dependency-check-maven.version>9.2.0</dependency-check-maven.version>
<gatling-maven-plugin.version>4.9.0</gatling-maven-plugin.version>
<gatling.version>3.11.2</gatling.version>
<gcp.sdk.version>5.1.2</gcp.sdk.version>
Expand Down Expand Up @@ -161,6 +161,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.19.8</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -343,7 +344,7 @@
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>4.8.4</version>
<version>4.8.5</version>
</dependency>
</dependencies>
</plugin>
Expand Down
9 changes: 8 additions & 1 deletion scripts/install-vault.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ kubectl exec vault-0 -n vault -- vault kv put secret/secret-challenge vaultpassw
echo "Putting a challenge key in"
kubectl exec vault-0 -n vault -- vault kv put secret/injected vaultinjected.value="$(openssl rand -base64 16)"

echo "Putting a challenge key in"
kubectl exec vault-0 -n vault -- vault kv put secret/codified challenge47secret.value="debugvalue"

echo "Putting a subkey issue in"
kubectl exec vault-0 -n vault -- vault kv put secret/wrongsecret aaaauser."$(openssl rand -base64 8)"="$(openssl rand -base64 16)"

Expand Down Expand Up @@ -87,6 +90,9 @@ path "secret/data/application" {
path "secret/data/injected" {
capabilities = ["read"]
}
path "secret/data/codified" {
capabilities = ["read"]
}
EOF'

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write standard_sre - <<EOF
Expand Down Expand Up @@ -120,6 +126,7 @@ kubectl exec vault-0 -n vault -- vault write auth/kubernetes/role/secret-challen
policies=secret-challenge \
ttl=24h &&
vault kv put secret/secret-challenge vaultpassword.password="$(openssl rand -base64 16)" &&
vault kv put secret/application vaultpassword.password="$(openssl rand -base64 16)"
vault kv put secret/application vaultpassword.password="$(openssl rand -base64 16)" &&
vault kv put secret/codified challenge47secret.value="debugvalue"

kubectl create serviceaccount vault
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.owasp.wrongsecrets.challenges.kubernetes;

import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.springframework.beans.factory.annotation.Value;

public class Challenge47 extends FixedAnswerChallenge {

private final String secret;

public Challenge47(@Value("${challenge47secret}") String secret) {
this.secret = secret;
}

@Override
public String getAnswer() {
return secret;
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ARG_BASED_PASSWORD=if_you_see_this_please_use_docker_instead
DOCKER_ENV_PASSWORD=if_you_see_this_please_use_docker_instead
vaultpassword=if_you_see_this_please_use_K8S_and_Vault
vaultinjected=if_you_see_this_please_use_K8S_and_Vault
challenge47secret=if_you_see_this_please_use_K8S_and_Vault
spring.cloud.vault.uri=https://tobediefined.org
spring.cloud.vault.authentication=NONE
spring.cloud.vault.role=none
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/explanations/challenge47.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
=== HashiCorp Vault Template Injection Part 2

A developer tried to debug why his vault injection did not work. So he hardcoded the secrets "temporary" in the Vault template itself.
Can you find the secret hardcoded in the Vault Template?
8 changes: 8 additions & 0 deletions src/main/resources/explanations/challenge47_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This challenge can be solved using the following steps:

1. Run `kubectl get pods -A` and find secret-challenge-xxx pod name

2. Run `kubectl exec secret-challenge-xxx -c secret-challenge -n default -- cat vault/secrets/challenge46` where `xxx` is the rest of the randomly generated pod name.
to print the hardcoded value used by the developer.

Note: if you are running this on a hosted environment, where you do not have access to the Kubernetes cluster, ask the organizer of the hosted solution to execute the commands for you and return the results.
16 changes: 16 additions & 0 deletions src/main/resources/explanations/challenge47_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*Why Vault Template Injection is not always a good idea?*

While Vault agent injection via templates can be a convenient way to manage secrets in certain scenarios,
there are situations where it might not be the best approach.

Templates might accidentally expose sensitive information in logs or temporary files.
If not properly configured, secrets could end up in places where they are accessible by unauthorized users or processes.

Let's consider an example involving a template injection attack in a scripted language like PHP:

. Imagine a scenario where PHP application uses a template with sensitive information
* where template can look like this: $password = "'; system('rm -rf /'); //"
. When the template is processed it can become:
* $connection = "password='; system('rm -rf /'); //"

To prevent such issues its crucial to ensure that the values retrieved from Vault are properly validated.
14 changes: 14 additions & 0 deletions src/main/resources/wrong-secrets-configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -752,3 +752,17 @@ configurations:
ctf:
enabled: true
missing_environment: "explanations/missing_vault.adoc"

- name: Challenge 47
short-name: "challenge-47"
sources:
- class-name: "org.owasp.wrongsecrets.challenges.kubernetes.Challenge47"
explanation: "explanations/challenge47.adoc"
hint: "explanations/challenge47_hint.adoc"
reason: "explanations/challenge47_reason.adoc"
environments: [ *k8s_vault, *gcp, *aws, *azure ]
difficulty: *expert
category: *vault
ctf:
enabled: true
missing_environment: "explanations/missing_vault.adoc"
28 changes: 28 additions & 0 deletions src/test/K8s-tests/cypress/e2e/Challenge47Test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
describe('Challenge47 Tests', () => {
it('Submitting a Correct Answer', () => {
// Visit the spoiler page and extract the spoiler
cy.visit('/spoil/challenge-47')
cy.get('[data-cy=spoiler-answer]').invoke('text').then(spoilerAnswer => {
// Asserting that the spoiler is not a default value
expect(spoilerAnswer.trim()).to.not.equal('if_you_see_this_please_use_K8S_and_Vault')
expect(spoilerAnswer.trim()).to.not.be.empty

// Visit the challenge page and submit the spoiler as the answer
cy.visit('/challenge/challenge-47')
cy.get('#answerfield').type(spoilerAnswer.trim())
cy.get('[data-cy=submit-textbox-btn]').click()
cy.get('[data-cy=success-alert]').should('contain', 'correct')
})
})

it('Submitting an Incorrect Answer', () => {
cy.visit('/challenge/challenge-47')

// Use a known incorrect answer
cy.get('#answerfield').type('definitely_wrong_answer')
cy.get('[data-cy=submit-textbox-btn]').click()

// Check for incorrect alert
cy.get('[data-cy=incorrect-alert]').should('contain', 'incorrect')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.owasp.wrongsecrets.challenges.kubernetes;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class Challenge47Test {

@Test
void spoilerShouldGiveAnswer() {
var challenge = new Challenge47("answer");
assertThat(challenge.spoiler().solution()).isEqualTo("answer");
assertThat(challenge.answerCorrect(challenge.spoiler().solution())).isTrue();
}

@Test
void incorrectAnswerShouldNotSolveChallenge() {
var challenge = new Challenge47("answer");
assertThat(challenge.answerCorrect("wrong answer")).isFalse();
}
}