Skip to content
Merged
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
27 changes: 27 additions & 0 deletions src/main/java/org/owasp/wrongsecrets/AuditConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.owasp.wrongsecrets;

import groovy.util.logging.Slf4j;
import java.util.Map;
import java.util.UUID;
import lombok.Getter;
import org.springframework.boot.actuate.audit.AuditEvent;
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Getter
@Configuration
@Slf4j
public class AuditConfiguration {

private final String apiKey = UUID.randomUUID().toString();

@Bean
public InMemoryAuditEventRepository inMemoryAuditEventRepository() {
InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository();
AuditEvent auditEvent =
new AuditEvent("john.doe", "API_KEY_RECEIVED", Map.of("apiKey", apiKey));
repository.add(auditEvent);
return repository;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.owasp.wrongsecrets.challenges.docker;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.wrongsecrets.AuditConfiguration;
import org.owasp.wrongsecrets.challenges.Challenge;
import org.owasp.wrongsecrets.challenges.Spoiler;
import org.springframework.stereotype.Component;

/** This is a challenge based on finding API Key in Spring Boot Actuator audit events */
@Slf4j
@Component
@RequiredArgsConstructor
public class Challenge42 implements Challenge {

private final AuditConfiguration auditConfiguration;

@Override
public Spoiler spoiler() {
return new Spoiler(auditConfiguration.getApiKey());
}

@Override
public boolean answerCorrect(String answer) {
return auditConfiguration.getApiKey().equals(answer);
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ challenge41password=UEBzc3dvcmQxMjM=
management.endpoint.health.probes.enabled=true
management.health.livenessState.enabled=true
management.health.readinessState.enabled=true
management.endpoints.web.exposure.include=auditevents
#---
spring.config.activate.on-profile=kubernetes-vault
wrongsecretvalue=wrongsecret
Expand Down
12 changes: 12 additions & 0 deletions src/main/resources/explanations/challenge42.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== Spring Boot Actuator Audit Event

The developers decided to leverage the power of Spring Boot Actuator
to monitor and audit their application. The project involved interfacing with various external APIs,
each requiring a unique key for authentication. The audit events, detailed and informative, seemed like
the perfect solution for monitoring the inner workings of their system.

The team implemented a logging mechanism that included detailed audit events.
Unbeknownst to them, these logs contained traces of the sacred API key hidden within
the audit events.

Can you find this API key?
7 changes: 7 additions & 0 deletions src/main/resources/explanations/challenge42_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
This challenge can be solved using the following steps:

1. Check available Actuator endpoints at "/actuator"

2. Check audit events exposed at the "/actuator/auditevents" endpoint

3. Find API_KEY_RECEIVED event with exposed secret
6 changes: 6 additions & 0 deletions src/main/resources/explanations/challenge42_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*Why hiding API key in the audit events is not a good idea?*

In a secure and well-architected system, protecting sensitive information such as API keys is crucial.
Audit events are significant in tracking and monitoring activities within an application.

Ensure that API keys are not visible in plain text in the (audit) logs or any other output.
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 @@ -676,3 +676,16 @@ configurations:
category: *crypto
ctf:
enabled: true

- name: Challenge 42
short-name: "challenge-42"
sources:
- class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge42"
explanation: "explanations/challenge42.adoc"
hint: "explanations/challenge42_hint.adoc"
reason: "explanations/challenge42_reason.adoc"
environments: *docker_envs
difficulty: *normal
category: *logging
ctf:
enabled: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.owasp.wrongsecrets.challenges.docker;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.wrongsecrets.AuditConfiguration;

@ExtendWith(MockitoExtension.class)
public class Challenge42Test {

@Mock private AuditConfiguration auditConfiguration;

@BeforeEach
void init() {
when(auditConfiguration.getApiKey()).thenReturn("qemGhPXJjmipa9O7cYBJnuO79BQg");
}

@Test
void spoilerShouldGiveAnswer() {
var challenge = new Challenge42(auditConfiguration);
var solution = challenge.spoiler().solution();
assertEquals("qemGhPXJjmipa9O7cYBJnuO79BQg", solution);
}

@Test
void rightAnswerShouldSolveChallenge() {
var challenge = new Challenge42(auditConfiguration);
assertTrue(challenge.answerCorrect("qemGhPXJjmipa9O7cYBJnuO79BQg"));
}

@Test
void incorrectAnswerShouldNotSolveChallenge() {
var challenge = new Challenge42(auditConfiguration);
assertFalse(challenge.answerCorrect("wrong answer"));
}
}