Compare commits

..

1 Commits

Author SHA1 Message Date
bd5fe360c7 fix: WIP 2023-06-19 17:42:20 +02:00
469 changed files with 2759 additions and 5848 deletions

2
.github/FUNDING.yml vendored
View File

@ -1 +1 @@
custom: https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat custom: https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat

View File

@ -12,3 +12,4 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"

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

@ -1,17 +1,19 @@
name: "Main / Pull requests build" name: "Pull requests build"
on: on:
pull_request: pull_request:
paths-ignore: paths-ignore:
- '.txt' - '.txt'
- 'LICENSE' - 'LICENSE'
- 'docs/**' - 'docs/**'
branches: [main]
push:
branches:
- main
jobs: jobs:
build: pr-build:
if: >
github.event_name == 'pull_request' && !github.event.pull_request.draft && (
github.event.action == 'opened' ||
github.event.action == 'reopened' ||
github.event.action == 'synchronize'
)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@ -19,7 +21,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
@ -32,3 +34,27 @@ jobs:
restore-keys: ${{ runner.os }}-m2- restore-keys: ${{ runner.os }}-m2-
- name: Build with Maven - name: Build with Maven
run: mvn --no-transfer-progress verify run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.1.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@v4.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@v4.1.0
if: runner.os == 'Linux'
with:
context: ./
file: ./Dockerfile_desktop
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}

View File

@ -1,29 +0,0 @@
name: Pre-commit check
on:
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
pre-commit:
name: Pre-commit check
runs-on: ubuntu-latest
steps:
- name: Checkout git repository
uses: actions/checkout@v4
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: "3.9"
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Pre-commit checks
uses: pre-commit/action@v3.0.0
- name: pre-commit-ci-lite
uses: pre-commit-ci/lite-action@v1.0.1
if: always()

View File

@ -8,15 +8,13 @@ jobs:
if: github.repository == 'WebGoat/WebGoat' if: github.repository == 'WebGoat/WebGoat'
name: Release WebGoat name: Release WebGoat
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
@ -46,7 +44,7 @@ jobs:
files: | files: |
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: | body: |
## Version ${{ github.ref_name }} ## Version ${{ steps.tag.outputs.tag }}
### New functionality ### New functionality
@ -55,8 +53,8 @@ jobs:
### Bug fixes ### Bug fixes
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743) - [#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 ## Contributors
@ -74,26 +72,26 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU" - name: "Set up QEMU"
uses: docker/setup-qemu-action@v2.2.0 uses: docker/setup-qemu-action@v2.1.0
with: with:
platforms: all platforms: all
- name: "Set up Docker Buildx" - name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v2
- name: "Login to dockerhub" - name: "Login to dockerhub"
uses: docker/login-action@v3.0.0 uses: docker/login-action@v2.2.0
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push WebGoat" - name: "Build and push WebGoat"
uses: docker/build-push-action@v5.1.0 uses: docker/build-push-action@v4.1.0
with: with:
context: ./ context: ./
file: ./Dockerfile file: ./Dockerfile
push: true push: true
platforms: linux/amd64, linux/arm64 platforms: linux/amd64, linux/arm64, linux/arm/v7
tags: | tags: |
webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }} webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/webgoat:latest webgoat/webgoat:latest
@ -101,7 +99,7 @@ jobs:
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Build and push WebGoat desktop" - name: "Build and push WebGoat desktop"
uses: docker/build-push-action@v5.1.0 uses: docker/build-push-action@v4.1.0
with: with:
context: ./ context: ./
file: ./Dockerfile_desktop file: ./Dockerfile_desktop
@ -123,7 +121,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Set up JDK 17 - name: Set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
@ -147,3 +145,4 @@ jobs:
github_token: "${{ secrets.GITHUB_TOKEN }}" github_token: "${{ secrets.GITHUB_TOKEN }}"
title: ${{ github.event.commits[0].message }} title: ${{ github.event.commits[0].message }}
target_branch: main target_branch: main

View File

@ -23,14 +23,14 @@ jobs:
# Uses an default action to checkout the code # Uses an default action to checkout the code
- uses: actions/checkout@v3 - uses: actions/checkout@v3
# Uses an action to add Python to the VM # Uses an action to add Python to the VM
- name: Setup Python - name: Setup Pyton
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: '3.7' python-version: '3.7'
architecture: x64 architecture: x64
# Uses an action to add JDK 17 to the VM (and mvn?) # Uses an action to add JDK 17 to the VM (and mvn?)
- name: set up JDK 17 - name: set up JDK 17
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 17
@ -61,7 +61,7 @@ jobs:
# send report to forks only due to limits on permission tokens # send report to forks only due to limits on permission tokens
- name: Send report to commit - name: Send report to commit
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push' if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
uses: joonvena/robotframework-reporter-action@v2.2 uses: joonvena/robotframework-reporter-action@v2.1
with: with:
gh_access_token: ${{ secrets.GITHUB_TOKEN }} gh_access_token: ${{ secrets.GITHUB_TOKEN }}
report_path: 'robotreport' report_path: 'robotreport'

View File

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

2
.gitignore vendored
View File

@ -56,4 +56,4 @@ TestClass.class
**/*.flattened-pom.xml **/*.flattened-pom.xml
/.gitconfig /.gitconfig
webgoat.gitconfig webgoat.gitconfig

View File

@ -1,28 +0,0 @@
ci:
autofix_commit_msg: |
[pre-commit.ci] auto fixes from pre-commit.com hooks
autofix_prs: false # managed in the action step
autoupdate_branch: ""
autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
autoupdate_schedule: weekly
skip: []
submodules: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
exclude: ^(README.md|CREATE_RELEASE.md)
- id: trailing-whitespace
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.5.0
hooks:
- id: commitlint
stages: [commit-msg]
- repo: https://github.com/ejba/pre-commit-maven
rev: v0.3.4
hooks:
- id: maven
args: [ 'clean compile' ]
- id: maven-spotless-apply

View File

@ -16,4 +16,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
Getting Source ============== Getting Source ==============
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects. Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.

View File

@ -8,14 +8,14 @@ and 2023.01 in the `pom.xml`.
### Release notes: ### Release notes:
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of 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 mvn versions:set
<< update release notes >> << update release notes >>
mvn verify mvn verify
git commit .... git commit ....
git tag v2023.01 git tag v2023.01
git push --tags git push --tags
``` ```

View File

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

1
FAQ.md
View File

@ -5,3 +5,4 @@
### Integration tests fail ### Integration tests fail
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line. Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.

View File

