Skip to content

Commit

Permalink
Update POM file with new version: ctfd-safe-4
Browse files Browse the repository at this point in the history
  • Loading branch information
commjoen committed Aug 7, 2022
1 parent 1fe1a07 commit 7a5e30c
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 48 deletions.
8 changes: 5 additions & 3 deletions Dockerfile.web
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM jeroenwillemsen/wrongsecrets:ctfd-safe-3-no-vault
FROM jeroenwillemsen/wrongsecrets:ctfd-safe-4-no-vault

ARG argBasedVersion="1.5.0"
ARG CANARY_URLS="http://canarytokens.com/terms/about/s7cfbdakys13246ewd8ivuvku/post.jsp,http://canarytokens.com/terms/about/y0all60b627gzp19ahqh7rl6j/post.jsp"
Expand All @@ -9,8 +9,7 @@ ARG CTF_KEY=TRwzkRJnHOTckssAeyJbysWgP!Qc2T
ARG CHALLENGE_5_VALUE=if_you_see_this_please_use_k8s
ARG CHALLENGE_6_VALUE=if_you_see_this_please_use_k8s
ARG CHALLENGE_7_VALUE=if_you_see_this_please_use_K8S_and_Vault
#TODO: CONTINUE ON THE 3 CHALLENGES BELOW AND TEST THEM! (both with and without CTF!)
ARG CHALLENGE_9_VALUE=if_you_see_this_please_use
ARG CHALLENGE_9_VALUE=if_you_see_this_please_use_AWS_Setup
ARG CHALLENGE_10_VALUE=if_you_see_this_please_use
ARG CHALLENGE_11_VALUE=if_you_see_this_please_use
ENV APP_VERSION=$argBasedVersion
Expand All @@ -24,6 +23,9 @@ ENV keepasspath="/var/helpers/alibabacreds.kdbx"
ENV SPECIAL_K8S_SECRET=$CHALLENGE_5_VALUE
ENV SPECIAL_SPECIAL_K8S_SECRET=$CHALLENGE_6_VALUE
ENV vaultpassword=$CHALLENGE_7_VALUE
ENV default_aws_value_challenge_9=$CHALLENGE_9_VALUE
ENV default_aws_value_challenge_10=$CHALLENGE_10_VALUE
ENV default_aws_value_challenge_11=$CHALLENGE_11_VALUE
COPY .github/scripts/ /var/helpers
COPY src/test/resources/alibabacreds.kdbx /var/helpers
CMD java -Xms128m -Xmx128m -Xss512k -jar -Dserver.port=$PORT -XX:MaxRAMPercentage=75 -XX:MinRAMPercentage=25 -Dspring.profiles.active=without-vault application.jar
37 changes: 37 additions & 0 deletions ctf-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# CTF Instructions

