Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
39 changes: 39 additions & 0 deletions .github/scripts/docker-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,51 @@ build_update_pom() {
cd ../.. && ./mvnw clean && ./mvnw --batch-mode release:update-versions -DdevelopmentVersion=${tag}-SNAPSHOT && ./mvnw spotless:apply && ./mvnw install -DskipTests
cd .github/scripts
echo "Removing unnecessary binaries from the jar file"
# macOS / non-Linux binaries (never used in the Alpine Docker container)
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-golang
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-golang-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-c
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-c-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-arm-stripped
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-stripped
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-cplus
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-cplus-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge52-c
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge52-c-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge53-c
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge53-c-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-rust
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-rust-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-dotnet
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-dotnet-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-ctf
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-arm-ctf
# Linux glibc (non-musl) binaries (Alpine uses musl; golang uses glibc linux binary intentionally)
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-c-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-c-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-linux-arm-stripped
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-advanced-c-linux-stripped
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-cplus-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-cplus-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge52-c-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge52-c-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge53-c-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-challenge53-c-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-rust-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-rust-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-dotnet-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-dotnet-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-linux
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-linux-arm
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-linux-ctf
zip -d ../../target/*.jar BOOT-INF/classes/executables/wrongsecrets-swift-linux-arm-ctf
# Windows binaries
zip -d ../../target/*.jar BOOT-INF/classes/executables/*.exe
docker buildx create --name mybuilder
docker buildx use mybuilder
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/container_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,10 @@ jobs:
- uses: actions/checkout@v5
- name: Run compose and print out service
run: export DOCKER_BUILDKIT=1 && cd src/main/resources/challenges/challenge-51 && docker compose -f challenge51docker-compose.yml build && docker compose -f challenge51docker-compose.yml run myservice
challenge_63_swift_test:
name: Challenge 63 Swift binary test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Build and run Swift binary in Alpine container
run: export DOCKER_BUILDKIT=1 && docker build -f src/main/resources/challenges/challenge-63/Dockerfile_challenge63 -t challenge63-test . && docker run --rm challenge63-test
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
ARG spring_profile=""
ARG challenge59_webhook_url="YUhSMGNITTZMeTlvYjI5cmN5NXpiR0ZqYXk1amIyMHZjMlZ5ZG1salpYTXZWREEwVkRRd1RraFlMMEl3T1VSQlRrb3lUamRMTDJNeWFqYzFSVEUzVjFrd2NFeE5SRXRvU0RsbGQzZzBhdz09"
ENV SPRING_PROFILES_ACTIVE=$spring_profile
ENV ARG_BASED_PASSWORD=$argBasedPassword

Check warning on line 16 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "ARG_BASED_PASSWORD") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV APP_VERSION=$argBasedVersion

Check warning on line 17 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Variables should be defined before their use

UndefinedVar: Usage of undefined variable '$argBasedVersion' More info: https://docs.docker.com/go/dockerfile/rule/undefined-var/
ENV DOCKER_ENV_PASSWORD="This is it"

Check warning on line 18 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "DOCKER_ENV_PASSWORD") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV AZURE_KEY_VAULT_ENABLED=false

Check warning on line 19 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "AZURE_KEY_VAULT_ENABLED") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV CHALLENGE59_SLACK_WEBHOOK_URL=$challenge59_webhook_url
ENV WRONGSECRETS_MCP_SECRET=MCPStolenSecret42!

Check warning on line 21 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "WRONGSECRETS_MCP_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG GOOGLE_SERVICE_ACCOUNT_KEY="if_you_see_this_configure_the_google_service_account_properly"

Check warning on line 22 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GOOGLE_SERVICE_ACCOUNT_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG GOOGLE_DRIVE_DOCUMENT_ID="1PlZkwEd7GouyY4cdOxBuczm6XumQeuZN31LR2BXRgPs"
ENV GOOGLE_SERVICE_ACCOUNT_KEY=$GOOGLE_SERVICE_ACCOUNT_KEY

Check warning on line 24 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "GOOGLE_SERVICE_ACCOUNT_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV GOOGLE_DRIVE_DOCUMENT_ID=$GOOGLE_DRIVE_DOCUMENT_ID
ENV SPRINGDOC_UI=false
ENV SPRINGDOC_DOC=false
Expand All @@ -45,6 +45,7 @@
COPY --chown=wrongsecrets .github/scripts/.bash_history /home/wrongsecrets/
COPY --chown=wrongsecrets src/main/resources/executables/wrongsecrets*linux-musl* /home/wrongsecrets/
COPY --chown=wrongsecrets src/main/resources/executables/wrongsecrets-golang-linux /home/wrongsecrets/
COPY --chown=wrongsecrets src/main/resources/executables/wrongsecrets-golang-linux-arm /home/wrongsecrets/
COPY --chown=wrongsecrets src/test/resources/alibabacreds.kdbx /var/tmp/helpers
COPY --chown=wrongsecrets src/test/resources/RSAprivatekey.pem /var/tmp/helpers/
COPY --chown=wrongsecrets .ssh/ /home/wrongsecrets/.ssh/
Expand Down Expand Up @@ -75,4 +76,4 @@
RUN adduser -u 2000 -D wrongsecrets
USER wrongsecrets

CMD java -jar -XX:SharedArchiveFile=application.jsa -Dspring.profiles.active=$(echo ${SPRING_PROFILES_ACTIVE}) -Dspringdoc.swagger-ui.enabled=${SPRINGDOC_UI} -Dspringdoc.api-docs.enabled=${SPRINGDOC_DOC} -D application.jar

Check warning on line 79 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-preview

JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals

JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals More info: https://docs.docker.com/go/dockerfile/rule/json-args-recommended/
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.owasp.wrongsecrets.challenges.docker;

import lombok.extern.slf4j.Slf4j;
import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.owasp.wrongsecrets.challenges.docker.binaryexecution.BinaryExecutionHelper;
import org.owasp.wrongsecrets.challenges.docker.binaryexecution.MuslDetectorImpl;
import org.springframework.stereotype.Component;

/** This challenge is about finding a secret hardcoded in a Swift binary. */
@Slf4j
@Component
public class Challenge63 extends FixedAnswerChallenge {

@Override
public String getAnswer() {
BinaryExecutionHelper binaryExecutionHelper =
new BinaryExecutionHelper(63, new MuslDetectorImpl());
return binaryExecutionHelper.executeCommand("", "wrongsecrets-swift");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
Expand All @@ -22,6 +24,10 @@ private enum BinaryInstructionForFile {
Guess
}

private static final String[] SWIFT_LIB_PATHS = {
"/usr/share/swift/usr/lib/swift/linux", "/usr/lib/swift/linux", "/usr/local/lib/swift/linux"
};

public static final String ERROR_EXECUTION = EXECUTION_ERROR;
private final int challengeNumber;

Expand Down Expand Up @@ -128,6 +134,9 @@ private String executeCommand(
}
}
ps.redirectErrorStream(true);
if (execFile.getPath().contains("swift")) {
configureSwiftLibraryPath(ps);
}
Process pr = ps.start();
try (BufferedReader in =
new BufferedReader(new InputStreamReader(pr.getInputStream(), StandardCharsets.UTF_8))) {
Expand Down Expand Up @@ -272,4 +281,24 @@ private void deleteFile(File execFile) {
log.info("Deleting the file {} failed...", execFile.getPath());
}
}

private void configureSwiftLibraryPath(ProcessBuilder ps) {
List<String> existingPaths = new ArrayList<>();
String currentLdPath = ps.environment().get("LD_LIBRARY_PATH");
if (!Strings.isNullOrEmpty(currentLdPath)) {
existingPaths.add(currentLdPath);
}
for (String path : SWIFT_LIB_PATHS) {
File dir = new File(path);
if (dir.exists() && dir.isDirectory()) {
log.info("Found Swift library path: {}", path);
existingPaths.add(path);
}
}
if (!existingPaths.isEmpty()) {
String ldPath = String.join(":", existingPaths);
log.info("Setting LD_LIBRARY_PATH for Swift binary: {}", ldPath);
ps.environment().put("LD_LIBRARY_PATH", ldPath);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# syntax=docker/dockerfile:1.21
# Test that the wrongsecrets-swift musl binary runs correctly on Alpine.
# The musl binaries are fully statically linked (Swift runtime embedded), so they
# run natively on Alpine's musl libc without any extra shared libraries.

FROM alpine:3.21

# Copy the Linux musl x86_64 binary (build context is the repo root)
COPY src/main/resources/executables/wrongsecrets-swift-linux-musl /wrongsecrets-swift
RUN chmod +x /wrongsecrets-swift

# Run the binary and verify it produces non-empty output (the hardcoded secret)
CMD ["/bin/sh", "-c", "OUTPUT=$(/wrongsecrets-swift) && [ -n \"$OUTPUT\" ] && echo \"Swift binary works: $OUTPUT\" || (echo 'Swift binary failed or produced no output' && exit 1)"]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions src/main/resources/explanations/challenge63.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
=== Hiding in binaries part 5: the Swift binary

Similar to hiding secrets in an application written in C, you can do this in Swift! Swift is Apple's modern compiled language used across Apple platforms and Linux. Can you find the secret in our binary?

Let's debunk the "secrets are hard to find in native compiled applications" myth for Swift: can you find the secret in https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/wrongsecrets-swift[wrongsecrets-swift] (or https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/wrongsecrets-swift-arm[wrongsecrets-swift-arm], https://github.com/OWASP/wrongsecrets/tree/master/src/main/resources/executables/wrongsecrets-swift-linux[wrongsecrets-swift-linux])?

Try downloading the binary and run it locally (e.g. `./wrongsecrets-swift<theversion you need> <your answer>`).
25 changes: 25 additions & 0 deletions src/main/resources/explanations/challenge63_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
This challenge is specifically looking at a secret stored in a Swift binary as an array of characters.

You can solve this challenge using the following alternative solutions:

1. Find the secrets with https://ghidra-sre.org/[Ghidra].
- Install https://ghidra-sre.org/[Ghidra].
- Start it with `ghidraRun`.
- Load the application `wrongsecrets-swift` into Ghidra by choosing a new project, then import the file and then double-click on it.
- Allow Ghidra to analyze the application.
- Look for the `getSecret` function - you can search for it in the Symbol Tree.
- In the decompiled code, find the array of characters that make up the secret.
- Alternatively: on macOS, use `nm -gUj wrongsecrets-swift | grep getSecret` and then `swift-demangle --expand "s5swift9getSecretSSyF"` to find the function.

2. Find the secrets with https://www.radare.org[radare2].
- Install https://www.radare.org[radare2] with either `brew install radare2` on Mac or follow these steps: `git clone https://github.com/radareorg/radare2; cd radare2 ; sys/install.sh`
- Launch r2 analysis with `$ r2 -AAA wrongsecrets-swift`
- Search for strings with `iz | grep -i secret` or `iz | grep -i "This"`.
- Alternatively, look for the `getSecret` function: `afl | grep getSecret` and then print the function with `pdf @ <function_address>`.
- Examine the character array construction in the decompiled or disassembled code.

3. Find the secrets with https://binary.ninja[Binary Ninja] or similar tools:
- Load the binary and navigate to the Swift mangled function `s5swift9getSecretSSyF`.
- The secret is constructed from an array of characters.

Don't want to install the tools? check the https://github.com/OWASP/wrongsecrets/tree/master?tab=readme-ov-file#want-to-play-but-are-not-allowed-to-install-the-tools[WrongSecrets Desktop container]!
9 changes: 9 additions & 0 deletions src/main/resources/explanations/challenge63_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*Why Using binaries to hide a secret will only delay an attacker.*

With beautiful free Reverse engineering applications as Ghidra, not a lot of things remain safe. Anyone who can load the executable in Ghidra or Radare2 can easily start doing a reconnaissance and find secrets within your Swift binary.

Swift binaries, even though they use name mangling (you can use `swift-demangle` to demangle Swift symbol names), are still susceptible to reverse engineering. The secrets stored as character arrays or string literals can be found in the binary's data section.

Encrypting the secret with a key embedded in the binary, and other funny puzzles do delay an attacker and just make it fun finding the secret. Be aware that, if the secret needs to be used by the executable, it eventually needs to be in memory ready to be executed.

Still need to have a secret in the binary? Make sure it can only be retrieved remotely after authenticating against a server.
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"
explanation: "explanations/challenge63.adoc"
hint: "explanations/challenge63_hint.adoc"
reason: "explanations/challenge63_reason.adoc"
environments: *all_envs
difficulty: *master
category: *bin
ctf:
enabled: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.owasp.wrongsecrets.challenges.docker;

import static org.assertj.core.api.Assertions.assertThat;
import static org.owasp.wrongsecrets.Challenges.ErrorResponses.EXECUTION_ERROR;

import org.junit.jupiter.api.Test;
import org.owasp.wrongsecrets.challenges.Spoiler;

class Challenge63Test {

@Test
void spoilerShouldNotCrash() {
var challenge = new Challenge63();

assertThat(challenge.spoiler()).isNotEqualTo(new Spoiler(EXECUTION_ERROR));
assertThat(challenge.answerCorrect(challenge.spoiler().solution())).isTrue();
}

@Test
void incorrectAnswerShouldNotSolveChallenge() {
var challenge = new Challenge63();

assertThat(challenge.answerCorrect("wrong answer")).isFalse();
}
}
Loading