Compare commits
42 Commits
v2025.2
...
f2e2616a88
Author | SHA1 | Date | |
---|---|---|---|
f2e2616a88 | |||
f6c2996cd4 | |||
c25bc7d7a6 | |||
953e7fd206 | |||
e4cb868623 | |||
5efbd03d98 | |||
7fabcc7fd5 | |||
27ab9f89fa | |||
06c0be257f | |||
8b324b3954 | |||
cba4ff3d48 | |||
ca68d6bcf4 | |||
f6990690de | |||
634162f279 | |||
9f77d74f3e | |||
55ea361f45 | |||
fc6c61397d | |||
f45bf6171b | |||
b3dec8bdc9 | |||
c3f9158eab | |||
ec3b9e8aaf | |||
9ec75d5a56 | |||
49dc370931 | |||
1e1a8af39e | |||
451f5615d2 | |||
a4305f408e | |||
7dea5a1bde | |||
8cd0b0a8c9 | |||
72c09f7240 | |||
d8c402f0d6 | |||
95136c9930 | |||
23d6fe6f36 | |||
2c5e4c4491 | |||
c89fcb140a | |||
3cfd053c83 | |||
10adb1b05f | |||
c3ed45a733 | |||
e2f80b18e2 | |||
641f24df9d | |||
3b3933b69e | |||
05497371db | |||
32cf225d6b |
18
.gitea/workflows/datadog-sca.yml
Normal file
18
.gitea/workflows/datadog-sca.yml
Normal file
@ -0,0 +1,18 @@
|
||||
on: [push]
|
||||
|
||||
name: Datadog Software Composition Analysis
|
||||
|
||||
jobs:
|
||||
software-composition-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog SBOM Generation and Upload
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check imported libraries are secure and compliant
|
||||
id: datadog-software-composition-analysis
|
||||
uses: DataDog/datadog-sca-github-action@main
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
21
.gitea/workflows/datadog-secrets-scanning.yml
Normal file
21
.gitea/workflows/datadog-secrets-scanning.yml
Normal file
@ -0,0 +1,21 @@
|
||||
on: [push]
|
||||
|
||||
name: Datadog Secrets Scanning
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog Static Analyzer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check code for comitted secrets
|
||||
id: datadog-static-analysis
|
||||
uses: DataDog/datadog-static-analyzer-github-action@v1
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
||||
secrets_enabled: true
|
||||
static_analysis_enabled: false
|
||||
cpu_count: 2
|
41
.gitea/workflows/datadog-static-analysis.yml
Normal file
41
.gitea/workflows/datadog-static-analysis.yml
Normal file
@ -0,0 +1,41 @@
|
||||
on: [push]
|
||||
|
||||
name: Datadog Static Analysis
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog Static Analyzer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check code meets quality and security standards
|
||||
id: datadog-static-analysis
|
||||
uses: DataDog/datadog-static-analyzer-github-action@v1
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
||||
cpu_count: 2
|
||||
- name: Run Semgrep
|
||||
run: |
|
||||
python3 -m pip install --break-system-package semgrep
|
||||
semgrep scan --sarif -o /tmp/semgrep.sarif
|
||||
cat /tmp/semgrep.sarif
|
||||
# Download and install nvm:
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
|
||||
# in lieu of restarting the shell
|
||||
\. "$HOME/.nvm/nvm.sh"
|
||||
# Download and install Node.js:
|
||||
nvm install 22
|
||||
# Verify the Node.js version:
|
||||
node -v # Should print "v22.14.0".
|
||||
nvm current # Should print "v22.14.0".
|
||||
# Verify npm version:
|
||||
npm -v # Should print "10.9.2".
|
||||
npm install -g @datadog/datadog-ci
|
||||
datadog-ci sarif upload /tmp/semgrep.sarif
|
||||
env:
|
||||
DD_API_KEY: ${{ secrets.DD_API_KEY }}
|
||||
DD_APP_KEY: ${{ secrets.DD_APP_KEY }}
|
||||
DD_SITE: datadoghq.com
|
134
.gitea/workflows/release.yml
Normal file
134
.gitea/workflows/release.yml
Normal file
@ -0,0 +1,134 @@
|
||||
name: Scheduled Fake Commits
|
||||
|
||||
on:
|
||||
# Trigger the workflow on a schedule.
|
||||
schedule:
|
||||
# This expression means "run every 3 minutes". Useful for testing.
|
||||
# To revert to the original 8-hour schedule, change this to '0 */8 * * *'.
|
||||
- cron: "0 */8 * * *"
|
||||
|
||||
# To trigger manually for testing, you can add workflow_dispatch:
|
||||
# workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
create_scheduled_commits:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Fetch the full history to ensure pushes work correctly
|
||||
fetch-depth: 0
|
||||
# Use a token with write access. This should be stored as a secret in your Gitea repo settings.
|
||||
# The default GITEA_TOKEN might not have push permissions, so a Personal Access Token is recommended.
|
||||
# Ensure you have a secret named GITEA_TOKEN in your repository settings.
|
||||
token: ${{ secrets.GITEA_TOKEN }} # Replace GITEA_TOKEN with the name of your secret
|
||||
|
||||
- name: Set up Git config
|
||||
# Configure Git user details globally for the runner
|
||||
run: |
|
||||
echo "setting up git config"
|
||||
git config --global user.name "Gitea Actions Bot"
|
||||
git config --global user.email "actions-bot@your-gitea-instance.com" # Replace with a suitable email
|
||||
echo "git config setup complete"
|
||||
|
||||
- name: Create and Push Commits
|
||||
env:
|
||||
# Define your list of authors here. Each author should be on a new line,
|
||||
# formatted as "Author Name <author@email.com>".
|
||||
# For production, this should ideally be stored as a secret named FAKE_COMMIT_AUTHORS.
|
||||
# For debugging, you can define it directly here as you have done.
|
||||
AUTHOR_LIST: |
|
||||
Author One <author1@example.com>
|
||||
Author Two <author2@example.com>
|
||||
Author Three <author3@example.com>
|
||||
Author Four <author4@example.com>
|
||||
Author Five <author5@example.com>
|
||||
Author Six <author6@example.com>
|
||||
Author Seven <author7@example.com>
|
||||
Author Eight <author8@example.com>
|
||||
Author Nine <author9@example.com>
|
||||
Author Ten <author10@example.com>
|
||||
DWSAuthor One <dwsauthor1@example.com>
|
||||
DWSAuthor Two <dwsauthor2@example.com>
|
||||
DWSAuthor Three <dwsauthor3@example.com>
|
||||
DWSAuthor Four <autdwshor4@example.com>
|
||||
DWSAuthor Five <autdwshor5@example.com>
|
||||
DWSAuthor Six <autdwshor6@example.com>
|
||||
DWSAuthor Seven <adwsuthor7@example.com>
|
||||
DWSAuthor Eight <adwsuthor8@example.com>
|
||||
DWSAuthor Nine <autdwshor9@example.com>
|
||||
DWSAuthor Ten <autdwshor10@example.com>
|
||||
COMMIT_COUNT: 12 # Number of commits to create
|
||||
SLEEP_SECONDS: 120 # Delay between commits in seconds
|
||||
TARGET_BRANCH: main # The branch to commit to
|
||||
|
||||
run: |
|
||||
echo "starting Create and Push Commits step"
|
||||
echo "AUTHOR_LIST content:"
|
||||
echo "$AUTHOR_LIST" # Echo the content of the variable for debugging
|
||||
|
||||
echo "reading author's list into array"
|
||||
# Read authors into a Bash array using readarray
|
||||
readarray -t authors <<< "$AUTHOR_LIST"
|
||||
echo "finished reading author's list into array"
|
||||
|
||||
# Check if authors list is empty
|
||||
if [ ${#authors[@]} -eq 0 ]; then
|
||||
echo "Error: AUTHOR_LIST is empty or could not be parsed into an array."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting commit creation process..."
|
||||
echo "Authors available: ${#authors[@]}"
|
||||
echo "Commits to create: $COMMIT_COUNT"
|
||||
echo "Delay between commits: $SLEEP_SECONDS seconds"
|
||||
echo "Target branch: $TARGET_BRANCH"
|
||||
|
||||
# Loop to create the specified number of commits
|
||||
for i in $(seq 1 $COMMIT_COUNT); do
|
||||
# Calculate the index for the current author, cycling through the list
|
||||
author_index=$(( (i - 1) % ${#authors[@]} ))
|
||||
current_author="${authors[$author_index]}"
|
||||
|
||||
echo "Processing author: $current_author" # Debug echo
|
||||
|
||||
# Extract name and email from the author string
|
||||
# Assumes format "Name <email>"
|
||||
author_name=$(echo "$current_author" | sed -E 's/^(.*) <.*>$/\1/')
|
||||
author_email=$(echo "$current_author" | sed -E 's/^.* <(.*)>$/\1/')
|
||||
|
||||
echo "Extracted name: $author_name, email: $author_email" # Debug echo
|
||||
|
||||
echo "--- Creating commit $i of $COMMIT_COUNT by $author_name ---"
|
||||
|
||||
# Configure git user for this specific commit
|
||||
git config user.name "$author_name"
|
||||
git config user.email "$author_email"
|
||||
|
||||
# Create a dummy change: append current timestamp and author to a file
|
||||
# This ensures there's always something to commit
|
||||
echo "$(date): Commit $i by $author_name" >> fake_commit_log.txt
|
||||
|
||||
# Stage the changes
|
||||
git add fake_commit_log.txt
|
||||
|
||||
# Commit the changes
|
||||
git commit -m "Automated commit $i by $author_name"
|
||||
|
||||
# Push the commit to the target branch
|
||||
# Use --set-upstream origin $TARGET_BRANCH on the first push if needed
|
||||
echo "Pushing commit..."
|
||||
git push origin HEAD:$TARGET_BRANCH
|
||||
|
||||
echo "Commit $i pushed successfully."
|
||||
|
||||
# Wait for the specified delay before the next commit, unless it's the last one
|
||||
if [ $i -lt $COMMIT_COUNT ]; then
|
||||
echo "Waiting for $SLEEP_SECONDS seconds..."
|
||||
sleep $SLEEP_SECONDS
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Finished creating $COMMIT_COUNT commits."
|
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@ -68,7 +68,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: "Set up QEMU"
|
||||
uses: docker/setup-qemu-action@v3.4.0
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
@ -76,13 +76,13 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: "Login to dockerhub"
|
||||
uses: docker/login-action@v3.3.0
|
||||
uses: docker/login-action@v3.4.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: "Build and push WebGoat"
|
||||
uses: docker/build-push-action@v6.14.0
|
||||
uses: docker/build-push-action@v6.16.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile
|
||||
@ -95,7 +95,7 @@ jobs:
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
|
||||
- name: "Build and push WebGoat desktop"
|
||||
uses: docker/build-push-action@v6.14.0
|
||||
uses: docker/build-push-action@v6.16.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile_desktop
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -39,7 +39,6 @@ UserDatabase.mv.db
|
||||
webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props
|
||||
webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom
|
||||
webgoat-lessons/**/target
|
||||
**/*.jar
|
||||
**/.DS_Store
|
||||
webgoat-server/mongo-data/*
|
||||
webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml
|
||||
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1,2 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
|
@ -99,7 +99,7 @@ For a full overview of all the parameters you can use, please check the [WebGoat
|
||||
|
||||
### Prerequisites:
|
||||
|
||||
* Java 17 or 21
|
||||
* Java 23
|
||||
* Your favorite IDE
|
||||
* Git, or Git support in your IDE
|
||||
|
||||
|
@ -1,5 +1,17 @@
|
||||
# WebGoat release notes
|
||||
|
||||
## Version 2025.3
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Changed URLs imply other exclusion filters for ZAP (#2052)
|
||||
- XSS lesson stage 12 (2 issues) (#1178)
|
||||
|
||||
### 🔄 Technical tasks
|
||||
|
||||
- bump docker/setup-qemu-action from 3.4.0 to 3.6.0 (#2049)
|
||||
- bump docker/build-push-action from 6.14.0 to 6.15.0 (#2050)
|
||||
|
||||
## Version 2025.2
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="refresh" content="0;url=https://owasp.org/www-project-webgoat/" />
|
||||
<link rel="canonical" href="https://owasp.org/www-project-webgoat/" />
|
||||
<meta http-equiv="refresh" content="0;url=https://webgoat.org" />
|
||||
<link rel="canonical" href="https://webgoat.org" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
The page been moved to <a href="https://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a>
|
||||
The page been moved to <a href="https://webgoat.org">https://webgoat.org</a>
|
||||
</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
2
fake_commit_log.txt
Normal file
2
fake_commit_log.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Sat May 10 12:27:40 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 12:28:00 UTC 2025: Commit 2 by Author Two
|
33
pom.xml
33
pom.xml
@ -5,12 +5,12 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.4.3</version>
|
||||
<version>3.4.4</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat</artifactId>
|
||||
<version>2025.2</version>
|
||||
<version>2025.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>WebGoat</name>
|
||||
@ -63,29 +63,29 @@
|
||||
<properties>
|
||||
<!-- Shared properties with plugins and version numbers across submodules-->
|
||||
<asciidoctorj.version>3.0.0</asciidoctorj.version>
|
||||
<bootstrap.version>5.3.3</bootstrap.version>
|
||||
<bootstrap.version>5.3.5</bootstrap.version>
|
||||
<cglib.version>3.3.0</cglib.version>
|
||||
<!-- do not update necessary for lesson -->
|
||||
<checkstyle.version>3.6.0</checkstyle.version>
|
||||
<commons-collections.version>3.2.1</commons-collections.version>
|
||||
<commons-compress.version>1.27.1</commons-compress.version>
|
||||
<commons-io.version>2.18.0</commons-io.version>
|
||||
<commons-io.version>2.19.0</commons-io.version>
|
||||
<commons-lang3.version>3.14.0</commons-lang3.version>
|
||||
<commons-text.version>1.13.0</commons-text.version>
|
||||
<guava.version>33.4.0-jre</guava.version>
|
||||
<commons-text.version>1.13.1</commons-text.version>
|
||||
<guava.version>33.4.8-jre</guava.version>
|
||||
<jacoco.version>0.8.11</jacoco.version>
|
||||
<java.version>23</java.version>
|
||||
<jaxb.version>2.3.1</jaxb.version>
|
||||
<jjwt.version>0.9.1</jjwt.version>
|
||||
<jose4j.version>0.9.3</jose4j.version>
|
||||
<jquery.version>3.7.1</jquery.version>
|
||||
<jsoup.version>1.18.3</jsoup.version>
|
||||
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
|
||||
<jsoup.version>1.19.1</jsoup.version>
|
||||
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
|
||||
<maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version>
|
||||
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
|
||||
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
||||
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
|
||||
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
|
||||
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
||||
<maven.compiler.proc>full</maven.compiler.proc>
|
||||
<maven.compiler.source>23</maven.compiler.source>
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
@ -96,14 +96,14 @@
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
|
||||
<waittimeForServerStart>60</waittimeForServerStart>
|
||||
<webdriver.version>5.9.3</webdriver.version>
|
||||
<webdriver.version>6.0.1</webdriver.version>
|
||||
<webgoat.context>/WebGoat</webgoat.context>
|
||||
<webgoat.port>8080</webgoat.port>
|
||||
<webgoat.sslenabled>false</webgoat.sslenabled>
|
||||
<webjars-locator-core.version>0.59</webjars-locator-core.version>
|
||||
<webwolf.context>/WebWolf</webwolf.context>
|
||||
<webwolf.port>9090</webwolf.port>
|
||||
<wiremock.version>3.12.0</wiremock.version>
|
||||
<wiremock.version>3.13.0</wiremock.version>
|
||||
<xml-resolver.version>1.2</xml-resolver.version>
|
||||
<xstream.version>1.4.5</xstream.version>
|
||||
<!-- do not update necessary for lesson -->
|
||||
@ -217,12 +217,12 @@
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby</artifactId>
|
||||
<version>9.4.12.0</version>
|
||||
<version>10.0.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>playwright</artifactId>
|
||||
<version>1.50.0</version>
|
||||
<version>1.51.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
@ -238,7 +238,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.36</version>
|
||||
<version>1.18.38</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@ -510,7 +510,7 @@
|
||||
<configuration>
|
||||
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
|
||||
<!-- Necessary for vulnerable components lesson -->
|
||||
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||
<argLine>--enable-native-access=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED
|
||||
@ -536,7 +536,7 @@
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>2.44.3</version>
|
||||
<version>2.44.4</version>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>
|
||||
@ -694,6 +694,7 @@
|
||||
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||
<argument>-Dspring.main.banner-mode=off</argument>
|
||||
<argument>--enable-native-access=ALL-UNNAMED</argument>
|
||||
<argument>--add-opens</argument>
|
||||
<argument>java.base/java.lang=ALL-UNNAMED</argument>
|
||||
<argument>--add-opens</argument>
|
||||
|
@ -4,12 +4,9 @@
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -21,7 +18,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
void testChallenge1() {
|
||||
startLesson("Challenge1");
|
||||
|
||||
byte[] resultBytes =
|
||||
byte[] resultBytes =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
@ -38,8 +35,8 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
params.put("username", "admin");
|
||||
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/1"), params, true);
|
||||
String result =
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/1"), params, true);
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
@ -54,22 +51,9 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true);
|
||||
|
||||
checkResults("Challenge1");
|
||||
|
||||
List<String> capturefFlags =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("scoreboard-data"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
||||
assertTrue(capturefFlags.contains("Admin lost password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -81,7 +65,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
params.put("username_login", "Larry");
|
||||
params.put("password_login", "1' or '1'='1");
|
||||
|
||||
String result =
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
@ -96,22 +80,9 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true);
|
||||
|
||||
checkResults("Challenge5");
|
||||
|
||||
List<String> capturefFlags =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("scoreboard-data"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
||||
assertTrue(capturefFlags.contains("Without password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -120,7 +91,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
cleanMailbox();
|
||||
|
||||
// One should first be able to download git.zip from WebGoat
|
||||
RestAssured.given()
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
@ -131,7 +102,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.asString();
|
||||
|
||||
// Should email WebWolf inbox this should give a hint to the link being static
|
||||
RestAssured.given()
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
@ -157,18 +128,20 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||
|
||||
// Call reset link with admin link
|
||||
String result =
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
|
||||
.get(
|
||||
webGoatUrlConfig.url("challenge/7/reset-password/{link}"),
|
||||
"375afe1104f4a487a73823c50a9292a2")
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value())
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/7"), Map.of("flag", flag), true);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/7"), Map.of("flag", flag), true);
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,6 @@ package org.owasp.webgoat.integration;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Angel Olle Blazquez
|
||||
*/
|
||||
class SessionManagementIT extends IntegrationTest {
|
||||
|
||||
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
|
||||
|
@ -19,12 +19,17 @@ public class PlaywrightTest {
|
||||
public static class WebGoatOptions implements OptionsFactory {
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
return new Options().setHeadless(true).setContextOptions(getContextOptions());
|
||||
return new Options()
|
||||
.setHeadless(true)
|
||||
.setContextOptions(getContextOptions());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static Browser.NewContextOptions getContextOptions() {
|
||||
return new Browser.NewContextOptions().setBaseURL(webGoatUrlConfig.getBaseUrl());
|
||||
return new Browser.NewContextOptions()
|
||||
.setLocale("en-US")
|
||||
.setBaseURL(webGoatUrlConfig.getBaseUrl());
|
||||
}
|
||||
|
||||
public static String webGoatUrl(String path) {
|
||||
|
@ -35,7 +35,7 @@ public class RegistrationUITest extends PlaywrightTest {
|
||||
@Test
|
||||
@DisplayName("Should register a new user")
|
||||
void registerNewUser(Browser browser) {
|
||||
var page = browser.newContext().newPage();
|
||||
var page = browser.newContext(new Browser.NewContextOptions().setLocale("en-US")).newPage();
|
||||
var registrationPage = new RegistrationPage(page);
|
||||
registrationPage.open();
|
||||
|
||||
|
@ -33,19 +33,19 @@ public class Authentication {
|
||||
|
||||
public static Page sylvester(Browser browser) {
|
||||
User user = login(browser, sylvester);
|
||||
return browser.newContext(new Browser.NewContextOptions().setStorageState(user.auth)).newPage();
|
||||
return browser.newContext(new Browser.NewContextOptions().setLocale("en-US").setStorageState(user.auth)).newPage();
|
||||
}
|
||||
|
||||
public static Page tweety(Browser browser) {
|
||||
User user = login(browser, tweety);
|
||||
return browser.newContext(new Browser.NewContextOptions().setStorageState(user.auth)).newPage();
|
||||
return browser.newContext(new Browser.NewContextOptions().setLocale("en-US").setStorageState(user.auth)).newPage();
|
||||
}
|
||||
|
||||
private static User login(Browser browser, User user) {
|
||||
if (user.loggedIn()) {
|
||||
return user;
|
||||
}
|
||||
var page = browser.newContext().newPage();
|
||||
var page = browser.newContext(new Browser.NewContextOptions().setLocale("en-US")).newPage();
|
||||
RegistrationPage registrationPage = new RegistrationPage(page);
|
||||
registrationPage.open();
|
||||
registrationPage.register(user.name, user.password);
|
||||
|
@ -42,8 +42,6 @@ public class VulnerableTaskHolder implements Serializable {
|
||||
|
||||
/**
|
||||
* Execute a task when de-serializing a saved or received object.
|
||||
*
|
||||
* @author stupid develop
|
||||
*/
|
||||
private void readObject(ObjectInputStream stream) throws Exception {
|
||||
// unserialize data so taskName and taskAction are available
|
||||
|
@ -11,11 +11,6 @@ import java.io.IOException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
|
||||
/**
|
||||
* AjaxAuthenticationEntryPoint class.
|
||||
*
|
||||
* @author zupzup
|
||||
*/
|
||||
public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
|
||||
public AjaxAuthenticationEntryPoint(String loginFormUrl) {
|
||||
super(loginFormUrl);
|
||||
|
@ -47,17 +47,26 @@ public class LessonTemplateResolver extends FileTemplateResolver {
|
||||
var templateName = resourceName.substring(PREFIX.length());
|
||||
byte[] resource = resources.get(templateName);
|
||||
if (resource == null) {
|
||||
try {
|
||||
resource =
|
||||
resourceLoader
|
||||
.getResource("classpath:/" + templateName)
|
||||
.getInputStream()
|
||||
.readAllBytes();
|
||||
} catch (IOException e) {
|
||||
log.error("Unable to find lesson HTML: {}", template);
|
||||
}
|
||||
resources.put(templateName, resource);
|
||||
resource = loadAndCache(templateName);
|
||||
}
|
||||
|
||||
if (resource == null) {
|
||||
return new StringTemplateResource("Unable to find lesson HTML: %s".formatted(templateName));
|
||||
}
|
||||
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private byte[] loadAndCache(String templateName) {
|
||||
try {
|
||||
var resource =
|
||||
resourceLoader.getResource("classpath:/" + templateName).getInputStream().readAllBytes();
|
||||
resources.put(templateName, resource);
|
||||
return resource;
|
||||
} catch (IOException e) {
|
||||
log.error(
|
||||
"Unable to find lesson HTML: '{}', does the name of HTML file name match the lesson class name?",
|
||||
templateName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.addViewController("/lesson_content").setViewName("lesson_content");
|
||||
registry.addViewController("/start.mvc").setViewName("main_new");
|
||||
registry.addViewController("/scoreboard").setViewName("scoreboard");
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -10,12 +10,6 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Welcome class.
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Controller
|
||||
public class Welcome {
|
||||
|
||||
|
@ -11,8 +11,6 @@ import org.springframework.context.support.ReloadableResourceBundleMessageSource
|
||||
/**
|
||||
* ExposedReloadableResourceMessageBundleSource class. Extends the reloadable message source with a
|
||||
* way to get all messages
|
||||
*
|
||||
* @author zupzup
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class Messages extends ReloadableResourceBundleMessageSource {
|
||||
|
@ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* LessonInfoModel class.
|
||||
*
|
||||
* @author dm
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class LessonInfoModel {
|
||||
|
@ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LessonMenuItem class.
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
public class LessonMenuItem {
|
||||
|
||||
private String name;
|
||||
|
@ -18,11 +18,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* LessonProgressService class.
|
||||
*
|
||||
* @author webgoat
|
||||
*/
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class LessonProgressService {
|
||||
|
@ -6,12 +6,6 @@ package org.owasp.webgoat.container.session;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* LabelDebugger class.
|
||||
*
|
||||
* @author dm
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
public class LabelDebugger implements Serializable {
|
||||
|
||||
private boolean enabled = false;
|
||||
|
@ -84,6 +84,6 @@ public class LessonProgress {
|
||||
}
|
||||
|
||||
long numberOfSolvedAssignments() {
|
||||
return assignments.size();
|
||||
return assignments.stream().filter(AssignmentProgress::isSolved).count();
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2017 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.container.users;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.container.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.owasp.webgoat.container.session.Course;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Temp endpoint just for the CTF.
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 3/23/17.
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class Scoreboard {
|
||||
|
||||
private final UserProgressRepository userTrackerRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final Course course;
|
||||
private final PluginMessages pluginMessages;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private class Ranking {
|
||||
private String username;
|
||||
private List<String> flagsCaptured;
|
||||
}
|
||||
|
||||
@GetMapping("/scoreboard-data")
|
||||
public List<Ranking> getRankings() {
|
||||
return userRepository.findAll().stream()
|
||||
.filter(user -> !user.getUsername().startsWith("csrf-"))
|
||||
.map(
|
||||
user ->
|
||||
new Ranking(
|
||||
user.getUsername(),
|
||||
challengesSolved(userTrackerRepository.findByUser(user.getUsername()))))
|
||||
.sorted((o1, o2) -> o2.getFlagsCaptured().size() - o1.getFlagsCaptured().size())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> challengesSolved(UserProgress userTracker) {
|
||||
List<String> challenges =
|
||||
List.of(
|
||||
"Challenge1",
|
||||
"Challenge2",
|
||||
"Challenge3",
|
||||
"Challenge4",
|
||||
"Challenge5",
|
||||
"Challenge6",
|
||||
"Challenge7",
|
||||
"Challenge8",
|
||||
"Challenge9");
|
||||
return challenges.stream()
|
||||
.map(userTracker::getLessonProgress)
|
||||
.flatMap(Optional::stream)
|
||||
.filter(LessonProgress::isLessonSolved)
|
||||
.map(LessonProgress::getLessonName)
|
||||
.map(this::toLessonTitle)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String toLessonTitle(String id) {
|
||||
String titleKey =
|
||||
course.getLessons().stream()
|
||||
.filter(l -> l.getId().equals(id))
|
||||
.findFirst()
|
||||
.map(Lesson::getTitle)
|
||||
.orElse("No title");
|
||||
return pluginMessages.getMessage(titleKey, titleKey);
|
||||
}
|
||||
}
|
@ -10,10 +10,6 @@ import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserForm {
|
||||
|
@ -41,7 +41,7 @@ public class UserProgress {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an existing lesson tracker or create a new one based on the lesson
|
||||
* Returns an existing lesson progress or create a new one based on the lesson
|
||||
*
|
||||
* @param lesson the lesson
|
||||
* @return a lesson tracker created if not already present
|
||||
@ -49,7 +49,7 @@ public class UserProgress {
|
||||
public LessonProgress getLessonProgress(Lesson lesson) {
|
||||
Optional<LessonProgress> progress =
|
||||
lessonProgress.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst();
|
||||
if (!progress.isPresent()) {
|
||||
if (progress.isEmpty()) {
|
||||
LessonProgress newLessonTracker = new LessonProgress(lesson);
|
||||
lessonProgress.add(newLessonTracker);
|
||||
return newLessonTracker;
|
||||
@ -58,16 +58,6 @@ public class UserProgress {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query method for finding a specific lesson tracker based on id
|
||||
*
|
||||
* @param id the id of the lesson
|
||||
* @return optional due to the fact we can only create a lesson tracker based on a lesson
|
||||
*/
|
||||
public Optional<LessonProgress> getLessonProgress(String id) {
|
||||
return lessonProgress.stream().filter(l -> l.getLessonName().equals(id)).findFirst();
|
||||
}
|
||||
|
||||
public void assignmentSolved(Lesson lesson, String assignmentName) {
|
||||
LessonProgress progress = getLessonProgress(lesson);
|
||||
progress.incrementAttempts();
|
||||
|
@ -7,10 +7,6 @@ package org.owasp.webgoat.container.users;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<WebGoatUser, String> {
|
||||
|
||||
WebGoatUser findByUsername(String username);
|
||||
|
@ -14,10 +14,6 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class UserService implements UserDetailsService {
|
||||
|
@ -10,10 +10,6 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/15/17.
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
|
@ -9,10 +9,6 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class UserValidator implements Validator {
|
||||
|
@ -15,10 +15,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Getter
|
||||
@Entity
|
||||
public class WebGoatUser implements UserDetails {
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/21/17.
|
||||
*/
|
||||
@Component
|
||||
public class ChallengeIntro extends Lesson {
|
||||
|
||||
|
@ -9,10 +9,6 @@ import java.time.LocalDateTime;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
public class Email implements Serializable {
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/21/17.
|
||||
*/
|
||||
@Component
|
||||
public class Challenge1 extends Lesson {
|
||||
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/21/17.
|
||||
*/
|
||||
@Component
|
||||
public class Challenge5 extends Lesson {
|
||||
|
||||
|
@ -29,10 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/8/17.
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
public class Assignment7 implements AssignmentEndpoint {
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/21/17.
|
||||
*/
|
||||
@Component
|
||||
public class Challenge7 extends Lesson {
|
||||
|
||||
|
@ -8,9 +8,6 @@ import java.util.Random;
|
||||
|
||||
/**
|
||||
* WARNING: DO NOT CHANGE FILE WITHOUT CHANGING .git contents
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/17/17.
|
||||
*/
|
||||
public class PasswordResetLink {
|
||||
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/21/17.
|
||||
*/
|
||||
@Component
|
||||
public class Challenge8 extends Lesson {
|
||||
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author TMelzer
|
||||
* @since 30.11.18
|
||||
*/
|
||||
@Component
|
||||
public class ChromeDevTools extends Lesson {
|
||||
|
||||
|
@ -15,12 +15,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* This is just a class used to make the HTTP request.
|
||||
*
|
||||
* @author TMelzer
|
||||
* @since 30.11.18
|
||||
*/
|
||||
@RestController
|
||||
public class NetworkDummy implements AssignmentEndpoint {
|
||||
|
||||
|
@ -19,9 +19,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
/**
|
||||
* Assignment where the user has to look through an HTTP Request using the Developer Tools and find
|
||||
* a specific number.
|
||||
*
|
||||
* @author TMelzer
|
||||
* @since 30.11.18
|
||||
*/
|
||||
@RestController
|
||||
@AssignmentHints({"networkHint1", "networkHint2"})
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author BenediktStuhrmann
|
||||
* @since 11/2/18.
|
||||
*/
|
||||
@Component
|
||||
public class CIA extends Lesson {
|
||||
|
||||
|
@ -15,10 +15,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/6/17.
|
||||
*/
|
||||
@RestController
|
||||
@AssignmentHints({
|
||||
"client.side.filtering.free.hint1",
|
||||
|
@ -15,10 +15,6 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/6/17.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/clientSideFiltering/challenge-store")
|
||||
public class ShopEndpoint {
|
||||
|
@ -10,10 +10,6 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/8/17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
|
@ -8,12 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author Angel Olle Blazquez
|
||||
*
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class HijackSession extends Lesson {
|
||||
|
||||
|
@ -21,12 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author Angel Olle Blazquez
|
||||
*
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@AssignmentHints({
|
||||
"hijacksession.hints.1",
|
||||
|
@ -9,9 +9,6 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Angel Olle Blazquez
|
||||
*/
|
||||
@Getter
|
||||
@ToString
|
||||
public class Authentication implements Principal {
|
||||
|
@ -6,9 +6,6 @@ package org.owasp.webgoat.lessons.hijacksession.cas;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* @author Angel Olle Blazquez
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AuthenticationProvider<T extends Principal> {
|
||||
|
||||
|
@ -15,10 +15,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.annotation.ApplicationScope;
|
||||
|
||||
/**
|
||||
* @author Angel Olle Blazquez
|
||||
*/
|
||||
|
||||
// weak id value and mechanism
|
||||
|
||||
@ApplicationScope
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/22/17.
|
||||
*/
|
||||
@Component
|
||||
public class JWT extends Lesson {
|
||||
|
||||
|
@ -4,10 +4,6 @@
|
||||
*/
|
||||
package org.owasp.webgoat.lessons.jwt.votes;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/30/17.
|
||||
*/
|
||||
public class Views {
|
||||
public interface GuestView {}
|
||||
|
||||
|
@ -7,10 +7,6 @@ package org.owasp.webgoat.lessons.jwt.votes;
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 5/2/17.
|
||||
*/
|
||||
@Getter
|
||||
public class Vote {
|
||||
@JsonView(Views.GuestView.class)
|
||||
|
@ -17,10 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
public class QuestionsAssignment implements AssignmentEndpoint {
|
||||
|
||||
|
@ -29,10 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
@AssignmentHints({
|
||||
"password-reset-hint1",
|
||||
|
@ -22,12 +22,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Part of the password reset assignment. Used to send the e-mail.
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
public class ResetLinkAssignmentForgotPassword implements AssignmentEndpoint {
|
||||
|
||||
|
@ -17,12 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Assignment for picking a good security question.
|
||||
*
|
||||
* @author Tobias Melzer
|
||||
* @since 11.12.18
|
||||
*/
|
||||
@RestController
|
||||
public class SecurityQuestionAssignment implements AssignmentEndpoint {
|
||||
|
||||
|
@ -23,10 +23,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
public class SimpleMailAssignment implements AssignmentEndpoint {
|
||||
private final String webWolfURL;
|
||||
|
@ -9,10 +9,6 @@ import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/18/17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class PasswordChangeForm {
|
||||
|
@ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author BenediktStuhrmann
|
||||
* @since 12/2/18.
|
||||
*/
|
||||
@Component
|
||||
public class SecurePasswords extends Lesson {
|
||||
|
||||
|
@ -8,12 +8,6 @@ import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author Angel Olle Blazquez
|
||||
*
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class SpoofCookie extends Lesson {
|
||||
|
||||
|
@ -25,12 +25,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author Angel Olle Blazquez
|
||||
*
|
||||
*/
|
||||
|
||||
@AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"})
|
||||
@RestController
|
||||
public class SpoofCookieAssignment implements AssignmentEndpoint {
|
||||
|
@ -9,12 +9,6 @@ import java.util.Base64;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.security.crypto.codec.Hex;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author Angel Olle Blazquez
|
||||
*
|
||||
*/
|
||||
|
||||
public class EncDec {
|
||||
|
||||
// PoC: weak encoding method
|
||||
|
@ -17,10 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 6/13/17.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("SqlInjectionMitigations/servers")
|
||||
@Slf4j
|
||||
|
@ -18,10 +18,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
public class LandingAssignment implements AssignmentEndpoint {
|
||||
private final String landingPageUrl;
|
||||
|
@ -20,10 +20,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@RestController
|
||||
public class MailAssignment implements AssignmentEndpoint {
|
||||
|
||||
|
@ -10,10 +10,6 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/8/17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
|
@ -12,10 +12,6 @@ import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/8/17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
|
@ -14,10 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 5/4/17.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("xxe/comments")
|
||||
@AllArgsConstructor
|
||||
|
@ -14,10 +14,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Configuration
|
||||
public class MvcConfiguration implements WebMvcConfigurer {
|
||||
|
||||
|
@ -18,10 +18,6 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
|
@ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.mailbox;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/17/17.
|
||||
*/
|
||||
public interface MailboxRepository extends JpaRepository<Email, String> {
|
||||
|
||||
List<Email> findByRecipientOrderByTimeDesc(String recipient);
|
||||
|
@ -21,9 +21,6 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific user.
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
|
@ -16,9 +16,6 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
|
||||
/**
|
||||
* Keep track of all the incoming requests, we are only keeping track of request originating from
|
||||
* WebGoat.
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
public class WebWolfTraceRepository implements HttpExchangeRepository {
|
||||
private enum MatchingMode {
|
||||
|
@ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.user;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Repository("webWolfUserRepository")
|
||||
public interface UserRepository extends JpaRepository<WebWolfUser, String> {
|
||||
|
||||
|
@ -8,10 +8,6 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Service
|
||||
public class UserService implements UserDetailsService {
|
||||
|
||||
|
@ -15,10 +15,6 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "WEB_GOAT_USER")
|
||||
|
@ -36,10 +36,6 @@ logging.level.org.hidbernate.SQL=INFO
|
||||
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||
webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||
webgoat.build.version=@project.version@
|
||||
webgoat.email=webgoat@owasp.org
|
||||
webgoat.emaillist=owasp-webgoat@lists.owasp.org
|
||||
webgoat.feedback.address=webgoat@owasp.org
|
||||
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
|
||||
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
|
||||
webgoat.default.language=en
|
||||
webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path}
|
||||
@ -51,9 +47,9 @@ webwolf.url=http://${webwolf.host}:${webwolf.port}${webwolf.context}
|
||||
webwolf.landingpage.url=${webwolf.url}/landing
|
||||
webwolf.mail.url=${webwolf.url}/mail
|
||||
|
||||
spring.jpa.properties.jakarta.persistence.schema-generation.scripts.action=create
|
||||
spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-target=create.sql
|
||||
spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-source=metadata
|
||||
#spring.jpa.properties.jakarta.persistence.schema-generation.scripts.action=create
|
||||
#spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-target=create.sql
|
||||
#spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-source=metadata
|
||||
|
||||
spring.jackson.serialization.indent_output=true
|
||||
spring.jackson.serialization.write-dates-as-timestamps=false
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
The challenges contain more a CTF like lessons where we do not provide any explanations what you need to do, no hints
|
||||
will be provided. You can use these challenges in a CTF style where you can run WebGoat on one server and all
|
||||
participants can join and hack the challenges. A scoreboard is available at link:scoreboard["scoreboard",window=_blank]
|
||||
participants can join and hack the challenges.
|
||||
|
||||
:hardbreaks:
|
||||
In this CTF you will need to solve a couple of challenges, each challenge will give you a flag which you will
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="~{doc:lessons/challenges/documentation/Challenge_introduction.adoc}"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
@ -45,7 +45,7 @@
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
th:action="@{/chromeDevTools/network}">
|
||||
th:action="@{/ChromeDevTools/network}">
|
||||
<script>
|
||||
// sample custom javascript in the recommended way ...
|
||||
// a namespace has been assigned for it, but you can roll your own if you prefer
|
||||
@ -66,7 +66,7 @@
|
||||
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
th:action="@{/chromeDevTools/network}">
|
||||
th:action="@{/ChromeDevTools/network}">
|
||||
<table>
|
||||
<tr>
|
||||
<td>What is the number you found: </td>
|
||||
|
@ -1,24 +1,7 @@
|
||||
==== Setting up browser
|
||||
|
||||
If you use the latest ZAP version (>= 2.8.0), you only need to start ZAP and click the browser button to be able to proxy, see image below:
|
||||
|
||||
{nbsp} +
|
||||
|
||||
image::images/zap-browser-button.png[ZAP Start,style="lesson-image"]
|
||||
|
||||
{nbsp} +
|
||||
|
||||
In the browser type: http://localhost:8080/WebGoat, you should see WebGoat and the OWASP ZAP Heads On Display (if you use OWASP ZAP as the proxy):
|
||||
|
||||
{nbsp} +
|
||||
|
||||
image::images/loginscreen.png[Browser with HUD,style="lesson-image"]
|
||||
|
||||
{nbsp} +
|
||||
|
||||
You might notice that this is the Dutch login screen. The browser determines the language settings. For some pages, there will be some local translations. You can contribute to WebGoat and add more for your preferred language. You can disable the Heads On Display by clicking on the highlighted button. You can learn about the OWASP ZAP HUD on their website. For now, we recommend disabling it as it kind of blocks the menu items.
|
||||
|
||||
You should see the following in OWASP ZAP on the history panel:
|
||||
As the ZAP setup for proxying localhost varies based on your browser, we recommend following the instructions at: https://www.zaproxy.org/docs/desktop/start/proxies/
|
||||
After you setup the proxy, you should see the following in OWASP ZAP on the history panel:
|
||||
|
||||
{nbsp} +
|
||||
|
||||
|
@ -17,7 +17,7 @@ And in the `URL Exc Regex` box type:
|
||||
|
||||
[source]
|
||||
----
|
||||
.*lesson.*.mvc
|
||||
.*lesson.*.mvc.*
|
||||
----
|
||||
|
||||
Click 'Apply to close the window, and ZAP will now no longer show internal WebGoat requests.
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
Before Width: | Height: | Size: 88 KiB |
@ -16,9 +16,9 @@ An example JKU would look like this:
|
||||
}
|
||||
----
|
||||
|
||||
=== Vulnerability
|
||||
=== Vulnerability: JWT claim misuse with JKU
|
||||
|
||||
JWT claim misuse with JKU The vulnerability arises when a JWT is signed with a weak or predictable key and the server provides a JKU that points to an external location hosting the public key.
|
||||
The vulnerability arises when a JWT is signed with a weak or predictable key and the server provides a JKU that points to an external location hosting the public key.
|
||||
|
||||
Attackers can exploit this vulnerability by crafting a JWT with malicious claims and using the `jku` to trick the server into verifying the JWT using a weak or manipulated key.
|
||||
It all depends on the library being used inside the application.
|
||||
@ -39,6 +39,7 @@ However, filtering on URLs is quite challenging to implement, and this can be by
|
||||
|
||||
- **Successful attack**: If the server uses the weak or manipulated key to verify the JWT, the attacker gains unauthorized access or executes their intended exploit.
|
||||
|
||||
|
||||
=== Mitigation
|
||||
|
||||
To prevent JWT claim misuse with JKU, developers and security professionals should follow these best practices:
|
||||
|
@ -72,7 +72,7 @@
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
th:action="@{/SqlInjectionMitigations/attack}"
|
||||
th:action="@{/SqlOnlyInputValidation/attack}"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
@ -95,7 +95,7 @@
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="POST" name="form"
|
||||
th:action="@{/SqlInjectionMitigations/attack}"
|
||||
th:action="@{/SqlOnlyInputValidationOnKeywords/attack}"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -1,43 +1,49 @@
|
||||
{
|
||||
"questions": [{
|
||||
"text": "What is the difference between a prepared statement and a statement?",
|
||||
"solutions": {
|
||||
"1": "Prepared statements are statements with hard-coded parameters.",
|
||||
"2": "Prepared statements are not stored in the database.",
|
||||
"3": "A statement is faster.",
|
||||
"4": "A statement has got values instead of a prepared statement"
|
||||
}
|
||||
}, {
|
||||
"text": "Which one of the following characters is a placeholder for variables?",
|
||||
"solutions": {
|
||||
"1": "*",
|
||||
"2": "=",
|
||||
"3": "?",
|
||||
"4": "!"
|
||||
}
|
||||
}, {
|
||||
"text": "How can prepared statements be faster than statements?",
|
||||
"solutions": {
|
||||
"1": "They are not static so they can compile better written code than statements.",
|
||||
"2": "Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.",
|
||||
"3": "Prepared statements are stored and wait for input it raises performance considerably.",
|
||||
"4": "Oracle optimized prepared statements. Because of the minimal use of the databases resources it is faster."
|
||||
}
|
||||
}, {
|
||||
"text": "How can a prepared statement prevent SQL-Injection?",
|
||||
"solutions": {
|
||||
"1": "Prepared statements have got an inner check to distinguish between input and logical errors.",
|
||||
"2": "Prepared statements use the placeholders to make rules what input is allowed to use.",
|
||||
"3": "Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.",
|
||||
"4": "Prepared statements always read inputs literally and never mixes it with its SQL commands."
|
||||
}
|
||||
}, {
|
||||
"text": "What happens if a person with malicious intent writes into a register form :Robert); DROP TABLE Students;-- that has a prepared statement?",
|
||||
"solutions": {
|
||||
"1": "The table Students and all of its content will be deleted.",
|
||||
"2": "The input deletes all students with the name Robert.",
|
||||
"3": "The database registers 'Robert' and deletes the table afterwards.",
|
||||
"4": "The database registers 'Robert' ); DROP TABLE Students;--'."
|
||||
}
|
||||
}]
|
||||
"questions": [
|
||||
{
|
||||
"text": "What is the difference between a prepared statement and a statement?",
|
||||
"solutions": {
|
||||
"1": "Prepared statements are statements with hard-coded parameters.",
|
||||
"2": "Prepared statements are not stored in the database.",
|
||||
"3": "A statement is faster executes faster than a prepared statement.",
|
||||
"4": "A statement includes actual values, whereas a prepared statement uses placeholders."
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "Which one of the following characters is a placeholder for variables?",
|
||||
"solutions": {
|
||||
"1": "*",
|
||||
"2": "=",
|
||||
"3": "?",
|
||||
"4": "!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "How can prepared statements be faster than statements?",
|
||||
"solutions": {
|
||||
"1": "Prepared statements are not static, allowing them to be optimized more efficiently than regular statements.",
|
||||
"2": "Prepared statements are compiled once by the database management system and then reused with different inputs, reducing compilation overhead.",
|
||||
"3": "Since prepared statements are stored and wait for input, they improve performance significantly.",
|
||||
"4": "Oracle optimizes prepared statements, making them faster by minimizing the use of database resources."
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "How do prepared statements help prevent SQL injection?",
|
||||
"solutions": {
|
||||
"1": "Prepared statements have built-in mechanisms to distinguish between user input and SQL logic, preventing malicious manipulation.",
|
||||
"2": "Prepared statements use placeholders to enforce rules on allowed input, reducing the risk of SQL injection.",
|
||||
"3": "Placeholders prevent user input from being directly appended to the SQL query, ensuring a clear separation between code and data.",
|
||||
"4": "Prepared statements treat all user input as literal values, never mixing it with SQL commands."
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "What happens if a person with malicious intent enters the following input into a registration form that uses a prepared statement? Input: Robert); DROP TABLE Students;--",
|
||||
"solutions": {
|
||||
"1": "The Students table and all its data will be deleted.",
|
||||
"2": "The input deletes all students named Robert.",
|
||||
"3": "The database registers Robert and then deletes the table.",
|
||||
"4": "The database treats the entire input as a plain string: Robert); DROP TABLE Students;-- without executing it as SQL."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
{
|
||||
"questions": [{
|
||||
"text": "Are trusted websites immune to XSS attacks?",
|
||||
"text": "Is a well known website, like Netflix, immune to XSS attacks?",
|
||||
"solutions": {
|
||||
"1": "Yes they are safe because the browser checks the code before executing.",
|
||||
"2": "Yes because Google has got an algorithm that blocks malicious code.",
|
||||
"3": "No because the script that is executed will break through the defense algorithm of the browser.",
|
||||
"4": "No because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious."
|
||||
"1": "Yes, they are safe because the browser checks the code before executing.",
|
||||
"2": "Yes, because Google has got an algorithm that blocks malicious code.",
|
||||
"3": "No, because the script that is executed will break through the defense algorithm of the browser.",
|
||||
"4": "No, because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious."
|
||||
}
|
||||
}, {
|
||||
"text": "When do XSS attacks occur?",
|
||||
"solutions": {
|
||||
"1": "Data enters a web application through a trusted source.",
|
||||
"2": "Data enters a browser application through the website.",
|
||||
"3": "The data is included in dynamic content that is sent to a web user without being validated for malicious content.",
|
||||
"4": "The data is excluded in static content that way it is sent without being validated."
|
||||
"1": "When malicious scripts are injected into a website's server-side code.",
|
||||
"2": "When a user submits sensitive information without encryption.",
|
||||
"3": "When a website fails to validate or sanitize user input, allowing malicious scripts to be executed in a user's browser.",
|
||||
"4": "When a website uses outdated SSL/TLS protocols."
|
||||
}
|
||||
}, {
|
||||
"text": "What are Stored XSS attacks?",
|
||||
@ -27,17 +27,17 @@
|
||||
"text": "What are Reflected XSS attacks?",
|
||||
"solutions": {
|
||||
"1": "Reflected attacks reflect malicious code from the database to the web server and then reflect it back to the user.",
|
||||
"2": "They reflect the injected script off the web server. That occurs when input sent to the web server is part of the request.",
|
||||
"2": "They reflect the injected script off the web server. That occurs when input sent to the web server is part of the response.",
|
||||
"3": "Reflected attacks reflect from the firewall off to the database where the user requests information from.",
|
||||
"4": "Reflected XSS is an attack where the injected script is reflected off the database and web server to the user."
|
||||
}
|
||||
}, {
|
||||
"text": "Is JavaScript the only way to perform XSS attacks?",
|
||||
"solutions": {
|
||||
"1": "Yes you can only make use of tags through JavaScript.",
|
||||
"2": "Yes otherwise you cannot steal cookies.",
|
||||
"3": "No there is ECMAScript too.",
|
||||
"4": "No there are many other ways. Like HTML, Flash or any other type of code that the browser executes."
|
||||
"1": "Yes, you can only make use of tags through JavaScript.",
|
||||
"2": "Yes, otherwise you cannot steal cookies.",
|
||||
"3": "No, there is ECMAScript too.",
|
||||
"4": "No, there are many other ways. Like HTML, Flash or any other type of code that the browser executes."
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
@ -1172,46 +1172,10 @@ span.show-next-page, span.show-prev-page {
|
||||
width: 95% !important
|
||||
}
|
||||
|
||||
/* scoreboard */
|
||||
div.scoreboard-title {
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
.scoreboard-table tr {
|
||||
}
|
||||
|
||||
div.scoreboard-username {
|
||||
background-color: #222;
|
||||
color: aliceblue;
|
||||
padding: 4px;
|
||||
padding-left: 8px;
|
||||
font-size: medium;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
th.username {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
td.user-flags {
|
||||
padding-left: 8px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
div.captured-flag {
|
||||
border-radius: 6px;
|
||||
background-color: #444;
|
||||
color: white;
|
||||
padding: 4px;
|
||||
font-size: medium;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.scoreboard-page {
|
||||
background-color: #e0dfdc;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.fa-flag {
|
||||
color: red
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
define(['jquery',
|
||||
'underscore',
|
||||
'backbone'],
|
||||
function($,
|
||||
_,
|
||||
Backbone) {
|
||||
return Backbone.Model.extend({
|
||||
});
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user