So you want to play a CTF with WrongSecrets? This is the place to read up all about it.
Our CTF setup makes use of the [Juice Shop CTF CLI extension](https://github.com/juice-shop/juice-shop-ctf), which you
can read all about at [here](https://pwning.owasp-juice.shop/part1/ctf.html).

The difference between Juiceshop and WrongSecrets, is that WrongSecrets is more of a secrets-hunter game. Thiss means
that your contestants will try to find the CTF key soon after a few challenges. That is why we should separate out the
actual container for which the CTF scores are generated, from the container where the challenges live in.

You can see this practice already here in our repository: Our standard [Dockerfile](/Dockerfile) does not contain any
CTF entries, our Heroku [Dockerfile.web](/Dockerfile.web) does contain them.
So make sure you host your actual scoring Dockerfile.web at a place where your contestants cannot enter the container (
image) in order to extract the CTF key.

## Setting up CTFs

There are 3 flavors of CTF to be setup: Docker/Heroku, K8S, Cloud based.

### Docker or Heroku CTF

When doing a Docker or Heroku based CTF, you can follow
the [instructions in the readme](https://github.com/commjoen/wrongsecrets#ctfd-support).
If you want to use your own CTF key, you can build a container with the following
arguments `CTF_ENABLED=true,HINTS_ENABLED=false,CTF_KEY=<YOURNEWKEYHERE>`. Just make sure you provide the same key
to `juice-shop-ctf` when you run it.

Want to make it a little more exciting? Override the Dockerfile with your preferred values, so that copying from online
hosted solutions no longer works!

### K8s based CTF - TODO

TODO

### Cloud based CTF - TODO


19 changes: 16 additions & 3 deletions src/main/java/org/owasp/wrongsecrets/RuntimeEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ public class RuntimeEnvironment {
private boolean ctfModeEnabled;

@Value("${SPECIAL_K8S_SECRET}")
private String challenge5Value; //used to determine if they are overriden;
private String challenge5Value; //used to determine if k8s/vault challenges are overriden;

@Value("${default_aws_value_challenge_9}")
private String defaultChallenge9Value; //used to determine if the cloud challenge values are overriden

private static final Map<Environment, List<Environment>> envToOverlappingEnvs = Map.of(
HEROKU_DOCKER, List.of(DOCKER, HEROKU_DOCKER),
Expand Down Expand Up @@ -60,6 +63,11 @@ private boolean isK8sUnlockedInCTFMode() {
return ctfModeEnabled && !challenge5Value.equals(defaultValueChallenge5);
}

private boolean isCloudUnlockedInCTFMode() {
String defaultValueAWSValue = "if_you_see_this_please_use_AWS_Setup";
return ctfModeEnabled && !defaultChallenge9Value.equals(defaultValueAWSValue);
}

@Autowired
public RuntimeEnvironment(@Value("${K8S_ENV}") String currentRuntimeEnvironment) {
this.runtimeEnvironment = Environment.fromId(currentRuntimeEnvironment);
Expand All @@ -70,9 +78,14 @@ public RuntimeEnvironment(Environment runtimeEnvironment) {
}

public boolean canRun(Challenge challenge) {
if (isCloudUnlockedInCTFMode()) {
return true;
}
if (isK8sUnlockedInCTFMode()) {
return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment) || challenge.supportedRuntimeEnvironments().contains(K8S) || challenge.supportedRuntimeEnvironments().contains(VAULT);
} //TODO: WRITE TEST FOR THIS & UPDATE UI THEN!
return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment) ||
challenge.supportedRuntimeEnvironments().contains(DOCKER) || challenge.supportedRuntimeEnvironments().contains(K8S) ||
challenge.supportedRuntimeEnvironments().contains(VAULT);
}
return challenge.supportedRuntimeEnvironments().contains(runtimeEnvironment)
|| !Collections.disjoint(envToOverlappingEnvs.get(runtimeEnvironment), challenge.supportedRuntimeEnvironments());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ public ResponseEntity<String> processCanaryToken(@RequestBody CanaryToken canary
}
log.info("Canarytoken called, with manage_url {}", canaryToken.getManageUrl());
log.info("Total number of canary callback calls: {}", canaryCounter.getTotalCount());
/*
todo:
- follow 3 of baeldung.com/spring-server-sent-events, but make sure you register the emitter per connection
- and in a map lookup which emiter you can use for the given connection to send the event.
*/
return new ResponseEntity<>("all good", HttpStatus.ACCEPTED);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@
import org.owasp.wrongsecrets.RuntimeEnvironment;
import org.owasp.wrongsecrets.ScoreCard;
import org.owasp.wrongsecrets.asciidoc.TemplateGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@Slf4j
@RestController
Expand All @@ -35,11 +32,14 @@ public class ChallengesAPIController {

private final TemplateGenerator templateGenerator;

private final RuntimeEnvironment runtimeEnvironment;

public ChallengesAPIController(ScoreCard scoreCard, List<ChallengeUI> challenges, RuntimeEnvironment runtimeEnvironment, TemplateGenerator templateGenerator) {
this.scoreCard = scoreCard;
this.challenges = challenges;
this.descriptions = new ArrayList<>();
this.hints = new ArrayList<>();
this.runtimeEnvironment = runtimeEnvironment;
this.templateGenerator = templateGenerator;
}

Expand Down Expand Up @@ -117,8 +117,8 @@ private String extractResource(String resourceName) {
}

private String getDisabledEnv(ChallengeUI challenge) {
if (!challenge.getChallenge().supportedRuntimeEnvironments().contains(RuntimeEnvironment.Environment.DOCKER)) {
return "Docker";
if (runtimeEnvironment.canRun(challenge.getChallenge())) {
return runtimeEnvironment.getRuntimeEnvironment().name();
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class Challenge10 extends CloudChallenge {

public Challenge10(ScoreCard scoreCard,
@Value("${secretmountpath}") String filePath,
@Value("${default_aws_value}") String awsDefaultValue,
@Value("${default_aws_value_challenge_10}") String awsDefaultValue,
RuntimeEnvironment runtimeEnvironment) {
super(scoreCard, runtimeEnvironment);
this.awsDefaultValue = awsDefaultValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public class Challenge11 extends CloudChallenge {
private final String azureVaultUri;
private final String azureWrongSecret3;

private final String ctfValue;

private final boolean ctfEnabled;

public Challenge11(ScoreCard scoreCard,
@Value("${AWS_ROLE_ARN}") String awsRoleArn,
@Value("${AWS_WEB_IDENTITY_TOKEN_FILE}") String tokenFileLocation,
Expand All @@ -56,6 +60,8 @@ public Challenge11(ScoreCard scoreCard,
@Value("${azure.keyvault.uri}") String azureVaultUri,
@Value("${wrongsecret-3}") String azureWrongSecret3, // Exclusively auto-wired for Azure
@Value("${GCP_PROJECT_ID}") String projectId,
@Value("${default_aws_value_challenge_11}") String ctfValue,
@Value("${ctf_enabled}") boolean ctfEnabled,
RuntimeEnvironment runtimeEnvironment) {
super(scoreCard, runtimeEnvironment);
this.awsRoleArn = awsRoleArn;
Expand All @@ -67,6 +73,8 @@ public Challenge11(ScoreCard scoreCard,
this.projectId = projectId;
this.azureVaultUri = azureVaultUri;
this.azureWrongSecret3 = azureWrongSecret3;
this.ctfValue = ctfValue;
this.ctfEnabled = ctfEnabled;
this.challengeAnswer = getChallenge11Value(runtimeEnvironment);
}

Expand Down Expand Up @@ -96,6 +104,9 @@ public String getTech() {

private String getChallenge11Value(RuntimeEnvironment runtimeEnvironment) {
if (runtimeEnvironment != null && runtimeEnvironment.getRuntimeEnvironment() != null) {
if (ctfEnabled && ctfValue != awsDefaultValue) {
return ctfValue;
}
return switch (runtimeEnvironment.getRuntimeEnvironment()) {
case AWS -> getAWSChallenge11Value();
case GCP -> getGCPChallenge11Value();
Expand All @@ -112,27 +123,27 @@ private String getAWSChallenge11Value() {
try { //based on https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/sts/src/main/java/com/example/sts
String webIDentityToken = Files.readString(Paths.get(tokenFileLocation));
StsClient stsClient = StsClient.builder()
.region(Region.of(awsRegion))
.build();
.region(Region.of(awsRegion))
.build();
AssumeRoleWithWebIdentityRequest webIdentityRequest = AssumeRoleWithWebIdentityRequest.builder()
.roleArn(awsRoleArn)
.roleSessionName("WrongsecretsApp")
.webIdentityToken(webIDentityToken)
.build();
.roleArn(awsRoleArn)
.roleSessionName("WrongsecretsApp")
.webIdentityToken(webIDentityToken)
.build();

AssumeRoleWithWebIdentityResponse tokenResponse = stsClient.assumeRoleWithWebIdentity(webIdentityRequest);
log.info("The token value is " + tokenResponse.credentials().sessionToken());
SsmClient ssmClient = SsmClient.builder()
.region(Region.of(awsRegion))
.credentialsProvider(StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
.stsClient(stsClient)
.refreshRequest(webIdentityRequest)
.build())
.build();
.region(Region.of(awsRegion))
.credentialsProvider(StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
.stsClient(stsClient)
.refreshRequest(webIdentityRequest)
.build())
.build();
GetParameterRequest parameterRequest = GetParameterRequest.builder()
.name("wrongsecretvalue")
.withDecryption(true)
.build();
.name("wrongsecretvalue")
.withDecryption(true)
.build();
GetParameterResponse parameterResponse = ssmClient.getParameter(parameterRequest);
log.info("The parameter value is " + parameterResponse.parameter().value());
ssmClient.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class Challenge9 extends CloudChallenge {

public Challenge9(ScoreCard scoreCard,
@Value("${secretmountpath}") String filePath,
@Value("${default_aws_value}") String awsDefaultValue,
@Value("${default_aws_value_challenge_9}") String awsDefaultValue,
RuntimeEnvironment runtimeEnvironment) {
super(scoreCard, runtimeEnvironment);
this.awsDefaultValue = awsDefaultValue;
Expand Down
18 changes: 18 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ 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
default_aws_value=if_you_see_this_please_use_AWS_Setup
default_aws_value_challenge_9=if_you_see_this_please_use_AWS_Setup
default_aws_value_challenge_10=if_you_see_this_please_use_AWS_Setup
default_aws_value_challenge_11=if_you_see_this_please_use_AWS_Setup
default_gcp_value=if_you_see_this_please_use_GCP_Setup
default_azure_value=if_you_see_this_please_use_Azure_Setup
AWS_ROLE_ARN=if_you_see_this_please_use_AWS_Setup
Expand Down Expand Up @@ -68,3 +71,18 @@ spring.config.activate.on-profile=without-vault
wrongsecretvalue=wrongsecret
spring.cloud.vault.enabled=false
asciidoctor.enabled=false
#---
spring.config.activate.on-profile=without-vault-ctf-emulation
wrongsecretvalue=wrongsecret
spring.cloud.vault.enabled=false
asciidoctor.enabled=false
ctf_enabled=true
ctf_key=randomtextforkey
vaultpassword=ACTUAL_ANSWER_CHALLENGE7
secretmountpath=nothere
SPECIAL_K8S_SECRET=ACTUAL_ANSWER_CHALLENGE5
SPECIAL_SPECIAL_K8S_SECRET=ACTUAL_ANSWER_CHALLENGE6
default_aws_value_challenge_9=ACTUAL_ANSWER_CHALLENGE9
default_aws_value_challenge_10=ACTUAL_ANSWER_CHALLENGE10
default_aws_value_challenge_11=ACTUAL_ANSWER_CHALLENGE_11
K8S_ENV=Heroku(Docker)
2 changes: 1 addition & 1 deletion src/main/resources/templates/challenge.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
</div>
<div th:if="${missingEnvWarning} eq 'AWS' or ${missingEnvWarning} eq 'GCP'" class="alert alert-danger"
role="alert">
We are running outside a properly configured AWS environment. Please run this in an AWS/GCP environment as
We are running outside a properly configured Cloud environment. Please run this in an AWS/Azure/GCP environment as
explained in the <a href="https://github.com/commjoen/wrongsecrets#cloud-challenges">README.md</a>.
</div>
</div>
Expand Down
Loading

0 comments on commit 7a5e30c

Please sign in to comment.