Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add challenge 37 for ZAP configuration with authenticated endpoint #941

Merged
merged 56 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
56c66d2
Fist setups
commjoen Aug 20, 2023
b6ea0bd
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Aug 20, 2023
ce6a030
Fist setups part 2
commjoen Aug 21, 2023
3046160
Fist setups part 2
commjoen Aug 21, 2023
f49db81
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Aug 21, 2023
a5b8107
fix: add HTTP basic authentication for challenge 37
Aug 29, 2023
1dcbbdb
fix: configure basic-auth username/password
Aug 29, 2023
c7e9904
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Aug 29, 2023
8faec85
fix: update Canary token security configuration
Aug 29, 2023
2968234
Adding basic docs
commjoen Aug 29, 2023
03468e7
fix: update Heroku security config
Aug 29, 2023
12aeb83
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 1, 2023
35be7ca
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 4, 2023
f62c9fd
silly setup for getting challenge to work
commjoen Sep 4, 2023
6cabc87
additional fix: no deprecated api
commjoen Sep 4, 2023
61c3d2b
additional fix: no deprecated api - permit the rest
commjoen Sep 4, 2023
e434ffb
Update dast-zap-test.yml to no longer contain: authorization
commjoen Sep 4, 2023
57eeb6c
Test with an options file
commjoen Sep 5, 2023
0eb276a
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 5, 2023
d5c072c
Test with an options file
commjoen Sep 5, 2023
8821631
migrate to checkout v4
commjoen Sep 5, 2023
0327b82
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 5, 2023
03d4dce
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 5, 2023
d3d6532
possible fix to ref config file
commjoen Sep 5, 2023
a098d51
fix: security configuration
Sep 5, 2023
6576482
Fix merge conflicts
Sep 5, 2023
fec4a36
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Sep 5, 2023
c4b2db3
Update rule-config.tsv
commjoen Sep 5, 2023
f55bbb4
Added missing docs and stable answer key
commjoen Sep 6, 2023
c625e08
Added missing docs and todos for challenge37
commjoen Sep 10, 2023
835ee84
Added missing tests challeenge7
commjoen Sep 10, 2023
cb60f75
extending missing tests
commjoen Sep 10, 2023
19e3846
extending missing vars
commjoen Sep 10, 2023
66351a6
extending missing vars
commjoen Sep 10, 2023
afaf394
fix: security configuration
Sep 12, 2023
012b213
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Sep 12, 2023
25fb757
Apply suggestions from code review
commjoen Sep 13, 2023
2eb95f4
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 13, 2023
084f628
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 15, 2023
9bca2ec
Merge branch 'master' into feature-zap-scan-leak
commjoen Sep 27, 2023
a35d014
Fixed ZAP auth issue
commjoen Sep 29, 2023
7faaa21
Fixed ZAP auth issue
commjoen Sep 29, 2023
e25cf0f
Fixed ZAP auth issue
commjoen Sep 29, 2023
7fcc093
Fixed ZAP auth issue
commjoen Sep 29, 2023
dd6e843
Fixed ZAP auth issue
commjoen Sep 29, 2023
03c6314
retry fix ZAP auth issue
commjoen Sep 29, 2023
4e0ca66
retry fix ZAP auth issue
commjoen Sep 29, 2023
b7aa351
retry fix ZAP auth issue
commjoen Sep 29, 2023
30dd292
retry fix ZAP auth issue
commjoen Sep 29, 2023
b2622ce
retry fix ZAP auth issue
commjoen Sep 29, 2023
c6ba1cf
retry fix ZAP auth issue
commjoen Sep 30, 2023
8501750
retry fix ZAP auth issue
commjoen Sep 30, 2023
9d5d1a6
retry fix ZAP auth issue
commjoen Sep 30, 2023
c2670e8
retry fix ZAP auth issue
commjoen Sep 30, 2023
84115c3
retry fix ZAP auth issue
commjoen Sep 30, 2023
e8546d8
Merge branch 'master' into feature-zap-scan-leak
commjoen Oct 2, 2023
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
3 changes: 3 additions & 0 deletions .github/workflows/dast-zap-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ jobs:
run: nohup ./mvnw spring-boot:run -Dspring-boot.run.profiles=without-vault &
- name: ZAP Scan
uses: zaproxy/[email protected]
env:
ZAP_AUTH_HEADER_VALUE: "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
with:
allow_issue_writing: false
docker_name: "owasp/zap2docker-stable"
target: "http://localhost:8080"
rules_file_name: config/zap/rule-config.tsv
fail_action: true
cmd_options: '-z "-configFile /zap/wrk/config/zap/options.prop"'
4 changes: 4 additions & 0 deletions Dockerfile.web
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ ARG CANARY_URLS="http://canarytokens.com/terms/about/s7cfbdakys13246ewd8ivuvku/p
ARG CTF_ENABLED=false
ARG HINTS_ENABLED=true
ARG CHALLENGE_ACHT_CTF_HOST_VALUE="not_set"
ARG CHALLENGE_THIRTY_HOST_VALUE="not_set"
ARG $CHALLENGE_RANDO_KEY_CTF_TO_PROVIDE_TO_HOST="not_set"
#ONLY OVERRIDE THE ARGS BELOW WHEN YOU ARE SETTING UP A CTF!
ARG CTF_KEY=TRwzkRJnHOTckssAeyJbysWgP!Qc2T
ARG CHALLENGE_5_VALUE=if_you_see_this_please_use_k8s
Expand All @@ -24,6 +26,8 @@ ENV SPECIAL_K8S_SECRET=$CHALLENGE_5_VALUE
ENV SPECIAL_SPECIAL_K8S_SECRET=$CHALLENGE_6_VALUE
ENV vaultpassword=$CHALLENGE_7_VALUE
ENV challenge_acht_ctf_host_value=$CHALLENGE_ACHT_CTF_HOST_VALUE
ENV challenge_thirty_ctf_to_provide_to_host_value=$CHALLENGE_THIRTY_HOST_VALUE
ENV challenge_rando_key_ctf_to_provide_to_host_value=$CHALLENGE_RANDO_KEY_CTF_TO_PROVIDE_TO_HOST
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
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