@ -16,4 +16,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
Getting Source ============== Getting Source ==============
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects. Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.

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) [![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/) [![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/)
@ -44,27 +44,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 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. If you want to reuse the container, give it a name:
E.g.
```shell ```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 As long as you don't remove the container you can use:
you can use custom host entries. For example:
```shell ```shell
127.0.0.1 www.webgoat.local www.webwolf.local docker start webgoat
``` ```
Then you can run the container with: This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
```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/
## 2. Run using Docker with complete Linux Desktop ## 2. Run using Docker with complete Linux Desktop
@ -79,8 +71,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) Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```shell ```shell
export TZ=Europe/Amsterdam # or your timezone java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.3.jar
java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar
``` ```
Click the link in the log to start WebGoat. Click the link in the log to start WebGoat.
@ -89,7 +80,7 @@ Click the link in the log to start WebGoat.
### Prerequisites: ### Prerequisites:
* Java 17 or 21 * Java 17
* Your favorite IDE * Your favorite IDE
* Git, or Git support in your IDE * Git, or Git support in your IDE
@ -141,10 +132,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: For instance running as a jar on a Linux/macOS it will look like this:
```Shell ```Shell
export TZ=Europe/Amsterdam # or your timezone
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" 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: Or in a docker run it would (once this version is pushed into docker hub) look like this:

View File

@ -16,19 +16,19 @@ The following steps are required when you want to add a new language
1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html) 1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html)
1. Add the parts for showing the flag and providing the correct value for the flag= parameter 1. Add the parts for showing the flag and providing the correct value for the flag= parameter
2. 2.
2. Add a flag image to src/main/resources/webgoat/static/css/img 3. Add a flag image to src/main/resources/webgoat/static/css/img
1. See the main_new.html for a link to download flag resources 1. See the main_new.html for a link to download flag resources
3. Add a welcome page to the introduction lesson 4. Add a welcome page to the introduction lesson
1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish) 1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish)
2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable 2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable
4. Translate the main labels 5. Translate the main labels
1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish) 1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish)
2. Translate the label values 2. Translate the label values
5. Optionally translate lessons by 6. Optionally translate lessons by
1. Adding lang specifc adoc files in documentation folder of the lesson 1. Adding lang specifc adoc files in documentation folder of the lesson
2. Adding WebGoatLabels.properties of a specific language if you want to 2. Adding WebGoatLabels.properties of a specific language if you want to
6. Run mvn clean to see if the LabelAndHintIntegration test passes 7. Run mvn clean to see if the LabelAndHintIntegration test passes
7. Run WebGoat and verify that your own language and the other languages work as expected 8. Run WebGoat and verify that your own language and the other languages work as expected
If you only want to translate more for a certain language, you only need to do step 4-8 If you only want to translate more for a certain language, you only need to do step 4-8

View File

@ -1,60 +1,5 @@
# WebGoat release notes # WebGoat release notes
## Version 2023.8
### 🚀 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 ## Version 2023.4
### New functionality ### New functionality
@ -215,3 +160,4 @@ Special thanks to the following contributors providing us with a pull request:
And everyone who provided feedback through Github. And everyone who provided feedback through Github.
Team WebGoat Team WebGoat

View File

@ -8,4 +8,4 @@
<suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" /> <suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" />
<suppress files="SimpleXXE.java" checks="IllegalImportCheck" /> <suppress files="SimpleXXE.java" checks="IllegalImportCheck" />
<suppress files="HtmlTamperingTask.java" checks="ParameterName" /> <suppress files="HtmlTamperingTask.java" checks="ParameterName" />
</suppressions> </suppressions>

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. 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: You can start WebGoat and ZAP by opening a terminal and type:
./start_webgoat.sh ./start-webgoat.sh
./start_zap.sh ./start_zap.sh
Happy hacking, Happy hacking,

View File

@ -1,3 +1,4 @@
# WebGoat landing page # WebGoat landing page
Old GitHub page which now redirects to OWASP website. Old GitHub page which now redirects to OWASP website.

View File

@ -11,4 +11,4 @@
The page been moved to <a href="https://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a> The page been moved to <a href="https://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a>
</h1> </h1>
</body> </body>
</html> </html>

2
mvnw vendored
View File

@ -246,7 +246,7 @@ else
else else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi fi
else else
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download" echo "Falling back to using Java to download"

103
pom.xml
View File

@ -5,12 +5,12 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version> <version>3.1.0</version>
</parent> </parent>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId> <artifactId>webgoat</artifactId>
<version>2023.9-SNAPSHOT</version> <version>2023.5-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>WebGoat</name> <name>WebGoat</name>
@ -109,29 +109,30 @@
<properties> <properties>
<!-- Shared properties with plugins and version numbers across submodules--> <!-- Shared properties with plugins and version numbers across submodules-->
<asciidoctorj.version>2.5.10</asciidoctorj.version> <asciidoctorj.version>2.5.3</asciidoctorj.version>
<bootstrap.version>5.3.2</bootstrap.version> <!-- Upgrading needs UI work in WebWolf -->
<bootstrap.version>3.3.7</bootstrap.version>
<cglib.version>3.3.0</cglib.version> <cglib.version>3.3.0</cglib.version>
<!-- do not update necessary for lesson --> <!-- do not update necessary for lesson -->
<checkstyle.version>3.3.1</checkstyle.version> <checkstyle.version>3.3.0</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version> <commons-collections.version>3.2.1</commons-collections.version>
<commons-io.version>2.15.1</commons-io.version> <commons-io.version>2.11.0</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-text.version>1.10.0</commons-text.version> <commons-text.version>1.10.0</commons-text.version>
<guava.version>32.1.3-jre</guava.version> <guava.version>31.1-jre</guava.version>
<jacoco.version>0.8.11</jacoco.version> <jacoco.version>0.8.10</jacoco.version>
<java.version>17</java.version> <java.version>17</java.version>
<jaxb.version>2.3.1</jaxb.version> <jaxb.version>2.3.1</jaxb.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<jose4j.version>0.9.3</jose4j.version> <jose4j.version>0.9.3</jose4j.version>
<jquery.version>3.7.0</jquery.version> <jquery.version>3.5.1</jquery.version>
<jsoup.version>1.16.1</jsoup.version> <jsoup.version>1.16.1</jsoup.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-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-jar-plugin.version>3.1.2</maven-jar-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-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-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.1.0</maven-surefire-plugin.version>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<pmd.version>3.15.0</pmd.version> <pmd.version>3.15.0</pmd.version>
@ -139,16 +140,14 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version> <thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
<webdriver.version>5.3.3</webdriver.version> <webdriver.version>5.3.2</webdriver.version>
<webgoat.context>/</webgoat.context> <webgoat.port>8080</webgoat.port>
<webgoat.sslenabled>false</webgoat.sslenabled> <webwolf.port>9090</webwolf.port>
<webjars-locator-core.version>0.53</webjars-locator-core.version>
<webwolf.context>/</webwolf.context>
<wiremock.version>2.27.2</wiremock.version> <wiremock.version>2.27.2</wiremock.version>
<xml-resolver.version>1.2</xml-resolver.version> <xml-resolver.version>1.2</xml-resolver.version>
<xstream.version>1.4.5</xstream.version> <xstream.version>1.4.5</xstream.version>
<!-- do not update necessary for lesson --> <!-- do not update necessary for lesson -->
<zxcvbn.version>1.8.0</zxcvbn.version> <zxcvbn.version>1.7.0</zxcvbn.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -201,17 +200,6 @@
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
<version>${jjwt.version}</version> <version>${jjwt.version}</version>
</dependency> </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> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@ -242,11 +230,6 @@
<artifactId>jquery</artifactId> <artifactId>jquery</artifactId>
<version>${jquery.version}</version> <version>${jquery.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
<version>${webjars-locator-core.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.tomakehurst</groupId> <groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId> <artifactId>wiremock</artifactId>
@ -260,12 +243,12 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId> <artifactId>commons-compress</artifactId>
<version>1.25.0</version> <version>1.22</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jruby</groupId> <groupId>org.jruby</groupId>
<artifactId>jruby</artifactId> <artifactId>jruby</artifactId>
<version>9.4.3.0</version> <version>9.4.2.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -327,10 +310,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId> <groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId> <artifactId>thymeleaf-extras-springsecurity6</artifactId>
@ -367,15 +346,6 @@
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
</dependency> </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> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@ -404,10 +374,6 @@
<groupId>org.webjars</groupId> <groupId>org.webjars</groupId>
<artifactId>jquery</artifactId> <artifactId>jquery</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>jakarta.xml.bind</groupId> <groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId> <artifactId>jakarta.xml.bind-api</artifactId>
@ -512,19 +478,10 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<configuration> <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> <systemPropertyVariables>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile> <logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables> </systemPropertyVariables>
<argLine>-Xmx512m</argLine> <argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
<includes>org/owasp/webgoat/*Test</includes> <includes>org/owasp/webgoat/*Test</includes>
</configuration> </configuration>
<executions> <executions>
@ -547,7 +504,6 @@
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
<configuration> <configuration>
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED <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/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.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
@ -565,6 +521,7 @@
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version> <version>${checkstyle.version}</version>
<configuration> <configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput> <consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError> <failsOnError>true</failsOnError>
<configLocation>config/checkstyle/checkstyle.xml</configLocation> <configLocation>config/checkstyle/checkstyle.xml</configLocation>
@ -575,7 +532,7 @@
<plugin> <plugin>
<groupId>com.diffplug.spotless</groupId> <groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId> <artifactId>spotless-maven-plugin</artifactId>
<version>2.41.1</version> <version>2.33.0</version>
<configuration> <configuration>
<formats> <formats>
<format> <format>
@ -693,15 +650,16 @@
<portNames> <portNames>
<portName>webgoat.port</portName> <portName>webgoat.port</portName>
<portName>webwolf.port</portName> <portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames> </portNames>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.honton.chas</groupId> <groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId> <artifactId>process-exec-maven-plugin</artifactId>
<version>0.9.2</version> <version>0.9</version>
<executions> <executions>
<execution> <execution>
<id>start-jar</id> <id>start-jar</id>
@ -709,18 +667,8 @@
<goal>start</goal> <goal>start</goal>
</goals> </goals>
<phase>pre-integration-test</phase> <phase>pre-integration-test</phase>
<configuration> <configuration>
<workingDir>${project.build.directory}</workingDir> <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> <arguments>
<argument>java</argument> <argument>java</argument>
<argument>-jar</argument> <argument>-jar</argument>
@ -728,6 +676,8 @@
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> <argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
<argument>-Dwebgoat.user.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>-Dspring.main.banner-mode=off</argument>
<argument>-Dwebgoat.port=${webgoat.port}</argument>
<argument>-Dwebwolf.port=${webwolf.port}</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument> <argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
@ -753,6 +703,7 @@
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument> <argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
</arguments> </arguments>
<waitForInterrupt>false</waitForInterrupt> <waitForInterrupt>false</waitForInterrupt>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>
@ -777,6 +728,7 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>6.5.1</version>
<configuration> <configuration>
<failBuildOnCVSS>7</failBuildOnCVSS> <failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>false</skipProvidedScope> <skipProvidedScope>false</skipProvidedScope>
@ -825,6 +777,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions> <executions>
<execution> <execution>
<id>before-unit-test</id> <id>before-unit-test</id>

View File

@ -12,10 +12,8 @@ Then see security settings and allow the file to run
pip3 install virtualenv --user pip3 install virtualenv --user
python3 -m virtualenv .venv python3 -m virtualenv .venv
source .venv/bin/activate source .venv/bin/activate
pip install --upgrade robotframework pip install robotframework
pip install --upgrade robotframework-SeleniumLibrary pip install robotframework-SeleniumLibrary
pip install --upgrade webdriver-manager pip install webdriver-manager
brew upgrade
robot --variable HEADLESS:"0" --variable ENDPOINT:"http://127.0.0.1:8080/WebGoat" goat.robot 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 Documentation Setup WebGoat Robotframework tests
Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot
Library String Library String
Library OperatingSystem
Suite Setup Initial_Page ${ENDPOINT} ${BROWSER} Suite Setup Initial_Page ${ENDPOINT} ${BROWSER}
Suite Teardown Close_Page Suite Teardown Close_Page
@ -12,7 +11,7 @@ ${BROWSER} chrome
${SLEEP} 100 ${SLEEP} 100
${DELAY} 0.25 ${DELAY} 0.25
${ENDPOINT} http://127.0.0.1:8080/WebGoat ${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 ${USERNAME} robotuser
${PASSWORD} password ${PASSWORD} password
${HEADLESS} ${FALSE} ${HEADLESS} ${FALSE}
@ -23,25 +22,22 @@ Initial_Page
[Arguments] ${ENDPOINT} ${BROWSER} [Arguments] ${ENDPOINT} ${BROWSER}
Log To Console Start WebGoat UI Testing Log To Console Start WebGoat UI Testing
IF ${HEADLESS} 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 ELSE
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
END 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 Switch Browser webgoat
Maximize Browser Window Maximize Browser Window
Set Window Size ${1400} ${1000} 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 Switch Browser webwolf
Maximize Browser Window Maximize Browser Window
Set Window Size ${1400} ${1000} Set Window Size ${1400} ${1000}
Set Window Position ${500} ${0} Set Window Position ${400} ${200}
Set Selenium Speed ${DELAY} Set Selenium Speed ${DELAY}
Close_Page Close_Page
@ -57,7 +53,6 @@ Close_Page
*** Test Cases *** *** Test Cases ***
Check_Initial_Page Check_Initial_Page
[Tags] WebGoatTests
Switch Browser webgoat Switch Browser webgoat
Page Should Contain Username Page Should Contain Username
Click Button Sign in Click Button Sign in
@ -65,7 +60,6 @@ Check_Initial_Page
Click Link /WebGoat/registration Click Link /WebGoat/registration
Check_Registration_Page Check_Registration_Page
[Tags] WebGoatTests
Page Should Contain Username Page Should Contain Username
Input Text username ${USERNAME} Input Text username ${USERNAME}
Input Text password ${PASSWORD} Input Text password ${PASSWORD}
@ -74,7 +68,6 @@ Check_Registration_Page
Click Button Sign up Click Button Sign up
Check_Welcome_Page Check_Welcome_Page
[Tags] WebGoatTests
Page Should Contain WebGoat Page Should Contain WebGoat
Go To ${ENDPOINT}/login Go To ${ENDPOINT}/login
Page Should Contain Username Page Should Contain Username
@ -84,7 +77,6 @@ Check_Welcome_Page
Page Should Contain WebGoat Page Should Contain WebGoat
Check_Menu_Page Check_Menu_Page
[Tags] WebGoatTests
Click Element css=a[category='Introduction'] Click Element css=a[category='Introduction']
Click Element Introduction-WebGoat Click Element Introduction-WebGoat
CLick Element Introduction-WebWolf CLick Element Introduction-WebWolf
@ -101,29 +93,9 @@ Check_Menu_Page
Check_WebWolf Check_WebWolf
Switch Browser 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 username ${USERNAME}
Input Text password ${PASSWORD} Input Text password ${PASSWORD}
Click Button Sign In 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() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix")) .get(url("/WebGoat/access-control/users-admin-fix"))
.then() .then()
.statusCode(HttpStatus.SC_FORBIDDEN); .statusCode(HttpStatus.SC_FORBIDDEN);
@ -40,7 +40,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(String.format(userTemplate, this.getUser(), this.getUser())) .body(String.format(userTemplate, this.getUser(), this.getUser()))
.post(url("access-control/users")) .post(url("/WebGoat/access-control/users"))
.then() .then()
.statusCode(HttpStatus.SC_OK); .statusCode(HttpStatus.SC_OK);
@ -51,14 +51,15 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix")) .get(url("/WebGoat/access-control/users-admin-fix"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.jsonPath() .jsonPath()
.get("find { it.username == \"Jerry\" }.userHash"); .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() { private void assignment2() {
@ -68,18 +69,18 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users")) .get(url("/WebGoat/access-control/users"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.jsonPath() .jsonPath()
.get("find { it.username == \"Jerry\" }.userHash"); .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() { private void assignment1() {
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config"); 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() { public void init() {
startLesson("CSRF"); startLesson("CSRF");
webwolfFileDir = getWebWolfFileServerLocation(); webwolfFileDir = getWebWolfFileServerLocation();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("csrf/basic-get-flag"))); uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("csrf/review"))); uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("csrf/feedback/message"))); uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
uploadTrickHtml( uploadTrickHtml(
"csrf8.html", "csrf8.html",
trickHTML8.replace("WEBGOATURL", url("login")).replace("USERNAME", this.getUser())); trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
} }
@TestFactory @TestFactory
@ -103,7 +103,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", htmlName, htmlContent.getBytes()) .multiPart("file", htmlName, htmlContent.getBytes())
.post(webWolfUrl("fileupload")) .post(webWolfUrl("/WebWolf/fileupload"))
.then() .then()
.extract() .extract()
.response() .response()
@ -118,7 +118,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("files/" + this.getUser() + "/" + htmlName)) .get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
.then() .then()
.extract() .extract()
.response() .response()
@ -136,7 +136,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.post(goatURL) .post(goatURL)
.then() .then()
.extract() .extract()
@ -146,7 +146,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("confirmFlagVal", flag); 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) { private void checkAssignment4(String goatURL) {
@ -163,7 +163,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.formParams(params) .formParams(params)
.post(goatURL) .post(goatURL)
.then() .then()
@ -184,7 +184,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.contentType(ContentType.TEXT) .contentType(ContentType.TEXT)
.body( .body(
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is" "{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
@ -198,7 +198,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("confirmFlagVal", flag); params.put("confirmFlagVal", flag);
checkAssignment(url("csrf/feedback"), params, true); checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
} }
private void checkAssignment8(String goatURL) { private void checkAssignment8(String goatURL) {
@ -217,7 +217,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrl("/files/fake.html"))
.params(params) .params(params)
.post(goatURL) .post(goatURL)
.then() .then()
@ -239,7 +239,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie) .cookie("JSESSIONID", newCookie)
.post(url("csrf/login")) .post(url("/csrf/login"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -253,8 +253,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
Overview[] assignments = Overview[] assignments =
RestAssured.given() RestAssured.given()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.relaxedHTTPSValidation() .get(url("/service/lessonoverview.mvc"))
.get(url("service/lessonoverview.mvc"))
.then() .then()
.extract() .extract()
.jsonPath() .jsonPath()

View File

@ -22,7 +22,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/logo")) .get(url("/WebGoat/challenge/logo"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -34,14 +34,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
params.put("username", "admin"); params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode)); params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("challenge/1"), params, true); checkAssignment(url("/WebGoat/challenge/1"), params, true);
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.post(url("challenge/1")) .post(url("/WebGoat/challenge/1"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -50,7 +50,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear(); params.clear();
params.put("flag", flag); params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true); checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/1"); checkResults("/challenge/1");
@ -59,7 +59,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data")) .get(url("/WebGoat/scoreboard-data"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -83,7 +83,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.post(url("challenge/5")) .post(url("/WebGoat/challenge/5"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -92,7 +92,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear(); params.clear();
params.put("flag", flag); params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true); checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/5"); checkResults("/challenge/5");
@ -101,7 +101,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data")) .get(url("/WebGoat/scoreboard-data"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -120,7 +120,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/7/.git")) .get(url("/WebGoat/challenge/7/.git"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -132,7 +132,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", getUser() + "@webgoat.org") .formParams("email", getUser() + "@webgoat.org")
.post(url("challenge/7")) .post(url("/WebGoat/challenge/7"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -144,7 +144,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail")) .get(webWolfUrl("/mail"))
.then() .then()
.extract() .extract()
.response() .response()
@ -158,13 +158,13 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2") .get(url("/challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
.then() .then()
.statusCode(HttpStatus.ACCEPTED.value()) .statusCode(HttpStatus.ACCEPTED.value())
.extract() .extract()
.asString(); .asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
checkAssignment(url("challenge/flag"), Map.of("flag", flag), true); checkAssignment(url("/WebGoat/challenge/flag"), Map.of("flag", flag), true);
} }
} }

View File

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

View File

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

View File

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

View File

@ -5,6 +5,7 @@ import static io.restassured.RestAssured.given;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert; import org.hamcrest.MatcherAssert;
@ -14,42 +15,34 @@ import org.springframework.http.HttpStatus;
public abstract class IntegrationTest { public abstract class IntegrationTest {
private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080"); private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
private static String webGoatContext =
System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/");
@Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090");
@Getter @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 boolean useSSL = false;
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 String webgoatUrl = private static String webgoatUrl =
(useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext; (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext; private static String webWolfUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
@Getter private String webGoatCookie; @Getter private String webGoatCookie;
@Getter private String webWolfCookie; @Getter private String webWolfCookie;
@Getter private final String user = "webgoat"; @Getter private final String user = "webgoat";
protected String url(String url) { protected String url(String url) {
url = url.replaceFirst("/WebGoat/", "");
url = url.replaceFirst("/WebGoat", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webgoatUrl + url; return webgoatUrl + url;
} }
protected String webWolfUrl(String url) { protected String webWolfUrl(String url) {
url = url.replaceFirst("/WebWolf/", "");
url = url.replaceFirst("/WebWolf", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webWolfUrl + url; return webWolfUrl + url;
} }
protected String webWolfFileUrl(String fileName) {
return webWolfUrl("files") + "/" + getUser() + "/" + fileName;
}
@BeforeEach @BeforeEach
public void login() { public void login() {
String location = String location =
@ -238,7 +231,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("file-server-location")) .get(webWolfUrl("/file-server-location"))
.then() .then()
.extract() .extract()
.response() .response()
@ -253,7 +246,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("server-directory")) .get(url("/server-directory"))
.then() .then()
.extract() .extract()
.response() .response()
@ -266,7 +259,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.delete(webWolfUrl("mail")) .delete(webWolfUrl("/mail"))
.then() .then()
.statusCode(HttpStatus.ACCEPTED.value()); .statusCode(HttpStatus.ACCEPTED.value());
} }

View File

@ -14,10 +14,7 @@ import io.restassured.RestAssured;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant; import java.time.Instant;
import java.util.Base64; import java.util.Base64;
import java.util.Calendar; import java.util.Calendar;
@ -26,8 +23,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert; import org.hamcrest.MatcherAssert;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwk.RsaJsonWebKey;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint; import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
@ -45,9 +40,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
buyAsTom(); buyAsTom();
deleteTomThroughKidClaim(); deleteTom();
deleteTomThroughJkuClaim();
quiz(); quiz();
@ -88,7 +81,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParam("jwt-encode-user", "user") .formParam("jwt-encode-user", "user")
.post(url("JWT/decode")) .post(url("/WebGoat/JWT/decode"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -103,7 +96,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/secret/gettoken")) .get(url("/WebGoat/JWT/secret/gettoken"))
.then() .then()
.extract() .extract()
.response() .response()
@ -117,7 +110,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParam("token", generateToken(secret)) .formParam("token", generateToken(secret))
.post(url("JWT/secret")) .post(url("/WebGoat/JWT/secret"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -131,7 +124,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/votings/login?user=Tom")) .get(url("/WebGoat/JWT/votings/login?user=Tom"))
.then() .then()
.extract() .extract()
.cookie("access_token"); .cookie("access_token");
@ -164,7 +157,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("access_token", replacedToken) .cookie("access_token", replacedToken)
.post(url("JWT/votings")) .post(url("/WebGoat/JWT/votings"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -205,7 +198,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Authorization", "Bearer " + replacedToken) .header("Authorization", "Bearer " + replacedToken)
.post(url("JWT/refresh/checkout")) .post(url("/WebGoat/JWT/refresh/checkout"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -213,7 +206,8 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
CoreMatchers.is(true)); CoreMatchers.is(true));
} }
private void deleteTomThroughKidClaim() { private void deleteTom() {
Map<String, Object> header = new HashMap(); Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE); header.put(Header.TYPE, Header.JWT_TYPE);
header.put( header.put(
@ -238,54 +232,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/kid/delete?token=" + token)) .post(url("/WebGoat/JWT/final/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))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -298,6 +245,6 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
params.put("question_0_solution", "Solution 1"); params.put("question_0_solution", "Solution 1");
params.put("question_1_solution", "Solution 2"); params.put("question_1_solution", "Solution 2");
checkAssignment(url("JWT/quiz"), params, true); checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
} }
} }

View File

@ -11,13 +11,12 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestFactory;
import org.springframework.http.HttpHeaders;
public class PasswordResetLessonIntegrationTest extends IntegrationTest { public class PasswordResetLessonIntegrationTest extends IntegrationTest {
@BeforeEach @BeforeEach
public void init() { public void init() {
startLesson("PasswordReset"); startLesson("/PasswordReset");
} }
@TestFactory @TestFactory
@ -69,6 +68,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
// WebWolf // WebWolf
var link = getPasswordResetLinkFromLandingPage(); var link = getPasswordResetLinkFromLandingPage();
// WebGoat // WebGoat
changePassword(link); changePassword(link);
checkAssignment( checkAssignment(
@ -85,7 +85,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail")) .get(webWolfUrl("/WebWolf/mail"))
.then() .then()
.extract() .extract()
.response() .response()
@ -119,7 +119,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests")) .get(webWolfUrl("/WebWolf/requests"))
.then() .then()
.extract() .extract()
.response() .response()
@ -136,7 +136,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
private void clickForgotEmailLink(String user) { private void clickForgotEmailLink(String user) {
RestAssured.given() RestAssured.given()
.when() .when()
.header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort())) .header("host", String.format("%s:%s", "localhost", getWebWolfPort()))
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user) .formParams("email", user)

View File

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

View File

@ -29,7 +29,7 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(Map.of("flag", "test")) .formParams(Map.of("flag", "test"))
.post(url("challenge/flag")); .post(url("/challenge/flag"));
}; };
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS); ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
List<? extends Callable<Response>> flagCalls = List<? extends Callable<Response>> flagCalls =

View File

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

View File

@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
*/ */
class SessionManagementIT extends IntegrationTest { 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 @Test
void hijackSessionTest() { void hijackSessionTest() {

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ public class XSSIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("checkboxAttack1", "value"); params.put("checkboxAttack1", "value");
checkAssignment(url("CrossSiteScripting/attack1"), params, true); checkAssignment(url("/CrossSiteScripting/attack1"), params, true);
params.clear(); params.clear();
params.put("QTY1", "1"); params.put("QTY1", "1");
@ -23,11 +23,11 @@ public class XSSIntegrationTest extends IntegrationTest {
params.put("QTY4", "1"); params.put("QTY4", "1");
params.put("field1", "<script>alert('XSS+Test')</script>"); params.put("field1", "<script>alert('XSS+Test')</script>");
params.put("field2", "111"); params.put("field2", "111");
checkAssignmentWithGet(url("CrossSiteScripting/attack5a"), params, true); checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true);
params.clear(); params.clear();
params.put("DOMTestRoute", "start.mvc#test"); params.put("DOMTestRoute", "start.mvc#test");
checkAssignment(url("CrossSiteScripting/attack6a"), params, true); checkAssignment(url("/CrossSiteScripting/attack6a"), params, true);
params.clear(); params.clear();
params.put("param1", "42"); params.put("param1", "42");
@ -41,7 +41,7 @@ public class XSSIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln") .header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest") .header("X-Requested-With", "XMLHttpRequest")
.formParams(params) .formParams(params)
.post(url("CrossSiteScripting/phone-home-xss")) .post(url("/CrossSiteScripting/phone-home-xss"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -50,7 +50,7 @@ public class XSSIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("successMessage", secretNumber); params.put("successMessage", secretNumber);
checkAssignment(url("CrossSiteScripting/dom-follow-up"), params, true); checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
params.clear(); params.clear();
params.put( params.put(
@ -73,44 +73,8 @@ public class XSSIntegrationTest extends IntegrationTest {
"question_4_solution", "question_4_solution",
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that" "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
+ " the browser executes."); + " the browser executes.");
checkAssignment(url("CrossSiteScripting/quiz"), params, true); checkAssignment(url("/CrossSiteScripting/quiz"), params, true);
params.clear(); checkResults("/CrossSiteScripting/");
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");
} }
} }

View File

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

View File

@ -6,6 +6,7 @@ import javax.sql.DataSource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway; import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.service.RestartLessonService; import org.owasp.webgoat.container.service.RestartLessonService;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -19,6 +20,7 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class DatabaseConfiguration { public class DatabaseConfiguration {
private final DataSourceProperties properties; private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean @Bean
@Primary @Primary

View File

@ -242,7 +242,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor()); registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(new UserInterceptor());
} }
@Bean @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 java.io.File;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession; 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.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean; 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.PropertySource;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode; 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; import org.springframework.web.client.RestTemplate;
@Configuration @Configuration
@ -55,8 +50,6 @@ import org.springframework.web.client.RestTemplate;
@EnableAutoConfiguration @EnableAutoConfiguration
public class WebGoat { public class WebGoat {
@Autowired private UserRepository userRepository;
@Bean(name = "pluginTargetDirectory") @Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome); return new File(webgoatHome);
@ -65,14 +58,7 @@ public class WebGoat {
@Bean @Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession() { public WebSession webSession() {
WebGoatUser webGoatUser = null; return new WebSession();
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);
} }
@Bean @Bean

View File

@ -54,41 +54,32 @@ public class WebSecurityConfig {
@Bean @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests( http.authorizeHttpRequests(
auth -> auth ->
auth.requestMatchers( auth.requestMatchers(
"/", "/css/**",
"/favicon.ico", "/images/**",
"/css/**", "/js/**",
"/images/**", "fonts/**",
"/js/**", "/plugins/**",
"fonts/**", "/registration",
"/plugins/**", "/register.mvc",
"/registration", "/actuator/**")
"/register.mvc") .permitAll()
.permitAll() .anyRequest()
.anyRequest() .authenticated());
.authenticated()) http.formLogin()
.formLogin( .loginPage("/login")
login -> .defaultSuccessUrl("/welcome.mvc", true)
login .usernameParameter("username")
.loginPage("/login") .passwordParameter("password")
.defaultSuccessUrl("/welcome.mvc", true) .permitAll();
.usernameParameter("username") http.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
.passwordParameter("password") http.csrf().disable();
.permitAll())
.oauth2Login( http.headers().cacheControl().disable();
oidc -> { http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
oidc.defaultSuccessUrl("/login-oauth.mvc"); return http.build();
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();
} }
@Autowired @Autowired
@ -107,6 +98,7 @@ public class WebSecurityConfig {
return authenticationConfiguration.getAuthenticationManager(); return authenticationConfiguration.getAuthenticationManager();
} }
@SuppressWarnings("deprecation")
@Bean @Bean
public NoOpPasswordEncoder passwordEncoder() { public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();

View File

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

View File

@ -1,9 +1,12 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/** /**
* Usage in asciidoc: * Usage in asciidoc:
@ -23,7 +26,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
@Override @Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) { public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv(); 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 target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target; var href = hostname + "/" + target;
@ -42,4 +45,29 @@ public class WebWolfMacro extends InlineMacroProcessor {
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) { private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().anyMatch(a -> a.equals("noLink")); 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) { public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config); super(macroName, config);
} }
@Override
protected boolean includeWebWolfContext() {
return false;
}
} }

View File

@ -3,6 +3,7 @@ package org.owasp.webgoat.container.session;
import java.io.Serializable; import java.io.Serializable;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.WebGoatUser; 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 { public class WebSession implements Serializable {
private static final long serialVersionUID = -4270066103101711560L; private static final long serialVersionUID = -4270066103101711560L;
private WebGoatUser currentUser; private final WebGoatUser currentUser;
private transient Lesson currentLesson; private transient Lesson currentLesson;
private boolean securityEnabled; private boolean securityEnabled;
public WebSession(WebGoatUser webGoatUser) { public WebSession() {
this.currentUser = webGoatUser; this.currentUser =
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
} }
/** /**

View File

@ -3,10 +3,8 @@ package org.owasp.webgoat.container.users;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.UUID;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -46,12 +44,4 @@ public class RegistrationController {
return "redirect:/attack"; 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

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

View File

@ -29,7 +29,8 @@ import java.util.Random;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.container.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -40,9 +41,10 @@ public class CSRFGetFlag {
@Autowired UserSessionData userSessionData; @Autowired UserSessionData userSessionData;
@Autowired private PluginMessages pluginMessages; @Autowired private PluginMessages pluginMessages;
@PostMapping( @RequestMapping(
path = "/csrf/basic-get-flag", path = "/csrf/basic-get-flag",
produces = {"application/json"}) produces = {"application/json"},
method = RequestMethod.POST)
@ResponseBody @ResponseBody
public Map<String, Object> invoke(HttpServletRequest req) { public Map<String, Object> invoke(HttpServletRequest req) {

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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.otherProfile8",
"idor.hints.otherProfile9" "idor.hints.otherProfile9"
}) })
public class IDOREditOtherProfile extends AssignmentEndpoint { public class IDOREditOtherProfiile extends AssignmentEndpoint {
@Autowired private UserSessionData userSessionData; @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 // 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); userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
if (currentUserProfile.getRole() <= 1 if (currentUserProfile.getRole() <= 1
&& currentUserProfile.getColor().equalsIgnoreCase("red")) { && currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this) return success(this)
.feedback("idor.edit.profile.success1") .feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString()) .output(currentUserProfile.profileToMap().toString())
@ -78,16 +77,16 @@ public class IDOREditOtherProfile extends AssignmentEndpoint {
} }
if (currentUserProfile.getRole() > 1 if (currentUserProfile.getRole() > 1
&& currentUserProfile.getColor().equalsIgnoreCase("red")) { && currentUserProfile.getColor().toLowerCase().equals("red")) {
return failed(this) return success(this)
.feedback("idor.edit.profile.failure1") .feedback("idor.edit.profile.failure1")
.output(currentUserProfile.profileToMap().toString()) .output(currentUserProfile.profileToMap().toString())
.build(); .build();
} }
if (currentUserProfile.getRole() <= 1 if (currentUserProfile.getRole() <= 1
&& !currentUserProfile.getColor().equalsIgnoreCase("red")) { && !currentUserProfile.getColor().toLowerCase().equals("red")) {
return failed(this) return success(this)
.feedback("idor.edit.profile.failure2") .feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString()) .output(currentUserProfile.profileToMap().toString())
.build(); .build();

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
@ -24,6 +23,8 @@
package org.owasp.webgoat.lessons.idor; package org.owasp.webgoat.lessons.idor;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints; import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.container.assignments.AttackResult;
@ -55,9 +56,9 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
produces = {"application/json"}) produces = {"application/json"})
@ResponseBody @ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) { public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
Map<String, Object> details = new HashMap<>();
Object obj = userSessionData.getValue("idor-authenticated-as"); if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
if (obj != null && obj.equals("tom")) {
// going to use session auth to view this one // going to use session auth to view this one
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id"); String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
if (userId != null && !userId.equals(authUserId)) { if (userId != null && !userId.equals(authUserId)) {
@ -65,8 +66,7 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
UserProfile requestedProfile = new UserProfile(userId); UserProfile requestedProfile = new UserProfile(userId);
// secure code would ensure there was a horizontal access control check prior to dishing up // secure code would ensure there was a horizontal access control check prior to dishing up
// the requested profile // the requested profile
if (requestedProfile.getUserId() != null if (requestedProfile.getUserId().equals("2342388")) {
&& requestedProfile.getUserId().equals("2342388")) {
return success(this) return success(this)
.feedback("idor.view.profile.success") .feedback("idor.view.profile.success")
.output(requestedProfile.profileToMap().toString()) .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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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(); return failed(this).feedback("idor.view.own.profile.failure2").build();
} }
} catch (Exception ex) { } 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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. * 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.Claims;
import io.jsonwebtoken.JwsHeader; import io.jsonwebtoken.JwsHeader;
@ -38,30 +38,28 @@ import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@AssignmentHints({ @AssignmentHints({
"jwt-kid-hint1", "jwt-final-hint1",
"jwt-kid-hint2", "jwt-final-hint2",
"jwt-kid-hint3", "jwt-final-hint3",
"jwt-kid-hint4", "jwt-final-hint4",
"jwt-kid-hint5", "jwt-final-hint5",
"jwt-kid-hint6" "jwt-final-hint6"
}) })
@RequestMapping("/JWT/kid") public class JWTFinalEndpoint extends AssignmentEndpoint {
public class JWTHeaderKIDEndpoint extends AssignmentEndpoint {
private final LessonDataSource dataSource; private final LessonDataSource dataSource;
private JWTHeaderKIDEndpoint(LessonDataSource dataSource) { private JWTFinalEndpoint(LessonDataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@PostMapping("/follow/{user}") @PostMapping("/JWT/final/follow/{user}")
public @ResponseBody String follow(@PathVariable("user") String user) { public @ResponseBody String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) { if ("Jerry".equals(user)) {
return "Following yourself seems redundant"; 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) { public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) { if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build(); return failed(this).feedback("jwt-invalid-token").build();

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

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

View File

@ -48,19 +48,16 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
private final RestTemplate restTemplate; private final RestTemplate restTemplate;
private String webWolfHost; private String webWolfHost;
private String webWolfPort; private String webWolfPort;
private String webWolfURL;
private final String webWolfMailURL; private final String webWolfMailURL;
public ResetLinkAssignmentForgotPassword( public ResetLinkAssignmentForgotPassword(
RestTemplate restTemplate, RestTemplate restTemplate,
@Value("${webwolf.host}") String webWolfHost, @Value("${webwolf.host}") String webWolfHost,
@Value("${webwolf.port}") String webWolfPort, @Value("${webwolf.port}") String webWolfPort,
@Value("${webwolf.url}") String webWolfURL,
@Value("${webwolf.mail.url}") String webWolfMailURL) { @Value("${webwolf.mail.url}") String webWolfMailURL) {
this.restTemplate = restTemplate; this.restTemplate = restTemplate;
this.webWolfHost = webWolfHost; this.webWolfHost = webWolfHost;
this.webWolfPort = webWolfPort; this.webWolfPort = webWolfPort;
this.webWolfURL = webWolfURL;
this.webWolfMailURL = webWolfMailURL; this.webWolfMailURL = webWolfMailURL;
} }
@ -70,12 +67,12 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
@RequestParam String email, HttpServletRequest request) { @RequestParam String email, HttpServletRequest request) {
String resetLink = UUID.randomUUID().toString(); String resetLink = UUID.randomUUID().toString();
ResetLinkAssignment.resetLinks.add(resetLink); ResetLinkAssignment.resetLinks.add(resetLink);
String host = request.getHeader(HttpHeaders.HOST); String host = request.getHeader("host");
if (ResetLinkAssignment.TOM_EMAIL.equals(email) if (ResetLinkAssignment.TOM_EMAIL.equals(email)
&& (host.contains(webWolfPort) && (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); ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
fakeClickingLinkEmail(webWolfURL, resetLink); fakeClickingLinkEmail(host, resetLink);
} else { } else {
try { try {
sendMailToUser(email, host, resetLink); sendMailToUser(email, host, resetLink);
@ -100,13 +97,13 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class); this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
} }
private void fakeClickingLinkEmail(String webWolfURL, String resetLink) { private void fakeClickingLinkEmail(String host, String resetLink) {
try { try {
HttpHeaders httpHeaders = new HttpHeaders(); HttpHeaders httpHeaders = new HttpHeaders();
HttpEntity httpEntity = new HttpEntity(httpHeaders); HttpEntity httpEntity = new HttpEntity(httpHeaders);
new RestTemplate() new RestTemplate()
.exchange( .exchange(
String.format("%s/PasswordReset/reset/reset-password/%s", webWolfURL, resetLink), String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink),
HttpMethod.GET, HttpMethod.GET,
httpEntity, httpEntity,
Void.class); Void.class);

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
@ -28,7 +27,6 @@ import jakarta.servlet.http.HttpServletResponse;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; 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.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec; import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException; 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 @RestController
public class SpoofCookieAssignment extends AssignmentEndpoint { public class SpoofCookieAssignment extends AssignmentEndpoint {

View File

@ -58,8 +58,7 @@ public class LandingAssignment extends AssignmentEndpoint {
public ModelAndView openPasswordReset(HttpServletRequest request) throws URISyntaxException { public ModelAndView openPasswordReset(HttpServletRequest request) throws URISyntaxException {
URI uri = new URI(request.getRequestURL().toString()); URI uri = new URI(request.getRequestURL().toString());
ModelAndView modelAndView = new ModelAndView(); ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject( modelAndView.addObject("webwolfUrl", landingPageUrl);
"webwolfLandingPageUrl", landingPageUrl.replace("//landing", "/landing"));
modelAndView.addObject("uniqueCode", StringUtils.reverse(getWebSession().getUserName())); modelAndView.addObject("uniqueCode", StringUtils.reverse(getWebSession().getUserName()));
modelAndView.setViewName("lessons/webwolfintroduction/templates/webwolfPasswordReset.html"); modelAndView.setViewName("lessons/webwolfintroduction/templates/webwolfPasswordReset.html");

View File

@ -35,6 +35,6 @@ public class CrossSiteScripting extends Lesson {
@Override @Override
public String getTitle() { public String getTitle() {
return "4.xss.title"; return "xss.title";
} }
} }

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
@ -31,9 +30,12 @@ import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController // @RestController
@Deprecated
// TODO This assignment seems not to be in use in the UI
// it is there to make sure the lesson can be marked complete
// in order to restore it, make it accessible through the UI and uncomment RestController
@AssignmentHints( @AssignmentHints(
value = { value = {
"xss-mitigation-3-hint1", "xss-mitigation-3-hint1",
@ -58,9 +60,9 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
String lastNameElement = String lastNameElement =
doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text(); doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
boolean includeCorrect = false; Boolean includeCorrect = false;
boolean firstNameCorrect = false; Boolean firstNameCorrect = false;
boolean lastNameCorrect = false; Boolean lastNameCorrect = false;
if (include.contains("<%@") if (include.contains("<%@")
&& include.contains("taglib") && include.contains("taglib")

View File

@ -22,15 +22,20 @@
package org.owasp.webgoat.lessons.xss; package org.owasp.webgoat.lessons.xss;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints; import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController // @RestController
@Deprecated
// TODO This assignment seems not to be in use in the UI
// it is there to make sure the lesson can be marked complete
// in order to restore it, make it accessible through the UI and uncomment RestController@Slf4j
@Slf4j
@AssignmentHints(value = {"xss-mitigation-4-hint1"}) @AssignmentHints(value = {"xss-mitigation-4-hint1"})
public class CrossSiteScriptingLesson4 extends AssignmentEndpoint { public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
@ -39,6 +44,7 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
public AttackResult completed(@RequestParam String editor2) { public AttackResult completed(@RequestParam String editor2) {
String editor = editor2.replaceAll("\\<.*?>", ""); String editor = editor2.replaceAll("\\<.*?>", "");
log.debug(editor);
if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"") if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"")
|| editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"") || editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"")
@ -48,8 +54,10 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
&& editor.contains("CleanResults") && editor.contains("CleanResults")
&& editor.contains("MyCommentDAO.addComment(threadID, userID") && editor.contains("MyCommentDAO.addComment(threadID, userID")
&& editor.contains(".getCleanHTML());")) { && editor.contains(".getCleanHTML());")) {
log.debug("true");
return success(this).feedback("xss-mitigation-4-success").build(); return success(this).feedback("xss-mitigation-4-success").build();
} else { } else {
log.debug("false");
return failed(this).feedback("xss-mitigation-4-failed").build(); return failed(this).feedback("xss-mitigation-4-failed").build();
} }
} }

View File

@ -15,8 +15,7 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 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. * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
@ -25,9 +24,7 @@ package org.owasp.webgoat.lessons.xss;
import org.owasp.webgoat.container.lessons.Category; import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class CrossSiteScriptingMitigation extends Lesson { public class CrossSiteScriptingMitigation extends Lesson {
@Override @Override
public Category getDefaultCategory() { public Category getDefaultCategory() {
@ -36,6 +33,6 @@ public class CrossSiteScriptingMitigation extends Lesson {
@Override @Override
public String getTitle() { public String getTitle() {
return "6.xss-mitigation.title"; return "xss-mitigation.title";
} }
} }

View File

@ -24,9 +24,7 @@ package org.owasp.webgoat.lessons.xss.stored;
import org.owasp.webgoat.container.lessons.Category; import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson; import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class CrossSiteScriptingStored extends Lesson { public class CrossSiteScriptingStored extends Lesson {
@Override @Override
public Category getDefaultCategory() { public Category getDefaultCategory() {
@ -35,6 +33,6 @@ public class CrossSiteScriptingStored extends Lesson {
@Override @Override
public String getTitle() { public String getTitle() {
return "5.xss-stored.title"; return "xss-stored.title";
} }
} }

View File

@ -34,15 +34,21 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint { public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
// TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up") @PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
@ResponseBody @ResponseBody
public AttackResult completed(@RequestParam String successMessage) { public AttackResult completed(@RequestParam String successMessage) {
UserSessionData userSessionData = getUserSessionData(); UserSessionData userSessionData = getUserSessionData();
if (successMessage.equals(userSessionData.getValue("randValue"))) { if (successMessage.equals(userSessionData.getValue("randValue").toString())) {
return success(this).feedback("xss-stored-callback-success").build(); return success(this).feedback("xss-stored-callback-success").build();
} else { } else {
return failed(this).feedback("xss-stored-callback-failure").build(); return failed(this).feedback("xss-stored-callback-failure").build();
} }
} }
} }
// something like ...
// http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere%3Cscript%3Ewebgoat.customjs.phoneHome();%3C%2Fscript%3E
// or
// http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere<script>webgoat.customjs.phoneHome();<%2Fscript>

View File

@ -72,6 +72,7 @@ public class StoredXssComments extends AssignmentEndpoint {
"Can you post a comment, calling webgoat.customjs.phoneHome() ?")); "Can you post a comment, calling webgoat.customjs.phoneHome() ?"));
} }
// TODO This assignment seems not to be in use in the UI
@GetMapping( @GetMapping(
path = "/CrossSiteScriptingStored/stored-xss", path = "/CrossSiteScriptingStored/stored-xss",
produces = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE,
@ -88,6 +89,7 @@ public class StoredXssComments extends AssignmentEndpoint {
return allComments; return allComments;
} }
// TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss") @PostMapping("/CrossSiteScriptingStored/stored-xss")
@ResponseBody @ResponseBody
public AttackResult createNewComment(@RequestBody String commentStr) { public AttackResult createNewComment(@RequestBody String commentStr) {

View File

@ -29,8 +29,9 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -42,7 +43,7 @@ public class Ping {
@Autowired private WebSession webSession; @Autowired private WebSession webSession;
@GetMapping @RequestMapping(method = RequestMethod.GET)
@ResponseBody @ResponseBody
public String logRequest( public String logRequest(
@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) { @RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {

View File

@ -31,30 +31,20 @@ import org.owasp.webgoat.webwolf.WebWolf;
import org.springframework.boot.Banner; import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
@Slf4j @Slf4j
public class StartWebGoat { public class StartWebGoat {
public static void main(String[] args) { public static void main(String[] args) {
var parentBuilder = new SpringApplicationBuilder()
new SpringApplicationBuilder() .parent(ParentConfig.class)
.parent(ParentConfig.class) .web(WebApplicationType.NONE)
.web(WebApplicationType.NONE) .bannerMode(Banner.Mode.OFF)
.bannerMode(Banner.Mode.OFF); .child(WebGoat.class)
parentBuilder.child(WebWolf.class).web(WebApplicationType.SERVLET).run(args); .web(WebApplicationType.SERVLET)
ApplicationContext webGoatContext = .sibling(WebWolf.class)
parentBuilder.child(WebGoat.class).web(WebApplicationType.SERVLET).run(args); .bannerMode(Banner.Mode.OFF)
.web(WebApplicationType.SERVLET)
printStartUpMessage(webGoatContext); .run(args);
}
private static void printStartUpMessage(ApplicationContext webGoatContext) {
var url = webGoatContext.getEnvironment().getProperty("webgoat.url");
var sslEnabled =
webGoatContext.getEnvironment().getProperty("server.ssl.enabled", Boolean.class);
log.warn(
"Please browse to " + "{} to start using WebGoat...",
sslEnabled ? url.replace("http", "https") : url);
} }
} }

View File

@ -0,0 +1,33 @@
package org.owasp.webgoat.server;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
@Slf4j
@NoArgsConstructor
public class StartupMessage {
private String port;
private String address;
@EventListener
void onStartup(ApplicationReadyEvent event) {
if (StringUtils.hasText(port)
&& !StringUtils.hasText(System.getProperty("running.in.docker"))) {
log.info("Please browse to http://{}:{}/WebGoat to get started...", address, port);
}
if (event.getApplicationContext().getApplicationName().contains("WebGoat")) {
port = event.getApplicationContext().getEnvironment().getProperty("server.port");
address = event.getApplicationContext().getEnvironment().getProperty("server.address");
}
}
@EventListener
void onShutdown(ContextStoppedEvent event) {}
}

View File

@ -22,23 +22,20 @@
package org.owasp.webgoat.webwolf; package org.owasp.webgoat.webwolf;
import static java.util.Comparator.comparing;
import static org.springframework.http.MediaType.ALL_VALUE; import static org.springframework.http.MediaType.ALL_VALUE;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.TimeZone; import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.owasp.webgoat.webwolf.user.WebGoatUser;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -55,18 +52,12 @@ import org.springframework.web.servlet.view.RedirectView;
@Slf4j @Slf4j
public class FileServer { public class FileServer {
private static final DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Value("${webwolf.fileserver.location}") @Value("${webwolf.fileserver.location}")
private String fileLocation; private String fileLocation;
@Value("${server.address}") @Value("${server.address}")
private String server; private String server;
@Value("${server.servlet.context-path}")
private String contextPath;
@Value("${server.port}") @Value("${server.port}")
private int port; private int port;
@ -80,11 +71,9 @@ public class FileServer {
} }
@PostMapping(value = "/fileupload") @PostMapping(value = "/fileupload")
public ModelAndView importFile( public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
@RequestParam("file") MultipartFile myFile, Authentication authentication) var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
throws IOException { var destinationDir = new File(fileLocation, user.getUsername());
String username = authentication.getName();
var destinationDir = new File(fileLocation, username);
destinationDir.mkdirs(); destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename())); myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename())); log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
@ -94,47 +83,41 @@ public class FileServer {
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful")); new ModelMap().addAttribute("uploadSuccess", "File uploaded successful"));
} }
@AllArgsConstructor
@Getter
private class UploadedFile {
private final String name;
private final String size;
private final String link;
}
@GetMapping(value = "/files") @GetMapping(value = "/files")
public ModelAndView getFiles( public ModelAndView getFiles(HttpServletRequest request) {
HttpServletRequest request, Authentication authentication, TimeZone timezone) { WebGoatUser user =
String username = (null != authentication) ? authentication.getName() : "anonymous"; (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
File destinationDir = new File(fileLocation, username); File destinationDir = new File(fileLocation, username);
ModelAndView modelAndView = new ModelAndView(); ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("files"); modelAndView.setViewName("files");
File changeIndicatorFile = new File(destinationDir, username + "_changed"); File changeIndicatorFile = new File(destinationDir, user.getUsername() + "_changed");
if (changeIndicatorFile.exists()) { if (changeIndicatorFile.exists()) {
modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess")); modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess"));
} }
changeIndicatorFile.delete(); changeIndicatorFile.delete();
record UploadedFile(String name, String size, String link, String creationTime) {} var uploadedFiles = new ArrayList<>();
var uploadedFiles = new ArrayList<UploadedFile>();
File[] files = destinationDir.listFiles(File::isFile); File[] files = destinationDir.listFiles(File::isFile);
if (files != null) { if (files != null) {
for (File file : files) { for (File file : files) {
String size = FileUtils.byteCountToDisplaySize(file.length()); String size = FileUtils.byteCountToDisplaySize(file.length());
String link = String.format("files/%s/%s", username, file.getName()); String link = String.format("files/%s/%s", username, file.getName());
uploadedFiles.add( uploadedFiles.add(new UploadedFile(file.getName(), size, link));
new UploadedFile(file.getName(), size, link, getCreationTime(timezone, file)));
} }
} }
modelAndView.addObject( modelAndView.addObject("files", uploadedFiles);
"files", modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
uploadedFiles.stream().sorted(comparing(UploadedFile::creationTime).reversed()).toList());
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port + contextPath);
return modelAndView; return modelAndView;
} }
private String getCreationTime(TimeZone timezone, File file) {
try {
FileTime creationTime = (FileTime) Files.getAttribute(file.toPath(), "creationTime");
ZonedDateTime zonedDateTime = creationTime.toInstant().atZone(timezone.toZoneId());
return dateTimeFormatter.format(zonedDateTime);
} catch (IOException e) {
return "unknown";
}
}
} }

View File

@ -24,10 +24,8 @@ package org.owasp.webgoat.webwolf;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import java.io.File; import java.io.File;
import org.owasp.webgoat.container.UserInterceptor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -57,12 +55,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("webwolf-login"); registry.addViewController("/login").setViewName("webwolf-login");
registry.addViewController("/home").setViewName("home"); registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor());
} }
@PostConstruct @PostConstruct

View File

@ -22,7 +22,6 @@
package org.owasp.webgoat.webwolf; package org.owasp.webgoat.webwolf;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.AjaxAuthenticationEntryPoint;
import org.owasp.webgoat.webwolf.user.UserService; import org.owasp.webgoat.webwolf.user.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -47,39 +46,16 @@ public class WebSecurityConfig {
@Bean @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests( http.authorizeHttpRequests(
auth -> { auth -> auth.requestMatchers(HttpMethod.POST, "/fileupload").authenticated());
auth.requestMatchers("/css/**", "/webjars/**", "/favicon.ico", "/js/**", "/images/**") http.authorizeHttpRequests(
.permitAll(); auth ->
auth.requestMatchers( auth.requestMatchers(HttpMethod.GET, "/files", "/mail", "/requests").authenticated());
HttpMethod.GET, http.authorizeHttpRequests().anyRequest().permitAll();
"/fileupload/**", http.csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=true");
"/files/**", http.formLogin().loginPage("/login").defaultSuccessUrl("/home", true).permitAll();
"/landing/**", http.logout().permitAll();
"/PasswordReset/**") return http.build();
.permitAll();
auth.requestMatchers(HttpMethod.POST, "/files", "/mail", "/requests").permitAll();
auth.anyRequest().authenticated();
})
.csrf(csrf -> csrf.disable())
.formLogin(
login ->
login
.loginPage("/login")
.failureUrl("/login?error=true")
.defaultSuccessUrl("/home", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll())
.oauth2Login(
oidc -> {
oidc.defaultSuccessUrl("/home");
})
.logout(logout -> logout.deleteCookies("WEBWOLFSESSION").invalidateHttpSession(true))
.exceptionHandling(
handling ->
handling.authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")))
.build();
} }
@Autowired @Autowired

View File

@ -1,11 +1,11 @@
package org.owasp.webgoat.webwolf.jwt; package org.owasp.webgoat.webwolf.jwt;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.Base64Utils.decodeFromUrlSafeString;
import static org.springframework.util.StringUtils.hasText; import static org.springframework.util.StringUtils.hasText;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Base64;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -103,8 +103,8 @@ public class JWTToken {
var builder = JWTToken.builder().encoded(jwt); var builder = JWTToken.builder().encoded(jwt);
if (token.length >= 2) { if (token.length >= 2) {
var header = new String(Base64.getUrlDecoder().decode(token[0]), UTF_8); var header = new String(decodeFromUrlSafeString(token[0]), UTF_8);
var payloadAsString = new String(Base64.getUrlDecoder().decode(token[1]), UTF_8); var payloadAsString = new String(decodeFromUrlSafeString(token[1]), UTF_8);
var headers = parse(header); var headers = parse(header);
var payload = parse(payloadAsString); var payload = parse(payloadAsString);
builder.header(write(header, headers)); builder.header(write(header, headers));

View File

@ -25,8 +25,8 @@ package org.owasp.webgoat.webwolf.mailbox;
import java.util.List; import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -42,16 +42,16 @@ public class MailboxController {
private final MailboxRepository mailboxRepository; private final MailboxRepository mailboxRepository;
@GetMapping("/mail") @GetMapping("/mail")
public ModelAndView mail(Authentication authentication, Model model) { public ModelAndView mail() {
String username = (null != authentication) ? authentication.getName() : "anonymous"; UserDetails user =
(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
ModelAndView modelAndView = new ModelAndView(); ModelAndView modelAndView = new ModelAndView();
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(username); List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
if (emails != null && !emails.isEmpty()) { if (emails != null && !emails.isEmpty()) {
modelAndView.addObject("total", emails.size()); modelAndView.addObject("total", emails.size());
modelAndView.addObject("emails", emails); modelAndView.addObject("emails", emails);
} }
modelAndView.setViewName("mailbox"); modelAndView.setViewName("mailbox");
model.addAttribute("username", username);
return modelAndView; return modelAndView;
} }

View File

@ -22,6 +22,8 @@
package org.owasp.webgoat.webwolf.requests; package org.owasp.webgoat.webwolf.requests;
import static java.util.stream.Collectors.toList;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant; import java.time.Instant;
@ -31,7 +33,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.actuate.web.exchanges.HttpExchange; import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -61,29 +64,30 @@ public class Requests {
} }
@GetMapping @GetMapping
public ModelAndView get(Authentication authentication) { public ModelAndView get() {
var model = new ModelAndView("requests"); var model = new ModelAndView("requests");
String username = (null != authentication) ? authentication.getName() : "anonymous"; var user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var traces = var traces =
traceRepository.findAll().stream() traceRepository.findAllTraces().stream()
.filter(t -> allowedTrace(t, username)) .filter(t -> allowedTrace(t, user))
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))) .map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
.toList(); .collect(toList());
model.addObject("traces", traces); model.addObject("traces", traces);
return model; return model;
} }
private boolean allowedTrace(HttpExchange t, String username) { private boolean allowedTrace(HttpExchange t, UserDetails user) {
HttpExchange.Request req = t.getRequest(); HttpExchange.Request req = t.getRequest();
boolean allowed = true; boolean allowed = true;
/* do not show certain traces to other users in a classroom setup */ /* do not show certain traces to other users in a classroom setup */
if (req.getUri().getPath().contains("/files") && !req.getUri().getPath().contains(username)) { if (req.getUri().getPath().contains("/files")
&& !req.getUri().getPath().contains(user.getUsername())) {
allowed = false; allowed = false;
} else if (req.getUri().getPath().contains("/landing") } else if (req.getUri().getPath().contains("/landing")
&& req.getUri().getQuery() != null && req.getUri().getQuery() != null
&& req.getUri().getQuery().contains("uniqueCode") && req.getUri().getQuery().contains("uniqueCode")
&& !req.getUri().getQuery().contains(StringUtils.reverse(username))) { && !req.getUri().getQuery().contains(StringUtils.reverse(user.getUsername()))) {
allowed = false; allowed = false;
} }
@ -91,7 +95,7 @@ public class Requests {
} }
private String path(HttpExchange t) { private String path(HttpExchange t) {
return t.getRequest().getUri().getPath(); return (String) t.getRequest().getUri().getPath();
} }
private String toJsonString(HttpExchange t) { private String toJsonString(HttpExchange t) {

View File

@ -22,12 +22,10 @@
package org.owasp.webgoat.webwolf.requests; package org.owasp.webgoat.webwolf.requests;
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.contains;
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.endsWith;
import com.google.common.collect.EvictingQueue; import com.google.common.collect.EvictingQueue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.web.exchanges.HttpExchange; import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
@ -38,51 +36,34 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
* @author nbaars * @author nbaars
* @since 8/13/17. * @since 8/13/17.
*/ */
@Slf4j
public class WebWolfTraceRepository implements HttpExchangeRepository { public class WebWolfTraceRepository implements HttpExchangeRepository {
private enum MatchingMode {
CONTAINS,
ENDS_WITH,
EQUALS;
}
record Exclusion(String path, MatchingMode mode) {
public boolean matches(String path) {
return switch (mode) {
case CONTAINS -> path.contains(this.path);
case ENDS_WITH -> path.endsWith(this.path);
case EQUALS -> path.equals(this.path);
};
}
public static Exclusion contains(String exclusionPattern) {
return new Exclusion(exclusionPattern, MatchingMode.CONTAINS);
}
public static Exclusion endsWith(String exclusionPattern) {
return new Exclusion(exclusionPattern, MatchingMode.ENDS_WITH);
}
}
private final EvictingQueue<HttpExchange> traces = EvictingQueue.create(10000); private final EvictingQueue<HttpExchange> traces = EvictingQueue.create(10000);
private final List<Exclusion> exclusionList = private final List<String> exclusionList =
List.of( List.of(
contains("/tmpdir"), "/tmpdir",
contains("/home"), "/home",
endsWith("/files"), "/files",
contains("/images/"), "/images/",
contains("/js/"), "/favicon.ico",
contains("/webjars/"), "/js/",
contains("/requests"), "/webjars/",
contains("/css/"), "/requests",
contains("/mail")); "/css/",
"/mail");
@Override @Override
public List<HttpExchange> findAll() { public List<HttpExchange> findAll() {
return List.of();
}
public List<HttpExchange> findAllTraces() {
return new ArrayList<>(traces); return new ArrayList<>(traces);
} }
private boolean isInExclusionList(String path) { private boolean isInExclusionList(String path) {
return exclusionList.stream().anyMatch(e -> e.matches(path)); return exclusionList.stream().anyMatch(e -> path.contains(e));
} }
@Override @Override

View File

@ -1,12 +1,10 @@
server.error.include-stacktrace=always server.error.include-stacktrace=always
server.error.path=/error.html server.error.path=/error.html
server.servlet.context-path=${WEBGOAT_CONTEXT:/WebGoat} server.servlet.context-path=/WebGoat
server.servlet.session.persistent=false server.servlet.session.persistent=false
server.port=${WEBGOAT_PORT:8080} server.port=${webgoat.port:8080}
server.address=${WEBGOAT_HOST:127.0.0.1} server.address=${webgoat.host}
webgoat.host=${WEBGOAT_HOST:127.0.0.1} webgoat.host=${WEBGOAT_HOST:127.0.0.1}
webgoat.port=${WEBGOAT_PORT:8080}
webgoat.context=${WEBGOAT_CONTEXT:/WebGoat}
spring.application.name=WebGoat spring.application.name=WebGoat
server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12} server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12}
@ -29,10 +27,9 @@ logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=INFO
logging.level.org.springframework.web=INFO logging.level.org.springframework.web=INFO
logging.level.org.springframework=INFO logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=INFO logging.level.org.springframework.boot.devtools=INFO
logging.level.org.owasp=INFO logging.level.org.owasp=DEBUG
logging.level.org.owasp.webgoat=INFO logging.level.org.owasp.webgoat=DEBUG
logging.level.org.hidbernate.SQL=INFO logging.level.org.hidbernate.SQL=DEBUG
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/ webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/ webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
@ -43,12 +40,10 @@ webgoat.feedback.address=webgoat@owasp.org
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A> webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en webgoat.default.language=en
webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path}
webwolf.host=${WEBWOLF_HOST:127.0.0.1} webwolf.host=${WEBWOLF_HOST:127.0.0.1}
webwolf.port=${WEBWOLF_PORT:9090} webwolf.port=${WEBWOLF_PORT:9090}
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf} webwolf.url=http://${webwolf.host}:${webwolf.port}
webwolf.url=http://${WEBWOLF_HOST:127.0.0.1}:${WEBWOLF_PORT:9090}${WEBWOLF_CONTEXT:/WebWolf}
webwolf.landingpage.url=${webwolf.url}/landing webwolf.landingpage.url=${webwolf.url}/landing
webwolf.mail.url=${webwolf.url}/mail webwolf.mail.url=${webwolf.url}/mail
@ -67,6 +62,3 @@ exclude.lessons=${EXCLUDE_LESSONS:none,none}
management.health.db.enabled=true management.health.db.enabled=true
management.endpoint.health.show-details=always management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=env, health,configprops management.endpoints.web.exposure.include=env, health,configprops
spring.security.oauth2.client.registration.github.client-id=${WEBGOAT_OAUTH_CLIENTID:dummy}
spring.security.oauth2.client.registration.github.client-secret=${WEBGOAT_OAUTH_CLIENTSECRET:dummy}

View File

@ -1,13 +1,10 @@
server.error.include-stacktrace=always server.error.include-stacktrace=always
server.error.path=/error.html server.error.path=/error.html
server.servlet.context-path=${webwolf.context} server.port=${webwolf.port:9090}
server.port=${webwolf.port}
server.address=${webwolf.host} server.address=${webwolf.host}
spring.application.name=WebWolf spring.application.name=WebWolf
webwolf.host=${WEBWOLF_HOST:127.0.0.1} webwolf.host=${WEBWOLF_HOST:127.0.0.1}
webwolf.port=${WEBWOLF_PORT:9090}
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
management.server.port=-1 management.server.port=-1
server.servlet.session.cookie.name=WEBWOLFSESSION server.servlet.session.cookie.name=WEBWOLFSESSION
@ -50,6 +47,3 @@ spring.jackson.serialization.write-dates-as-timestamps=false
#For static file refresh ... and faster dev :D #For static file refresh ... and faster dev :D
spring.devtools.restart.additional-paths=webwolf/src/main/resources/static/ spring.devtools.restart.additional-paths=webwolf/src/main/resources/static/
spring.security.oauth2.client.registration.github.client-id=${WEBWOLF_OAUTH_CLIENTID:dummy}
spring.security.oauth2.client.registration.github.client-secret=${WEBWOLF_OAUTH_CLIENTSECRET:dummy}

View File

@ -63,4 +63,4 @@ CREATE TABLE CONTAINER.EMAIL(
TITLE VARCHAR(255) TITLE VARCHAR(255)
); );
ALTER TABLE CONTAINER.EMAIL ALTER COLUMN ID RESTART WITH 2; ALTER TABLE CONTAINER.EMAIL ALTER COLUMN ID RESTART WITH 2;

View File

@ -1,3 +1,4 @@
ALTER TABLE CONTAINER.ASSIGNMENT ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1); ALTER TABLE CONTAINER.ASSIGNMENT ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1);
ALTER TABLE CONTAINER.LESSON_TRACKER ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1); ALTER TABLE CONTAINER.LESSON_TRACKER ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1);
ALTER TABLE CONTAINER.USER_TRACKER ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1); ALTER TABLE CONTAINER.USER_TRACKER ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1);

View File

@ -53,7 +53,7 @@ reset.lesson=Reset lesson
sign.in=Sign in sign.in=Sign in
register.new=or register yourself as a new user register.new=or register yourself as a new user
sign.up=Sign up sign.up=Sign up
register.title=Register register.title=Register
searchmenu=Search lesson searchmenu=Search lesson
@ -66,7 +66,7 @@ security.enabled=Security enabled, you can try the previous challenges and see t
security.disabled=Security enabled, you can try the previous challenges and see the effect! security.disabled=Security enabled, you can try the previous challenges and see the effect!
termsofuse=Terms of use termsofuse=Terms of use
register.condition.1=While running this program your machine will be extremely vulnerable to attack.\ register.condition.1=While running this program your machine will be extremely vulnerable to attack.\
You should disconnect from the Internet while using this program. WebGoat's default configuration binds to localhost to minimize the exposure. You should disconnect from the Internet while using this program. WebGoat's default configuration binds to localhost to minimize the exposure.
register.condition.2=This program is for educational purposes only. If you attempt \ register.condition.2=This program is for educational purposes only. If you attempt \
these techniques without authorization, you are very likely to get caught. If \ these techniques without authorization, you are very likely to get caught. If \
you are caught engaging in unauthorized hacking, most companies will fire you. \ you are caught engaging in unauthorized hacking, most companies will fire you. \

View File

@ -37,4 +37,5 @@ username=Benutzername
password=Passwort password=Passwort
password.confirm=Wiederhohl Passwort password.confirm=Wiederhohl Passwort
sign.up=Anmelden sign.up=Anmelden
register.title=Registrieren register.title=Registrieren

View File

@ -1,50 +0,0 @@
lesson.completed=Felicidades. Has completado con éxito esta lección.
assignment.solved=Felicidades. Has completado con éxito la tarea.
assignment.not.solved=Lo siento, la solución no es correcta. Por favor, inténtalo de nuevo.
RestartLesson=Reiniciar esta lección
SolutionVideos=Videos de la solución
ErrorGenerating=Error generando
InvalidData=Datos inválidos
Go!=!Vamos!
password=Contraseña
password.confirm=Confirmar contraseña
username=Nombre de usuario
logged_out=Has cerrado sesión correctamente.
invalid_username_password=Nombre de usuario y contraseña inválidos.
login.page.title=Página de inicio de sesión
accounts.build.in=Las siguientes cuentas están integradas en WebGoat
accounts.table.account=Cuenta
accounts.table.user=Usuario
accounts.table.password=Contraseña
logout=Cerrar sesión
version=Versión
build=Compilación
report.card=Informe
about=Acerca de WebGoat
contact=Contáctanos
show.hints=Mostrar pistas
lesson.overview=Descripción de la lección
reset.lesson=Restablecer lección
sign.in=Iniciar sesión
register.new=o regístrate como un nuevo usuario
sign.up=Registrarse
register.title=Registro
searchmenu=Búsqueda de lecciones
not.empty=Este campo es obligatorio.
username.size=Por favor, utiliza entre 6 y 10 caracteres.
username.duplicate=El usuario ya existe.
password.size=La contraseña debe contener al menos 6 caracteres.
password.diff=Las contraseñas no coinciden.
security.enabled=Seguridad habilitada, puedes probar los desafíos anteriores y ver el efecto.
security.disabled=Seguridad deshabilitada, puedes probar los desafíos anteriores y ver el efecto.
termsofuse=Términos de uso
register.condition.1=Mientras ejecutas este programa, tu máquina será extremadamente vulnerable a ataques.\
Deberías desconectarte de Internet mientras usas este programa. La configuración predeterminada de WebGoat se une a localhost para minimizar la exposición.
register.condition.2=Este programa es solo con fines educativos. Si intentas \
estas técnicas sin autorización, es muy probable que te descubran. Si \
te descubren participando en hacking no autorizado, la mayoría de las empresas te despedirán. \
Alegar que estabas realizando investigación de seguridad no funcionará, ya que eso es lo \
primero que afirman todos los hackers.
terms.agree=Aceptar los términos y condiciones

View File

@ -59,4 +59,4 @@ register.condition.1=Wanneer u WebGoat runt op uw computer, bent u kwetsbaar voo
Zorg dat u geen verbinding heeft met internet en dat toegang tot WebGoat alleen lokaal mogelijk is om het aanvalsoppervlak te verkleinen. Zorg dat u geen verbinding heeft met internet en dat toegang tot WebGoat alleen lokaal mogelijk is om het aanvalsoppervlak te verkleinen.
register.condition.2=WebGoat is bedoeld als educatieve applicatie op het gebied van secure software development. \ register.condition.2=WebGoat is bedoeld als educatieve applicatie op het gebied van secure software development. \
Gebruik wat u leert om applicaties beter te maken en niet om zonder toestemming applicaties te schaden. \ Gebruik wat u leert om applicaties beter te maken en niet om zonder toestemming applicaties te schaden. \
In dat laatste geval loopt u risico op rechtsvervoling en ontslag. In dat laatste geval loopt u risico op rechtsvervoling en ontslag.

View File

@ -1,11 +0,0 @@
== Restablecimiento de contraseña con autenticación de dos factores (2FA)
Un excelente ejemplo de elusión de autenticación es (https://henryhoggard.co.uk/blog/Paypal-2FA-Bypass). El usuario no pudo recibir un SMS con un código, así que optó por un método alternativo que implicaba preguntas de seguridad. Utilizando un proxy, eliminó por completo los parámetros y tuvo éxito.
image::images/paypal-2fa-bypass.png[Paypal 2FA bypass,1397,645,style="lesson-image"]
=== El escenario
Cuando restableces tu contraseña desde un lugar o dispositivo no reconocido por tu proveedor, te solicitarán responder a las preguntas de seguridad que configuraste. El inconveniente adicional es que estas preguntas de seguridad también están almacenadas en otro dispositivo, que no tienes contigo y del cual no recuerdas las respuestas.
Ya has proporcionado tu nombre de usuario/correo electrónico y has optado por el método de verificación alternativo.

View File

@ -1,15 +0,0 @@
== Elusion de Autenticación
En el contexto de elusiones de autenticación, los atacantes realizan manipulaciones en el sistema con el objetivo de crear las condiciones necesarias para evadir los mecanismos de autenticación. Estas manipulaciones pueden implicar cambios en la configuración o la lógica del sistema, con el fin de aprovechar posibles fallos y eludir las medidas de seguridad establecidas.
=== Entradas Ocultas
Una estrategia básica implica confiar en una entrada que se encuentra oculta en la página web o en el Modelo de Objetos del Documento (DOM).
=== Eliminación de Parámetros
A veces, si un atacante no conoce el valor correcto de un parámetro en la solicitud web, puede optar por eliminarlo por completo para observar las consecuencias.
=== Navegación Forzada
Si una sección de un sitio no está adecuadamente protegida por la configuración, esa sección del sitio puede ser accedida mediante adivinanzas/fuerza bruta.

View File

@ -1,7 +0,0 @@
=== Más Contenido, También Videos ...
Puedes estructurar y dar formato al contenido como prefieras. Incluso puedes incluir videos si lo deseas (aunque puede depender del soporte del navegador). Tal vez prefieras que esté más relacionado con la seguridad de las aplicaciones web que el contenido de este.
video::video/sample-video.m4v[width=480,start=5]
see http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#videos for more detail on video syntax

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