Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.owasp.wrongsecrets.challenges.docker.challenge63;

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

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

@Slf4j
@Component
public class Challenge63 implements Challenge {

private static final String HARDCODED_KEY = "SuperSecretKey12";
private static final String HARDCODED_IV = "InitVector123456";
private static final String CIPHERTEXT = "TDPwOvcLsbCWV5erlk6OHFnlFoXNtdQOt2JQeq+i4Ho=";

@Override
public Spoiler spoiler() {
return new Spoiler(getAnswer());
}

@Override
public boolean answerCorrect(String answer) {
return getAnswer().equals(answer);
}

private String getAnswer() {
try {
byte[] keyBytes = HARDCODED_KEY.getBytes("UTF-8");
byte[] ivBytes = HARDCODED_IV.getBytes("UTF-8");
byte[] cipherBytes = Base64.getDecoder().decode(CIPHERTEXT);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

Check failure

Code scanning / CodeQL

Use of a broken or risky cryptographic algorithm High

Cryptographic algorithm
AES/CBC/PKCS5Padding
is insecure. CBC mode with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks. Consider using GCM instead.
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(cipherBytes);
return new String(decrypted, "UTF-8").trim();
} catch (Exception e) {
log.error("Decryption failed", e);
return "decryption-error";
}
}
}
24 changes: 24 additions & 0 deletions src/main/resources/explanations/challenge63.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== Hardcoded Encryption Key Challenge
This challenge demonstrates a common but dangerous mistake: encrypting a secret while hardcoding the encryption key in the same source file.

A developer has attempted to protect a secret by encrypting it with AES. However, both the encryption key and the initialization vector (IV) are hardcoded directly in the Java source code alongside the ciphertext. This makes the encryption completely ineffective — anyone with access to the source code can decrypt the secret trivially.

**Your goal:**
1. **Find the Java source file** for this challenge in the codebase
2. **Locate the hardcoded AES key and IV** in the source code
3. **Decrypt the ciphertext** using the key and IV you found
4. **Submit the plaintext** as your answer

**How to decrypt:**
[source,bash]
----
echo "TDPwOvcLsbCWV5erlk6OHFnlFoXNtdQOt2JQeq+i4Ho=" | openssl enc -d -aes-128-cbc \
-K $(echo -n "SuperSecretKey12" | xxd -p) \
-iv $(echo -n "InitVector123456" | xxd -p) \
-base64
----

****
*Note:*
The key insight here is that encryption does NOT protect a secret if the key is stored alongside the ciphertext. This is equivalent to locking a box and taping the key to the outside.
****
26 changes: 26 additions & 0 deletions src/main/resources/explanations/challenge63_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
=== Hint for Challenge 63
This challenge demonstrates bad encryption practices — specifically hardcoding an AES key in source code.

**Where to look:**
1. **Find the Challenge63 Java source file** in the `challenges/docker/challenge63/` directory
2. **Look for static final String constants** near the top of the class
3. **You will find the AES key, IV, and ciphertext** all in the same file

**How to decrypt once you have the key:**
[source,python]
----
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64

key = b'SuperSecretKey12'
iv = b'InitVector123456'
ciphertext = base64.b64decode("TDPwOvcLsbCWV5erlk6OHFnlFoXNtdQOt2JQeq+i4Ho=")

cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
print(plaintext.strip())
----

**Remember:** If an attacker can read your source code, hardcoded keys offer zero protection.
21 changes: 21 additions & 0 deletions src/main/resources/explanations/challenge63_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
=== Reason for Challenge 63
This challenge highlights a widespread mistake in software development: using encryption while storing the key in the same location as the ciphertext.

**Why this is dangerous:**
- Encryption is only as strong as the secrecy of the key
- Hardcoding the key in source code means anyone with repository access can decrypt the secret
- Source code is often more widely accessible than developers realize — through Git history, leaked repos, or insider access
- Many secret scanning tools will detect both the key and ciphertext patterns

**The correct approach:**
- Store encryption keys in a dedicated secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- Never commit keys to version control
- Use environment variables for keys, not source code constants
- Consider whether encryption is even necessary if the key must live near the data

**Real world examples:**
This exact pattern has been found in numerous data breaches where developers believed their secrets were "safe" because they were encrypted, not realizing the key was equally exposed.

**References:**
- https://owasp.org/www-project-top-ten/[OWASP Top 10]
- https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html[OWASP Secrets Management Cheat Sheet]
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 @@ -961,3 +961,16 @@ configurations:
category: *ai
ctf:
enabled: true

- name: Challenge 63
short-name: "challenge-63"
sources:
- class-name: "org.owasp.wrongsecrets.challenges.docker.challenge63.Challenge63"
explanation: "explanations/challenge63.adoc"
hint: "explanations/challenge63_hint.adoc"
reason: "explanations/challenge63_reason.adoc"
environments: *all_envs
difficulty: *normal
category: *crypto
ctf:
enabled: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.owasp.wrongsecrets.challenges.docker;

import org.junit.jupiter.api.Test;
import org.owasp.wrongsecrets.challenges.docker.challenge63.Challenge63;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;

class Challenge63Test {

@Test
void testAnswerIsCorrect() {
Challenge63 challenge = new Challenge63();
assertTrue(challenge.answerCorrect("wh0sp1ay1ngwrongs3cr3ts"));
}

@Test
void testWrongAnswerIsRejected() {
Challenge63 challenge = new Challenge63();
assertFalse(challenge.answerCorrect("wronganswer"));
}

@Test
void testSpoilerRevealsAnswer() {
Challenge63 challenge = new Challenge63();
assertEquals("wh0sp1ay1ngwrongs3cr3ts", challenge.spoiler().solution());
}
}
Loading