Compare commits

..

1 Commits

Author SHA1 Message Date
5ef865a54b chore: release version 2023.4 2023-02-17 13:07:22 +01:00
251 changed files with 1543 additions and 4857 deletions

View File

@ -1,17 +1,7 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
ignore:
- dependency-name: "org.webjars:bootstrap" # First the WebWolf UI needs to be refactored due to breaking changes
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
interval: "daily"

View File

@ -1,54 +0,0 @@
name: "Branch build"
on:
push:
branches:
- "*"
- "!main"
jobs:
branch-build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java-version: [ 17, 21 ]
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ matrix.java-version }}
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.3.1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2-
- name: Build with Maven
run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.2.0
- name: "Set up Docker Buildx"
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v2
- name: "Verify Docker WebGoat build"
if: runner.os == 'Linux'
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Verify Docker WebGoat desktop build"
uses: docker/build-push-action@v5.1.0
if: runner.os == 'Linux'
with:
context: ./
file: ./Dockerfile_desktop
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}

View File

@ -21,13 +21,13 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@ -36,13 +36,13 @@ jobs:
run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v2.1.0
- name: "Set up Docker Buildx"
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
- name: "Verify Docker WebGoat build"
if: runner.os == 'Linux'
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v4.0.0
with:
context: ./
file: ./Dockerfile
@ -50,7 +50,7 @@ jobs:
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Verify Docker WebGoat desktop build"
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v4.0.0
if: runner.os == 'Linux'
with:
context: ./

View File

@ -14,14 +14,14 @@ jobs:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@ -44,7 +44,7 @@ jobs:
files: |
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: |
## Version ${{ github.ref_name }}
## Version ${{ steps.tag.outputs.tag }}
### New functionality
@ -54,7 +54,7 @@ jobs:
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ steps.tag.outputs.tag }}...${{ steps.tag.outputs.tag }}
## Contributors
@ -72,21 +72,21 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU"
uses: docker/setup-qemu-action@v2.2.0
uses: docker/setup-qemu-action@v2.1.0
with:
platforms: all
- name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
- name: "Login to dockerhub"
uses: docker/login-action@v3.0.0
uses: docker/login-action@v2.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push WebGoat"
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v4.0.0
with:
context: ./
file: ./Dockerfile
@ -99,12 +99,12 @@ jobs:
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Build and push WebGoat desktop"
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v4.0.0
with:
context: ./
file: ./Dockerfile_desktop
push: true
platforms: linux/amd64, linux/arm64
platforms: linux/amd64, linux/arm64, linux/arm/v7
tags: |
webgoat/webgoat-desktop:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/webgoat-desktop:latest
@ -121,9 +121,8 @@ jobs:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64

View File

@ -30,14 +30,14 @@ jobs:
architecture: x64
# Uses an action to add JDK 17 to the VM (and mvn?)
- name: set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
#Uses an action to set up a cache using a certain key based on the hash of the dependencies
- name: Cache Maven packages
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.5
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
@ -48,8 +48,6 @@ jobs:
robotframework
robotframework-SeleniumLibrary
webdriver-manager
selenium==4.9.1
# TODO https://github.com/robotframework/SeleniumLibrary/issues/1835
- name: Run with Maven
run: mvn --no-transfer-progress spring-boot:run &
- name: Wait to start
@ -61,7 +59,7 @@ jobs:
# send report to forks only due to limits on permission tokens
- name: Send report to commit
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
uses: joonvena/robotframework-reporter-action@v2.2
uses: joonvena/robotframework-reporter-action@v2.1
with:
gh_access_token: ${{ secrets.GITHUB_TOKEN }}
report_path: 'robotreport'

View File

@ -10,7 +10,7 @@ jobs:
if: github.repository == 'WebGoat/WebGoat'
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.3.0
- uses: actions/first-interaction@v1.1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'

View File

