Compare commits
89 Commits
Author | SHA1 | Date | |
---|---|---|---|
27f23fea19 | |||
9bd7a81435 | |||
08ccb069df | |||
2357651570 | |||
b25caa5c2f | |||
9c354d5699 | |||
84029345b4 | |||
a0ca199cdc | |||
2058298e2d | |||
17acef57b4 | |||
d913967ec5 | |||
87edc7d1db | |||
ac7a9c7863 | |||
2803ef45e4 | |||
5357a65e05 | |||
d343c60781 | |||
98acc1f55a | |||
f99888e61b | |||
29dda49190 | |||
369be6f688 | |||
d5f869c006 | |||
a9caaabb47 | |||
fb2ff01775 | |||
89ecf1d2ad | |||
1b66a742da | |||
a831da5886 | |||
fd5189c102 | |||
ae261f201a | |||
3d651526be | |||
c7c2a61f65 | |||
b7f657ad2c | |||
7fea42afe9 | |||
826887cc83 | |||
62db86246e | |||
f7a9995fe0 | |||
d6c4e8e454 | |||
26628a39e1 | |||
2d26a318d1 | |||
dc16e9a0fb | |||
88a321c268 | |||
8450c5a5be | |||
ba75e10efd | |||
d1e44bbc98 | |||
5a4974f3c2 | |||
4fc1d1fb22 | |||
084a105c69 | |||
7485cb8b9a | |||
c312ae989f | |||
5fde7fbf29 | |||
a32c56bfc7 | |||
6fd3eb57eb | |||
1743d017ff | |||
2b2638943b | |||
45c26d8aaf | |||
be30551850 | |||
49862f6b90 | |||
4009785bb8 | |||
d8341c86a1 | |||
055578893d | |||
b89ebd70ad | |||
7b81247dd1 | |||
3bc2e57c9c | |||
c3ec168d59 | |||
a67fbf5a5a | |||
3365c8d447 | |||
368c046779 | |||
8749137d1e | |||
786cabd251 | |||
dda8b10f55 | |||
d6ca083529 | |||
7c92d625dd | |||
4ba818533c | |||
a9b1fd66b8 | |||
8f6e47e6d4 | |||
61de52840f | |||
fd3eb2451c | |||
32fa1ec0a6 | |||
ad00119b0d | |||
25f49537e7 | |||
8cb735e623 | |||
155a40aab4 | |||
6c4ddbbaad | |||
d704f69879 | |||
3b2b613aa5 | |||
934ba3e496 | |||
8ec718c1ef | |||
1df7ca61a3 | |||
75398feca0 | |||
76a2365abf |
1
.github/dependabot.yml
vendored
1
.github/dependabot.yml
vendored
@ -12,4 +12,3 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
|
54
.github/workflows/branchbuild.txt
vendored
Normal file
54
.github/workflows/branchbuild.txt
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
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 }}
|
40
.github/workflows/build.yml
vendored
40
.github/workflows/build.yml
vendored
@ -1,19 +1,17 @@
|
||||
name: "Pull requests build"
|
||||
name: "Main / Pull requests build"
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.txt'
|
||||
- 'LICENSE'
|
||||
- 'docs/**'
|
||||
branches: [main]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
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'
|
||||
)
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
@ -21,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
@ -34,27 +32,3 @@ jobs:
|
||||
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.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 }}
|
||||
|
29
.github/workflows/pre-commit.yaml
vendored
Normal file
29
.github/workflows/pre-commit.yaml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
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()
|
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@ -8,13 +8,15 @@ jobs:
|
||||
if: github.repository == 'WebGoat/WebGoat'
|
||||
name: Release WebGoat
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
environment:
|
||||
name: release
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
@ -44,7 +46,7 @@ jobs:
|
||||
files: |
|
||||
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
|
||||
body: |
|
||||
## Version ${{ steps.tag.outputs.tag }}
|
||||
## Version ${{ github.ref_name }}
|
||||
|
||||
### New functionality
|
||||
|
||||
@ -54,7 +56,7 @@ jobs:
|
||||
|
||||
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
|
||||
|
||||
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ steps.tag.outputs.tag }}...${{ steps.tag.outputs.tag }}
|
||||
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
|
||||
|
||||
|
||||
## Contributors
|
||||
@ -72,26 +74,26 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: "Set up QEMU"
|
||||
uses: docker/setup-qemu-action@v2.1.0
|
||||
uses: docker/setup-qemu-action@v2.2.0
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: "Set up Docker Buildx"
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: "Login to dockerhub"
|
||||
uses: docker/login-action@v2.2.0
|
||||
uses: docker/login-action@v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: "Build and push WebGoat"
|
||||
uses: docker/build-push-action@v4.1.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64, linux/arm64, linux/arm/v7
|
||||
platforms: linux/amd64, linux/arm64
|
||||
tags: |
|
||||
webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }}
|
||||
webgoat/webgoat:latest
|
||||
@ -99,7 +101,7 @@ jobs:
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
|
||||
- name: "Build and push WebGoat desktop"
|
||||
uses: docker/build-push-action@v4.1.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile_desktop
|
||||
@ -121,7 +123,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
@ -145,4 +147,3 @@ jobs:
|
||||
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
title: ${{ github.event.commits[0].message }}
|
||||
target_branch: main
|
||||
|
||||
|
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@ -23,14 +23,14 @@ jobs:
|
||||
# Uses an default action to checkout the code
|
||||
- uses: actions/checkout@v3
|
||||
# Uses an action to add Python to the VM
|
||||
- name: Setup Pyton
|
||||
uses: actions/setup-python@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: x64
|
||||
# Uses an action to add JDK 17 to the VM (and mvn?)
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
# send report to forks only due to limits on permission tokens
|
||||
- name: Send report to commit
|
||||
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
|
||||
uses: joonvena/robotframework-reporter-action@v2.1
|
||||
uses: joonvena/robotframework-reporter-action@v2.2
|
||||
with:
|
||||
gh_access_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
report_path: 'robotreport'
|
||||
|
2
.github/workflows/welcome.yml
vendored
2
.github/workflows/welcome.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
if: github.repository == 'WebGoat/WebGoat'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/first-interaction@v1.1.1
|
||||
- uses: actions/first-interaction@v1.3.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'
|
||||
|
28
.pre-commit-config.yaml
Normal file
28
.pre-commit-config.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
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
|
@ -8,7 +8,7 @@ and 2023.01 in the `pom.xml`.
|
||||
### Release notes:
|
||||
|
||||
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of
|
||||
committers.
|
||||
committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main`
|
||||
|
||||
```
|
||||
mvn versions:set
|
||||
|
10
Dockerfile
10
Dockerfile
@ -1,4 +1,4 @@
|
||||
FROM docker.io/eclipse-temurin:19-jre-focal
|
||||
FROM docker.io/eclipse-temurin:21.0.1_12-jre
|
||||
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
|
||||
MAINTAINER "WebGoat team"
|
||||
|
||||
@ -14,6 +14,8 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
|
||||
EXPOSE 8080
|
||||
EXPOSE 9090
|
||||
|
||||
ENV TZ=Europe/Amsterdam
|
||||
|
||||
WORKDIR /home/webgoat
|
||||
ENTRYPOINT [ "java", \
|
||||
"-Duser.home=/home/webgoat", \
|
||||
@ -30,8 +32,4 @@ ENTRYPOINT [ "java", \
|
||||
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||
"-Drunning.in.docker=true", \
|
||||
"-Dwebgoat.host=0.0.0.0", \
|
||||
"-Dwebwolf.host=0.0.0.0", \
|
||||
"-Dwebgoat.port=8080", \
|
||||
"-Dwebwolf.port=9090", \
|
||||
"-jar", "webgoat.jar" ]
|
||||
"-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]
|
||||
|
1
FAQ.md
1
FAQ.md
@ -5,4 +5,3 @@
|
||||
### Integration tests fail
|
||||
|
||||
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.
|
||||
|
||||
|
28
README.md
28
README.md
@ -1,4 +1,4 @@
|
||||
# WebGoat 8: A deliberately insecure Web Application
|
||||
# WebGoat: A deliberately insecure Web Application
|
||||
|
||||
[](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml)
|
||||
[](https://jdk.java.net/)
|
||||
@ -44,19 +44,27 @@ 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
|
||||
```
|
||||
|
||||
If you want to reuse the container, give it a name:
|
||||
For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable.
|
||||
E.g.
|
||||
|
||||
```shell
|
||||
docker run --name webgoat -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 -e TZ=America/Boise webgoat/webgoat
|
||||
```
|
||||
|
||||
As long as you don't remove the container you can use:
|
||||
If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but
|
||||
you can use custom host entries. For example:
|
||||
|
||||
```shell
|
||||
docker start webgoat
|
||||
127.0.0.1 www.webgoat.local www.webwolf.local
|
||||
```
|
||||
|
||||
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
|
||||
Then you can run the container with:
|
||||
|
||||
```shell
|
||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
|
||||
```
|
||||
|
||||
Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/
|
||||
|
||||
## 2. Run using Docker with complete Linux Desktop
|
||||
|
||||
@ -71,7 +79,8 @@ docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
|
||||
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||
|
||||
```shell
|
||||
java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.3.jar
|
||||
export TZ=Europe/Amsterdam # or your timezone
|
||||
java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar
|
||||
```
|
||||
|
||||
Click the link in the log to start WebGoat.
|
||||
@ -80,7 +89,7 @@ Click the link in the log to start WebGoat.
|
||||
|
||||
### Prerequisites:
|
||||
|
||||
* Java 17
|
||||
* Java 17 or 21
|
||||
* Your favorite IDE
|
||||
* Git, or Git support in your IDE
|
||||
|
||||
@ -132,9 +141,10 @@ For specialist only. There is a way to set up WebGoat with a personalized menu.
|
||||
For instance running as a jar on a Linux/macOS it will look like this:
|
||||
|
||||
```Shell
|
||||
export TZ=Europe/Amsterdam # or your timezone
|
||||
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
|
||||
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
|
||||
java -jar target/webgoat-2023.3-SNAPSHOT.jar
|
||||
java -jar target/webgoat-2023.6-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
||||
|
@ -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. Add the parts for showing the flag and providing the correct value for the flag= parameter
|
||||
2.
|
||||
3. Add a flag image to src/main/resources/webgoat/static/css/img
|
||||
2.
|
||||
2. 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
|
||||
4. Add a welcome page to the introduction lesson
|
||||
3. 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)
|
||||
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
|
||||
5. Translate the main labels
|
||||
4. Translate the main labels
|
||||
1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish)
|
||||
2. Translate the label values
|
||||
6. Optionally translate lessons by
|
||||
5. Optionally translate lessons by
|
||||
1. Adding lang specifc adoc files in documentation folder of the lesson
|
||||
2. Adding WebGoatLabels.properties of a specific language if you want to
|
||||
7. Run mvn clean to see if the LabelAndHintIntegration test passes
|
||||
8. Run WebGoat and verify that your own language and the other languages work as expected
|
||||
6. 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
|
||||
|
||||
If you only want to translate more for a certain language, you only need to do step 4-8
|
||||
|
@ -1,5 +1,60 @@
|
||||
# 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
|
||||
|
||||
### New functionality
|
||||
@ -160,4 +215,3 @@ Special thanks to the following contributors providing us with a pull request:
|
||||
And everyone who provided feedback through Github.
|
||||
|
||||
Team WebGoat
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
With this image you have WebGoat and ZAP and a browser available to you in a browser running on Ubuntu.
|
||||
You can start WebGoat and ZAP by opening a terminal and type:
|
||||
|
||||
./start-webgoat.sh
|
||||
./start_webgoat.sh
|
||||
./start_zap.sh
|
||||
|
||||
Happy hacking,
|
||||
|
@ -1,4 +1,3 @@
|
||||
# WebGoat landing page
|
||||
|
||||
Old GitHub page which now redirects to OWASP website.
|
||||
|
||||
|
103
pom.xml
103
pom.xml
@ -5,12 +5,12 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.5</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat</artifactId>
|
||||
<version>2023.5-SNAPSHOT</version>
|
||||
<version>2023.9-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>WebGoat</name>
|
||||
@ -109,30 +109,29 @@
|
||||
|
||||
<properties>
|
||||
<!-- Shared properties with plugins and version numbers across submodules-->
|
||||
<asciidoctorj.version>2.5.3</asciidoctorj.version>
|
||||
<!-- Upgrading needs UI work in WebWolf -->
|
||||
<bootstrap.version>3.3.7</bootstrap.version>
|
||||
<asciidoctorj.version>2.5.10</asciidoctorj.version>
|
||||
<bootstrap.version>5.3.2</bootstrap.version>
|
||||
<cglib.version>3.3.0</cglib.version>
|
||||
<!-- do not update necessary for lesson -->
|
||||
<checkstyle.version>3.3.0</checkstyle.version>
|
||||
<checkstyle.version>3.3.1</checkstyle.version>
|
||||
<commons-collections.version>3.2.1</commons-collections.version>
|
||||
<commons-io.version>2.11.0</commons-io.version>
|
||||
<commons-io.version>2.15.1</commons-io.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<commons-text.version>1.10.0</commons-text.version>
|
||||
<guava.version>31.1-jre</guava.version>
|
||||
<jacoco.version>0.8.10</jacoco.version>
|
||||
<guava.version>32.1.3-jre</guava.version>
|
||||
<jacoco.version>0.8.11</jacoco.version>
|
||||
<java.version>17</java.version>
|
||||
<jaxb.version>2.3.1</jaxb.version>
|
||||
<jjwt.version>0.9.1</jjwt.version>
|
||||
<jose4j.version>0.9.3</jose4j.version>
|
||||
<jquery.version>3.5.1</jquery.version>
|
||||
<jquery.version>3.7.0</jquery.version>
|
||||
<jsoup.version>1.16.1</jsoup.version>
|
||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
|
||||
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
|
||||
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
||||
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
|
||||
<maven-surefire-plugin.version>3.1.0</maven-surefire-plugin.version>
|
||||
<maven-surefire-plugin.version>3.2.1</maven-surefire-plugin.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<pmd.version>3.15.0</pmd.version>
|
||||
@ -140,14 +139,16 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
|
||||
<webdriver.version>5.3.2</webdriver.version>
|
||||
<webgoat.port>8080</webgoat.port>
|
||||
<webwolf.port>9090</webwolf.port>
|
||||
<webdriver.version>5.3.3</webdriver.version>
|
||||
<webgoat.context>/</webgoat.context>
|
||||
<webgoat.sslenabled>false</webgoat.sslenabled>
|
||||
<webjars-locator-core.version>0.53</webjars-locator-core.version>
|
||||
<webwolf.context>/</webwolf.context>
|
||||
<wiremock.version>2.27.2</wiremock.version>
|
||||
<xml-resolver.version>1.2</xml-resolver.version>
|
||||
<xstream.version>1.4.5</xstream.version>
|
||||
<!-- do not update necessary for lesson -->
|
||||
<zxcvbn.version>1.7.0</zxcvbn.version>
|
||||
<zxcvbn.version>1.8.0</zxcvbn.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -200,6 +201,17 @@
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>jwks-rsa</artifactId>
|
||||
<version>0.22.1</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
@ -230,6 +242,11 @@
|
||||
<artifactId>jquery</artifactId>
|
||||
<version>${jquery.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>webjars-locator-core</artifactId>
|
||||
<version>${webjars-locator-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
@ -243,12 +260,12 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.22</version>
|
||||
<version>1.25.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby</artifactId>
|
||||
<version>9.4.2.0</version>
|
||||
<version>9.4.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
@ -310,6 +327,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
|
||||
@ -346,6 +367,15 @@
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>jwks-rsa</artifactId>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
@ -374,6 +404,10 @@
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>webjars-locator-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
@ -478,10 +512,19 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<environmentVariables>
|
||||
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
|
||||
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
|
||||
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
|
||||
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
|
||||
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
|
||||
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
|
||||
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
|
||||
</environmentVariables>
|
||||
<systemPropertyVariables>
|
||||
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
|
||||
</systemPropertyVariables>
|
||||
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
|
||||
<argLine>-Xmx512m</argLine>
|
||||
<includes>org/owasp/webgoat/*Test</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
@ -504,6 +547,7 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
|
||||
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||
@ -521,7 +565,6 @@
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${checkstyle.version}</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
|
||||
@ -532,7 +575,7 @@
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>2.33.0</version>
|
||||
<version>2.41.1</version>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>
|
||||
@ -650,16 +693,15 @@
|
||||
<portNames>
|
||||
<portName>webgoat.port</portName>
|
||||
<portName>webwolf.port</portName>
|
||||
<portName>jmxPort</portName>
|
||||
</portNames>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.bazaarvoice.maven.plugins</groupId>
|
||||
<groupId>org.honton.chas</groupId>
|
||||
<artifactId>process-exec-maven-plugin</artifactId>
|
||||
<version>0.9</version>
|
||||
<version>0.9.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-jar</id>
|
||||
@ -667,8 +709,18 @@
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
<phase>pre-integration-test</phase>
|
||||
|
||||
<configuration>
|
||||
<workingDir>${project.build.directory}</workingDir>
|
||||
<environment>
|
||||
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
|
||||
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
|
||||
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
|
||||
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
|
||||
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
|
||||
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
|
||||
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
|
||||
</environment>
|
||||
<arguments>
|
||||
<argument>java</argument>
|
||||
<argument>-jar</argument>
|
||||
@ -676,8 +728,6 @@
|
||||
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||
<argument>-Dspring.main.banner-mode=off</argument>
|
||||
<argument>-Dwebgoat.port=${webgoat.port}</argument>
|
||||
<argument>-Dwebwolf.port=${webwolf.port}</argument>
|
||||
<argument>--add-opens</argument>
|
||||
<argument>java.base/java.lang=ALL-UNNAMED</argument>
|
||||
<argument>--add-opens</argument>
|
||||
@ -703,7 +753,6 @@
|
||||
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
|
||||
</arguments>
|
||||
<waitForInterrupt>false</waitForInterrupt>
|
||||
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
@ -728,7 +777,6 @@
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>6.5.1</version>
|
||||
<configuration>
|
||||
<failBuildOnCVSS>7</failBuildOnCVSS>
|
||||
<skipProvidedScope>false</skipProvidedScope>
|
||||
@ -777,7 +825,6 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>${jacoco.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>before-unit-test</id>
|
||||
|
@ -12,8 +12,10 @@ Then see security settings and allow the file to run
|
||||
pip3 install virtualenv --user
|
||||
python3 -m virtualenv .venv
|
||||
source .venv/bin/activate
|
||||
pip install robotframework
|
||||
pip install robotframework-SeleniumLibrary
|
||||
pip install webdriver-manager
|
||||
pip install --upgrade robotframework
|
||||
pip install --upgrade robotframework-SeleniumLibrary
|
||||
pip install --upgrade webdriver-manager
|
||||
brew upgrade
|
||||
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!
|
||||
|
@ -2,6 +2,7 @@
|
||||
Documentation Setup WebGoat Robotframework tests
|
||||
Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot
|
||||
Library String
|
||||
Library OperatingSystem
|
||||
|
||||
Suite Setup Initial_Page ${ENDPOINT} ${BROWSER}
|
||||
Suite Teardown Close_Page
|
||||
@ -11,7 +12,7 @@ ${BROWSER} chrome
|
||||
${SLEEP} 100
|
||||
${DELAY} 0.25
|
||||
${ENDPOINT} http://127.0.0.1:8080/WebGoat
|
||||
${ENDPOINT_WOLF} http://127.0.0.1:9090
|
||||
${ENDPOINT_WOLF} http://127.0.0.1:9090/WebWolf
|
||||
${USERNAME} robotuser
|
||||
${PASSWORD} password
|
||||
${HEADLESS} ${FALSE}
|
||||
@ -22,22 +23,25 @@ Initial_Page
|
||||
[Arguments] ${ENDPOINT} ${BROWSER}
|
||||
Log To Console Start WebGoat UI Testing
|
||||
IF ${HEADLESS}
|
||||
Open Browser ${ENDPOINT} ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");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'});add_argument("-headless");add_argument("--start-maximized") alias=webgoat
|
||||
ELSE
|
||||
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
|
||||
END
|
||||
IF ${HEADLESS}
|
||||
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
|
||||
ELSE
|
||||
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
|
||||
END
|
||||
Switch Browser webgoat
|
||||
Maximize Browser Window
|
||||
Set Window Size ${1400} ${1000}
|
||||
Set Window Position ${0} ${0}
|
||||
Set Selenium Speed ${DELAY}
|
||||
Log To Console Start WebWolf UI Testing
|
||||
IF ${HEADLESS}
|
||||
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'});add_argument("-headless");add_argument("--start-maximized") alias=webwolf
|
||||
ELSE
|
||||
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
|
||||
END
|
||||
Switch Browser webwolf
|
||||
Maximize Browser Window
|
||||
Set Window Size ${1400} ${1000}
|
||||
Set Window Position ${400} ${200}
|
||||
Set Window Position ${500} ${0}
|
||||
Set Selenium Speed ${DELAY}
|
||||
|
||||
Close_Page
|
||||
@ -53,6 +57,7 @@ Close_Page
|
||||
*** Test Cases ***
|
||||
|
||||
Check_Initial_Page
|
||||
[Tags] WebGoatTests
|
||||
Switch Browser webgoat
|
||||
Page Should Contain Username
|
||||
Click Button Sign in
|
||||
@ -60,6 +65,7 @@ Check_Initial_Page
|
||||
Click Link /WebGoat/registration
|
||||
|
||||
Check_Registration_Page
|
||||
[Tags] WebGoatTests
|
||||
Page Should Contain Username
|
||||
Input Text username ${USERNAME}
|
||||
Input Text password ${PASSWORD}
|
||||
@ -68,6 +74,7 @@ Check_Registration_Page
|
||||
Click Button Sign up
|
||||
|
||||
Check_Welcome_Page
|
||||
[Tags] WebGoatTests
|
||||
Page Should Contain WebGoat
|
||||
Go To ${ENDPOINT}/login
|
||||
Page Should Contain Username
|
||||
@ -77,6 +84,7 @@ Check_Welcome_Page
|
||||
Page Should Contain WebGoat
|
||||
|
||||
Check_Menu_Page
|
||||
[Tags] WebGoatTests
|
||||
Click Element css=a[category='Introduction']
|
||||
Click Element Introduction-WebGoat
|
||||
CLick Element Introduction-WebWolf
|
||||
@ -93,9 +101,29 @@ Check_Menu_Page
|
||||
|
||||
Check_WebWolf
|
||||
Switch Browser webwolf
|
||||
location should be ${ENDPOINT_WOLF}/WebWolf
|
||||
Go To ${ENDPOINT_WOLF}/mail
|
||||
location should be ${ENDPOINT_WOLF}/login
|
||||
Input Text username ${USERNAME}
|
||||
Input Text password ${PASSWORD}
|
||||
Click Button Sign In
|
||||
Go To ${ENDPOINT_WOLF}/mail
|
||||
Go To ${ENDPOINT_WOLF}/requests
|
||||
Go To ${ENDPOINT_WOLF}/files
|
||||
|
||||
Check_JWT_Page
|
||||
Go To ${ENDPOINT_WOLF}/jwt
|
||||
Click Element token
|
||||
Wait Until Element Is Enabled token 5s
|
||||
Input Text token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
Click Element secretKey
|
||||
Input Text secretKey none
|
||||
Sleep 2s # Pause before reading the result
|
||||
${OUT_VALUE} Get Value xpath=//textarea[@id='token']
|
||||
Log To Console Found token ${OUT_VALUE}
|
||||
${OUT_RESULT} Evaluate "ImuPnHvLdU7ULKfbD4aJU" in """${OUT_VALUE}"""
|
||||
Log To Console Found token ${OUT_RESULT}
|
||||
Capture Page Screenshot
|
||||
|
||||
Check_Files_Page
|
||||
Go To ${ENDPOINT_WOLF}/files
|
||||
Choose File css:input[type="file"] ${CURDIR}/goat.robot
|
||||
Click Button Upload files
|
||||
|
@ -25,7 +25,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("/WebGoat/access-control/users-admin-fix"))
|
||||
.get(url("access-control/users-admin-fix"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_FORBIDDEN);
|
||||
|
||||
@ -40,7 +40,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.body(String.format(userTemplate, this.getUser(), this.getUser()))
|
||||
.post(url("/WebGoat/access-control/users"))
|
||||
.post(url("access-control/users"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK);
|
||||
|
||||
@ -51,15 +51,14 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("/WebGoat/access-control/users-admin-fix"))
|
||||
.get(url("access-control/users-admin-fix"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"Jerry\" }.userHash");
|
||||
|
||||
checkAssignment(
|
||||
url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true);
|
||||
checkAssignment(url("access-control/user-hash-fix"), Map.of("userHash", userHash), true);
|
||||
}
|
||||
|
||||
private void assignment2() {
|
||||
@ -69,18 +68,18 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("/WebGoat/access-control/users"))
|
||||
.get(url("access-control/users"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"Jerry\" }.userHash");
|
||||
|
||||
checkAssignment(url("/WebGoat/access-control/user-hash"), Map.of("userHash", userHash), true);
|
||||
checkAssignment(url("access-control/user-hash"), Map.of("userHash", userHash), true);
|
||||
}
|
||||
|
||||
private void assignment1() {
|
||||
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config");
|
||||
checkAssignment(url("/WebGoat/access-control/hidden-menu"), params, true);
|
||||
checkAssignment(url("access-control/hidden-menu"), params, true);
|
||||
}
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
public void init() {
|
||||
startLesson("CSRF");
|
||||
webwolfFileDir = getWebWolfFileServerLocation();
|
||||
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
|
||||
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
|
||||
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
|
||||
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("csrf/basic-get-flag")));
|
||||
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("csrf/review")));
|
||||
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("csrf/feedback/message")));
|
||||
uploadTrickHtml(
|
||||
"csrf8.html",
|
||||
trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
|
||||
trickHTML8.replace("WEBGOATURL", url("login")).replace("USERNAME", this.getUser()));
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
@ -103,7 +103,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", htmlName, htmlContent.getBytes())
|
||||
.post(webWolfUrl("/WebWolf/fileupload"))
|
||||
.post(webWolfUrl("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -118,7 +118,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
|
||||
.get(webWolfUrl("files/" + this.getUser() + "/" + htmlName))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -136,7 +136,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.header("Referer", webWolfUrl("files/fake.html"))
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract()
|
||||
@ -146,7 +146,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true);
|
||||
checkAssignment(url("csrf/confirm-flag-1"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment4(String goatURL) {
|
||||
@ -163,7 +163,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.header("Referer", webWolfUrl("files/fake.html"))
|
||||
.formParams(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
@ -184,7 +184,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.header("Referer", webWolfUrl("files/fake.html"))
|
||||
.contentType(ContentType.TEXT)
|
||||
.body(
|
||||
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
|
||||
@ -198,7 +198,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
|
||||
params.clear();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
||||
checkAssignment(url("csrf/feedback"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment8(String goatURL) {
|
||||
@ -217,7 +217,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.header("Referer", webWolfUrl("files/fake.html"))
|
||||
.params(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
@ -239,7 +239,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", newCookie)
|
||||
.post(url("/csrf/login"))
|
||||
.post(url("csrf/login"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -253,7 +253,8 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
||||
Overview[] assignments =
|
||||
RestAssured.given()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/service/lessonoverview.mvc"))
|
||||
.relaxedHTTPSValidation()
|
||||
.get(url("service/lessonoverview.mvc"))
|
||||
.then()
|
||||
.extract()
|
||||
.jsonPath()
|
||||
|
@ -22,7 +22,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/challenge/logo"))
|
||||
.get(url("challenge/logo"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -34,14 +34,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
params.put("username", "admin");
|
||||
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
|
||||
|
||||
checkAssignment(url("/WebGoat/challenge/1"), params, true);
|
||||
checkAssignment(url("challenge/1"), params, true);
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(url("/WebGoat/challenge/1"))
|
||||
.post(url("challenge/1"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -50,7 +50,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
||||
checkAssignment(url("challenge/flag"), params, true);
|
||||
|
||||
checkResults("/challenge/1");
|
||||
|
||||
@ -59,7 +59,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/scoreboard-data"))
|
||||
.get(url("scoreboard-data"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -83,7 +83,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(url("/WebGoat/challenge/5"))
|
||||
.post(url("challenge/5"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -92,7 +92,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
||||
checkAssignment(url("challenge/flag"), params, true);
|
||||
|
||||
checkResults("/challenge/5");
|
||||
|
||||
@ -101,7 +101,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/scoreboard-data"))
|
||||
.get(url("scoreboard-data"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -120,7 +120,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/challenge/7/.git"))
|
||||
.get(url("challenge/7/.git"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -132,7 +132,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("email", getUser() + "@webgoat.org")
|
||||
.post(url("/WebGoat/challenge/7"))
|
||||
.post(url("challenge/7"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -144,7 +144,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/mail"))
|
||||
.get(webWolfUrl("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -158,13 +158,13 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
|
||||
.get(url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value())
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
checkAssignment(url("/WebGoat/challenge/flag"), Map.of("flag", flag), true);
|
||||
checkAssignment(url("challenge/flag"), Map.of("flag", flag), true);
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/crypto/encoding/basic"))
|
||||
.get(url("crypto/encoding/basic"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
@ -64,7 +64,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("answer_user", answer_user);
|
||||
params.put("answer_pwd", answer_pwd);
|
||||
checkAssignment(url("/crypto/encoding/basic-auth"), params, true);
|
||||
checkAssignment(url("crypto/encoding/basic-auth"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment3() {
|
||||
@ -72,7 +72,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("answer_pwd1", answer_1);
|
||||
checkAssignment(url("/crypto/encoding/xor"), params, true);
|
||||
checkAssignment(url("crypto/encoding/xor"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment4() throws NoSuchAlgorithmException {
|
||||
@ -82,7 +82,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/crypto/hashing/md5"))
|
||||
.get(url("crypto/hashing/md5"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
@ -92,7 +92,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/crypto/hashing/sha256"))
|
||||
.get(url("crypto/hashing/sha256"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
@ -112,7 +112,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("answer_pwd1", answer_1);
|
||||
params.put("answer_pwd2", answer_2);
|
||||
checkAssignment(url("/WebGoat/crypto/hashing"), params, true);
|
||||
checkAssignment(url("crypto/hashing"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
@ -122,7 +122,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/crypto/signing/getprivate"))
|
||||
.get(url("crypto/signing/getprivate"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
@ -135,7 +135,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("modulus", modulus);
|
||||
params.put("signature", signature);
|
||||
checkAssignment(url("/crypto/signing/verify"), params, true);
|
||||
checkAssignment(url("crypto/signing/verify"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignmentDefaults() {
|
||||
@ -151,6 +151,6 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("secretText", text);
|
||||
params.put("secretFileName", "default_secret");
|
||||
checkAssignment(url("/crypto/secure/defaults"), params, true);
|
||||
checkAssignment(url("crypto/secure/defaults"), params, true);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class DeserializationIntegrationTest extends IntegrationTest {
|
||||
params.put(
|
||||
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
|
||||
}
|
||||
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
|
||||
checkAssignment(url("InsecureDeserialization/task"), params, true);
|
||||
|
||||
checkResults("/InsecureDeserialization/");
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
params.put(
|
||||
"question_3_solution",
|
||||
"Solution 2: The systems security is compromised even if only one goal is harmed.");
|
||||
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
|
||||
checkAssignment(url("cia/quiz"), params, true);
|
||||
checkResults("/cia/");
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("payload", solution);
|
||||
checkAssignment(url("/WebGoat/VulnerableComponents/attack1"), params, true);
|
||||
checkAssignment(url("VulnerableComponents/attack1"), params, true);
|
||||
checkResults("/VulnerableComponents/");
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("username", "CaptainJack");
|
||||
params.put("password", "BlackPearl");
|
||||
checkAssignment(url("/WebGoat/InsecureLogin/task"), params, true);
|
||||
checkAssignment(url("InsecureLogin/task"), params, true);
|
||||
checkResults("/InsecureLogin/");
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("password", "ajnaeliclm^&&@kjn.");
|
||||
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
|
||||
checkAssignment(url("SecurePasswords/assignment"), params, true);
|
||||
checkResults("SecurePasswords/");
|
||||
|
||||
startLesson("AuthBypass");
|
||||
@ -127,7 +127,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
|
||||
checkAssignment(url("auth-bypass/verify-account"), params, true);
|
||||
checkResults("/auth-bypass/");
|
||||
|
||||
startLesson("HttpProxies");
|
||||
@ -138,8 +138,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("x-request-intercepted", "true")
|
||||
.contentType(ContentType.JSON)
|
||||
.get(
|
||||
url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -165,7 +164,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.formParams(params)
|
||||
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
|
||||
.post(url("CrossSiteScripting/phone-home-xss"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -174,12 +173,12 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
params.clear();
|
||||
params.put("successMessage", secretNumber);
|
||||
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
|
||||
checkAssignment(url("ChromeDevTools/dummy"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("number", "24");
|
||||
params.put("network_num", "24");
|
||||
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
|
||||
checkAssignment(url("ChromeDevTools/network"), params, true);
|
||||
|
||||
checkResults("/ChromeDevTools/");
|
||||
}
|
||||
@ -194,7 +193,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(url("/auth-bypass/verify-account"), params, true);
|
||||
checkAssignment(url("auth-bypass/verify-account"), params, true);
|
||||
checkResults("/auth-bypass/");
|
||||
}
|
||||
|
||||
@ -205,7 +204,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("param1", "secr37Value");
|
||||
params.put("param2", "Main");
|
||||
checkAssignment(url("/lesson-template/sample-attack"), params, true);
|
||||
checkAssignment(url("lesson-template/sample-attack"), params, true);
|
||||
checkResults("/lesson-template/");
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,9 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.SneakyThrows;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -19,7 +17,6 @@ import org.junit.jupiter.api.TestFactory;
|
||||
public class IDORIntegrationTest extends IntegrationTest {
|
||||
|
||||
@BeforeEach
|
||||
@SneakyThrows
|
||||
public void init() {
|
||||
startLesson("IDOR");
|
||||
}
|
||||
@ -27,56 +24,63 @@ public class IDORIntegrationTest extends IntegrationTest {
|
||||
@TestFactory
|
||||
Iterable<DynamicTest> testIDORLesson() {
|
||||
return Arrays.asList(
|
||||
dynamicTest("login", () -> loginIDOR()), dynamicTest("profile", () -> profile()));
|
||||
dynamicTest("assignment 2 - login", this::loginIDOR),
|
||||
dynamicTest("profile", this::profile));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void shutdown() throws IOException {
|
||||
public void shutdown() {
|
||||
checkResults("/IDOR");
|
||||
}
|
||||
|
||||
private void loginIDOR() throws IOException {
|
||||
private void loginIDOR() {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username", "tom");
|
||||
params.put("password", "cat");
|
||||
|
||||
checkAssignment(url("/WebGoat/IDOR/login"), params, true);
|
||||
checkAssignment(url("IDOR/login"), params, true);
|
||||
}
|
||||
|
||||
private void profile() {
|
||||
|
||||
// View profile - assignment 3a
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/IDOR/profile"))
|
||||
.get(url("IDOR/profile"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("userId"),
|
||||
CoreMatchers.is("2342384"));
|
||||
|
||||
// Show difference - assignment 3b
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("attributes", "userId,role");
|
||||
checkAssignment(url("/WebGoat/IDOR/diff-attributes"), params, true);
|
||||
checkAssignment(url("IDOR/diff-attributes"), params, true);
|
||||
|
||||
// View profile another way - assignment 4
|
||||
params.clear();
|
||||
params.put("url", "WebGoat/IDOR/profile/2342384");
|
||||
checkAssignment(url("/WebGoat/IDOR/profile/alt-path"), params, true);
|
||||
checkAssignment(url("IDOR/profile/alt-path"), params, true);
|
||||
|
||||
// assignment 5a
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/IDOR/profile/2342388"))
|
||||
.get(url("IDOR/profile/2342388"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
|
||||
// assignment 5b
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
@ -86,7 +90,7 @@ public class IDORIntegrationTest extends IntegrationTest {
|
||||
.body(
|
||||
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
|
||||
+ " \"userId\":\"2342388\"}")
|
||||
.put(url("/WebGoat/IDOR/profile/2342388"))
|
||||
.put(url("IDOR/profile/2342388"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
|
@ -5,7 +5,6 @@ import static io.restassured.RestAssured.given;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
@ -15,34 +14,42 @@ import org.springframework.http.HttpStatus;
|
||||
|
||||
public abstract class IntegrationTest {
|
||||
|
||||
private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
|
||||
private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080");
|
||||
private static String webGoatContext =
|
||||
System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/");
|
||||
|
||||
@Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090");
|
||||
|
||||
@Getter
|
||||
private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
|
||||
private static String webWolfHost = System.getenv().getOrDefault("WEBWOLF_HOST", "127.0.0.1");
|
||||
|
||||
private static boolean useSSL = false;
|
||||
@Getter
|
||||
private static String webGoatHost = System.getenv().getOrDefault("WEBGOAT_HOST", "127.0.0.1");
|
||||
|
||||
private static String webWolfContext =
|
||||
System.getenv().getOrDefault("WEBWOLF_CONTEXT", "/WebWolf/");
|
||||
|
||||
private static boolean useSSL =
|
||||
Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "false"));
|
||||
private static String webgoatUrl =
|
||||
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
|
||||
private static String webWolfUrl =
|
||||
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
|
||||
(useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext;
|
||||
private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext;
|
||||
@Getter private String webGoatCookie;
|
||||
@Getter private String webWolfCookie;
|
||||
@Getter private final String user = "webgoat";
|
||||
|
||||
protected String url(String url) {
|
||||
url = url.replaceFirst("/WebGoat/", "");
|
||||
url = url.replaceFirst("/WebGoat", "");
|
||||
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||
return webgoatUrl + url;
|
||||
}
|
||||
|
||||
protected String webWolfUrl(String url) {
|
||||
url = url.replaceFirst("/WebWolf/", "");
|
||||
url = url.replaceFirst("/WebWolf", "");
|
||||
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||
return webWolfUrl + url;
|
||||
}
|
||||
|
||||
protected String webWolfFileUrl(String fileName) {
|
||||
return webWolfUrl("files") + "/" + getUser() + "/" + fileName;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void login() {
|
||||
String location =
|
||||
@ -231,7 +238,7 @@ public abstract class IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/file-server-location"))
|
||||
.get(webWolfUrl("file-server-location"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -246,7 +253,7 @@ public abstract class IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/server-directory"))
|
||||
.get(url("server-directory"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -259,7 +266,7 @@ public abstract class IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.delete(webWolfUrl("/mail"))
|
||||
.delete(webWolfUrl("mail"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
}
|
||||
|
@ -14,7 +14,10 @@ import io.restassured.RestAssured;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
@ -23,6 +26,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.jose4j.jwk.JsonWebKeySet;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
|
||||
|
||||
@ -40,7 +45,9 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
buyAsTom();
|
||||
|
||||
deleteTom();
|
||||
deleteTomThroughKidClaim();
|
||||
|
||||
deleteTomThroughJkuClaim();
|
||||
|
||||
quiz();
|
||||
|
||||
@ -81,7 +88,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParam("jwt-encode-user", "user")
|
||||
.post(url("/WebGoat/JWT/decode"))
|
||||
.post(url("JWT/decode"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -96,7 +103,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/JWT/secret/gettoken"))
|
||||
.get(url("JWT/secret/gettoken"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -110,7 +117,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParam("token", generateToken(secret))
|
||||
.post(url("/WebGoat/JWT/secret"))
|
||||
.post(url("JWT/secret"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -124,7 +131,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
|
||||
.get(url("JWT/votings/login?user=Tom"))
|
||||
.then()
|
||||
.extract()
|
||||
.cookie("access_token");
|
||||
@ -157,7 +164,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("access_token", replacedToken)
|
||||
.post(url("/WebGoat/JWT/votings"))
|
||||
.post(url("JWT/votings"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -198,7 +205,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Authorization", "Bearer " + replacedToken)
|
||||
.post(url("/WebGoat/JWT/refresh/checkout"))
|
||||
.post(url("JWT/refresh/checkout"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -206,8 +213,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void deleteTom() {
|
||||
|
||||
private void deleteTomThroughKidClaim() {
|
||||
Map<String, Object> header = new HashMap();
|
||||
header.put(Header.TYPE, Header.JWT_TYPE);
|
||||
header.put(
|
||||
@ -232,7 +238,54 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.post(url("/WebGoat/JWT/final/delete?token=" + token))
|
||||
.post(url("JWT/kid/delete?token=" + token))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void deleteTomThroughJkuClaim() throws NoSuchAlgorithmException {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
var jwks = new JsonWebKeySet(new RsaJsonWebKey((RSAPublicKey) keyPair.getPublic()));
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", "jwks.json", jwks.toJson().getBytes())
|
||||
.post(webWolfUrl("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
|
||||
Map<String, Object> header = new HashMap();
|
||||
header.put(Header.TYPE, Header.JWT_TYPE);
|
||||
header.put(JwsHeader.JWK_SET_URL, webWolfFileUrl("jwks.json"));
|
||||
String token =
|
||||
Jwts.builder()
|
||||
.setHeader(header)
|
||||
.setIssuer("WebGoat Token Builder")
|
||||
.setAudience("webgoat.org")
|
||||
.setIssuedAt(Calendar.getInstance().getTime())
|
||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "Tom")
|
||||
.claim("Email", "tom@webgoat.org")
|
||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||
.signWith(SignatureAlgorithm.RS256, keyPair.getPrivate())
|
||||
.compact();
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.post(url("JWT/jku/delete?token=" + token))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -245,6 +298,6 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
params.put("question_0_solution", "Solution 1");
|
||||
params.put("question_1_solution", "Solution 2");
|
||||
|
||||
checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
|
||||
checkAssignment(url("JWT/quiz"), params, true);
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,13 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
startLesson("/PasswordReset");
|
||||
startLesson("PasswordReset");
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
@ -68,7 +69,6 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
// WebWolf
|
||||
var link = getPasswordResetLinkFromLandingPage();
|
||||
|
||||
// WebGoat
|
||||
changePassword(link);
|
||||
checkAssignment(
|
||||
@ -85,7 +85,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/mail"))
|
||||
.get(webWolfUrl("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -119,7 +119,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/requests"))
|
||||
.get(webWolfUrl("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -136,7 +136,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
private void clickForgotEmailLink(String user) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.header("host", String.format("%s:%s", "localhost", getWebWolfPort()))
|
||||
.header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort()))
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("email", user)
|
||||
|
@ -55,7 +55,7 @@ class PathTraversalIT extends IntegrationTest {
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
|
||||
.param("fullName", "../John Doe")
|
||||
.post(url("/WebGoat/PathTraversal/profile-upload"))
|
||||
.post(url("PathTraversal/profile-upload"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -71,7 +71,7 @@ class PathTraversalIT extends IntegrationTest {
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
|
||||
.param("fullNameFix", "..././John Doe")
|
||||
.post(url("/WebGoat/PathTraversal/profile-upload-fix"))
|
||||
.post(url("PathTraversal/profile-upload-fix"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -89,7 +89,7 @@ class PathTraversalIT extends IntegrationTest {
|
||||
"uploadedFileRemoveUserInput",
|
||||
"../test.jpg",
|
||||
Files.readAllBytes(fileToUpload.toPath()))
|
||||
.post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
|
||||
.post(url("PathTraversal/profile-upload-remove-user-input"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -98,7 +98,7 @@ class PathTraversalIT extends IntegrationTest {
|
||||
}
|
||||
|
||||
private void assignment4() throws IOException {
|
||||
var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
|
||||
var uri = "PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
|
||||
RestAssured.given()
|
||||
.urlEncodingEnabled(false)
|
||||
.when()
|
||||
@ -110,7 +110,7 @@ class PathTraversalIT extends IntegrationTest {
|
||||
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
|
||||
|
||||
checkAssignment(
|
||||
url("/WebGoat/PathTraversal/random"),
|
||||
url("PathTraversal/random"),
|
||||
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
|
||||
true);
|
||||
}
|
||||
@ -133,8 +133,10 @@ class PathTraversalIT extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
|
||||
.post(url("/WebGoat/PathTraversal/zip-slip"))
|
||||
.post(url("PathTraversal/zip-slip"))
|
||||
.then()
|
||||
.log()
|
||||
.all()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
|
@ -29,7 +29,7 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(Map.of("flag", "test"))
|
||||
.post(url("/challenge/flag"));
|
||||
.post(url("challenge/flag"));
|
||||
};
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
|
||||
List<? extends Callable<Response>> flagCalls =
|
||||
|
@ -15,11 +15,11 @@ public class SSRFIntegrationTest extends IntegrationTest {
|
||||
params.clear();
|
||||
params.put("url", "images/jerry.png");
|
||||
|
||||
checkAssignment(url("/WebGoat/SSRF/task1"), params, true);
|
||||
checkAssignment(url("SSRF/task1"), params, true);
|
||||
params.clear();
|
||||
params.put("url", "http://ifconfig.pro");
|
||||
|
||||
checkAssignment(url("/WebGoat/SSRF/task2"), params, true);
|
||||
checkAssignment(url("SSRF/task2"), params, true);
|
||||
|
||||
checkResults("/SSRF/");
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
class SessionManagementIT extends IntegrationTest {
|
||||
|
||||
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
|
||||
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
|
||||
|
||||
@Test
|
||||
void hijackSessionTest() {
|
||||
|
@ -16,27 +16,27 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
||||
params.put("password_reg", "password");
|
||||
params.put("email_reg", "someone@microsoft.com");
|
||||
params.put("confirm_password", "password");
|
||||
checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
|
||||
checkAssignmentWithPUT(url("SqlInjectionAdvanced/challenge"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("username_login", "tom");
|
||||
params.put("password_login", "thisisasecretfortomonly");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
|
||||
checkAssignment(url("SqlInjectionAdvanced/challenge_Login"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_6a",
|
||||
"Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from"
|
||||
+ " user_system_data --");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6b", "passW0rD");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
|
||||
checkAssignment(url("SqlInjectionAdvanced/attack6b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
@ -54,7 +54,7 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
||||
params.put(
|
||||
"question_4_solution",
|
||||
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
|
||||
checkAssignment(url("SqlInjectionAdvanced/quiz"), params, true);
|
||||
|
||||
checkResults("/SqlInjectionAdvanced/");
|
||||
}
|
||||
|
@ -34,44 +34,44 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("query", sql_2);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack2"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_3);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack3"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_4_add);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack4"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_5);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack5"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("operator", sql_9_operator);
|
||||
params.put("account", sql_9_account);
|
||||
params.put("injection", sql_9_injection);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true);
|
||||
checkAssignment(url("SqlInjection/assignment5a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("login_count", sql_10_login_count);
|
||||
params.put("userid", sql_10_userid);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true);
|
||||
checkAssignment(url("SqlInjection/assignment5b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("name", sql_11_a);
|
||||
params.put("auth_tan", sql_11_b);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack8"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("name", sql_12_a);
|
||||
params.put("auth_tan", sql_12_b);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack9"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("action_string", sql_13);
|
||||
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
|
||||
checkAssignment(url("SqlInjection/attack10"), params, true);
|
||||
|
||||
checkResults("/SqlInjection/");
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
params.put("field5", "?");
|
||||
params.put("field6", "prep.setString(1,\"\")");
|
||||
params.put("field7", "prep.setString(2,\\\"\\\")");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
|
||||
checkAssignment(url("SqlInjectionMitigations/attack10a"), params, true);
|
||||
|
||||
params.put(
|
||||
"editor",
|
||||
@ -37,18 +37,18 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
+ "} catch (Exception e) {\r\n"
|
||||
+ " System.out.println(\"Oops. Something went wrong!\");\r\n"
|
||||
+ "}");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
|
||||
checkAssignment(url("SqlInjectionMitigations/attack10b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
|
||||
checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true);
|
||||
checkAssignment(url("SqlOnlyInputValidation/attack"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_sql_only_input_validation_on_keywords",
|
||||
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
|
||||
checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true);
|
||||
checkAssignment(url("SqlOnlyInputValidationOnKeywords/attack"), params, true);
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
@ -57,7 +57,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
.contentType(ContentType.JSON)
|
||||
.get(
|
||||
url(
|
||||
"/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname"
|
||||
"SqlInjectionMitigations/servers?column=(case when (true) then hostname"
|
||||
+ " else id end)"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
@ -67,7 +67,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
|
||||
.get(url("SqlInjectionMitigations/servers?column=unknown"))
|
||||
.then()
|
||||
.statusCode(500)
|
||||
.body(
|
||||
@ -78,7 +78,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
|
||||
params.clear();
|
||||
params.put("ip", "104.130.219.202");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true);
|
||||
checkAssignment(url("SqlInjectionMitigations/attack12a"), params, true);
|
||||
|
||||
checkResults();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package org.owasp.webgoat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -11,21 +10,20 @@ import org.junit.jupiter.api.Test;
|
||||
public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() throws IOException {
|
||||
public void runTests() {
|
||||
startLesson("WebWolfIntroduction");
|
||||
|
||||
// Assignment 3
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("email", this.getUser() + "@webgoat.org");
|
||||
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
|
||||
checkAssignment(url("WebWolf/mail/send"), params, false);
|
||||
|
||||
String responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/mail"))
|
||||
.get(webWolfUrl("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -39,7 +37,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
|
||||
params.clear();
|
||||
params.put("uniqueCode", uniqueCode);
|
||||
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);
|
||||
checkAssignment(url("WebWolf/mail"), params, true);
|
||||
|
||||
// Assignment 4
|
||||
RestAssured.given()
|
||||
@ -47,7 +45,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.queryParams(params)
|
||||
.get(url("/WebGoat/WebWolf/landing/password-reset"))
|
||||
.get(url("WebWolf/landing/password-reset"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
RestAssured.given()
|
||||
@ -55,7 +53,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.queryParams(params)
|
||||
.get(webWolfUrl("/landing"))
|
||||
.get(webWolfUrl("landing"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
responseBody =
|
||||
@ -63,7 +61,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/requests"))
|
||||
.get(webWolfUrl("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -72,7 +70,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
assertTrue(responseBody.contains(uniqueCode));
|
||||
params.clear();
|
||||
params.put("uniqueCode", uniqueCode);
|
||||
checkAssignment(url("/WebGoat/WebWolf/landing"), params, true);
|
||||
checkAssignment(url("WebWolf/landing"), params, true);
|
||||
|
||||
checkResults("/WebWolf");
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public class XSSIntegrationTest extends IntegrationTest {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("checkboxAttack1", "value");
|
||||
checkAssignment(url("/CrossSiteScripting/attack1"), params, true);
|
||||
checkAssignment(url("CrossSiteScripting/attack1"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("QTY1", "1");
|
||||
@ -23,11 +23,11 @@ public class XSSIntegrationTest extends IntegrationTest {
|
||||
params.put("QTY4", "1");
|
||||
params.put("field1", "<script>alert('XSS+Test')</script>");
|
||||
params.put("field2", "111");
|
||||
checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true);
|
||||
checkAssignmentWithGet(url("CrossSiteScripting/attack5a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("DOMTestRoute", "start.mvc#test");
|
||||
checkAssignment(url("/CrossSiteScripting/attack6a"), params, true);
|
||||
checkAssignment(url("CrossSiteScripting/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("param1", "42");
|
||||
@ -41,7 +41,7 @@ public class XSSIntegrationTest extends IntegrationTest {
|
||||
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.formParams(params)
|
||||
.post(url("/CrossSiteScripting/phone-home-xss"))
|
||||
.post(url("CrossSiteScripting/phone-home-xss"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
@ -50,7 +50,7 @@ public class XSSIntegrationTest extends IntegrationTest {
|
||||
|
||||
params.clear();
|
||||
params.put("successMessage", secretNumber);
|
||||
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
|
||||
checkAssignment(url("CrossSiteScripting/dom-follow-up"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
@ -73,8 +73,44 @@ public class XSSIntegrationTest extends IntegrationTest {
|
||||
"question_4_solution",
|
||||
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
|
||||
+ " the browser executes.");
|
||||
checkAssignment(url("/CrossSiteScripting/quiz"), params, true);
|
||||
checkAssignment(url("CrossSiteScripting/quiz"), params, true);
|
||||
|
||||
checkResults("/CrossSiteScripting/");
|
||||
params.clear();
|
||||
params.put(
|
||||
"editor",
|
||||
"<%@ taglib uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\" %>"
|
||||
+ "<html>"
|
||||
+ "<head>"
|
||||
+ "<title>Using GET and POST Method to Read Form Data</title>"
|
||||
+ "</head>"
|
||||
+ "<body>"
|
||||
+ "<h1>Using POST Method to Read Form Data</h1>"
|
||||
+ "<table>"
|
||||
+ "<tbody>"
|
||||
+ "<tr>"
|
||||
+ "<td><b>First Name:</b></td>"
|
||||
+ "<td>${e:forHtml(param.first_name)}</td>"
|
||||
+ "</tr>"
|
||||
+ "<tr>"
|
||||
+ "<td><b>Last Name:</b></td>"
|
||||
+ "<td>${e:forHtml(param.last_name)}</td>"
|
||||
+ "</tr>"
|
||||
+ "</tbody>"
|
||||
+ "</table>"
|
||||
+ "</body>"
|
||||
+ "</html>");
|
||||
checkAssignment(url("CrossSiteScripting/attack3"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"editor2",
|
||||
"Policy.getInstance(\"antisamy-slashdot.xml\");"
|
||||
+ "Sammy s = new AntiSamy();"
|
||||
+ "s.scan(newComment,\"\");"
|
||||
+ "CleanResults();"
|
||||
+ "MyCommentDAO.addComment(threadID, userID).getCleanHTML());");
|
||||
checkAssignment(url("CrossSiteScripting/attack4"), params, true);
|
||||
|
||||
checkResults("/CrossSiteScripting");
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
.get(url("service/enable-security.mvc"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
|
||||
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
|
||||
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
|
||||
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
|
||||
checkAssignment(
|
||||
url("/WebGoat/xxe/blind"),
|
||||
url("xxe/blind"),
|
||||
ContentType.XML,
|
||||
"<comment><text>" + getSecret() + "</text></comment>",
|
||||
false);
|
||||
@ -68,7 +68,7 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
}
|
||||
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
|
||||
String dtd7String =
|
||||
dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
|
||||
dtd7.replace("WEBWOLFURL", webWolfUrl("landing")).replace("SECRET", secretFile);
|
||||
|
||||
// upload DTD
|
||||
RestAssured.given()
|
||||
@ -76,7 +76,7 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", "blind.dtd", dtd7String.getBytes())
|
||||
.post(webWolfUrl("/fileupload"))
|
||||
.post(webWolfUrl("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -84,8 +84,8 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
.asString();
|
||||
// upload attack
|
||||
String xxe7String =
|
||||
xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
|
||||
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
|
||||
xxe7.replace("WEBWOLFURL", webWolfUrl("files")).replace("USERNAME", this.getUser());
|
||||
checkAssignment(url("xxe/blind"), ContentType.XML, xxe7String, false);
|
||||
|
||||
// read results from WebWolf
|
||||
String result =
|
||||
@ -93,7 +93,7 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/requests"))
|
||||
.get(webWolfUrl("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
@ -114,10 +114,10 @@ public class XXEIntegrationTest extends IntegrationTest {
|
||||
startLesson("XXE", true);
|
||||
webGoatHomeDirectory = webGoatServerDirectory();
|
||||
webWolfFileServerLocation = getWebWolfFileServerLocation();
|
||||
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
|
||||
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
|
||||
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, true);
|
||||
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, true);
|
||||
checkAssignment(
|
||||
url("/WebGoat/xxe/blind"),
|
||||
url("xxe/blind"),
|
||||
ContentType.XML,
|
||||
"<comment><text>" + getSecret() + "</text></comment>",
|
||||
true);
|
||||
|
@ -6,7 +6,6 @@ import javax.sql.DataSource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.owasp.webgoat.container.lessons.LessonScanner;
|
||||
import org.owasp.webgoat.container.service.RestartLessonService;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -20,7 +19,6 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
public class DatabaseConfiguration {
|
||||
|
||||
private final DataSourceProperties properties;
|
||||
private final LessonScanner lessonScanner;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
|
@ -242,6 +242,7 @@ public class MvcConfiguration implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(localeChangeInterceptor());
|
||||
registry.addInterceptor(new UserInterceptor());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -0,0 +1,53 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -34,6 +34,9 @@ package org.owasp.webgoat.container;
|
||||
import java.io.File;
|
||||
import org.owasp.webgoat.container.session.UserSessionData;
|
||||
import org.owasp.webgoat.container.session.WebSession;
|
||||
import org.owasp.webgoat.container.users.UserRepository;
|
||||
import org.owasp.webgoat.container.users.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -42,6 +45,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
@ -50,6 +55,8 @@ import org.springframework.web.client.RestTemplate;
|
||||
@EnableAutoConfiguration
|
||||
public class WebGoat {
|
||||
|
||||
@Autowired private UserRepository userRepository;
|
||||
|
||||
@Bean(name = "pluginTargetDirectory")
|
||||
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
|
||||
return new File(webgoatHome);
|
||||
@ -58,7 +65,14 @@ public class WebGoat {
|
||||
@Bean
|
||||
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
public WebSession webSession() {
|
||||
return new WebSession();
|
||||
WebGoatUser webGoatUser = null;
|
||||
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
if (principal instanceof WebGoatUser) {
|
||||
webGoatUser = (WebGoatUser) principal;
|
||||
} else if (principal instanceof DefaultOAuth2User) {
|
||||
webGoatUser = userRepository.findByUsername(((DefaultOAuth2User) principal).getName());
|
||||
}
|
||||
return new WebSession(webGoatUser);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -54,32 +54,41 @@ public class WebSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(
|
||||
auth ->
|
||||
auth.requestMatchers(
|
||||
"/css/**",
|
||||
"/images/**",
|
||||
"/js/**",
|
||||
"fonts/**",
|
||||
"/plugins/**",
|
||||
"/registration",
|
||||
"/register.mvc",
|
||||
"/actuator/**")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated());
|
||||
http.formLogin()
|
||||
.loginPage("/login")
|
||||
.defaultSuccessUrl("/welcome.mvc", true)
|
||||
.usernameParameter("username")
|
||||
.passwordParameter("password")
|
||||
.permitAll();
|
||||
http.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
|
||||
http.csrf().disable();
|
||||
|
||||
http.headers().cacheControl().disable();
|
||||
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
|
||||
return http.build();
|
||||
return http.authorizeHttpRequests(
|
||||
auth ->
|
||||
auth.requestMatchers(
|
||||
"/",
|
||||
"/favicon.ico",
|
||||
"/css/**",
|
||||
"/images/**",
|
||||
"/js/**",
|
||||
"fonts/**",
|
||||
"/plugins/**",
|
||||
"/registration",
|
||||
"/register.mvc")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated())
|
||||
.formLogin(
|
||||
login ->
|
||||
login
|
||||
.loginPage("/login")
|
||||
.defaultSuccessUrl("/welcome.mvc", true)
|
||||
.usernameParameter("username")
|
||||
.passwordParameter("password")
|
||||
.permitAll())
|
||||
.oauth2Login(
|
||||
oidc -> {
|
||||
oidc.defaultSuccessUrl("/login-oauth.mvc");
|
||||
oidc.loginPage("/login");
|
||||
})
|
||||
.logout(logout -> logout.deleteCookies("JSESSIONID").invalidateHttpSession(true))
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.headers(headers -> headers.disable())
|
||||
.exceptionHandling(
|
||||
handling ->
|
||||
handling.authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@ -98,7 +107,6 @@ public class WebSecurityConfig {
|
||||
return authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Bean
|
||||
public NoOpPasswordEncoder passwordEncoder() {
|
||||
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
|
||||
|
@ -16,7 +16,7 @@ public class EnvironmentExposure implements ApplicationContextAware {
|
||||
private static ApplicationContext context;
|
||||
|
||||
public static Environment getEnv() {
|
||||
return context.getEnvironment();
|
||||
return (null != context) ? context.getEnvironment() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,12 +1,9 @@
|
||||
package org.owasp.webgoat.container.asciidoc;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.asciidoctor.ast.ContentNode;
|
||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
/**
|
||||
* Usage in asciidoc:
|
||||
@ -26,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
|
||||
@Override
|
||||
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
|
||||
var env = EnvironmentExposure.getEnv();
|
||||
var hostname = determineHost(env.getProperty("webwolf.port"));
|
||||
var hostname = env.getProperty("webwolf.url");
|
||||
var target = (String) attributes.getOrDefault("target", "home");
|
||||
var href = hostname + "/" + target;
|
||||
|
||||
@ -45,29 +42,4 @@ public class WebWolfMacro extends InlineMacroProcessor {
|
||||
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
|
||||
return attributes.values().stream().anyMatch(a -> a.equals("noLink"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the host from the hostname and ports that were used. The purpose is to make it
|
||||
* possible to use the application behind a reverse proxy. For instance in the docker
|
||||
* compose/stack version with webgoat webwolf and nginx proxy. You do not have to use the
|
||||
* indicated hostname, but if you do, you should define two hosts aliases 127.0.0.1
|
||||
* www.webgoat.local www.webwolf.local
|
||||
*/
|
||||
private String determineHost(String port) {
|
||||
HttpServletRequest request =
|
||||
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||
String host = request.getHeader("Host");
|
||||
int semicolonIndex = host.indexOf(":");
|
||||
if (semicolonIndex == -1 || host.endsWith(":80")) {
|
||||
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
|
||||
} else {
|
||||
host = host.substring(0, semicolonIndex);
|
||||
host = host.concat(":").concat(port);
|
||||
}
|
||||
return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : "");
|
||||
}
|
||||
|
||||
protected boolean includeWebWolfContext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,4 @@ public class WebWolfRootMacro extends WebWolfMacro {
|
||||
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
|
||||
super(macroName, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean includeWebWolfContext() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package org.owasp.webgoat.container.session;
|
||||
import java.io.Serializable;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.owasp.webgoat.container.users.WebGoatUser;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
@ -40,13 +39,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
public class WebSession implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4270066103101711560L;
|
||||
private final WebGoatUser currentUser;
|
||||
private WebGoatUser currentUser;
|
||||
private transient Lesson currentLesson;
|
||||
private boolean securityEnabled;
|
||||
|
||||
public WebSession() {
|
||||
this.currentUser =
|
||||
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
public WebSession(WebGoatUser webGoatUser) {
|
||||
this.currentUser = webGoatUser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,8 +3,10 @@ package org.owasp.webgoat.container.users;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -44,4 +46,12 @@ public class RegistrationController {
|
||||
|
||||
return "redirect:/attack";
|
||||
}
|
||||
|
||||
@GetMapping("/login-oauth.mvc")
|
||||
public String registrationOAUTH(Authentication authentication, HttpServletRequest request)
|
||||
throws ServletException {
|
||||
log.info("register oauth user in database");
|
||||
userService.addUser(authentication.getName(), UUID.randomUUID().toString());
|
||||
return "redirect:/welcome.mvc";
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public class AccountVerificationHelper {
|
||||
static {
|
||||
secQuestionStore.put(verifyUserId, userSecQuestions);
|
||||
}
|
||||
|
||||
// end 'data store set up'
|
||||
|
||||
// this is to aid feedback in the attack process and is not intended to be part of the
|
||||
@ -68,6 +69,7 @@ public class AccountVerificationHelper {
|
||||
|
||||
return likely;
|
||||
}
|
||||
|
||||
// end of cheating check ... the method below is the one of real interest. Can you find the flaw?
|
||||
|
||||
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
|
||||
|
@ -29,8 +29,7 @@ import java.util.Random;
|
||||
import org.owasp.webgoat.container.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.container.session.UserSessionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -41,10 +40,9 @@ public class CSRFGetFlag {
|
||||
@Autowired UserSessionData userSessionData;
|
||||
@Autowired private PluginMessages pluginMessages;
|
||||
|
||||
@RequestMapping(
|
||||
@PostMapping(
|
||||
path = "/csrf/basic-get-flag",
|
||||
produces = {"application/json"},
|
||||
method = RequestMethod.POST)
|
||||
produces = {"application/json"})
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke(HttpServletRequest req) {
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
"idor.hints.otherProfile8",
|
||||
"idor.hints.otherProfile9"
|
||||
})
|
||||
public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
public class IDOREditOtherProfile extends AssignmentEndpoint {
|
||||
|
||||
@Autowired private UserSessionData userSessionData;
|
||||
|
||||
@ -69,7 +70,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
// we will persist in the session object for now in case we want to refer back or use it later
|
||||
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
|
||||
if (currentUserProfile.getRole() <= 1
|
||||
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||
return success(this)
|
||||
.feedback("idor.edit.profile.success1")
|
||||
.output(currentUserProfile.profileToMap().toString())
|
||||
@ -77,16 +78,16 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
}
|
||||
|
||||
if (currentUserProfile.getRole() > 1
|
||||
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
return success(this)
|
||||
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||
return failed(this)
|
||||
.feedback("idor.edit.profile.failure1")
|
||||
.output(currentUserProfile.profileToMap().toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
if (currentUserProfile.getRole() <= 1
|
||||
&& !currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||
return success(this)
|
||||
&& !currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||
return failed(this)
|
||||
.feedback("idor.edit.profile.failure2")
|
||||
.output(currentUserProfile.profileToMap().toString())
|
||||
.build();
|
||||
@ -97,7 +98,8 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
.feedback("idor.edit.profile.failure3")
|
||||
.output(currentUserProfile.profileToMap().toString())
|
||||
.build();
|
||||
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
} else if (userSubmittedProfile.getUserId() != null
|
||||
&& userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
return failed(this).feedback("idor.edit.profile.failure4").build();
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -23,8 +24,6 @@
|
||||
package org.owasp.webgoat.lessons.idor;
|
||||
|
||||
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.AssignmentHints;
|
||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
@ -56,9 +55,9 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
|
||||
produces = {"application/json"})
|
||||
@ResponseBody
|
||||
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
||||
Map<String, Object> details = new HashMap<>();
|
||||
|
||||
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
||||
Object obj = userSessionData.getValue("idor-authenticated-as");
|
||||
if (obj != null && obj.equals("tom")) {
|
||||
// going to use session auth to view this one
|
||||
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
|
||||
if (userId != null && !userId.equals(authUserId)) {
|
||||
@ -66,7 +65,8 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
|
||||
UserProfile requestedProfile = new UserProfile(userId);
|
||||
// secure code would ensure there was a horizontal access control check prior to dishing up
|
||||
// the requested profile
|
||||
if (requestedProfile.getUserId().equals("2342388")) {
|
||||
if (requestedProfile.getUserId() != null
|
||||
&& requestedProfile.getUserId().equals("2342388")) {
|
||||
return success(this)
|
||||
.feedback("idor.view.profile.success")
|
||||
.output(requestedProfile.profileToMap().toString())
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -68,7 +69,7 @@ public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint {
|
||||
return failed(this).feedback("idor.view.own.profile.failure2").build();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
return failed(this).feedback("an error occurred with your request").build();
|
||||
return failed(this).output("an error occurred with your request").build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
@ -0,0 +1,70 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons.jwt;
|
||||
package org.owasp.webgoat.lessons.jwt.claimmisuse;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.JwsHeader;
|
||||
@ -38,28 +38,30 @@ import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@AssignmentHints({
|
||||
"jwt-final-hint1",
|
||||
"jwt-final-hint2",
|
||||
"jwt-final-hint3",
|
||||
"jwt-final-hint4",
|
||||
"jwt-final-hint5",
|
||||
"jwt-final-hint6"
|
||||
"jwt-kid-hint1",
|
||||
"jwt-kid-hint2",
|
||||
"jwt-kid-hint3",
|
||||
"jwt-kid-hint4",
|
||||
"jwt-kid-hint5",
|
||||
"jwt-kid-hint6"
|
||||
})
|
||||
public class JWTFinalEndpoint extends AssignmentEndpoint {
|
||||
@RequestMapping("/JWT/kid")
|
||||
public class JWTHeaderKIDEndpoint extends AssignmentEndpoint {
|
||||
|
||||
private final LessonDataSource dataSource;
|
||||
|
||||
private JWTFinalEndpoint(LessonDataSource dataSource) {
|
||||
private JWTHeaderKIDEndpoint(LessonDataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@PostMapping("/JWT/final/follow/{user}")
|
||||
@PostMapping("/follow/{user}")
|
||||
public @ResponseBody String follow(@PathVariable("user") String user) {
|
||||
if ("Jerry".equals(user)) {
|
||||
return "Following yourself seems redundant";
|
||||
@ -68,7 +70,7 @@ public class JWTFinalEndpoint extends AssignmentEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/JWT/final/delete")
|
||||
@PostMapping("/delete")
|
||||
public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
return failed(this).feedback("jwt-invalid-token").build();
|
@ -39,7 +39,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
"access-control.hash.hint9",
|
||||
"access-control.hash.hint10",
|
||||
"access-control.hash.hint11",
|
||||
"access-control.hash.hint12"
|
||||
"access-control.hash.hint12",
|
||||
"access-control.hash.hint13"
|
||||
})
|
||||
public class MissingFunctionACYourHashAdmin extends AssignmentEndpoint {
|
||||
|
||||
|
@ -48,16 +48,19 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
|
||||
private final RestTemplate restTemplate;
|
||||
private String webWolfHost;
|
||||
private String webWolfPort;
|
||||
private String webWolfURL;
|
||||
private final String webWolfMailURL;
|
||||
|
||||
public ResetLinkAssignmentForgotPassword(
|
||||
RestTemplate restTemplate,
|
||||
@Value("${webwolf.host}") String webWolfHost,
|
||||
@Value("${webwolf.port}") String webWolfPort,
|
||||
@Value("${webwolf.url}") String webWolfURL,
|
||||
@Value("${webwolf.mail.url}") String webWolfMailURL) {
|
||||
this.restTemplate = restTemplate;
|
||||
this.webWolfHost = webWolfHost;
|
||||
this.webWolfPort = webWolfPort;
|
||||
this.webWolfURL = webWolfURL;
|
||||
this.webWolfMailURL = webWolfMailURL;
|
||||
}
|
||||
|
||||
@ -67,12 +70,12 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
|
||||
@RequestParam String email, HttpServletRequest request) {
|
||||
String resetLink = UUID.randomUUID().toString();
|
||||
ResetLinkAssignment.resetLinks.add(resetLink);
|
||||
String host = request.getHeader("host");
|
||||
String host = request.getHeader(HttpHeaders.HOST);
|
||||
if (ResetLinkAssignment.TOM_EMAIL.equals(email)
|
||||
&& (host.contains(webWolfPort)
|
||||
|| host.contains(webWolfHost))) { // User indeed changed the host header.
|
||||
&& host.contains(webWolfHost))) { // User indeed changed the host header.
|
||||
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
|
||||
fakeClickingLinkEmail(host, resetLink);
|
||||
fakeClickingLinkEmail(webWolfURL, resetLink);
|
||||
} else {
|
||||
try {
|
||||
sendMailToUser(email, host, resetLink);
|
||||
@ -97,13 +100,13 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
|
||||
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
|
||||
}
|
||||
|
||||
private void fakeClickingLinkEmail(String host, String resetLink) {
|
||||
private void fakeClickingLinkEmail(String webWolfURL, String resetLink) {
|
||||
try {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
HttpEntity httpEntity = new HttpEntity(httpHeaders);
|
||||
new RestTemplate()
|
||||
.exchange(
|
||||
String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink),
|
||||
String.format("%s/PasswordReset/reset/reset-password/%s", webWolfURL, resetLink),
|
||||
HttpMethod.GET,
|
||||
httpEntity,
|
||||
Void.class);
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -27,6 +28,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
|
||||
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
|
||||
@ -44,6 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*
|
||||
*/
|
||||
|
||||
@AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"})
|
||||
@RestController
|
||||
public class SpoofCookieAssignment extends AssignmentEndpoint {
|
||||
|
||||
|
@ -58,7 +58,8 @@ public class LandingAssignment extends AssignmentEndpoint {
|
||||
public ModelAndView openPasswordReset(HttpServletRequest request) throws URISyntaxException {
|
||||
URI uri = new URI(request.getRequestURL().toString());
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
modelAndView.addObject("webwolfUrl", landingPageUrl);
|
||||
modelAndView.addObject(
|
||||
"webwolfLandingPageUrl", landingPageUrl.replace("//landing", "/landing"));
|
||||
modelAndView.addObject("uniqueCode", StringUtils.reverse(getWebSession().getUserName()));
|
||||
|
||||
modelAndView.setViewName("lessons/webwolfintroduction/templates/webwolfPasswordReset.html");
|
||||
|
@ -35,6 +35,6 @@ public class CrossSiteScripting extends Lesson {
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "xss.title";
|
||||
return "4.xss.title";
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -30,12 +31,9 @@ import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
// @RestController
|
||||
@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
|
||||
@RestController
|
||||
@AssignmentHints(
|
||||
value = {
|
||||
"xss-mitigation-3-hint1",
|
||||
@ -60,9 +58,9 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
||||
String lastNameElement =
|
||||
doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
|
||||
|
||||
Boolean includeCorrect = false;
|
||||
Boolean firstNameCorrect = false;
|
||||
Boolean lastNameCorrect = false;
|
||||
boolean includeCorrect = false;
|
||||
boolean firstNameCorrect = false;
|
||||
boolean lastNameCorrect = false;
|
||||
|
||||
if (include.contains("<%@")
|
||||
&& include.contains("taglib")
|
||||
|
@ -22,20 +22,15 @@
|
||||
|
||||
package org.owasp.webgoat.lessons.xss;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.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
|
||||
@RestController
|
||||
@AssignmentHints(value = {"xss-mitigation-4-hint1"})
|
||||
public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
||||
|
||||
@ -44,7 +39,6 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
||||
public AttackResult completed(@RequestParam String editor2) {
|
||||
|
||||
String editor = editor2.replaceAll("\\<.*?>", "");
|
||||
log.debug(editor);
|
||||
|
||||
if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"")
|
||||
|| editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"")
|
||||
@ -54,10 +48,8 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
||||
&& editor.contains("CleanResults")
|
||||
&& editor.contains("MyCommentDAO.addComment(threadID, userID")
|
||||
&& editor.contains(".getCleanHTML());")) {
|
||||
log.debug("true");
|
||||
return success(this).feedback("xss-mitigation-4-success").build();
|
||||
} else {
|
||||
log.debug("false");
|
||||
return failed(this).feedback("xss-mitigation-4-failed").build();
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
* Getting Source
|
||||
* ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
@ -24,7 +25,9 @@ package org.owasp.webgoat.lessons.xss;
|
||||
|
||||
import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CrossSiteScriptingMitigation extends Lesson {
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
@ -33,6 +36,6 @@ public class CrossSiteScriptingMitigation extends Lesson {
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "xss-mitigation.title";
|
||||
return "6.xss-mitigation.title";
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,9 @@ package org.owasp.webgoat.lessons.xss.stored;
|
||||
|
||||
import org.owasp.webgoat.container.lessons.Category;
|
||||
import org.owasp.webgoat.container.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CrossSiteScriptingStored extends Lesson {
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
@ -33,6 +35,6 @@ public class CrossSiteScriptingStored extends Lesson {
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "xss-stored.title";
|
||||
return "5.xss-stored.title";
|
||||
}
|
||||
}
|
||||
|
@ -34,21 +34,15 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RestController
|
||||
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
|
||||
|
||||
// TODO This assignment seems not to be in use in the UI
|
||||
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam String successMessage) {
|
||||
UserSessionData userSessionData = getUserSessionData();
|
||||
|
||||
if (successMessage.equals(userSessionData.getValue("randValue").toString())) {
|
||||
if (successMessage.equals(userSessionData.getValue("randValue"))) {
|
||||
return success(this).feedback("xss-stored-callback-success").build();
|
||||
} else {
|
||||
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>
|
||||
|
@ -72,7 +72,6 @@ public class StoredXssComments extends AssignmentEndpoint {
|
||||
"Can you post a comment, calling webgoat.customjs.phoneHome() ?"));
|
||||
}
|
||||
|
||||
// TODO This assignment seems not to be in use in the UI
|
||||
@GetMapping(
|
||||
path = "/CrossSiteScriptingStored/stored-xss",
|
||||
produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
@ -89,7 +88,6 @@ public class StoredXssComments extends AssignmentEndpoint {
|
||||
return allComments;
|
||||
}
|
||||
|
||||
// TODO This assignment seems not to be in use in the UI
|
||||
@PostMapping("/CrossSiteScriptingStored/stored-xss")
|
||||
@ResponseBody
|
||||
public AttackResult createNewComment(@RequestBody String commentStr) {
|
||||
|
@ -29,9 +29,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.container.session.WebSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@ -43,7 +42,7 @@ public class Ping {
|
||||
|
||||
@Autowired private WebSession webSession;
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
public String logRequest(
|
||||
@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {
|
||||
|
@ -31,20 +31,30 @@ import org.owasp.webgoat.webwolf.WebWolf;
|
||||
import org.springframework.boot.Banner;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
@Slf4j
|
||||
public class StartWebGoat {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder()
|
||||
.parent(ParentConfig.class)
|
||||
.web(WebApplicationType.NONE)
|
||||
.bannerMode(Banner.Mode.OFF)
|
||||
.child(WebGoat.class)
|
||||
.web(WebApplicationType.SERVLET)
|
||||
.sibling(WebWolf.class)
|
||||
.bannerMode(Banner.Mode.OFF)
|
||||
.web(WebApplicationType.SERVLET)
|
||||
.run(args);
|
||||
var parentBuilder =
|
||||
new SpringApplicationBuilder()
|
||||
.parent(ParentConfig.class)
|
||||
.web(WebApplicationType.NONE)
|
||||
.bannerMode(Banner.Mode.OFF);
|
||||
parentBuilder.child(WebWolf.class).web(WebApplicationType.SERVLET).run(args);
|
||||
ApplicationContext webGoatContext =
|
||||
parentBuilder.child(WebGoat.class).web(WebApplicationType.SERVLET).run(args);
|
||||
|
||||
printStartUpMessage(webGoatContext);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
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) {}
|
||||
}
|
@ -22,20 +22,23 @@
|
||||
|
||||
package org.owasp.webgoat.webwolf;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
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 lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import java.util.TimeZone;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.webgoat.webwolf.user.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -52,12 +55,18 @@ import org.springframework.web.servlet.view.RedirectView;
|
||||
@Slf4j
|
||||
public class FileServer {
|
||||
|
||||
private static final DateTimeFormatter dateTimeFormatter =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Value("${webwolf.fileserver.location}")
|
||||
private String fileLocation;
|
||||
|
||||
@Value("${server.address}")
|
||||
private String server;
|
||||
|
||||
@Value("${server.servlet.context-path}")
|
||||
private String contextPath;
|
||||
|
||||
@Value("${server.port}")
|
||||
private int port;
|
||||
|
||||
@ -71,9 +80,11 @@ public class FileServer {
|
||||
}
|
||||
|
||||
@PostMapping(value = "/fileupload")
|
||||
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
|
||||
var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
var destinationDir = new File(fileLocation, user.getUsername());
|
||||
public ModelAndView importFile(
|
||||
@RequestParam("file") MultipartFile myFile, Authentication authentication)
|
||||
throws IOException {
|
||||
String username = authentication.getName();
|
||||
var destinationDir = new File(fileLocation, username);
|
||||
destinationDir.mkdirs();
|
||||
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
|
||||
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
|
||||
@ -83,41 +94,47 @@ public class FileServer {
|
||||
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")
|
||||
public ModelAndView getFiles(HttpServletRequest request) {
|
||||
WebGoatUser user =
|
||||
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
String username = user.getUsername();
|
||||
public ModelAndView getFiles(
|
||||
HttpServletRequest request, Authentication authentication, TimeZone timezone) {
|
||||
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
||||
File destinationDir = new File(fileLocation, username);
|
||||
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
modelAndView.setViewName("files");
|
||||
File changeIndicatorFile = new File(destinationDir, user.getUsername() + "_changed");
|
||||
File changeIndicatorFile = new File(destinationDir, username + "_changed");
|
||||
if (changeIndicatorFile.exists()) {
|
||||
modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess"));
|
||||
}
|
||||
changeIndicatorFile.delete();
|
||||
|
||||
var uploadedFiles = new ArrayList<>();
|
||||
record UploadedFile(String name, String size, String link, String creationTime) {}
|
||||
|
||||
var uploadedFiles = new ArrayList<UploadedFile>();
|
||||
File[] files = destinationDir.listFiles(File::isFile);
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
String size = FileUtils.byteCountToDisplaySize(file.length());
|
||||
String link = String.format("files/%s/%s", username, file.getName());
|
||||
uploadedFiles.add(new UploadedFile(file.getName(), size, link));
|
||||
uploadedFiles.add(
|
||||
new UploadedFile(file.getName(), size, link, getCreationTime(timezone, file)));
|
||||
}
|
||||
}
|
||||
|
||||
modelAndView.addObject("files", uploadedFiles);
|
||||
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
|
||||
modelAndView.addObject(
|
||||
"files",
|
||||
uploadedFiles.stream().sorted(comparing(UploadedFile::creationTime).reversed()).toList());
|
||||
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port + contextPath);
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ package org.owasp.webgoat.webwolf;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import org.owasp.webgoat.container.UserInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
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.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@ -55,6 +57,12 @@ public class MvcConfiguration implements WebMvcConfigurer {
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/login").setViewName("webwolf-login");
|
||||
registry.addViewController("/home").setViewName("home");
|
||||
registry.addViewController("/").setViewName("home");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new UserInterceptor());
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
|
@ -22,6 +22,7 @@
|
||||
package org.owasp.webgoat.webwolf;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webgoat.container.AjaxAuthenticationEntryPoint;
|
||||
import org.owasp.webgoat.webwolf.user.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -46,16 +47,39 @@ public class WebSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(
|
||||
auth -> auth.requestMatchers(HttpMethod.POST, "/fileupload").authenticated());
|
||||
http.authorizeHttpRequests(
|
||||
auth ->
|
||||
auth.requestMatchers(HttpMethod.GET, "/files", "/mail", "/requests").authenticated());
|
||||
http.authorizeHttpRequests().anyRequest().permitAll();
|
||||
http.csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=true");
|
||||
http.formLogin().loginPage("/login").defaultSuccessUrl("/home", true).permitAll();
|
||||
http.logout().permitAll();
|
||||
return http.build();
|
||||
return http.authorizeHttpRequests(
|
||||
auth -> {
|
||||
auth.requestMatchers("/css/**", "/webjars/**", "/favicon.ico", "/js/**", "/images/**")
|
||||
.permitAll();
|
||||
auth.requestMatchers(
|
||||
HttpMethod.GET,
|
||||
"/fileupload/**",
|
||||
"/files/**",
|
||||
"/landing/**",
|
||||
"/PasswordReset/**")
|
||||
.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
|
||||
|
@ -1,11 +1,11 @@
|
||||
package org.owasp.webgoat.webwolf.jwt;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.springframework.util.Base64Utils.decodeFromUrlSafeString;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -103,8 +103,8 @@ public class JWTToken {
|
||||
var builder = JWTToken.builder().encoded(jwt);
|
||||
|
||||
if (token.length >= 2) {
|
||||
var header = new String(decodeFromUrlSafeString(token[0]), UTF_8);
|
||||
var payloadAsString = new String(decodeFromUrlSafeString(token[1]), UTF_8);
|
||||
var header = new String(Base64.getUrlDecoder().decode(token[0]), UTF_8);
|
||||
var payloadAsString = new String(Base64.getUrlDecoder().decode(token[1]), UTF_8);
|
||||
var headers = parse(header);
|
||||
var payload = parse(payloadAsString);
|
||||
builder.header(write(header, headers));
|
||||
|
@ -25,8 +25,8 @@ package org.owasp.webgoat.webwolf.mailbox;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -42,16 +42,16 @@ public class MailboxController {
|
||||
private final MailboxRepository mailboxRepository;
|
||||
|
||||
@GetMapping("/mail")
|
||||
public ModelAndView mail() {
|
||||
UserDetails user =
|
||||
(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
public ModelAndView mail(Authentication authentication, Model model) {
|
||||
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
|
||||
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(username);
|
||||
if (emails != null && !emails.isEmpty()) {
|
||||
modelAndView.addObject("total", emails.size());
|
||||
modelAndView.addObject("emails", emails);
|
||||
}
|
||||
modelAndView.setViewName("mailbox");
|
||||
model.addAttribute("username", username);
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,6 @@
|
||||
|
||||
package org.owasp.webgoat.webwolf.requests;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.time.Instant;
|
||||
@ -33,8 +31,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -64,30 +61,29 @@ public class Requests {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ModelAndView get() {
|
||||
public ModelAndView get(Authentication authentication) {
|
||||
var model = new ModelAndView("requests");
|
||||
var user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
||||
var traces =
|
||||
traceRepository.findAllTraces().stream()
|
||||
.filter(t -> allowedTrace(t, user))
|
||||
traceRepository.findAll().stream()
|
||||
.filter(t -> allowedTrace(t, username))
|
||||
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
|
||||
.collect(toList());
|
||||
.toList();
|
||||
model.addObject("traces", traces);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private boolean allowedTrace(HttpExchange t, UserDetails user) {
|
||||
private boolean allowedTrace(HttpExchange t, String username) {
|
||||
HttpExchange.Request req = t.getRequest();
|
||||
boolean allowed = true;
|
||||
/* do not show certain traces to other users in a classroom setup */
|
||||
if (req.getUri().getPath().contains("/files")
|
||||
&& !req.getUri().getPath().contains(user.getUsername())) {
|
||||
if (req.getUri().getPath().contains("/files") && !req.getUri().getPath().contains(username)) {
|
||||
allowed = false;
|
||||
} else if (req.getUri().getPath().contains("/landing")
|
||||
&& req.getUri().getQuery() != null
|
||||
&& req.getUri().getQuery().contains("uniqueCode")
|
||||
&& !req.getUri().getQuery().contains(StringUtils.reverse(user.getUsername()))) {
|
||||
&& !req.getUri().getQuery().contains(StringUtils.reverse(username))) {
|
||||
allowed = false;
|
||||
}
|
||||
|
||||
@ -95,7 +91,7 @@ public class Requests {
|
||||
}
|
||||
|
||||
private String path(HttpExchange t) {
|
||||
return (String) t.getRequest().getUri().getPath();
|
||||
return t.getRequest().getUri().getPath();
|
||||
}
|
||||
|
||||
private String toJsonString(HttpExchange t) {
|
||||
|
@ -22,10 +22,12 @@
|
||||
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
|
||||
|
||||
@ -36,34 +38,51 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Slf4j
|
||||
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 List<String> exclusionList =
|
||||
private final List<Exclusion> exclusionList =
|
||||
List.of(
|
||||
"/tmpdir",
|
||||
"/home",
|
||||
"/files",
|
||||
"/images/",
|
||||
"/favicon.ico",
|
||||
"/js/",
|
||||
"/webjars/",
|
||||
"/requests",
|
||||
"/css/",
|
||||
"/mail");
|
||||
contains("/tmpdir"),
|
||||
contains("/home"),
|
||||
endsWith("/files"),
|
||||
contains("/images/"),
|
||||
contains("/js/"),
|
||||
contains("/webjars/"),
|
||||
contains("/requests"),
|
||||
contains("/css/"),
|
||||
contains("/mail"));
|
||||
|
||||
@Override
|
||||
public List<HttpExchange> findAll() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
public List<HttpExchange> findAllTraces() {
|
||||
return new ArrayList<>(traces);
|
||||
}
|
||||
|
||||
private boolean isInExclusionList(String path) {
|
||||
return exclusionList.stream().anyMatch(e -> path.contains(e));
|
||||
return exclusionList.stream().anyMatch(e -> e.matches(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,10 +1,12 @@
|
||||
server.error.include-stacktrace=always
|
||||
server.error.path=/error.html
|
||||
server.servlet.context-path=/WebGoat
|
||||
server.servlet.context-path=${WEBGOAT_CONTEXT:/WebGoat}
|
||||
server.servlet.session.persistent=false
|
||||
server.port=${webgoat.port:8080}
|
||||
server.address=${webgoat.host}
|
||||
server.port=${WEBGOAT_PORT:8080}
|
||||
server.address=${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
|
||||
|
||||
server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12}
|
||||
@ -27,9 +29,10 @@ logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.org.springframework=INFO
|
||||
logging.level.org.springframework.boot.devtools=INFO
|
||||
logging.level.org.owasp=DEBUG
|
||||
logging.level.org.owasp.webgoat=DEBUG
|
||||
logging.level.org.hidbernate.SQL=DEBUG
|
||||
logging.level.org.owasp=INFO
|
||||
logging.level.org.owasp.webgoat=INFO
|
||||
logging.level.org.hidbernate.SQL=INFO
|
||||
|
||||
|
||||
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||
webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||
@ -40,10 +43,12 @@ webgoat.feedback.address=webgoat@owasp.org
|
||||
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
|
||||
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
|
||||
webgoat.default.language=en
|
||||
webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path}
|
||||
|
||||
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
|
||||
webwolf.port=${WEBWOLF_PORT:9090}
|
||||
webwolf.url=http://${webwolf.host}:${webwolf.port}
|
||||
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
|
||||
webwolf.url=http://${WEBWOLF_HOST:127.0.0.1}:${WEBWOLF_PORT:9090}${WEBWOLF_CONTEXT:/WebWolf}
|
||||
webwolf.landingpage.url=${webwolf.url}/landing
|
||||
webwolf.mail.url=${webwolf.url}/mail
|
||||
|
||||
@ -62,3 +67,6 @@ exclude.lessons=${EXCLUDE_LESSONS:none,none}
|
||||
management.health.db.enabled=true
|
||||
management.endpoint.health.show-details=always
|
||||
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}
|
||||
|
@ -1,10 +1,13 @@
|
||||
server.error.include-stacktrace=always
|
||||
server.error.path=/error.html
|
||||
server.port=${webwolf.port:9090}
|
||||
server.servlet.context-path=${webwolf.context}
|
||||
server.port=${webwolf.port}
|
||||
server.address=${webwolf.host}
|
||||
spring.application.name=WebWolf
|
||||
|
||||
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
|
||||
webwolf.port=${WEBWOLF_PORT:9090}
|
||||
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
|
||||
|
||||
management.server.port=-1
|
||||
server.servlet.session.cookie.name=WEBWOLFSESSION
|
||||
@ -47,3 +50,6 @@ spring.jackson.serialization.write-dates-as-timestamps=false
|
||||
|
||||
#For static file refresh ... and faster dev :D
|
||||
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}
|
||||
|
@ -1,4 +1,3 @@
|
||||
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.USER_TRACKER ALTER COLUMN ID SET GENERATED BY DEFAULT AS IDENTITY(START WITH 1);
|
||||
|
||||
|
@ -38,4 +38,3 @@ password=Passwort
|
||||
password.confirm=Wiederhohl Passwort
|
||||
sign.up=Anmelden
|
||||
register.title=Registrieren
|
||||
|
||||
|
50
src/main/resources/i18n/messages_es.properties
Normal file
50
src/main/resources/i18n/messages_es.properties
Normal file
@ -0,0 +1,50 @@
|
||||
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
|
@ -0,0 +1,11 @@
|
||||
== 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.
|
@ -0,0 +1,15 @@
|
||||
== 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.
|
@ -0,0 +1,7 @@
|
||||
=== 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
|
@ -23,7 +23,7 @@
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="verify-account-form"
|
||||
method="POST" name="form"
|
||||
successCallback="onBypassResponse"
|
||||
action="/WebGoat/auth-bypass/verify-account">
|
||||
action="auth-bypass/verify-account">
|
||||
<p>Verify Your Account by answering the questions below:</p>
|
||||
|
||||
<p>What is the name of your favorite teacher?</p>
|
||||
@ -43,7 +43,7 @@
|
||||
<form class="attack-form" accept-charset="UNKNOWN" id="change-password-form"
|
||||
method="POST" name="form"
|
||||
successCallback="onBypassResponse"
|
||||
action="/WebGoat/auth-bypass/verify-account"
|
||||
action="auth-bypass/verify-account"
|
||||
style="display:none"><!-- start off hidden -->
|
||||
<p>Please provide a new password for your account</p>
|
||||
|
||||
|
@ -8,4 +8,3 @@ auth-bypass.hints.verify.1=The attack on this is similar to the story referenced
|
||||
auth-bypass.hints.verify.2=You do want to tamper the security question parameters, but not delete them
|
||||
auth-bypass.hints.verify.3=The logic to verify the account does expect 2 security questions to be answered, but there is a flaw in the implementation
|
||||
auth-bypass.hints.verify.4=Have you tried renaming the secQuestion0 and secQuestion1 parameters?
|
||||
|
||||
|
@ -9,7 +9,7 @@ var onViewProfile = function () {
|
||||
console.warn("on view profile activated")
|
||||
webgoat.customjs.jquery.ajax({
|
||||
method: "GET",
|
||||
url: "/WebGoat/IDOR/profile",
|
||||
url: "IDOR/profile",
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
}).then(webgoat.customjs.idorViewProfile);
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
== Restricciones de Campo
|
||||
En la mayoría de los navegadores, el cliente tiene control total o casi total sobre la parte HTML de la página web. Pueden modificar valores o restricciones según sus preferencias.
|
||||
|
||||
=== Tarea
|
||||
Envía una solicitud que eluda las restricciones de los cuatro campos mencionados.
|
@ -0,0 +1,6 @@
|
||||
== Validación
|
||||
|
||||
A menudo, hay algún mecanismo para evitar que los usuarios envíen valores de campo alterados al servidor, como la validación antes del envío. La mayoría de los navegadores populares, como Chrome, no permiten editar scripts durante la ejecución. Tendremos que eludir la validación de alguna otra manera.
|
||||
|
||||
=== Tarea
|
||||
Envía una solicitud que no cumpla con la expresión regular ubicada encima del campo en todos los campos.
|
@ -0,0 +1,9 @@
|
||||
== Concepto
|
||||
|
||||
Los usuarios tienen un gran control sobre la interfaz del usuario de la aplicación web. Pueden modificar el código HTML, y a veces también los scripts. Las aplicaciones que requieren un formato de entrada específico deben validar también los datos en el lado del servidor.
|
||||
|
||||
== Objetivos
|
||||
|
||||
* El usuario debe tener conocimientos básicos de HTML.
|
||||
* El usuario debe poder manipular una solicitud antes de enviarla (con un proxy u otras herramientas).
|
||||
* El usuario tiene que manipular las restricciones de campo y eludir la validación del lado del cliente.
|
@ -18,7 +18,7 @@
|
||||
<div class="container-fluid">
|
||||
<form class="attack-form" accept-charset="UNKNOWN" name="fieldRestrictions"
|
||||
method="POST"
|
||||
action="/WebGoat/BypassRestrictions/FieldRestrictions">
|
||||
action="BypassRestrictions/FieldRestrictions">
|
||||
|
||||
<div class="bypass-input-container"><b>Select field with two possible value</b>
|
||||
<div class="input-group">
|
||||
@ -66,7 +66,7 @@
|
||||
<form class="attack-form" accept-charset="UNKNOWN" name="frontendValidation"
|
||||
id="frontendValidation"
|
||||
method="POST"
|
||||
action="/WebGoat/BypassRestrictions/frontendValidation/"
|
||||
action="BypassRestrictions/frontendValidation"
|
||||
onsubmit="return validate()">
|
||||
<div>
|
||||
<strong>Field 1:</strong> exactly three lowercase characters(^[a-z]{3}$)
|
||||
|
@ -0,0 +1 @@
|
||||
El administrador olvidó dónde se guarda la contraseña, ¿puedes ayudar?
|
@ -0,0 +1 @@
|
||||
¿Puedes iniciar sesión como Larry?
|
@ -0,0 +1 @@
|
||||
¿Puedes iniciar sesión como Tom? Puede ser un poco más difícil que cuando lo hiciste con Larry.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user