Welcome to the OWASP WrongSecrets game! The game is packed with real life examples of how to _not_ store secrets in your software. Each of these examples is captured in a challenge, which you need to solve using various tools and techniques. Solving these challenges will help you recognize common mistakes & can help you to reflect on your own secrets management strategy.

Can you solve all the 35 challenges?
Can you solve all the 37 challenges?

Try some of them on [our Heroku demo environment](https://wrongsecrets.herokuapp.com/).

Expand Down Expand Up @@ -71,7 +71,7 @@ Copyright (c) 2020-2023 Jeroen Willemsen and WrongSecrets contributors.

## Basic docker exercises

_Can be used for challenges 1-4, 8, 12-32, 34, 35_
_Can be used for challenges 1-4, 8, 12-32, 34, 35-37_

For the basic docker exercises you currently require:

Expand Down Expand Up @@ -114,6 +114,8 @@ Now you can try to find the secrets by means of solving the challenge offered at
- [localhost:8080/challenge/32](http://localhost:8080/challenge/32)
- [localhost:8080/challenge/34](http://localhost:8080/challenge/34)
- [localhost:8080/challenge/35](http://localhost:8080/challenge/35)
- [localhost:8080/challenge/36](http://localhost:8080/challenge/36)
- [localhost:8080/challenge/37](http://localhost:8080/challenge/37)

Note that these challenges are still very basic, and so are their explanations. Feel free to file a PR to make them look
better ;-).
Expand All @@ -130,7 +132,7 @@ You can test them out at [https://wrongsecrets.fly.dev](https://wrongsecrets.fly

## Basic K8s exercise

_Can be used for challenges 1-6, 8, 12-35_
_Can be used for challenges 1-6, 8, 12-37_

### Minikube based

Expand Down Expand Up @@ -187,7 +189,7 @@ Don't want to go over the hassle of setting up K8S yourself? visit [https://wron

## Vault exercises with minikube

_Can be used for challenges 1-8, 12-35_
_Can be used for challenges 1-8, 12-37_
Make sure you have the following installed:

- minikube with docker (or comment out line 8 and work at your own k8s setup),
Expand All @@ -205,7 +207,7 @@ This is because if you run the start script again it will replace the secret in

## Cloud Challenges

_Can be used for challenges 1-35_
_Can be used for challenges 1-37_

**READ THIS**: Given that the exercises below contain IAM privilege escalation exercises,
never run this on an account which is related to your production environment or can influence your account-over-arching
Expand Down
6 changes: 6 additions & 0 deletions config/zap/options.prop
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
replacer.full_list(0).description=auth1
replacer.full_list(0).enabled=true
replacer.full_list(0).matchtype=REQ_HEADER
replacer.full_list(0).matchstr=Authorization
replacer.full_list(0).regex=false
replacer.full_list(0).replacement=Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
1 change: 1 addition & 0 deletions config/zap/rule-config.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
90033 IGNORE (Loosely Scoped Cookie)
10096 IGNORE (Timestamp Disclosure - Unix)
10112 IGNORE Session Management Response Identified
10105 IGNORE Authentication Credentials Captured
2 changes: 1 addition & 1 deletion ctf-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Want to make sure you don't need to bug your users to copy paste values twice to

Now users can directly use your Wrongsecrets setup together with the CTF-platform to play challenges without having to copy answers and flags twice!

Note: make sure that you do set `CTF_SERVER_ADDRESS` to point to the address where you are running your CTF-platform (E.g. CTFD/Facebook CTF) and that you set `challenge_acht_ctf_to_provide_to_host_value` and `challenge_thirty_ctf_to_provide_to_host_value` to the flag you store in your CTF-platform.
Note: make sure that you do set `CTF_SERVER_ADDRESS` to point to the address where you are running your CTF-platform (E.g. CTFD/Facebook CTF) and that you set `challenge_acht_ctf_to_provide_to_host_value`, `challenge_rando_key_ctf_to_provide_to_host_value`, and `challenge_thirty_ctf_to_provide_to_host_value` to the flag you store in your CTF-platform.

## Setting up CTFs

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.owasp.wrongsecrets;

public record BasicAuthentication(
String username, String password, String role, String urlPattern) {}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.owasp.wrongsecrets;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -40,11 +39,7 @@ public int getTotalReceivedPoints() {

@Override
public List<String> getCompletedChallenges() {
List<String> completed = new ArrayList<>();
for (Challenge challenge : solvedChallenges) {
completed.add(challenge.getNumber());
}
return completed;
return solvedChallenges.stream().map(Challenge::getNumber).toList();
}

@Override
Expand Down
82 changes: 82 additions & 0 deletions src/main/java/org/owasp/wrongsecrets/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.owasp.wrongsecrets;

import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.PortMapper;
import org.springframework.security.web.PortMapperImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain security(
HttpSecurity http,
ObjectProvider<PortMapper> portMapperProvider,
List<BasicAuthentication> auths)
throws Exception {
configureHerokuHttps(http, portMapperProvider.getIfAvailable(PortMapperImpl::new));
configureBasicAuthentication(http, auths);
configureCsrf(http);
return http.build();
}

@Bean
public UserDetailsService userDetailsService(List<BasicAuthentication> auths) {
var users =
auths.stream()
.map(
auth ->
User.builder()
.username(auth.username())
.password("{noop}" + auth.password())
.roles(auth.role())
.build())
.toList();
return new InMemoryUserDetailsManager(users);
}

private void configureCsrf(HttpSecurity http) throws Exception {
http.csrf(
csrf ->
csrf.ignoringRequestMatchers(
"/canaries/tokencallback", "/canaries/tokencallbackdebug"));
}

private void configureBasicAuthentication(HttpSecurity http, List<BasicAuthentication> auths)
throws Exception {
var patterns = auths.stream().map(auth -> auth.urlPattern()).toList();
http.authorizeHttpRequests(
authorize ->
authorize
.requestMatchers(patterns.toArray(new String[patterns.size()]))
.authenticated()
.anyRequest()
.permitAll())
.httpBasic(Customizer.withDefaults());
}

private void configureHerokuHttps(HttpSecurity http, PortMapper portMapper) throws Exception {
var requestMatcher =
new RequestMatcher() {
@Override
public boolean matches(HttpServletRequest request) {
return request.getRequestURL().toString().contains("heroku")
&& request.getHeader("x-forwarded-proto") != null;
}
};
http.requiresChannel(channel -> channel.requestMatchers(requestMatcher).requiresSecure())
.portMapper(configurer -> configurer.portMapper(portMapper));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

import io.swagger.v3.oas.annotations.Hidden;
import org.owasp.wrongsecrets.challenges.docker.Challenge30;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* This is a controller used in challenge 30 to retrieve data that can be put into localstorage by
* the frontend.
*/
@Controller
@RestController
public class ChallengeRestController {
private final Challenge30 challenge30;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.owasp.wrongsecrets.ScoreCard;
import org.owasp.wrongsecrets.challenges.docker.Challenge0;
import org.owasp.wrongsecrets.challenges.docker.Challenge30;
import org.owasp.wrongsecrets.challenges.docker.Challenge37;
import org.owasp.wrongsecrets.challenges.docker.Challenge8;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -54,6 +55,9 @@ public class ChallengesController {
@Value("${challenge_thirty_ctf_to_provide_to_host_value}")
private String keyToProvideToHostForChallenge30;

@Value("${challenge_rando_key_ctf_to_provide_to_host_value}")
private String getKeyToProvideToHostChallenge37;

@Value("${CTF_SERVER_ADDRESS}")
private String ctfServerAddress;

Expand Down Expand Up @@ -189,6 +193,19 @@ public String postController(
+ "for which you get your code: "
+ keyToProvideToHostForChallenge30);
}
} else if (challenge.getChallenge() instanceof Challenge37) {
if (!Strings.isNullOrEmpty(getKeyToProvideToHostChallenge37)
&& !keyToProvideToHostForChallenge30.equals(
"not_set")) { // this means that it was overriden with a code that needs to be
// returned to the ctf key exchange hos
model.addAttribute(
"answerCorrect",
"Your answer is correct! "
+ "fill in the following answer in the CTF instance at "
+ ctfServerAddress
+ "for which you get your code: "
+ getKeyToProvideToHostChallenge37);
}
} else {
model.addAttribute(
"answerCorrect",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.owasp.wrongsecrets.challenges.docker;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.owasp.wrongsecrets.BasicAuthentication;
import org.owasp.wrongsecrets.RuntimeEnvironment;
import org.owasp.wrongsecrets.ScoreCard;
import org.owasp.wrongsecrets.challenges.Challenge;
import org.owasp.wrongsecrets.challenges.ChallengeTechnology;
import org.owasp.wrongsecrets.challenges.Difficulty;
import org.owasp.wrongsecrets.challenges.Spoiler;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
* This is a challenge based on the idea of leaking a secret for an authenticated endpoint through a
* ZAP configuration file.
*/
@Slf4j
@Component
@Order(37)
public class Challenge37 extends Challenge {

private String secret;
private static final String password = "WWpOQ2JHSnBRbnBhV0U1b1lsZFZTd289Cg==";

public Challenge37(ScoreCard scoreCard) {
super(scoreCard);
secret = UUID.randomUUID().toString();
}

@Bean
public BasicAuthentication challenge37BasicAuth() {
return new BasicAuthentication("Aladdin", password, "ADMIN", "authenticated/**");
}

@Override
public boolean canRunInCTFMode() {
return true;
}

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

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

@Override
public int difficulty() {
return Difficulty.NORMAL;
}

/** {@inheritDoc} This is a CICD type of challenge */
@Override
public String getTech() {
return ChallengeTechnology.Tech.CICD.id;
}

@Override
public boolean isLimitedWhenOnlineHosted() {
return false;
}

@Override
public List<RuntimeEnvironment.Environment> supportedRuntimeEnvironments() {
return List.of(RuntimeEnvironment.Environment.DOCKER);
}

public String getPassword() {

return new String(Base64.decode(Base64.decode(Base64.decode(password))), StandardCharsets.UTF_8)
.replaceAll("\\r|\\n", "");
}
}
Loading