@ -3,7 +3,6 @@
[![GitHub contributors](https://img.shields.io/github/contributors/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/graphs/contributors)
![GitHub issues by-label "help wanted"](https://img.shields.io/github/issues/WebGoat/WebGoat/help%20wanted.svg)
![GitHub issues by-label "good first issue"](https://img.shields.io/github/issues/WebGoat/WebGoat/good%20first%20issue.svg)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white)](https://conventionalcommits.org)
This document describes how you can contribute to WebGoat. Please read it carefully.
@ -42,19 +41,6 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
### Write a good commit message
* We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and use the following types:
- fix:
- feat:
- build:
- chore:
- ci:
- docs:
- refactor:
- test:
Using this style of commits makes it possible to create our release notes automatically.
* Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d)
* If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message.

View File

@ -8,12 +8,11 @@ and 2023.01 in the `pom.xml`.
### Release notes:
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of
committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main`
committers.
```
mvn versions:set
<< update release notes >>
mvn verify
git commit ....
git tag v2023.01
git push --tags

View File

@ -1,4 +1,4 @@
FROM docker.io/eclipse-temurin:21.0.1_12-jre
FROM docker.io/eclipse-temurin:17-jre-focal
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
MAINTAINER "WebGoat team"
@ -14,8 +14,6 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
EXPOSE 8080
EXPOSE 9090
ENV TZ=Europe/Amsterdam
WORKDIR /home/webgoat
ENTRYPOINT [ "java", \
"-Duser.home=/home/webgoat", \
@ -29,7 +27,9 @@ ENTRYPOINT [ "java", \
"--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/sun.nio.ch=ALL-UNNAMED", \
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
"-Drunning.in.docker=true", \
"-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]
"-Dwebgoat.host=0.0.0.0", \
"-Dwebwolf.host=0.0.0.0", \
"-Dwebgoat.port=8080", \
"-Dwebwolf.port=9090", \
"-jar", "webgoat.jar" ]

View File

@ -10,17 +10,12 @@ COPY config/desktop/start_zap.sh /config/start_zap.sh
COPY config/desktop/WebGoat.txt /config/Desktop/
RUN \
case $(uname -m) in \
x86_64) ARCH=x64;; \
aarch64) ARCH=aarch64;; \
*) ARCH=unknown;; \
esac && \
curl -LO https://github.com/zaproxy/zaproxy/releases/download/v2.12.0/ZAP_2.12.0_Linux.tar.gz && \
tar zfxv ZAP_2.12.0_Linux.tar.gz && \
rm -rf ZAP_2.12.0_Linux.tar.gz && \
curl -LO https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.6%2B10/OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
tar zfxv OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
rm -rf OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
curl -LO https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.6%2B10/OpenJDK17U-jre_aarch64_linux_hotspot_17.0.6_10.tar.gz && \
tar zfxv OpenJDK17U-jre_aarch64_linux_hotspot_17.0.6_10.tar.gz && \
rm -rf OpenJDK17U-jre_aarch64_linux_hotspot_17.0.6_10.tar.gz && \
chmod +x /config/start_webgoat.sh && \
chmod +x /config/start_zap.sh && \
apt-get update && \

8
FAQ.md
View File

@ -1,8 +0,0 @@
# FAQ for development
## Introduction
### Integration tests fail
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.

View File

@ -1,4 +1,4 @@
# WebGoat: A deliberately insecure Web Application
# WebGoat 8: A deliberately insecure Web Application
[![Build](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml)
[![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/)
@ -6,7 +6,6 @@
[![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest)
[![Gitter](https://badges.gitter.im/OWASPWebGoat/community.svg)](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Discussions](https://img.shields.io/github/discussions/WebGoat/WebGoat)](https://github.com/WebGoat/WebGoat/discussions)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white)](https://conventionalcommits.org)
# Introduction
@ -44,27 +43,19 @@ Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
```
For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable.
E.g.
If you want to reuse the container, give it a name:
```shell
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
```
If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but
you can use custom host entries. For example:
As long as you don't remove the container you can use:
```shell
127.0.0.1 www.webgoat.local www.webwolf.local
docker start webgoat
```
Then you can run the container with:
```shell
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
```
Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
## 2. Run using Docker with complete Linux Desktop
@ -79,8 +70,7 @@ docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```shell
export TZ=Europe/Amsterdam # or your timezone
java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar
java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.3.jar
```
Click the link in the log to start WebGoat.
@ -89,7 +79,7 @@ Click the link in the log to start WebGoat.
### Prerequisites:
* Java 17 or 21
* Java 17
* Your favorite IDE
* Git, or Git support in your IDE
@ -141,10 +131,9 @@ For specialist only. There is a way to set up WebGoat with a personalized menu.
For instance running as a jar on a Linux/macOS it will look like this:
```Shell
export TZ=Europe/Amsterdam # or your timezone
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar target/webgoat-2023.6-SNAPSHOT.jar
java -jar target/webgoat-2023.3-SNAPSHOT.jar
```
Or in a docker run it would (once this version is pushed into docker hub) look like this:

View File

@ -1,60 +1,5 @@
# WebGoat release notes
## Version 2023.7
### 🚀 New functionality
- Consistent environment values and url references (#1677)
- Show directly requested file in requests overview
- Show creating time in file upload overview
### 🐞 Bug fixes
- Fix startup message (#1687)
- Fix/state of software supply chain links (#1683)
- Fix WebWolf UI (#1686)
### 🔄 Technical tasks
- bump actions/setup-java from 3 to 4 (#1690)
- bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
- bump com.diffplug.spotless:spotless-maven-plugin (#1688)
## Version 2023.5
### New functionality
- Implement JWT jku example (#1552)
- Java 21 initial support (#1622)
- improve MFAC lesson hint texts for a better user experience (#1424)
- upgrade to Spring Boot version 3 (#1477)
### Bug fixes
- typo in WebGoad.txt (#1667)
- search box moved and jwt encode/decode with little delay (#1664)
- skip validation for JWT (#1663)
- fixed issue in JWT test tool and added robot test (#1658)
- Password reset link test condition more strict and move all WebWolf links to /WebWolf (#1645)
- fix servers id (#1619)
- potential NPE in the stored XSS assignment
- crypto basics broken links
- fixes the default change in trailing slash matching and address the affected assignments
- hint that was breaking the template, causing hints from different assignments to mix (#1424)
- HijackSession lesson template deprecated Tymeleaf attribute
- Fix NPE in IDOR lesson
- Add new assignment IT tests
- XSS mitigation
- Stored Cross-Site Scripting Lesson
- Add Assignment7 Tests
- Fix IDOR lesson
- remove steps from release script (#1509)
- robotframework fails due to updated dependencies (#1508)
- fix Java image inside Docker file The image now downloads the correct Java version based on the architecture.
- Fix typo of HijackSession_content0.adoc
- Restrict SSRF Regexes
- update challenge code - Flags are now wired through a Spring config - Introduced Flag class - Removed Flags from the FlagController
## Version 2023.4
### New functionality

View File

@ -3,7 +3,7 @@
With this image you have WebGoat and ZAP and a browser available to you in a browser running on Ubuntu.
You can start WebGoat and ZAP by opening a terminal and type:
./start_webgoat.sh
./start-webgoat.sh
./start_zap.sh
Happy hacking,

229
pom.xml
View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<version>2.7.1</version>
</parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId>
<version>2023.7</version>
<version>2023.4</version>
<packaging>jar</packaging>
<name>WebGoat</name>
@ -27,7 +27,6 @@
<url>https://www.gnu.org/licenses/gpl-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<id>mayhew64</id>
@ -95,6 +94,7 @@
<archive>http://lists.owasp.org/pipermail/owasp-webgoat/</archive>
</mailingList>
</mailingLists>
<scm>
<connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection>
<developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection>
@ -108,47 +108,44 @@
</issueManagement>
<properties>
<!-- Shared properties with plugins and version numbers across submodules-->
<asciidoctorj.version>2.5.10</asciidoctorj.version>
<bootstrap.version>5.3.1</bootstrap.version>
<cglib.version>3.3.0</cglib.version>
<asciidoctorj.version>2.5.3</asciidoctorj.version>
<bootstrap.version>3.3.7</bootstrap.version>
<cglib.version>2.2</cglib.version>
<!-- do not update necessary for lesson -->
<checkstyle.version>3.3.1</checkstyle.version>
<checkstyle.version>3.1.2</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version>
<commons-io.version>2.15.1</commons-io.version>
<commons-io.version>2.6</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-text.version>1.10.0</commons-text.version>
<guava.version>32.1.3-jre</guava.version>
<jacoco.version>0.8.11</jacoco.version>
<commons-text.version>1.9</commons-text.version>
<guava.version>30.1-jre</guava.version>
<java.version>17</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.0</jquery.version>
<jsoup.version>1.16.1</jsoup.version>
<jose4j.version>0.7.6</jose4j.version>
<jquery.version>3.5.1</jquery.version>
<jsoup.version>1.14.3</jsoup.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</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.2.1</maven-surefire-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<pmd.version>3.15.0</pmd.version>
<!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
<webdriver.version>5.3.3</webdriver.version>
<webgoat.context>/</webgoat.context>
<webgoat.sslenabled>false</webgoat.sslenabled>
<webjars-locator-core.version>0.53</webjars-locator-core.version>
<webwolf.context>/</webwolf.context>
<thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
<webdriver.version>4.3.1</webdriver.version>
<webgoat.port>8080</webgoat.port>
<webwolf.port>9090</webwolf.port>
<wiremock.version>2.27.2</wiremock.version>
<xml-resolver.version>1.2</xml-resolver.version>
<xstream.version>1.4.5</xstream.version>
<!-- do not update necessary for lesson -->
<zxcvbn.version>1.8.0</zxcvbn.version>
<zxcvbn.version>1.5.2</zxcvbn.version>
</properties>
<dependencyManagement>
@ -157,7 +154,7 @@
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.5</version>
<version>9.1</version>
</dependency>
<dependency>
@ -201,17 +198,6 @@
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.22.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@ -242,11 +228,6 @@
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
<version>${webjars-locator-core.version}</version>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
@ -260,15 +241,16 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.25.0</version>
<version>1.21</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>9.4.3.0</version>
<version>9.3.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
@ -287,7 +269,6 @@
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -327,17 +308,9 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
@ -367,15 +340,6 @@
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@ -405,17 +369,8 @@
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<scope>runtime</scope>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
@ -431,7 +386,6 @@
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>3.0.0-beta-2</version>
<scope>test</scope>
</dependency>
<dependency>
@ -439,11 +393,6 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<repositories>
@ -512,19 +461,10 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<environmentVariables>
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
</environmentVariables>
<systemPropertyVariables>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables>
<argLine>-Xmx512m</argLine>
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
<includes>org/owasp/webgoat/*Test</includes>
</configuration>
<executions>
@ -547,12 +487,10 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
<argLine>--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
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED</argLine>
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED</argLine>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>src/it/java</exclude>
@ -565,6 +503,7 @@
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
@ -575,7 +514,7 @@
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.41.1</version>
<version>2.29.0</version>
<configuration>
<formats>
<format>
@ -636,7 +575,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.3.0</version>
<version>3.0.0</version>
<executions>
<execution>
<id>restrict-log4j-versions</id>
@ -693,15 +632,16 @@
<portNames>
<portName>webgoat.port</portName>
<portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.honton.chas</groupId>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>0.9.2</version>
<version>0.9</version>
<executions>
<execution>
<id>start-jar</id>
@ -709,18 +649,8 @@
<goal>start</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<workingDir>${project.build.directory}</workingDir>
<environment>
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
</environment>
<arguments>
<argument>java</argument>
<argument>-jar</argument>
@ -728,6 +658,8 @@
<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>-Dwebgoat.port=${webgoat.port}</argument>
<argument>-Dwebwolf.port=${webwolf.port}</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
@ -746,13 +678,10 @@
<argument>java.base/java.io=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/sun.nio.ch=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.io=ALL-UNNAMED</argument>
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
</arguments>
<waitForInterrupt>false</waitForInterrupt>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
</configuration>
</execution>
<execution>
@ -777,6 +706,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.5.1</version>
<configuration>
<failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>false</skipProvidedScope>
@ -797,81 +727,6 @@
</plugins>
</build>
</profile>
<profile>
<!-- run with: mvn test -Pcoverage -->
<id>coverage</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<argLine>--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
${surefire.jacoco.args}</argLine>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>src/it/java</exclude>
<exclude>org/owasp/webgoat/*Test</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>before-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco/jacoco-ut.exec</destFile>
<propertyName>surefire.jacoco.args</propertyName>
</configuration>
</execution>
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>CLASS</counter>
<value>COVEREDCOUNT</value>
<minimum>0.6</minimum>
</limit>
</limits>
</rule>
</rules>
<dataFile>${project.build.directory}/jacoco/jacoco-ut.exec</dataFile>
</configuration>
</execution>
<execution>
<id>after-unit-test</id>
<goals>
<goal>report</goal>
</goals>
<phase>test</phase>
<configuration>
<dataFile>${project.build.directory}/jacoco/jacoco-ut.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-unit-test-coverage-report</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -12,10 +12,8 @@ Then see security settings and allow the file to run
pip3 install virtualenv --user
python3 -m virtualenv .venv
source .venv/bin/activate
pip install --upgrade robotframework
pip install --upgrade robotframework-SeleniumLibrary
pip install --upgrade webdriver-manager
brew upgrade
pip install robotframework
pip install robotframework-SeleniumLibrary
pip install webdriver-manager
robot --variable HEADLESS:"0" --variable ENDPOINT:"http://127.0.0.1:8080/WebGoat" goat.robot
Make sure that the Chrome version, the webdriver version and all related components are up-to-date and compatible!

View File

@ -2,7 +2,6 @@
Documentation Setup WebGoat Robotframework tests
Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot
Library String
Library OperatingSystem
Suite Setup Initial_Page ${ENDPOINT} ${BROWSER}
Suite Teardown Close_Page
@ -12,7 +11,7 @@ ${BROWSER} chrome
${SLEEP} 100
${DELAY} 0.25
${ENDPOINT} http://127.0.0.1:8080/WebGoat
${ENDPOINT_WOLF} http://127.0.0.1:9090/WebWolf
${ENDPOINT_WOLF} http://127.0.0.1:9090
${USERNAME} robotuser
${PASSWORD} password
${HEADLESS} ${FALSE}
@ -23,25 +22,22 @@ Initial_Page
[Arguments] ${ENDPOINT} ${BROWSER}
Log To Console Start WebGoat UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'});add_argument("-headless");add_argument("--start-maximized") alias=webgoat
Open Browser ${ENDPOINT} ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
ELSE
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
END
IF ${HEADLESS}
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
ELSE
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
END
Switch Browser webgoat
Maximize Browser Window
Set Window Size ${1400} ${1000}
Set Window Position ${0} ${0}
Set Selenium Speed ${DELAY}
Log To Console Start WebWolf UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'});add_argument("-headless");add_argument("--start-maximized") alias=webwolf
ELSE
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
END
Switch Browser webwolf
Maximize Browser Window
Set Window Size ${1400} ${1000}
Set Window Position ${500} ${0}
Set Window Position ${400} ${200}
Set Selenium Speed ${DELAY}
Close_Page
@ -57,7 +53,6 @@ Close_Page
*** Test Cases ***
Check_Initial_Page
[Tags] WebGoatTests
Switch Browser webgoat
Page Should Contain Username
Click Button Sign in
@ -65,7 +60,6 @@ Check_Initial_Page
Click Link /WebGoat/registration
Check_Registration_Page
[Tags] WebGoatTests
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
@ -74,7 +68,6 @@ Check_Registration_Page
Click Button Sign up
Check_Welcome_Page
[Tags] WebGoatTests
Page Should Contain WebGoat
Go To ${ENDPOINT}/login
Page Should Contain Username
@ -84,7 +77,6 @@ Check_Welcome_Page
Page Should Contain WebGoat
Check_Menu_Page
[Tags] WebGoatTests
Click Element css=a[category='Introduction']
Click Element Introduction-WebGoat
CLick Element Introduction-WebWolf
@ -101,29 +93,9 @@ Check_Menu_Page
Check_WebWolf
Switch Browser webwolf
location should be ${ENDPOINT_WOLF}/login
location should be ${ENDPOINT_WOLF}/WebWolf
Go To ${ENDPOINT_WOLF}/mail
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Click Button Sign In
Go To ${ENDPOINT_WOLF}/mail
Go To ${ENDPOINT_WOLF}/requests
Go To ${ENDPOINT_WOLF}/files
Check_JWT_Page
Go To ${ENDPOINT_WOLF}/jwt
Click Element token
Wait Until Element Is Enabled token 5s
Input Text token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Click Element secretKey
Input Text secretKey none
Sleep 2s # Pause before reading the result
${OUT_VALUE} Get Value xpath=//textarea[@id='token']
Log To Console Found token ${OUT_VALUE}
${OUT_RESULT} Evaluate "ImuPnHvLdU7ULKfbD4aJU" in """${OUT_VALUE}"""
Log To Console Found token ${OUT_RESULT}
Capture Page Screenshot
Check_Files_Page
Go To ${ENDPOINT_WOLF}/files
Choose File css:input[type="file"] ${CURDIR}/goat.robot
Click Button Upload files

View File

@ -25,7 +25,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix"))
.get(url("/WebGoat/access-control/users-admin-fix"))
.then()
.statusCode(HttpStatus.SC_FORBIDDEN);
@ -40,7 +40,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.body(String.format(userTemplate, this.getUser(), this.getUser()))
.post(url("access-control/users"))
.post(url("/WebGoat/access-control/users"))
.then()
.statusCode(HttpStatus.SC_OK);
@ -51,14 +51,15 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix"))
.get(url("/WebGoat/access-control/users-admin-fix"))
.then()
.statusCode(200)
.extract()
.jsonPath()
.get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(url("access-control/user-hash-fix"), Map.of("userHash", userHash), true);
checkAssignment(
url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true);
}
private void assignment2() {
@ -68,18 +69,18 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("access-control/users"))
.get(url("/WebGoat/access-control/users"))
.then()
.statusCode(200)
.extract()
.jsonPath()
.get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(url("access-control/user-hash"), Map.of("userHash", userHash), true);
checkAssignment(url("/WebGoat/access-control/user-hash"), Map.of("userHash", userHash), true);
}
private void assignment1() {
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config");
checkAssignment(url("access-control/hidden-menu"), params, true);
checkAssignment(url("/WebGoat/access-control/hidden-menu"), params, true);
}
}

View File

@ -64,12 +64,12 @@ public class CSRFIntegrationTest extends IntegrationTest {
public void init() {
startLesson("CSRF");
webwolfFileDir = getWebWolfFileServerLocation();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("csrf/feedback/message")));
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
uploadTrickHtml(
"csrf8.html",
trickHTML8.replace("WEBGOATURL", url("login")).replace("USERNAME", this.getUser()));
trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
}
@TestFactory
@ -103,7 +103,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", htmlName, htmlContent.getBytes())
.post(webWolfUrl("fileupload"))
.post(webWolfUrl("/WebWolf/fileupload"))
.then()
.extract()
.response()
@ -118,7 +118,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("files/" + this.getUser() + "/" + htmlName))
.get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
.then()
.extract()
.response()
@ -136,7 +136,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html"))
.header("Referer", webWolfUrl("/files/fake.html"))
.post(goatURL)
.then()
.extract()
@ -146,7 +146,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("confirmFlagVal", flag);
checkAssignment(url("csrf/confirm-flag-1"), params, true);
checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true);
}
private void checkAssignment4(String goatURL) {
@ -163,7 +163,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html"))
.header("Referer", webWolfUrl("/files/fake.html"))
.formParams(params)
.post(goatURL)
.then()
@ -184,7 +184,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html"))
.header("Referer", webWolfUrl("/files/fake.html"))
.contentType(ContentType.TEXT)
.body(
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
@ -198,7 +198,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
params.clear();
params.put("confirmFlagVal", flag);
checkAssignment(url("csrf/feedback"), params, true);
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
}
private void checkAssignment8(String goatURL) {
@ -217,7 +217,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html"))
.header("Referer", webWolfUrl("/files/fake.html"))
.params(params)
.post(goatURL)
.then()
@ -239,7 +239,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie)
.post(url("csrf/login"))
.post(url("/csrf/login"))
.then()
.statusCode(200)
.extract()
@ -253,8 +253,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
Overview[] assignments =
RestAssured.given()
.cookie("JSESSIONID", getWebGoatCookie())
.relaxedHTTPSValidation()
.get(url("service/lessonoverview.mvc"))
.get(url("/service/lessonoverview.mvc"))
.then()
.extract()
.jsonPath()

View File

@ -7,14 +7,12 @@ 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;
import org.springframework.http.HttpStatus;
public class ChallengeIntegrationTest extends IntegrationTest {
@Test
void testChallenge1() {
public void testChallenge1() {
startLesson("Challenge1");
byte[] resultBytes =
@ -22,7 +20,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/logo"))
.get(url("/WebGoat/challenge/logo"))
.then()
.statusCode(200)
.extract()
@ -34,14 +32,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("challenge/1"), params, true);
checkAssignment(url("/WebGoat/challenge/1"), params, true);
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("challenge/1"))
.post(url("/WebGoat/challenge/1"))
.then()
.statusCode(200)
.extract()
@ -50,7 +48,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/1");
@ -59,7 +57,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data"))
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract()
@ -69,7 +67,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
}
@Test
void testChallenge5() {
public void testChallenge5() {
startLesson("Challenge5");
Map<String, Object> params = new HashMap<>();
@ -83,7 +81,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("challenge/5"))
.post(url("/WebGoat/challenge/5"))
.then()
.statusCode(200)
.extract()
@ -92,7 +90,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/5");
@ -101,7 +99,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data"))
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract()
@ -109,62 +107,4 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
assertTrue(capturefFlags.contains("Without password"));
}
@Test
void testChallenge7() {
startLesson("Challenge7");
cleanMailbox();
// One should first be able to download git.zip from WebGoat
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/7/.git"))
.then()
.statusCode(200)
.extract()
.asString();
// Should send an email to WebWolf inbox this should give a hint to the link being static
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", getUser() + "@webgoat.org")
.post(url("challenge/7"))
.then()
.statusCode(200)
.extract()
.asString();
// Check whether email has been received
var responseBody =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail"))
.then()
.extract()
.response()
.getBody()
.asString();
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
// Call reset link with admin link
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(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(url("challenge/flag"), Map.of("flag", flag), true);
}
}

View File

@ -52,7 +52,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/encoding/basic"))
.get(url("/crypto/encoding/basic"))
.then()
.extract()
.asString();
@ -64,7 +64,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("answer_user", answer_user);
params.put("answer_pwd", answer_pwd);
checkAssignment(url("crypto/encoding/basic-auth"), params, true);
checkAssignment(url("/crypto/encoding/basic-auth"), params, true);
}
private void checkAssignment3() {
@ -72,7 +72,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("answer_pwd1", answer_1);
checkAssignment(url("crypto/encoding/xor"), params, true);
checkAssignment(url("/crypto/encoding/xor"), params, true);
}
private void checkAssignment4() throws NoSuchAlgorithmException {
@ -82,7 +82,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/hashing/md5"))
.get(url("/crypto/hashing/md5"))
.then()
.extract()
.asString();
@ -92,7 +92,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/hashing/sha256"))
.get(url("/crypto/hashing/sha256"))
.then()
.extract()
.asString();
@ -112,7 +112,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("answer_pwd1", answer_1);
params.put("answer_pwd2", answer_2);
checkAssignment(url("crypto/hashing"), params, true);
checkAssignment(url("/WebGoat/crypto/hashing"), params, true);
}
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
@ -122,7 +122,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/signing/getprivate"))
.get(url("/crypto/signing/getprivate"))
.then()
.extract()
.asString();
@ -135,7 +135,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("modulus", modulus);
params.put("signature", signature);
checkAssignment(url("crypto/signing/verify"), params, true);
checkAssignment(url("/crypto/signing/verify"), params, true);
}
private void checkAssignmentDefaults() {
@ -151,6 +151,6 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("secretText", text);
params.put("secretFileName", "default_secret");
checkAssignment(url("crypto/secure/defaults"), params, true);
checkAssignment(url("/crypto/secure/defaults"), params, true);
}
}

View File

@ -26,7 +26,7 @@ public class DeserializationIntegrationTest extends IntegrationTest {
params.put(
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
}
checkAssignment(url("InsecureDeserialization/task"), params, true);
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
checkResults("/InsecureDeserialization/");
}

View File

@ -72,7 +72,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put(
"question_3_solution",
"Solution 2: The systems security is compromised even if only one goal is harmed.");
checkAssignment(url("cia/quiz"), params, true);
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
checkResults("/cia/");
}
@ -95,7 +95,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("payload", solution);
checkAssignment(url("VulnerableComponents/attack1"), params, true);
checkAssignment(url("/WebGoat/VulnerableComponents/attack1"), params, true);
checkResults("/VulnerableComponents/");
}
}
@ -107,7 +107,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("username", "CaptainJack");
params.put("password", "BlackPearl");
checkAssignment(url("InsecureLogin/task"), params, true);
checkAssignment(url("/WebGoat/InsecureLogin/task"), params, true);
checkResults("/InsecureLogin/");
}
@ -117,7 +117,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("password", "ajnaeliclm^&&@kjn.");
checkAssignment(url("SecurePasswords/assignment"), params, true);
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
checkResults("SecurePasswords/");
startLesson("AuthBypass");
@ -127,7 +127,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("auth-bypass/verify-account"), params, true);
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
startLesson("HttpProxies");
@ -138,7 +138,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true")
.contentType(ContentType.JSON)
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.get(
url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then()
.statusCode(200)
.extract()
@ -164,7 +165,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest")
.formParams(params)
.post(url("CrossSiteScripting/phone-home-xss"))
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
.then()
.statusCode(200)
.extract()
@ -173,12 +174,12 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("successMessage", secretNumber);
checkAssignment(url("ChromeDevTools/dummy"), params, true);
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
params.clear();
params.put("number", "24");
params.put("network_num", "24");
checkAssignment(url("ChromeDevTools/network"), params, true);
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
checkResults("/ChromeDevTools/");
}
@ -193,7 +194,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("auth-bypass/verify-account"), params, true);
checkAssignment(url("/auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
}
@ -204,7 +205,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("param1", "secr37Value");
params.put("param2", "Main");
checkAssignment(url("lesson-template/sample-attack"), params, true);
checkAssignment(url("/lesson-template/sample-attack"), params, true);
checkResults("/lesson-template/");
}
}

View File

@ -4,9 +4,11 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach;
@ -17,6 +19,7 @@ import org.junit.jupiter.api.TestFactory;
public class IDORIntegrationTest extends IntegrationTest {
@BeforeEach
@SneakyThrows
public void init() {
startLesson("IDOR");
}
@ -24,63 +27,56 @@ public class IDORIntegrationTest extends IntegrationTest {
@TestFactory
Iterable<DynamicTest> testIDORLesson() {
return Arrays.asList(
dynamicTest("assignment 2 - login", this::loginIDOR),
dynamicTest("profile", this::profile));
dynamicTest("login", () -> loginIDOR()), dynamicTest("profile", () -> profile()));
}
@AfterEach
public void shutdown() {
public void shutdown() throws IOException {
checkResults("/IDOR");
}
private void loginIDOR() {
private void loginIDOR() throws IOException {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "tom");
params.put("password", "cat");
checkAssignment(url("IDOR/login"), params, true);
checkAssignment(url("/WebGoat/IDOR/login"), params, true);
}
private void profile() {
// View profile - assignment 3a
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("IDOR/profile"))
.get(url("/WebGoat/IDOR/profile"))
.then()
.statusCode(200)
.extract()
.path("userId"),
CoreMatchers.is("2342384"));
// Show difference - assignment 3b
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("attributes", "userId,role");
checkAssignment(url("IDOR/diff-attributes"), params, true);
// View profile another way - assignment 4
checkAssignment(url("/WebGoat/IDOR/diff-attributes"), params, true);
params.clear();
params.put("url", "WebGoat/IDOR/profile/2342384");
checkAssignment(url("IDOR/profile/alt-path"), params, true);
checkAssignment(url("/WebGoat/IDOR/profile/alt-path"), params, true);
// assignment 5a
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("IDOR/profile/2342388"))
.get(url("/WebGoat/IDOR/profile/2342388"))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
// assignment 5b
MatcherAssert.assertThat(
RestAssured.given()
.when()
@ -90,7 +86,7 @@ public class IDORIntegrationTest extends IntegrationTest {
.body(
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
+ " \"userId\":\"2342388\"}")
.put(url("IDOR/profile/2342388"))
.put(url("/WebGoat/IDOR/profile/2342388"))
.then()
.statusCode(200)
.extract()

View File

@ -5,51 +5,43 @@ import static io.restassured.RestAssured.given;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.Map;
import java.util.Objects;
import lombok.Getter;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.http.HttpStatus;
public abstract class IntegrationTest {
private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080");
private static String webGoatContext =
System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/");
@Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090");
private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
@Getter
private static String webWolfHost = System.getenv().getOrDefault("WEBWOLF_HOST", "127.0.0.1");
private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
@Getter
private static String webGoatHost = System.getenv().getOrDefault("WEBGOAT_HOST", "127.0.0.1");
private static String webWolfContext =
System.getenv().getOrDefault("WEBWOLF_CONTEXT", "/WebWolf/");
private static boolean useSSL =
Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "false"));
private static boolean useSSL = false;
private static String webgoatUrl =
(useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext;
private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext;
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
private static String webWolfUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
@Getter private String webGoatCookie;
@Getter private String webWolfCookie;
@Getter private final String user = "webgoat";
protected String url(String url) {
url = url.replaceFirst("/WebGoat/", "");
url = url.replaceFirst("/WebGoat", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webgoatUrl + url;
}
protected String webWolfUrl(String url) {
url = url.replaceFirst("/WebWolf/", "");
url = url.replaceFirst("/WebWolf", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webWolfUrl + url;
}
protected String webWolfFileUrl(String fileName) {
return webWolfUrl("files") + "/" + getUser() + "/" + fileName;
}
@BeforeEach
public void login() {
String location =
@ -238,7 +230,7 @@ public abstract class IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("file-server-location"))
.get(webWolfUrl("/file-server-location"))
.then()
.extract()
.response()
@ -253,21 +245,11 @@ public abstract class IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("server-directory"))
.get(url("/server-directory"))
.then()
.extract()
.response()
.getBody()
.asString();
}
public void cleanMailbox() {
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.delete(webWolfUrl("mail"))
.then()
.statusCode(HttpStatus.ACCEPTED.value());
}
}

View File

@ -14,10 +14,7 @@ import io.restassured.RestAssured;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.util.Base64;
import java.util.Calendar;
@ -26,8 +23,6 @@ import java.util.HashMap;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwk.RsaJsonWebKey;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
@ -45,9 +40,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
buyAsTom();
deleteTomThroughKidClaim();
deleteTomThroughJkuClaim();
deleteTom();
quiz();
@ -88,7 +81,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParam("jwt-encode-user", "user")
.post(url("JWT/decode"))
.post(url("/WebGoat/JWT/decode"))
.then()
.statusCode(200)
.extract()
@ -103,7 +96,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/secret/gettoken"))
.get(url("/WebGoat/JWT/secret/gettoken"))
.then()
.extract()
.response()
@ -117,7 +110,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParam("token", generateToken(secret))
.post(url("JWT/secret"))
.post(url("/WebGoat/JWT/secret"))
.then()
.statusCode(200)
.extract()
@ -131,7 +124,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/votings/login?user=Tom"))
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
.then()
.extract()
.cookie("access_token");
@ -164,7 +157,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.cookie("access_token", replacedToken)
.post(url("JWT/votings"))
.post(url("/WebGoat/JWT/votings"))
.then()
.statusCode(200)
.extract()
@ -205,7 +198,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Authorization", "Bearer " + replacedToken)
.post(url("JWT/refresh/checkout"))
.post(url("/WebGoat/JWT/refresh/checkout"))
.then()
.statusCode(200)
.extract()
@ -213,7 +206,8 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
CoreMatchers.is(true));
}
private void deleteTomThroughKidClaim() {
private void deleteTom() {
Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE);
header.put(
@ -238,54 +232,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/kid/delete?token=" + token))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
}
private void deleteTomThroughJkuClaim() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
var jwks = new JsonWebKeySet(new RsaJsonWebKey((RSAPublicKey) keyPair.getPublic()));
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "jwks.json", jwks.toJson().getBytes())
.post(webWolfUrl("fileupload"))
.then()
.extract()
.response()
.getBody()
.asString();
Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE);
header.put(JwsHeader.JWK_SET_URL, webWolfFileUrl("jwks.json"));
String token =
Jwts.builder()
.setHeader(header)
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[] {"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.RS256, keyPair.getPrivate())
.compact();
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/jku/delete?token=" + token))
.post(url("/WebGoat/JWT/final/delete?token=" + token))
.then()
.statusCode(200)
.extract()
@ -298,6 +245,6 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
params.put("question_0_solution", "Solution 1");
params.put("question_1_solution", "Solution 2");
checkAssignment(url("JWT/quiz"), params, true);
checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
}
}

View File

@ -5,19 +5,20 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import io.restassured.RestAssured;
import java.util.Arrays;
import java.util.Map;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.springframework.http.HttpHeaders;
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
@BeforeEach
@SneakyThrows
public void init() {
startLesson("PasswordReset");
startLesson("/PasswordReset");
}
@TestFactory
@ -69,6 +70,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
// WebWolf
var link = getPasswordResetLinkFromLandingPage();
// WebGoat
changePassword(link);
checkAssignment(
@ -85,7 +87,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail"))
.get(webWolfUrl("/WebWolf/mail"))
.then()
.extract()
.response()
@ -119,7 +121,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests"))
.get(webWolfUrl("/WebWolf/requests"))
.then()
.extract()
.response()
@ -136,7 +138,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
private void clickForgotEmailLink(String user) {
RestAssured.given()
.when()
.header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort()))
.header("host", String.format("%s:%s", "localhost", getWebWolfPort()))
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user)

View File

@ -55,7 +55,7 @@ class PathTraversalIT extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullName", "../John Doe")
.post(url("PathTraversal/profile-upload"))
.post(url("/WebGoat/PathTraversal/profile-upload"))
.then()
.statusCode(200)
.extract()
@ -71,7 +71,7 @@ class PathTraversalIT extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullNameFix", "..././John Doe")
.post(url("PathTraversal/profile-upload-fix"))
.post(url("/WebGoat/PathTraversal/profile-upload-fix"))
.then()
.statusCode(200)
.extract()
@ -89,7 +89,7 @@ class PathTraversalIT extends IntegrationTest {
"uploadedFileRemoveUserInput",
"../test.jpg",
Files.readAllBytes(fileToUpload.toPath()))
.post(url("PathTraversal/profile-upload-remove-user-input"))
.post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
.then()
.statusCode(200)
.extract()
@ -98,7 +98,7 @@ class PathTraversalIT extends IntegrationTest {
}
private void assignment4() throws IOException {
var uri = "PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
RestAssured.given()
.urlEncodingEnabled(false)
.when()
@ -110,7 +110,7 @@ class PathTraversalIT extends IntegrationTest {
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
checkAssignment(
url("PathTraversal/random"),
url("/WebGoat/PathTraversal/random"),
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
true);
}
@ -133,10 +133,8 @@ class PathTraversalIT extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
.post(url("PathTraversal/zip-slip"))
.post(url("/WebGoat/PathTraversal/zip-slip"))
.then()
.log()
.all()
.statusCode(200)
.extract()
.path("lessonCompleted"),

View File

@ -29,9 +29,9 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(Map.of("flag", "test"))
.post(url("challenge/flag"));
.post(url("/challenge/flag/"));
};
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
ExecutorService executorService = Executors.newWorkStealingPool(NUMBER_OF_PARALLEL_THREADS);
List<? extends Callable<Response>> flagCalls =
IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList());
var responses = executorService.invokeAll(flagCalls);

View File

@ -15,11 +15,11 @@ public class SSRFIntegrationTest extends IntegrationTest {
params.clear();
params.put("url", "images/jerry.png");
checkAssignment(url("SSRF/task1"), params, true);
checkAssignment(url("/WebGoat/SSRF/task1"), params, true);
params.clear();
params.put("url", "http://ifconfig.pro");
checkAssignment(url("SSRF/task2"), params, true);
checkAssignment(url("/WebGoat/SSRF/task2"), params, true);
checkResults("/SSRF/");
}

View File

@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
*/
class SessionManagementIT extends IntegrationTest {
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
@Test
void hijackSessionTest() {

View File

@ -16,27 +16,27 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put("password_reg", "password");
params.put("email_reg", "someone@microsoft.com");
params.put("confirm_password", "password");
checkAssignmentWithPUT(url("SqlInjectionAdvanced/challenge"), params, true);
checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
params.clear();
params.put("username_login", "tom");
params.put("password_login", "thisisasecretfortomonly");
checkAssignment(url("SqlInjectionAdvanced/challenge_Login"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
params.clear();
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
params.clear();
params.put(
"userid_6a",
"Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from"
+ " user_system_data --");
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
params.clear();
params.put("userid_6b", "passW0rD");
checkAssignment(url("SqlInjectionAdvanced/attack6b"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
params.clear();
params.put(
@ -54,7 +54,7 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put(
"question_4_solution",
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
checkAssignment(url("SqlInjectionAdvanced/quiz"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
checkResults("/SqlInjectionAdvanced/");
}

View File

@ -34,44 +34,44 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("query", sql_2);
checkAssignment(url("SqlInjection/attack2"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true);
params.clear();
params.put("query", sql_3);
checkAssignment(url("SqlInjection/attack3"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true);
params.clear();
params.put("query", sql_4_add);
checkAssignment(url("SqlInjection/attack4"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
params.clear();
params.put("query", sql_5);
checkAssignment(url("SqlInjection/attack5"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);
params.clear();
params.put("operator", sql_9_operator);
params.put("account", sql_9_account);
params.put("injection", sql_9_injection);
checkAssignment(url("SqlInjection/assignment5a"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true);
params.clear();
params.put("login_count", sql_10_login_count);
params.put("userid", sql_10_userid);
checkAssignment(url("SqlInjection/assignment5b"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true);
params.clear();
params.put("name", sql_11_a);
params.put("auth_tan", sql_11_b);
checkAssignment(url("SqlInjection/attack8"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true);
params.clear();
params.put("name", sql_12_a);
params.put("auth_tan", sql_12_b);
checkAssignment(url("SqlInjection/attack9"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true);
params.clear();
params.put("action_string", sql_13);
checkAssignment(url("SqlInjection/attack10"), params, true);
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
checkResults("/SqlInjection/");
}

View File

@ -23,7 +23,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.put("field5", "?");
params.put("field6", "prep.setString(1,\"\")");
params.put("field7", "prep.setString(2,\\\"\\\")");
checkAssignment(url("SqlInjectionMitigations/attack10a"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
params.put(
"editor",
@ -37,18 +37,18 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
+ "} catch (Exception e) {\r\n"
+ " System.out.println(\"Oops. Something went wrong!\");\r\n"
+ "}");
checkAssignment(url("SqlInjectionMitigations/attack10b"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
params.clear();
params.put(
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
checkAssignment(url("SqlOnlyInputValidation/attack"), params, true);
checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true);
params.clear();
params.put(
"userid_sql_only_input_validation_on_keywords",
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
checkAssignment(url("SqlOnlyInputValidationOnKeywords/attack"), params, true);
checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true);
RestAssured.given()
.when()
@ -57,7 +57,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
.contentType(ContentType.JSON)
.get(
url(
"SqlInjectionMitigations/servers?column=(case when (true) then hostname"
"/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname"
+ " else id end)"))
.then()
.statusCode(200);
@ -67,7 +67,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("SqlInjectionMitigations/servers?column=unknown"))
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
.then()
.statusCode(500)
.body(
@ -78,7 +78,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.clear();
params.put("ip", "104.130.219.202");
checkAssignment(url("SqlInjectionMitigations/attack12a"), params, true);
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true);
checkResults();
}

View File

@ -3,6 +3,7 @@ package org.owasp.webgoat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import io.restassured.RestAssured;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
@ -10,20 +11,21 @@ import org.junit.jupiter.api.Test;
public class WebWolfIntegrationTest extends IntegrationTest {
@Test
public void runTests() {
public void runTests() throws IOException {
startLesson("WebWolfIntroduction");
// Assignment 3
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("email", this.getUser() + "@webgoat.org");
checkAssignment(url("WebWolf/mail/send"), params, false);
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
String responseBody =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail"))
.get(webWolfUrl("/WebWolf/mail"))
.then()
.extract()
.response()
@ -37,7 +39,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
params.clear();
params.put("uniqueCode", uniqueCode);
checkAssignment(url("WebWolf/mail"), params, true);
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);
// Assignment 4
RestAssured.given()
@ -45,7 +47,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.queryParams(params)
.get(url("WebWolf/landing/password-reset"))
.get(url("/WebGoat/WebWolf/landing/password-reset"))
.then()
.statusCode(200);
RestAssured.given()
@ -53,7 +55,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.queryParams(params)
.get(webWolfUrl("landing"))
.get(webWolfUrl("/landing"))
.then()
.statusCode(200);
responseBody =
@ -61,7 +63,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests"))
.get(webWolfUrl("/WebWolf/requests"))
.then()
.extract()
.response()
@ -70,7 +72,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
assertTrue(responseBody.contains(uniqueCode));
params.clear();
params.put("uniqueCode", uniqueCode);
checkAssignment(url("WebWolf/landing"), params, true);
checkAssignment(url("/WebGoat/WebWolf/landing"), params, true);
checkResults("/WebWolf");
}

View File

@ -14,7 +14,7 @@ public class XSSIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("checkboxAttack1", "value");
checkAssignment(url("CrossSiteScripting/attack1"), params, true);
checkAssignment(url("/CrossSiteScripting/attack1"), params, true);
params.clear();
params.put("QTY1", "1");
@ -23,11 +23,11 @@ public class XSSIntegrationTest extends IntegrationTest {
params.put("QTY4", "1");
params.put("field1", "<script>alert('XSS+Test')</script>");
params.put("field2", "111");
checkAssignmentWithGet(url("CrossSiteScripting/attack5a"), params, true);
checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true);
params.clear();
params.put("DOMTestRoute", "start.mvc#test");
checkAssignment(url("CrossSiteScripting/attack6a"), params, true);
checkAssignment(url("/CrossSiteScripting/attack6a"), params, true);
params.clear();
params.put("param1", "42");
@ -41,7 +41,7 @@ public class XSSIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest")
.formParams(params)
.post(url("CrossSiteScripting/phone-home-xss"))
.post(url("/CrossSiteScripting/phone-home-xss"))
.then()
.statusCode(200)
.extract()
@ -50,7 +50,7 @@ public class XSSIntegrationTest extends IntegrationTest {
params.clear();
params.put("successMessage", secretNumber);
checkAssignment(url("CrossSiteScripting/dom-follow-up"), params, true);
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
params.clear();
params.put(
@ -73,44 +73,8 @@ public class XSSIntegrationTest extends IntegrationTest {
"question_4_solution",
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
+ " the browser executes.");
checkAssignment(url("CrossSiteScripting/quiz"), params, true);
checkAssignment(url("/CrossSiteScripting/quiz"), params, true);
params.clear();
params.put(
"editor",
"<%@ taglib uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\" %>"
+ "<html>"
+ "<head>"
+ "<title>Using GET and POST Method to Read Form Data</title>"
+ "</head>"
+ "<body>"
+ "<h1>Using POST Method to Read Form Data</h1>"
+ "<table>"
+ "<tbody>"
+ "<tr>"
+ "<td><b>First Name:</b></td>"
+ "<td>${e:forHtml(param.first_name)}</td>"
+ "</tr>"
+ "<tr>"
+ "<td><b>Last Name:</b></td>"
+ "<td>${e:forHtml(param.last_name)}</td>"
+ "</tr>"
+ "</tbody>"
+ "</table>"
+ "</body>"
+ "</html>");
checkAssignment(url("CrossSiteScripting/attack3"), params, true);
params.clear();
params.put(
"editor2",
"Policy.getInstance(\"antisamy-slashdot.xml\");"
+ "Sammy s = new AntiSamy();"
+ "s.scan(newComment,\"\");"
+ "CleanResults();"
+ "MyCommentDAO.addComment(threadID, userID).getCleanHTML());");
checkAssignment(url("CrossSiteScripting/attack4"), params, true);
checkResults("/CrossSiteScripting");
checkResults("/CrossSiteScripting/");
}
}

View File

@ -45,10 +45,10 @@ public class XXEIntegrationTest extends IntegrationTest {
.get(url("service/enable-security.mvc"))
.then()
.statusCode(200);
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(
url("xxe/blind"),
url("/WebGoat/xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
false);
@ -68,7 +68,7 @@ public class XXEIntegrationTest extends IntegrationTest {
}
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
String dtd7String =
dtd7.replace("WEBWOLFURL", webWolfUrl("landing")).replace("SECRET", secretFile);
dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
// upload DTD
RestAssured.given()
@ -76,7 +76,7 @@ public class XXEIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("fileupload"))
.post(webWolfUrl("/fileupload"))
.then()
.extract()
.response()
@ -84,8 +84,8 @@ public class XXEIntegrationTest extends IntegrationTest {
.asString();
// upload attack
String xxe7String =
xxe7.replace("WEBWOLFURL", webWolfUrl("files")).replace("USERNAME", this.getUser());
checkAssignment(url("xxe/blind"), ContentType.XML, xxe7String, false);
xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
// read results from WebWolf
String result =
@ -93,7 +93,7 @@ public class XXEIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests"))
.get(webWolfUrl("/WebWolf/requests"))
.then()
.extract()
.response()
@ -114,10 +114,10 @@ public class XXEIntegrationTest extends IntegrationTest {
startLesson("XXE", true);
webGoatHomeDirectory = webGoatServerDirectory();
webWolfFileServerLocation = getWebWolfFileServerLocation();
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(
url("xxe/blind"),
url("/WebGoat/xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
true);

View File

@ -27,10 +27,10 @@
*/
package org.owasp.webgoat.container;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

View File

@ -33,7 +33,6 @@ package org.owasp.webgoat.container;
import static org.asciidoctor.Asciidoctor.Factory.create;
import io.undertow.util.Headers;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -42,6 +41,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.JavaExtensionRegistry;
@ -60,7 +60,7 @@ import org.thymeleaf.templateresource.StringTemplateResource;
* Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file:
*
* <p><code>
* <div th:replace="~{doc:AccessControlMatrix_plan.adoc}"></div>
* <div th:replace="doc:AccessControlMatrix_plan.adoc"></div>
* </code>
*/
@Slf4j

View File

@ -6,6 +6,7 @@ import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.service.RestartLessonService;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
@ -19,6 +20,7 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class DatabaseConfiguration {
private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean
@Primary
@ -48,13 +50,12 @@ public class DatabaseConfiguration {
}
@Bean
public Function<String, Flyway> flywayLessons() {
public Function<String, Flyway> flywayLessons(LessonDataSource lessonDataSource) {
return schema ->
Flyway.configure()
.configuration(Map.of("driver", properties.getDriverClassName()))
.schemas(schema)
.cleanDisabled(false)
.dataSource(dataSource())
.dataSource(lessonDataSource)
.locations("lessons")
.load();
}

View File

@ -56,10 +56,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
@ -242,7 +242,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(new UserInterceptor());
}
@Bean

View File

@ -1,53 +0,0 @@
package org.owasp.webgoat.container;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.owasp.webgoat.container.asciidoc.EnvironmentExposure;
import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class UserInterceptor implements HandlerInterceptor {
private Environment env = EnvironmentExposure.getEnv();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// Do nothing
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
if (null != modelAndView) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (null != authentication) {
modelAndView.getModel().put("username", authentication.getName());
}
if (null != env) {
String githubClientId =
env.getProperty("spring.security.oauth2.client.registration.github.client-id");
if (null != githubClientId && !githubClientId.equals("dummy")) {
modelAndView.getModel().put("oauth", Boolean.TRUE);
}
} else {
modelAndView.getModel().put("oauth", Boolean.FALSE);
}
}
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// Do nothing
}
}

View File

@ -34,9 +34,6 @@ package org.owasp.webgoat.container;
import java.io.File;
import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserRepository;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
@ -45,8 +42,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.web.client.RestTemplate;
@Configuration
@ -55,8 +50,6 @@ import org.springframework.web.client.RestTemplate;
@EnableAutoConfiguration
public class WebGoat {
@Autowired private UserRepository userRepository;
@Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome);
@ -65,14 +58,7 @@ public class WebGoat {
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession() {
WebGoatUser webGoatUser = null;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof WebGoatUser) {
webGoatUser = (WebGoatUser) principal;
} else if (principal instanceof DefaultOAuth2User) {
webGoatUser = userRepository.findByUsername(((DefaultOAuth2User) principal).getName());
}
return new WebSession(webGoatUser);
return new WebSession();
}
@Bean

View File

@ -37,58 +37,50 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
/** Security configuration for WebGoat. */
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig {
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(
auth ->
auth.requestMatchers(
"/",
"/favicon.ico",
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security =
http.authorizeRequests()
.antMatchers(
"/css/**",
"/images/**",
"/js/**",
"fonts/**",
"/plugins/**",
"/registration",
"/register.mvc")
"/register.mvc",
"/actuator/**")
.permitAll()
.anyRequest()
.authenticated())
.formLogin(
login ->
login
.authenticated();
security
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/welcome.mvc", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll())
.oauth2Login(
oidc -> {
oidc.defaultSuccessUrl("/login-oauth.mvc");
oidc.loginPage("/login");
})
.logout(logout -> logout.deleteCookies("JSESSIONID").invalidateHttpSession(true))
.csrf(csrf -> csrf.disable())
.headers(headers -> headers.disable())
.exceptionHandling(
handling ->
handling.authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")))
.build();
.permitAll();
security.and().logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
security.and().csrf().disable();
http.headers().cacheControl().disable();
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
}
@Autowired
@ -97,16 +89,18 @@ public class WebSecurityConfig {
}
@Bean
public UserDetailsService userDetailsServiceBean() {
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService;
}
@Override
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();

View File

@ -16,7 +16,7 @@ public class EnvironmentExposure implements ApplicationContextAware {
private static ApplicationContext context;
public static Environment getEnv() {
return (null != context) ? context.getEnvironment() : null;
return context.getEnvironment();
}
@Override

View File

@ -2,8 +2,11 @@ package org.owasp.webgoat.container.asciidoc;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* Usage in asciidoc:
@ -23,7 +26,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
@Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv();
var hostname = env.getProperty("webwolf.url");
var hostname = determineHost(env.getProperty("webwolf.port"));
var target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target;
@ -42,4 +45,29 @@ public class WebWolfMacro extends InlineMacroProcessor {
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().anyMatch(a -> a.equals("noLink"));
}
/**
* Determine the host from the hostname and ports that were used. The purpose is to make it
* possible to use the application behind a reverse proxy. For instance in the docker
* compose/stack version with webgoat webwolf and nginx proxy. You do not have to use the
* indicated hostname, but if you do, you should define two hosts aliases 127.0.0.1
* www.webgoat.local www.webwolf.local
*/
private String determineHost(String port) {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String host = request.getHeader("Host");
int semicolonIndex = host.indexOf(":");
if (semicolonIndex == -1 || host.endsWith(":80")) {
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
} else {
host = host.substring(0, semicolonIndex);
host = host.concat(":").concat(port);
}
return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : "");
}
protected boolean includeWebWolfContext() {
return true;
}
}

View File

@ -17,4 +17,9 @@ public class WebWolfRootMacro extends WebWolfMacro {
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected boolean includeWebWolfContext() {
return false;
}
}

View File

@ -75,8 +75,7 @@ public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
} else {
userTracker.assignmentFailed(webSession.getCurrentLesson());
}
userTrackerRepository.save(userTracker);
userTrackerRepository.saveAndFlush(userTracker);
return attackResult;
}
}

View File

@ -31,7 +31,7 @@
*/
package org.owasp.webgoat.container.controller;
import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.stereotype.Controller;

View File

@ -29,8 +29,8 @@
*/
package org.owasp.webgoat.container.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@ -49,7 +49,7 @@ public class Welcome {
/**
* welcome.
*
* @param request a {@link jakarta.servlet.http.HttpServletRequest} object.
* @param request a {@link javax.servlet.http.HttpServletRequest} object.
* @return a {@link org.springframework.web.servlet.ModelAndView} object.
*/
@GetMapping(path = {"welcome.mvc"})

View File

@ -1,14 +1,9 @@
package org.owasp.webgoat.container.lessons;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Transient;
import java.util.ArrayList;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import javax.persistence.*;
import lombok.*;
/**
* ************************************************************************************************
@ -46,7 +41,7 @@ import lombok.Getter;
public class Assignment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;

View File

@ -4,13 +4,15 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Handler which sets the correct schema for the currently bounded user. This way users are not
* seeing each other data, and we can reset data for just one particular user.
* seeing each other data and we can reset data for just one particular user.
*/
@Slf4j
public class LessonConnectionInvocationHandler implements InvocationHandler {
private final Connection targetConnection;

View File

@ -3,6 +3,7 @@ package org.owasp.webgoat.container.session;
import java.io.Serializable;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* *************************************************************************************************
@ -39,12 +40,13 @@ import org.owasp.webgoat.container.users.WebGoatUser;
public class WebSession implements Serializable {
private static final long serialVersionUID = -4270066103101711560L;
private WebGoatUser currentUser;
private final WebGoatUser currentUser;
private transient Lesson currentLesson;
private boolean securityEnabled;
public WebSession(WebGoatUser webGoatUser) {
this.currentUser = webGoatUser;
public WebSession() {
this.currentUser =
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**

View File

@ -1,20 +1,8 @@
package org.owasp.webgoat.container.users;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Version;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import lombok.Getter;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson;
@ -51,11 +39,10 @@ import org.owasp.webgoat.container.lessons.Lesson;
* @since October 29, 2003
*/
@Entity
@EqualsAndHashCode
public class LessonTracker {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Getter private String lessonName;

View File

@ -1,12 +1,11 @@
package org.owasp.webgoat.container.users;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
@ -24,6 +23,7 @@ public class RegistrationController {
private UserValidator userValidator;
private UserService userService;
private AuthenticationManager authenticationManager;
@GetMapping("/registration")
public String showForm(UserForm userForm) {
@ -46,12 +46,4 @@ public class RegistrationController {
return "redirect:/attack";
}
@GetMapping("/login-oauth.mvc")
public String registrationOAUTH(Authentication authentication, HttpServletRequest request)
throws ServletException {
log.info("register oauth user in database");
userService.addUser(authentication.getName(), UUID.randomUUID().toString());
return "redirect:/welcome.mvc";
}
}

View File

@ -1,8 +1,8 @@
package org.owasp.webgoat.container.users;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;

View File

@ -1,19 +1,11 @@
package org.owasp.webgoat.container.users;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson;
@ -51,11 +43,10 @@ import org.owasp.webgoat.container.lessons.Lesson;
*/
@Slf4j
@Entity
@EqualsAndHashCode
public class UserTracker {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "username")

View File

@ -1,10 +1,10 @@
package org.owasp.webgoat.container.users;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Transient;
import java.util.Collection;
import java.util.Collections;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

View File

@ -42,7 +42,6 @@ public class AccountVerificationHelper {
static {
secQuestionStore.put(verifyUserId, userSecQuestions);
}
// end 'data store set up'
// this is to aid feedback in the attack process and is not intended to be part of the
@ -69,7 +68,6 @@ public class AccountVerificationHelper {
return likely;
}
// end of cheating check ... the method below is the one of real interest. Can you find the flaw?
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {

View File

@ -22,13 +22,13 @@
package org.owasp.webgoat.lessons.authbypass;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;

View File

@ -1,13 +1,89 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
public record Flag(int number, String answer) {
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import javax.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
public boolean isCorrect(String flag) {
return answer.equals(flag);
/**
* @author nbaars
* @since 3/23/17.
*/
@RestController
public class Flag extends AssignmentEndpoint {
public static final Map<Integer, String> FLAGS = new HashMap<>();
@Autowired private UserTrackerRepository userTrackerRepository;
@Autowired private WebSession webSession;
@AllArgsConstructor
private class FlagPosted {
@Getter private boolean lessonCompleted;
}
@Override
public String toString() {
return answer;
@PostConstruct
public void initFlags() {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
}
@RequestMapping(
path = "/challenge/flag",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public AttackResult postFlag(@RequestParam String flag) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
String currentChallenge = webSession.getCurrentLesson().getName();
int challengeNumber =
Integer.valueOf(
currentChallenge.substring(currentChallenge.length() - 1, currentChallenge.length()));
String expectedFlag = FLAGS.get(challengeNumber);
final AttackResult attackResult;
if (expectedFlag.equals(flag)) {
userTracker.assignmentSolved(webSession.getCurrentLesson(), "Assignment" + challengeNumber);
attackResult = success(this).feedback("challenge.flag.correct").build();
} else {
userTracker.assignmentFailed(webSession.getCurrentLesson());
attackResult = failed(this).feedback("challenge.flag.incorrect").build();
}
userTrackerRepository.save(userTracker);
return attackResult;
}
}

View File

@ -1,52 +0,0 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AllArgsConstructor
public class FlagController extends AssignmentEndpoint {
private final WebSession webSession;
private final Flags flags;
@PostMapping(path = "/challenge/flag", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public AttackResult postFlag(@RequestParam String flag) {
Flag expectedFlag = flags.getFlag(webSession.getCurrentLesson());
if (expectedFlag.isCorrect(flag)) {
return success(this).feedback("challenge.flag.correct").build();
} else {
return failed(this).feedback("challenge.flag.incorrect").build();
}
}
}

View File

@ -1,27 +0,0 @@
package org.owasp.webgoat.lessons.challenges;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Flags {
private final Map<Integer, Flag> FLAGS = new HashMap<>();
public Flags() {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, new Flag(i, UUID.randomUUID().toString())));
}
public Flag getFlag(Lesson forLesson) {
String lessonName = forLesson.getName();
int challengeNumber = Integer.valueOf(lessonName.substring(lessonName.length() - 1));
return FLAGS.get(challengeNumber);
}
public Flag getFlag(int flagNumber) {
return FLAGS.get(flagNumber);
}
}

View File

@ -32,4 +32,6 @@ public interface SolutionConstants {
// TODO should be random generated when starting the server
String PASSWORD = "!!webgoat_admin_1234!!";
String PASSWORD_TOM = "thisisasecretfortomonly";
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
}

View File

@ -2,10 +2,11 @@ package org.owasp.webgoat.lessons.challenges.challenge1;
import static org.owasp.webgoat.lessons.challenges.SolutionConstants.PASSWORD;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flags;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@ -42,14 +43,12 @@ import org.springframework.web.bind.annotation.RestController;
* @since August 11, 2016
*/
@RestController
@RequiredArgsConstructor
public class Assignment1 extends AssignmentEndpoint {
private final Flags flags;
@PostMapping("/challenge/1")
@ResponseBody
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
public AttackResult completed(
@RequestParam String username, @RequestParam String password, HttpServletRequest request) {
boolean ipAddressKnown = true;
boolean passwordCorrect =
"admin".equals(username)
@ -57,10 +56,14 @@ public class Assignment1 extends AssignmentEndpoint {
.replace("1234", String.format("%04d", ImageServlet.PINCODE))
.equals(password);
if (passwordCorrect && ipAddressKnown) {
return success(this).feedback("challenge.solved").feedbackArgs(flags.getFlag(1)).build();
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(1)).build();
} else if (passwordCorrect) {
return failed(this).feedback("ip.address.unknown").build();
}
return failed(this).build();
}
public static boolean containsHeader(HttpServletRequest request) {
return StringUtils.hasText(request.getHeader("X-Forwarded-For"));
}
}

View File

@ -4,7 +4,8 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import java.io.IOException;
import java.util.Random;
import java.security.SecureRandom;
import javax.servlet.http.HttpServlet;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
@ -12,9 +13,10 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ImageServlet {
public class ImageServlet extends HttpServlet {
public static final int PINCODE = new Random().nextInt(10000);
private static final long serialVersionUID = 9132775506936676850L;
public static final int PINCODE = new SecureRandom().nextInt(10000);
@RequestMapping(
method = {GET, POST},

View File

@ -24,12 +24,11 @@ package org.owasp.webgoat.lessons.challenges.challenge5;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flags;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -38,11 +37,13 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
@RequiredArgsConstructor
public class Assignment5 extends AssignmentEndpoint {
private final LessonDataSource dataSource;
private final Flags flags;
public Assignment5(LessonDataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/challenge/5")
@ResponseBody
@ -65,7 +66,7 @@ public class Assignment5 extends AssignmentEndpoint {
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return success(this).feedback("challenge.solved").feedbackArgs(flags.getFlag(5)).build();
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
} else {
return failed(this).feedback("challenge.close").build();
}

View File

@ -1,14 +1,16 @@
package org.owasp.webgoat.lessons.challenges.challenge7;
import jakarta.servlet.http.HttpServletRequest;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Email;
import org.owasp.webgoat.lessons.challenges.Flags;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.owasp.webgoat.lessons.challenges.SolutionConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
@ -31,8 +33,6 @@ import org.springframework.web.client.RestTemplate;
@Slf4j
public class Assignment7 extends AssignmentEndpoint {
public static final String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
private static final String TEMPLATE =
"Hi, you requested a password reset link, please use this <a target='_blank'"
+ " href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your"
@ -44,26 +44,22 @@ public class Assignment7 extends AssignmentEndpoint {
+ "Kind regards, \n"
+ "Team WebGoat";
private final Flags flags;
private final RestTemplate restTemplate;
private final String webWolfMailURL;
@Autowired private RestTemplate restTemplate;
public Assignment7(
Flags flags, RestTemplate restTemplate, @Value("${webwolf.mail.url}") String webWolfMailURL) {
this.flags = flags;
this.restTemplate = restTemplate;
this.webWolfMailURL = webWolfMailURL;
}
@Value("${webwolf.mail.url}")
private String webWolfMailURL;
@GetMapping("/challenge/7/reset-password/{link}")
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
if (link.equals(ADMIN_PASSWORD_LINK)) {
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
return ResponseEntity.accepted()
.body(
"<h1>Success!!</h1>"
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
+ "<br/><br/>Here is your flag: "
+ flags.getFlag(7));
+ "<b>"
+ Flag.FLAGS.get(7)
+ "</b>");
}
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT)
.body("That is not the reset link for admin");
@ -98,6 +94,6 @@ public class Assignment7 extends AssignmentEndpoint {
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ClassPathResource git() {
return new ClassPathResource("lessons/challenges/challenge7/git.zip");
return new ClassPathResource("challenge7/git.zip");
}
}

View File

@ -1,14 +1,13 @@
package org.owasp.webgoat.lessons.challenges.challenge8;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.challenges.Flags;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
@ -16,9 +15,12 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController
@Slf4j
@RequiredArgsConstructor
public class Assignment8 extends AssignmentEndpoint {
private static final Map<Integer, Integer> votes = new HashMap<>();
@ -31,8 +33,6 @@ public class Assignment8 extends AssignmentEndpoint {
votes.put(5, 300);
}
private final Flags flags;
@GetMapping(value = "/challenge/8/vote/{stars}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> vote(
@ -47,7 +47,7 @@ public class Assignment8 extends AssignmentEndpoint {
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
votes.put(nrOfStars, allVotesForStar + 1);
return ResponseEntity.ok()
.header("X-FlagController", "Thanks for voting, your flag is: " + flags.getFlag(8))
.header("X-Flag", "Thanks for voting, your flag is: " + Flag.FLAGS.get(8))
.build();
}

View File

@ -22,7 +22,6 @@
package org.owasp.webgoat.lessons.clientsidefiltering;
import jakarta.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -32,6 +31,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

View File

@ -22,9 +22,9 @@
package org.owasp.webgoat.lessons.cryptography;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.MediaType;

View File

@ -22,10 +22,10 @@
package org.owasp.webgoat.lessons.cryptography;
import jakarta.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -22,11 +22,11 @@
package org.owasp.webgoat.lessons.cryptography;
import jakarta.servlet.http.HttpServletRequest;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;

View File

@ -24,11 +24,11 @@ package org.owasp.webgoat.lessons.csrf;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -22,10 +22,10 @@
package org.owasp.webgoat.lessons.csrf;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -22,7 +22,7 @@
package org.owasp.webgoat.lessons.csrf;
import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;

View File

@ -25,7 +25,6 @@ package org.owasp.webgoat.lessons.csrf;
import static org.springframework.http.MediaType.ALL_VALUE;
import com.google.common.collect.Lists;
import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@ -33,6 +32,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;

View File

@ -22,8 +22,8 @@
package org.owasp.webgoat.lessons.hijacksession;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -22,7 +22,7 @@
package org.owasp.webgoat.lessons.httpproxies;
import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.http.HttpMethod;

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -46,7 +45,7 @@ import org.springframework.web.bind.annotation.RestController;
"idor.hints.otherProfile8",
"idor.hints.otherProfile9"
})
public class IDOREditOtherProfile extends AssignmentEndpoint {
public class IDOREditOtherProfiile extends AssignmentEndpoint {
@Autowired private UserSessionData userSessionData;
@ -70,7 +69,7 @@ public class IDOREditOtherProfile extends AssignmentEndpoint {
// we will persist in the session object for now in case we want to refer back or use it later
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
if (currentUserProfile.getRole() <= 1
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
@ -78,16 +77,16 @@ public class IDOREditOtherProfile extends AssignmentEndpoint {
}
if (currentUserProfile.getRole() > 1
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
return failed(this)
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.failure1")
.output(currentUserProfile.profileToMap().toString())
.build();
}
if (currentUserProfile.getRole() <= 1
&& !currentUserProfile.getColor().equalsIgnoreCase("red")) {
return failed(this)
&& !currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build();
@ -98,8 +97,7 @@ public class IDOREditOtherProfile extends AssignmentEndpoint {
.feedback("idor.edit.profile.failure3")
.output(currentUserProfile.profileToMap().toString())
.build();
} else if (userSubmittedProfile.getUserId() != null
&& userSubmittedProfile.getUserId().equals(authUserId)) {
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
return failed(this).feedback("idor.edit.profile.failure4").build();
}

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,15 +15,16 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.idor;
import jakarta.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
@ -55,9 +56,9 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
produces = {"application/json"})
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
Map<String, Object> details = new HashMap<>();
Object obj = userSessionData.getValue("idor-authenticated-as");
if (obj != null && obj.equals("tom")) {
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
// going to use session auth to view this one
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
if (userId != null && !userId.equals(authUserId)) {
@ -65,8 +66,7 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
UserProfile requestedProfile = new UserProfile(userId);
// secure code would ensure there was a horizontal access control check prior to dishing up
// the requested profile
if (requestedProfile.getUserId() != null
&& requestedProfile.getUserId().equals("2342388")) {
if (requestedProfile.getUserId().equals("2342388")) {
return success(this)
.feedback("idor.view.profile.success")
.output(requestedProfile.profileToMap().toString())

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -69,7 +68,7 @@ public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint {
return failed(this).feedback("idor.view.own.profile.failure2").build();
}
} catch (Exception ex) {
return failed(this).output("an error occurred with your request").build();
return failed(this).feedback("an error occurred with your request").build();
}
}
}

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -20,7 +20,7 @@
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt.claimmisuse;
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
@ -38,30 +38,28 @@ import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AssignmentHints({
"jwt-kid-hint1",
"jwt-kid-hint2",
"jwt-kid-hint3",
"jwt-kid-hint4",
"jwt-kid-hint5",
"jwt-kid-hint6"
"jwt-final-hint1",
"jwt-final-hint2",
"jwt-final-hint3",
"jwt-final-hint4",
"jwt-final-hint5",
"jwt-final-hint6"
})
@RequestMapping("/JWT/kid")
public class JWTHeaderKIDEndpoint extends AssignmentEndpoint {
public class JWTFinalEndpoint extends AssignmentEndpoint {
private final LessonDataSource dataSource;
private JWTHeaderKIDEndpoint(LessonDataSource dataSource) {
private JWTFinalEndpoint(LessonDataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/follow/{user}")
@PostMapping("/JWT/final/follow/{user}")
public @ResponseBody String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) {
return "Following yourself seems redundant";
@ -70,7 +68,7 @@ public class JWTHeaderKIDEndpoint extends AssignmentEndpoint {
}
}
@PostMapping("/delete")
@PostMapping("/JWT/final/delete")
public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build();

View File

@ -31,14 +31,14 @@ import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.TextCodec;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -1,70 +0,0 @@
package org.owasp.webgoat.lessons.jwt.claimmisuse;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.JwkProviderBuilder;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPublicKey;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/JWT/jku")
@RestController
@AssignmentHints({
"jwt-jku-hint1",
"jwt-jku-hint2",
"jwt-jku-hint3",
"jwt-jku-hint4",
"jwt-jku-hint5"
})
public class JWTHeaderJKUEndpoint extends AssignmentEndpoint {
@PostMapping("/follow/{user}")
public @ResponseBody String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) {
return "Following yourself seems redundant";
} else {
return "You are now following Tom";
}
}
@PostMapping("/delete")
public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build();
} else {
try {
var decodedJWT = JWT.decode(token);
var jku = decodedJWT.getHeaderClaim("jku");
JwkProvider jwkProvider = new JwkProviderBuilder(new URL(jku.asString())).build();
var jwk = jwkProvider.get(decodedJWT.getKeyId());
var algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey());
JWT.require(algorithm).build().verify(decodedJWT);
String username = decodedJWT.getClaims().get("username").asString();
if ("Jerry".equals(username)) {
return failed(this).feedback("jwt-final-jerry-account").build();
}
if ("Tom".equals(username)) {
return success(this).build();
} else {
return failed(this).feedback("jwt-final-not-tom").build();
}
} catch (MalformedURLException | JWTVerificationException | JwkException e) {
return failed(this).feedback("jwt-invalid-token").output(e.toString()).build();
}
}
}
}

View File

@ -22,10 +22,10 @@
package org.owasp.webgoat.lessons.logging;
import jakarta.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;
import javax.annotation.PostConstruct;
import org.apache.logging.log4j.util.Strings;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;

View File

@ -39,8 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
"access-control.hash.hint9",
"access-control.hash.hint10",
"access-control.hash.hint11",
"access-control.hash.hint12",
"access-control.hash.hint13"
"access-control.hash.hint12"
})
public class MissingFunctionACYourHashAdmin extends AssignmentEndpoint {

View File

@ -22,8 +22,8 @@
package org.owasp.webgoat.lessons.passwordreset;
import jakarta.servlet.http.HttpServletRequest;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.beans.factory.annotation.Value;
@ -48,19 +48,16 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
private final RestTemplate restTemplate;
private String webWolfHost;
private String webWolfPort;
private String webWolfURL;
private final String webWolfMailURL;
public ResetLinkAssignmentForgotPassword(
RestTemplate restTemplate,
@Value("${webwolf.host}") String webWolfHost,
@Value("${webwolf.port}") String webWolfPort,
@Value("${webwolf.url}") String webWolfURL,
@Value("${webwolf.mail.url}") String webWolfMailURL) {
this.restTemplate = restTemplate;
this.webWolfHost = webWolfHost;
this.webWolfPort = webWolfPort;
this.webWolfURL = webWolfURL;
this.webWolfMailURL = webWolfMailURL;
}
@ -70,12 +67,12 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
@RequestParam String email, HttpServletRequest request) {
String resetLink = UUID.randomUUID().toString();
ResetLinkAssignment.resetLinks.add(resetLink);
String host = request.getHeader(HttpHeaders.HOST);
String host = request.getHeader("host");
if (ResetLinkAssignment.TOM_EMAIL.equals(email)
&& (host.contains(webWolfPort)
&& host.contains(webWolfHost))) { // User indeed changed the host header.
|| host.contains(webWolfHost))) { // User indeed changed the host header.
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
fakeClickingLinkEmail(webWolfURL, resetLink);
fakeClickingLinkEmail(host, resetLink);
} else {
try {
sendMailToUser(email, host, resetLink);
@ -100,13 +97,13 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
}
private void fakeClickingLinkEmail(String webWolfURL, String resetLink) {
private void fakeClickingLinkEmail(String host, String resetLink) {
try {
HttpHeaders httpHeaders = new HttpHeaders();
HttpEntity httpEntity = new HttpEntity(httpHeaders);
new RestTemplate()
.exchange(
String.format("%s/PasswordReset/reset/reset-password/%s", webWolfURL, resetLink),
String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink),
HttpMethod.GET,
httpEntity,
Void.class);

View File

@ -1,7 +1,7 @@
package org.owasp.webgoat.lessons.passwordreset.resetlink;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;

View File

@ -1,7 +1,5 @@
package org.owasp.webgoat.lessons.pathtraversal;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -10,6 +8,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.Base64;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,20 +15,18 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.spoofcookie;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
@ -46,7 +44,6 @@ import org.springframework.web.bind.annotation.RestController;
*
*/
@AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"})
@RestController
public class SpoofCookieAssignment extends AssignmentEndpoint {

View File

@ -22,11 +22,11 @@
package org.owasp.webgoat.lessons.sqlinjection.introduction;
import jakarta.annotation.PostConstruct;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.PostConstruct;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -22,9 +22,9 @@
package org.owasp.webgoat.lessons.sqlinjection.introduction;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.*;
import javax.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;

View File

@ -44,12 +44,12 @@ public class SSRFTask1 extends AssignmentEndpoint {
try {
StringBuilder html = new StringBuilder();
if (url.matches("images/tom\\.png")) {
if (url.matches("images/tom.png")) {
html.append(
"<img class=\"image\" alt=\"Tom\" src=\"images/tom.png\" width=\"25%\""
+ " height=\"25%\">");
return failed(this).feedback("ssrf.tom").output(html.toString()).build();
} else if (url.matches("images/jerry\\.png")) {
} else if (url.matches("images/jerry.png")) {
html.append(
"<img class=\"image\" alt=\"Jerry\" src=\"images/jerry.png\" width=\"25%\""
+ " height=\"25%\">");

View File

@ -46,7 +46,7 @@ public class SSRFTask2 extends AssignmentEndpoint {
}
protected AttackResult furBall(String url) {
if (url.matches("http://ifconfig\\.pro")) {
if (url.matches("http://ifconfig.pro")) {
String html;
try (InputStream in = new URL(url).openStream()) {
html =

Some files were not shown because too many files have changed in this diff Show More