Compare commits

..

9 Commits

1151 changed files with 8366 additions and 3941 deletions

View File

@ -1,3 +0,0 @@
**
!/target

View File

@ -12,4 +12,5 @@ ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false ij_formatter_tags_enabled = false
ij_wrap_on_typing = true
ij_java_names_count_to_use_import_on_demand = 999 ij_java_names_count_to_use_import_on_demand = 999

54
.github/workflows/branch_build.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: "Branch build"
on:
push:
branches-ignore:
- main
- develop
- release/*
jobs:
install-notest:
if: "github.repository != 'WebGoat/WebGoat'"
runs-on: ubuntu-latest
name: "Package and linting"
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2
- name: Test with Maven
run: mvn install -DskipTests
testing:
if: "github.repository != 'WebGoat/WebGoat'"
needs: install-notest
runs-on: ubuntu-latest
strategy:
matrix:
args:
- mvn -pl '!webgoat-integration-tests' test
- mvn -pl webgoat-integration-tests test
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2
- name: Test with Maven
run: ${{ matrix.args }}

View File

@ -1,72 +0,0 @@
name: "Build"
on:
pull_request:
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
push:
branches:
- main
- develop
- release/*
tags-ignore:
- '*'
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
jobs:
pr-build:
if: >
github.event_name == 'pull_request' && !github.event.pull_request.draft && (
github.event.action == 'opened' ||
github.event.action == 'reopened' ||
github.event.action == 'synchronize'
)
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.0.5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2-
- name: Build with Maven
run: mvn --no-transfer-progress package
build:
if: github.repository == 'WebGoat/WebGoat' && github.event_name == 'push'
runs-on: ubuntu-latest
name: "Branch build"
steps:
- uses: actions/checkout@v3
- name: set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.0.5
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2-
- name: Test with Maven
run: mvn --no-transfer-progress verify

45
.github/workflows/pr_build.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: "Pull request build"
on:
pull_request:
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
push:
branches:
- main
- release/*
tags-ignore:
- '*'
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
java: [17]
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build with Maven
run: mvn package

View File

@ -11,21 +11,21 @@ jobs:
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2.3.4
- name: "Get tag name" - name: "Get tag name"
id: tag id: tag
uses: dawidd6/action-get-tag@v1 uses: dawidd6/action-get-tag@v1
- name: Set up JDK 15 - name: Set up JDK 15
uses: actions/setup-java@v3 uses: actions/setup-java@v2
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 15 java-version: 15
architecture: x64 architecture: x64
- name: Cache Maven packages - name: Cache Maven packages
uses: actions/cache@v3.0.5 uses: actions/cache@v2.1.7
with: with:
path: ~/.m2 path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@ -38,15 +38,16 @@ jobs:
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: |
mvn --no-transfer-progress versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }} mvn versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }}
mvn --no-transfer-progress install -DskipTests mvn install -DskipTests
- name: "Create release" - name: "Create release"
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
draft: false draft: false
files: | files: |
webgoat/target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar webgoat-server/target/webgoat-server-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
webwolf/target/webwolf-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: | body: |
## Version ${{ steps.tag.outputs.tag }} ## Version ${{ steps.tag.outputs.tag }}
@ -74,37 +75,35 @@ 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.0.0 uses: docker/setup-qemu-action@v1.1.0
with: with:
platforms: all platforms: all
- name: "Set up Docker Buildx" - name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v1
- name: "Login to dockerhub" - name: "Login to dockerhub"
uses: docker/login-action@v2.0.0 uses: docker/login-action@v1.9.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"
uses: docker/build-push-action@v3.0.0 uses: docker/build-push-action@v2.7.0
with: with:
context: ./ context: ./docker
file: ./Dockerfile file: docker/Dockerfile
push: true push: true
platforms: linux/amd64, linux/arm64, linux/arm/v7 platforms: linux/amd64, linux/arm64, linux/arm/v7
tags: | tags: |
webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }} webgoat/goatandwolf:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/webgoat:latest webgoat/goatandwolf:latest
build-args: | build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Image digest" - name: "Image digest"
run: echo ${{ steps.docker_build.outputs.digest }} run: echo ${{ steps.docker_build.outputs.digest }}
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 development version
needs: [ release ] needs: [ release ]
@ -112,15 +111,15 @@ jobs:
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2.3.4
with: with:
ref: develop ref: develop
token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }} token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }}
- name: Set up JDK 17 - name: Set up JDK 15
uses: actions/setup-java@v3 uses: actions/setup-java@v2
with: with:
java-version: 17 java-version: 15
architecture: x64 architecture: x64
- name: Set version to next snapshot - name: Set version to next snapshot

View File

@ -1,32 +0,0 @@
FROM docker.io/eclipse-temurin:17-jdk-focal
RUN useradd -ms /bin/bash webgoat
RUN chgrp -R 0 /home/webgoat
RUN chmod -R g=u /home/webgoat
USER webgoat
COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
EXPOSE 8080
EXPOSE 9090
WORKDIR /home/webgoat
ENTRYPOINT [ "java", \
"-Duser.home=/home/webgoat", \
"-Dfile.encoding=UTF-8", \
"--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=true", \
"-Dwebgoat.host=0.0.0.0", \
"-Dwebwolf.host=0.0.0.0", \
"-Dwebgoat.port=8080", \
"-Dwebwolf.port=9090", \
"-jar", "webgoat.jar" ]

View File

@ -1,6 +1,6 @@
# WebGoat 8: A deliberately insecure Web Application # WebGoat 8: A deliberately insecure Web Application
[![Build](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml) [![Pull request build](https://github.com/WebGoat/WebGoat/actions/workflows/pr_build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/pr_build.yml)
[![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/) [![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/)
[![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/) [![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/)
[![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest) [![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest)
@ -33,15 +33,21 @@ For more details check [the Contribution guide](/CONTRIBUTING.md)
## 1. Run using Docker ## 1. Run 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/goatandwolf).
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. 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:80:8888 -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:v8.2.2
``` ```
The landing page will be located at: http://localhost
WebGoat will be located at: http://localhost:8080/WebGoat
WebWolf will be located at: http://localhost:9090/WebWolf
**Important**: *Change the ports if necessary, for example use `127.0.0.1:7777:9090` to map WebWolf to `http://localhost:7777/WebGoat`*
**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.* **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.*
@ -50,16 +56,19 @@ docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amster
Download the latest WebGoat and WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) Download the latest WebGoat and WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```shell ```shell
java -Dfile.encoding=UTF-8 -jar webgoat-8.2.3.jar java -Dfile.encoding=UTF-8 -jar webgoat-server-8.2.2.jar [--server.port=8080] [--server.address=localhost] [--hsqldb.port=9001]
java -Dfile.encoding=UTF-8 -jar webwolf-8.2.2.jar [--server.port=9090] [--server.address=localhost] [--hsqldb.port=9001]
``` ```
Click the link in the log to start WebGoat. WebGoat will be located at: http://localhost:8080/WebGoat and
WebWolf will be located at: http://localhost:9090/WebWolf (change ports if necessary)
## 3. Run from the sources ## 3. Run from the sources
### Prerequisites: ### Prerequisites:
* Java 17 * Java 17
* Maven > 3.2.1
* Your favorite IDE * Your favorite IDE
* Git, or Git support in your IDE * Git, or Git support in your IDE
@ -74,29 +83,18 @@ Now let's start by compiling the project.
```Shell ```Shell
cd WebGoat cd WebGoat
git checkout <<branch_name>> git checkout <<branch_name>>
# On Linux/Mac: mvn clean install
./mvnw clean install
# On Windows:
./mvnw.cmd clean install
# Using docker or podman, you can than build the container locally
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 8.x is using Spring-Boot.
```Shell ```Shell
# On Linux/Mac: mvn -pl webgoat-server spring-boot:run
./mvnw spring-boot:run
# On Windows:
./mvnw.cmd spring-boot:run
``` ```
... you should be running WebGoat on localhost:8080/WebGoat momentarily ... you should be running webgoat on localhost:8080/WebGoat momentarily
To change the IP address add the following variable to the `WebGoat/webgoat-container/src/main/resources/application.properties file`: To change the IP address add the following variable to the WebGoat/webgoat-container/src/main/resources/application.properties file:
``` ```
server.address=x.x.x.x server.address=x.x.x.x
@ -110,9 +108,9 @@ For instance running as a jar on a Linux/macOS it will look like this:
```Shell ```Shell
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar target/webgoat-8.2.3-SNAPSHOT.jar java -jar webgoat-server/target/webgoat-server-v8.2.2-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 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/goatandwolf
``` ```

View File

@ -4,21 +4,7 @@
### New functionality ### New functionality
- New year's resolution: major refactoring of WebGoat to simplify the setup and improve building times. - Update the Docker startup script, it is now possible to pass `skip-nginx` or set `SKIP_NGINX` as environment variable.
- Move away from multi-project setup:
- This has a huge performance benefit when building the application. Build time locally is now `Total time: 42.469 s` (depends on your local machine of course)
- No longer add Maven dependencies in several places
- H2 no longer needs to run as separate process, which solves the issue of WebWolf sharing and needing to configure the correct database connection.
- More explicit paths in html files to reference `adoc` files, less magic.
- Integrate WebWolf in WebGoat, the setup was way too complicated and needed configuration which could lead to mistakes and a not working application. This also simplifies the Docker configuration as there is only 1 Docker image.
- Add WebWolf button in WebGoat
- Move all lessons into `src/main/resources`
- WebGoat selects a port dynamically when starting. It will still start of port 8080 it will try another port to ease the user experience.
- WebGoat logs URL after startup: `Please browse to http://127.0.0.1:8080/WebGoat to get started...`
- Simplify `Dockerfile` as we no longer need a script to start everything
- Maven build now start WebGoat jar with Maven plugin to make sure we run against the latest build.
- Added `Initializable` interface for a lesson, an assignment can implement this interface to set it up for a specific user and to reset the assignment back to its original state when a reset lesson occurs. See `BlindSendFileAssignment` for an example.
- Integration tests now use the same user. This saves a lot of time as before every test used a different user which triggered the Flyway migration to set up the database schema for the user. This migration took a lot of time.
## Version 8.2.2 ## Version 8.2.2

View File

@ -1,77 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd"> <suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
This suppresses all CVE entries that have a score below CVSS 7. This suppresses false positives identified on spring framework.
]]></notes> ]]></notes>
<cvssBelow>7</cvssBelow> <cpe>cpe:/a:pivotal_software:spring_framework</cpe>
<cve>CVE-2020-5398</cve>
</suppress> </suppress>
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
file name: spring-tx-5.3.21.jar This suppresses false positives identified on spring framework.
]]></notes> ]]></notes>
<sha1>13f4f564024d2f85502c151942307c3ca851a4f7</sha1> <cpe>cpe:/a:redhat:undertow</cpe>
<cve>CVE-2016-1000027</cve> <cve>CVE-2019-14888</cve>
</suppress> </suppress>
<suppress> <suppress base="true">
<notes><![CDATA[ <notes><![CDATA[
file name: spring-core-5.3.21.jar This suppresses false positives identified on spring framework.
]]></notes> ]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-core@.*$</packageUrl> <cpe>cpe:/a:pivotal_software:spring_security</cpe>
<cve>CVE-2016-1000027</cve> <cve>CVE-2018-1258</cve>
</suppress> </suppress>
<suppress> <suppress base="true">
<notes><![CDATA[
file name: spring-aop-5.3.21.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-aop@.*$</packageUrl>
<cve>CVE-2016-1000027</cve>
</suppress>
<suppress>
<notes><![CDATA[
file name: spring-boot-starter-security-2.7.1.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework\.boot/spring\-boot\-starter\-security@.*$</packageUrl>
<cve>CVE-2022-22978</cve>
</suppress>
<suppress>
<notes><![CDATA[
file name: jruby-stdlib-9.2.20.1.jar: jopenssl.jar (shaded: rubygems:jruby-openssl:0.11.0)
]]></notes>
<packageUrl regex="true">^pkg:maven/rubygems/jruby\-openssl@.*$</packageUrl>
<cpe>cpe:/a:jruby:jruby</cpe> <cpe>cpe:/a:jruby:jruby</cpe>
<cpe>cpe:/a:openssl:openssl</cpe> <cve>CVE-2018-1000613</cve>
</suppress> <cve>CVE-2018-1000180</cve>
<suppress> <cve>CVE-2017-18640</cve>
<notes><![CDATA[ <cve>CVE-2011-4838</cve>
file name: xstream-1.4.5.jar </suppress>
]]></notes> <suppress base="true"><!-- vulnerable components lesson -->
<packageUrl regex="true">^pkg:maven/com\.thoughtworks\.xstream/xstream@.*$</packageUrl>
<cpe>cpe:/a:xstream_project:xstream</cpe> <cpe>cpe:/a:xstream_project:xstream</cpe>
<vulnerabilityName>CVE-2013-7285</vulnerabilityName> <cve>CVE-2017-7957</cve>
<vulnerabilityName>CVE-2016-3674</vulnerabilityName> <cve>CVE-2016-3674</cve>
<vulnerabilityName>CVE-2017-7957</vulnerabilityName> <cve>CVE-2020-26217</cve>
<vulnerabilityName>CVE-2020-26217</vulnerabilityName> <cve>CVE-2020-26258</cve>
<vulnerabilityName>CVE-2020-26258</vulnerabilityName> </suppress>
<vulnerabilityName>CVE-2020-26259</vulnerabilityName> <suppress base="true"><!-- webgoat-server -->
<vulnerabilityName>CVE-2021-21341</vulnerabilityName> <cpe>cpe:/a:postgresql:postgresql</cpe>
<vulnerabilityName>CVE-2021-21342</vulnerabilityName> <cve>CVE-2018-10936</cve>
<vulnerabilityName>CVE-2021-21343</vulnerabilityName> </suppress>
<vulnerabilityName>CVE-2021-21344</vulnerabilityName>
<vulnerabilityName>CVE-2021-21345</vulnerabilityName>
<vulnerabilityName>CVE-2021-21346</vulnerabilityName>
<vulnerabilityName>CVE-2021-21347</vulnerabilityName>
<vulnerabilityName>CVE-2021-21348</vulnerabilityName>
<vulnerabilityName>CVE-2021-21349</vulnerabilityName>
<vulnerabilityName>CVE-2021-21350</vulnerabilityName>
<vulnerabilityName>CVE-2021-21351</vulnerabilityName>
<vulnerabilityName>CVE-2021-43859</vulnerabilityName>
</suppress>
<suppress>
<notes><![CDATA[
file name: spring-jcl-5.3.21.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-.*@.*$</packageUrl>
<cve>CVE-2016-1000027</cve>
</suppress>
</suppressions> </suppressions>

1746
config/pmd/pmd-ruleset.xml Normal file

File diff suppressed because it is too large Load Diff

22
docker/Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM eclipse-temurin:17_35-jdk-focal
RUN apt-get update
RUN useradd -ms /bin/bash webgoat
RUN apt-get -y install apt-utils nginx
RUN chgrp -R 0 /home/webgoat
RUN chmod -R g=u /home/webgoat
USER webgoat
COPY --chown=webgoat nginx.conf /etc/nginx/nginx.conf
COPY --chown=webgoat index.html /usr/share/nginx/html/
COPY --chown=webgoat target/webgoat-server-*.jar /home/webgoat/webgoat.jar
COPY --chown=webgoat target/webwolf-*.jar /home/webgoat/webwolf.jar
COPY --chown=webgoat start.sh /home/webgoat
RUN chmod +x /home/webgoat/start.sh
EXPOSE 8080
EXPOSE 9090
WORKDIR /home/webgoat
ENTRYPOINT ["./start.sh"]

13
docker/Readme.md Normal file
View File

@ -0,0 +1,13 @@
# Docker all-in-one image
## Docker build
```shell
docker build --no-cache --build-arg webgoat_version=8.2.0-SNAPSHOT -t webgoat/goatandwolf:latest .
```
## Docker run
```shell
docker run -p 127.0.0.1:80:8888 -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:latest
```

70
docker/index.html Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.p1 {
font-family: Arial, Helvetica, sans-serif;
}
.webgoat {
float: left;
margin-right: 250px;
text-align: center;
}
.webwolf {
float: left;
width: 40%;
height: 40%;
text-align: center;
}
#images {
display: flex;
align-items: center;
justify-content: center;
}
body {
text-align: center;
}
</style>
</head>
<body>
<h1>
<center>
Landing page for WebGoat and WebWolf
</center>
</h1>
<blockquote class="p1">
WebGoat is a deliberately insecure web application maintained by <a href="http://www.owasp.org/">OWASP</a> designed
to teach web
application security lessons.
This program is a demonstration of common server-side application flaws. The
exercises are intended to be used by people to learn about application security and
penetration testing techniques.
</blockquote>
<br/>
<p class="p1">Click on one of the images to go to WebGoat or WebWolf</p>
<br/>
<br/>
<div id="images">
<a href="http://127.0.0.1:8080/WebGoat" title="Open WebGoat" target="_blank"><img class="webgoat"
src="http://127.0.0.1:8080/WebGoat/css/img/logoBG.jpg"></a>
<a href="http://127.0.0.1:9090/WebWolf" title="Open WebWolf" target="_blank"><img class="webwolf"
src="http://127.0.0.1:9090/images/wolf.png"></a>
</div>
</body>
</html>

140
docker/nginx.conf Normal file
View File

@ -0,0 +1,140 @@
error_log /tmp/error.log;
pid /tmp/nginx.pid;
worker_processes 1;
events { worker_connections 1024; }
http {
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
sendfile on;
upstream docker-webgoat {
server 127.0.0.1:8080;
}
upstream docker-webwolf {
server 127.0.0.1:9090;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
server {
listen 8888;
server_name www.webgoat.local;
root /var/www;
access_log /tmp/goataccess.log;
error_log /tmp/goaterror.log;
location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf|mvc|svg|txt|pdf|docx?|xlsx?)$ {
access_log off;
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
location / {
root /usr/share/nginx/html;
index index.html;
add_header Cache-Control no-cache;
expires 0;
}
location /WebGoat {
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
}
server {
listen 8888;
server_name www.webwolf.local;
root /var/www;
access_log /tmp/wolfaccess.log;
error_log /tmp/wolferror.log;
location /WebGoat/PasswordReset/ForgotPassword/create-password-reset-link {
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
location /PasswordReset/reset/reset-password {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /files {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /tmpdir {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /webjars {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /css {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /login {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /images {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /mail {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /upload {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /js {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /landing {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /logout {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /WebWolf {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
}
}

40
docker/pom.xml Normal file
View File

@ -0,0 +1,40 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>webgoat-all-in-one-docker</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.3-SNAPSHOT</version>
</parent>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<copy file="../webgoat-server/target/webgoat-server-${project.version}.jar" tofile="target/webgoat-server-${project.version}.jar"/>
<copy file="../webwolf/target/webwolf-${project.version}.jar" tofile="target/webwolf-${project.version}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,6 +2,22 @@
cd /home/webgoat cd /home/webgoat
function should_start_nginx() {
if [[ -v "${SKIP_NGINX}" ]]; then
return 1
else
for i in "${commandline_args[@]}" ; do [[ $i == "skip-nginx" ]] && return 1 ; done
fi
return 0
}
function nginx() {
if should_start_nginx; then
echo "Starting nginx..."
service nginx start
fi
}
function webgoat() { function webgoat() {
echo "Starting WebGoat...." echo "Starting WebGoat...."
java \ java \
@ -15,9 +31,12 @@ function webgoat() {
--add-opens java.desktop/java.awt.font=ALL-UNNAMED \ --add-opens java.desktop/java.awt.font=ALL-UNNAMED \
--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 \ -jar webgoat.jar --server.address=0.0.0.0 > webgoat.log
-Dwebgoat.host=0.0.0.0 -Dwebwolf.host=0.0.0.0 -Dwebgoat.port=8080 -Dwebwolf.port=9090 \ }
-jar webgoat.jar > webgoat.log
function webwolf() {
echo "Starting WebWolf..."
java -Duser.home=/home/webgoat -Dfile.encoding=UTF-8 -jar webwolf.jar --server.address=0.0.0.0 > webwolf.log
} }
function write_start_message() { function write_start_message() {
@ -32,9 +51,8 @@ function write_start_message() {
\ /\ / | __/ | |_) | | |__| | | (_) | | (_| | | |_ \ /\ / | __/ | |_) | | |__| | | (_) | | (_| | | |_
\/ \/ \___| |_.__/ \_____| \___/ \__,_| \__| \/ \/ \___| |_.__/ \_____| \___/ \__,_| \__|
" >> webgoat.log " >> webgoat.log
echo $'WebGoat successfully started...\n' >> webgoat.log echo "WebGoat and WebWolf successfully started..." >> webgoat.log
echo "NOTE: port numbers mentioned below may vary depending on your port mappings while starting the Docker container" >> webgoat.log pidof nginx >/dev/null && echo "Browse to http://localhost to get started" >> webgoat.log || echo "Browse to http://localhost:8080/WebGoat or http://localhost:9090/WebWolf to get started" >> webgoat.log
echo "Browse to http://localhost:8080/WebGoat to get started." >> webgoat.log
} }
function tail_log_file() { function tail_log_file() {
@ -44,7 +62,9 @@ function tail_log_file() {
commandline_args=("$@") commandline_args=("$@")
nginx
webgoat & webgoat &
webwolf &
write_start_message & write_start_message &
tail_log_file tail_log_file

View File

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

View File

@ -1,2 +1,2 @@
export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
./mvnw $@ mvn $@

View File

@ -0,0 +1,54 @@
# Helm chart deployment on OpenShift K8S clusters
This helm chart can be used on a OpenShift Code Ready Container environment or an OpenShift Cloud Container environment.
With the OpenShift CRC (Code Ready Container) cluster you run an entire environment on your local machine. (> 4 vCPU, >8GB mem)
See the Red Hat documentation for general understanding of OpenShift. Make sure helm is installed as well.
https://developers.redhat.com/developer-sandbox
## CRC commands
crc config set cpus 6
crc config set memory 12288
crc setup
crc start
eval $(crc oc-env)
oc login -u developer https://api.crc.testing:6443
oc new-project demo-project
The example without modification uses *demo-project* as the project/namespace for installing WebGoat and WebWolf.
## Helm install this example on your local Code Ready Container environment
helm install goat1 ./webgoat
## Helm install on single node Developer Sandbox (cloud)
oc login --token=sha256~phDWy6Wm_oJQW6kmOHEbLkRdDIXU6b70hRVmdSYWolM --server=https://api.sandbox-m2.rz9k.p1.openshiftapps.com:6443
helm install --set namespace=renezubcevic-dev --set accessMode=ReadWriteOnce --set urlpostfix=.apps.sandbox-m2.rz9k.p1.openshiftapps.com goat1 ./webgoat
A code ready container looks the same for all developers on their local machine, but a developer sandbox requires other credentials from your account in the cloud and different namespace and urlpostfix and also a different access mode for the persistent storage.
Of course the token here is a fake.
## uninstall
helm uninstall goat1
The URL on a Code Ready Container is build from router name + namespace + default extension .apps-crc.testing:
+ [https://webgoat-1-goat-demo-project.apps-crc.testing/WebGoat](https://webgoat-1-goat-demo-project.apps-crc.testing/WebGoat)
+ [http://webwolf-1-wolf-demo-project.apps-crc.testing/WebWolf](http://webwolf-1-wolf-demo-project.apps-crc.testing/WebWolf)
## Explanation
deployment.yaml contains two K8S deployment elements. Both use the same Persistent Volume Claim and use the same Volume mapping.
They both use the same image but with other entrypoint and command arguments. The java.io.dir is also mapped to this persistent volume mapping. The number of pods is 1 for both WebGoat and WebWolf. WebGoat uses the WEBWOLF_HOST parameter to know where the external address of WebWolf is defined. WebWolf uses WEBGOAT_HOST to define the internal service address to WebGoat for connecting to the HSQL database
persistent-storage-claim.yaml contains the OpenShift K8S extension for requestig a volume with Read-Write access that will survive any pod replacements.
service.yaml defines the service ports for both WebGoat and WebWolf
route-goat defines an https endpoint toward the 8080 port. route-wolf defines an http port towards the 9090 port.

View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -0,0 +1,9 @@
apiVersion: v2
name: modsec
description: ModSecurity Core Rule Set
type: application
version: 0.1.0
appVersion: "latest"

View File

@ -0,0 +1,18 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ .Values.modsec_server.name }}-configmap-modsec
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/part-of: {{ .Values.modsec_server.name }}
data:
PARANOIA: '1'
EXECUTING_PARANOIA: '2'
ANOMALYIN: '5'
ANOMALYOUT: '5'
ALLOWED_METHODS: 'GET POST'
ALLOWED_REQUEST_CONTENT_TYPE: "text/xml|application/xml|text/plain"
MAX_FILE_SIZE: '5242880'
PORT: '8001'
RESTRICTED_EXTENSIONS: '.conf/'
BACKEND: 'http://{{ .Values.webgoat_server.name }}-service:8080'

View File

@ -0,0 +1,45 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .Values.modsec_server.name }}
namespace: {{ .Values.namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.modsec_server.name }}
template:
metadata:
labels:
app: {{ .Values.modsec_server.name }}
spec:
containers:
- resources:
limits:
memory: "2Gi"
cpu: "1"
requests:
memory: "1Gi"
cpu: "0.5"
name: modsec
ports:
- containerPort: 8001
protocol: TCP
image: {{ .Values.modsec_server.image }}
imagePullPolicy: Always
terminationMessagePolicy: File
envFrom:
- configMapRef:
name: {{ .Values.modsec_server.name }}-configmap-modsec
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600

View File

@ -0,0 +1,16 @@
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.modsec_server.name }}
name: {{ .Values.modsec_server.name }}-modsec
namespace: {{ .Values.namespace }}
spec:
path: /
port:
targetPort: 8001
to:
kind: Service
name: {{ .Values.modsec_server.name }}-service
weight: 100
wildcardPolicy: None

View File

@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.modsec_server.name }}
name: {{ .Values.modsec_server.name }}-service
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 8001-tcp
port: 8001
protocol: TCP
targetPort: 8001
selector:
app: {{ .Values.modsec_server.name }}
sessionAffinity: None

View File

@ -0,0 +1,13 @@
namespace: demo-project
urlpostfix: .apps-crc.testing
accessMode: ReadWriteMany
modsec_server:
name: modsec-1
#image: docker.io/franbuehler/modsecurity-crs-rp
#image: docker.io/owasp/modsecurity-crs
image: docker.io/chrira/modsecurity-crs-rp:openshift
webgoat_server:
name: webgoat-1

View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -0,0 +1,9 @@
apiVersion: v2
name: webgoat
description: WebGoat Learning Environment
type: application
version: 0.1.0
appVersion: "8.2.3-SNAPSHOT"

View File

@ -0,0 +1,14 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ .Values.webgoat_server.name }}-configmap
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
data:
TZ: 'Europe/Amsterdam'
EXCLUDE_CATEGORIES: 'CLIENT_SIDE'
EXCLUDE_LESSONS: 'SqlInjectionAdvanced'
WEBWOLF_HOST: '{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}'
WEBWOLF_PORT: '80'
WEBGOAT_HOST: {{ .Values.webgoat_server.name }}-service

View File

@ -0,0 +1,91 @@
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}
namespace: {{ .Values.namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.webgoat_server.name }}
template:
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
spec:
volumes:
- name: webgoat-volume-1
persistentVolumeClaim:
claimName: {{ .Values.webgoat_server.name }}-pvc
containers:
- resources:
limits:
memory: "1Gi"
cpu: "500m"
requests:
memory: "200Mi"
cpu: "100m"
name: webgoat
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 9090
protocol: TCP
#livenessProbe:
# failureThreshold: 3
# periodSeconds: 10
# httpGet:
# path: /WebGoat
# port: 8080
#readinessProbe:
# failureThreshold: 3
# periodSeconds: 10
# initialDelaySeconds: 60
## httpGet:
# path: /WebGoat
# port: 8080
image: {{ .Values.webgoat_server.image }}
command:
- 'java'
args: ["-Duser.home=/home/webgoat",
"--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",
"-Djava.io.tmpdir=/home/webgoat/.webgoat-{{ .Chart.AppVersion }}",
"-Dfile.encoding=UTF-8",
"-Drunning.in.docker=true",
"-Dwebgoat.host=0.0.0.0",
"-Dwebwolf.landingpage.url=http://{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}/landing",
"-Dwebwolf.mail.url=http://{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}/mail",
"-jar","/home/webgoat/webgoat.jar",
"--server.address=0.0.0.0"
]
imagePullPolicy: Always
volumeMounts:
- name: webgoat-volume-1
mountPath: /home/webgoat/.webgoat-{{ .Chart.AppVersion }}
terminationMessagePolicy: File
envFrom:
- configMapRef:
name: {{ .Values.webgoat_server.name }}-configmap
- secretRef:
name: {{ .Values.webgoat_server.name }}-secret
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600

View File

@ -0,0 +1,13 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: '{{ .Values.webgoat_server.name }}-pvc'
namespace: '{{ .Values.namespace }}'
spec:
accessModes:
- '{{ .Values.accessMode }}'
resources:
requests:
storage: 1Gi
#volumeName: pv0028
volumeMode: Filesystem

View File

@ -0,0 +1,36 @@
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-goat
namespace: {{ .Values.namespace }}
spec:
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
path: /WebGoat
port:
targetPort: 8080
to:
kind: Service
name: {{ .Values.webgoat_server.name }}-service
weight: 100
wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-wolf
namespace: {{ .Values.namespace }}
spec:
path: /
port:
targetPort: 9090
to:
kind: Service
name: {{ .Values.webgoat_server.name }}-wolfservice
weight: 100
wildcardPolicy: None

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.webgoat_server.name }}-secret
namespace: {{ .Values.namespace }}
stringData:
ADMIN_PASSWORD: admin

View File

@ -0,0 +1,35 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-service
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: {{ .Values.webgoat_server.name }}
sessionAffinity: None
---
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-wolfservice
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 9090-tcp
port: 9090
protocol: TCP
targetPort: 9090
selector:
app: {{ .Values.webgoat_server.name }}
sessionAffinity: None

View File

@ -0,0 +1,11 @@
namespace: demo-project
urlpostfix: .apps-crc.testing
accessMode: ReadWriteMany
webgoat_server:
name: webgoat-1
image: docker.io/webgoat/webgoat:latest
webwolf_server:
name: webwolf-1
image: docker.io/webgoat/webgoat:latest

611
pom.xml
View File

@ -4,30 +4,33 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId> <artifactId>webgoat-parent</artifactId>
<packaging>jar</packaging> <packaging>pom</packaging>
<version>8.2.3-SNAPSHOT</version> <version>8.2.3-SNAPSHOT</version>
<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>2.5.4</version>
</parent> </parent>
<name>WebGoat</name> <name>WebGoat Parent Pom</name>
<description>WebGoat, a deliberately insecure Web Application</description> <description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
<inceptionYear>2006</inceptionYear> <inceptionYear>2006</inceptionYear>
<url>https://github.com/WebGoat/WebGoat</url> <url>https://github.com/WebGoat/WebGoat</url>
<organization> <organization>
<name>OWASP</name> <name>OWASP</name>
<url>https://github.com/WebGoat/WebGoat/</url> <url>https://github.com/WebGoat/WebGoat/</url>
</organization> </organization>
<licenses> <licenses>
<license> <license>
<name>GNU General Public License, version 2</name> <name>GNU General Public License, version 2</name>
<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>
@ -114,233 +117,122 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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>
<java.version>17</java.version>
<webgoat.port>8080</webgoat.port>
<webwolf.port>9090</webwolf.port>
<!-- 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.2</asciidoctorj.version>
<bootstrap.version>3.3.7</bootstrap.version>
<cglib.version>2.2</cglib.version> <!-- do not update necessary for lesson -->
<checkstyle.version>3.1.2</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version> <commons-collections.version>3.2.1</commons-collections.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-io.version>2.6</commons-io.version> <commons-io.version>2.6</commons-io.version>
<commons-text.version>1.9</commons-text.version>
<guava.version>30.1-jre</guava.version> <guava.version>30.1-jre</guava.version>
<jjwt.version>0.9.1</jjwt.version> <lombok.version>1.18.20</lombok.version>
<jose4j.version>0.7.6</jose4j.version> <wiremock.version>2.27.2</wiremock.version>
<jsoup.version>1.14.3</jsoup.version>
<jquery.version>3.5.1</jquery.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.0.0-M5</maven-surefire-plugin.version>
<pmd.version>3.15.0</pmd.version> <java.version>17</java.version>
<thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
<webdriver.version>4.3.1</webdriver.version>
<wiremock.version>2.27.2</wiremock.version>
<xml-resolver.version>1.2</xml-resolver.version>
<xstream.version>1.4.5</xstream.version> <!-- do not update necessary for lesson -->
<zxcvbn.version>1.5.2</zxcvbn.version>
</properties> </properties>
<dependencyManagement> <modules>
<dependencies> <module>webgoat-container</module>
<module>webgoat-lessons</module>
<module>webgoat-server</module>
<module>webwolf</module>
<module>webgoat-integration-tests</module>
<module>docker</module><!-- copy required jars in preparation of docker all-in-one build -->
</modules>
<dependency> <dependencies>
<groupId>org.ow2.asm</groupId> <dependency>
<artifactId>asm</artifactId> <groupId>org.springframework.boot</groupId>
<version>9.1</version> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
</dependencies>
<dependency> <build>
<groupId>org.apache.commons</groupId> <plugins>
<artifactId>commons-exec</artifactId> <plugin>
<version>1.3</version> <groupId>org.codehaus.mojo</groupId>
</dependency> <artifactId>flatten-maven-plugin</artifactId>
<dependency> <version>1.2.5</version>
<groupId>org.asciidoctor</groupId> <configuration>
<artifactId>asciidoctorj</artifactId> </configuration>
<version>${asciidoctorj.version}</version> <executions>
</dependency> <execution>
<dependency> <id>flatten</id>
<!-- jsoup HTML parser library @ https://jsoup.org/ --> <phase>process-resources</phase>
<groupId>org.jsoup</groupId> <goals>
<artifactId>jsoup</artifactId> <goal>flatten</goal>
<version>${jsoup.version}</version> </goals>
</dependency> </execution>
<dependency> </executions>
<groupId>com.nulab-inc</groupId> </plugin>
<artifactId>zxcvbn</artifactId> <plugin>
<version>${zxcvbn.version}</version> <groupId>org.apache.maven.plugins</groupId>
</dependency> <artifactId>maven-compiler-plugin</artifactId>
<dependency> <version>${maven-compiler-plugin.version}</version>
<groupId>com.thoughtworks.xstream</groupId> <configuration>
<artifactId>xstream</artifactId> <source>15</source>
<version>${xstream.version}</version> <target>15</target>
</dependency> <encoding>UTF-8</encoding>
<dependency> </configuration>
<groupId>cglib</groupId> </plugin>
<artifactId>cglib-nodep</artifactId> <plugin>
<version>${cglib.version}</version> <groupId>org.apache.maven.plugins</groupId>
</dependency> <artifactId>maven-checkstyle-plugin</artifactId>
<dependency> <version>3.1.2</version>
<groupId>xml-resolver</groupId> <configuration>
<artifactId>xml-resolver</artifactId> <encoding>UTF-8</encoding>
<version>${xml-resolver.version}</version> <consoleOutput>true</consoleOutput>
</dependency> <failsOnError>true</failsOnError>
<dependency> <configLocation>config/checkstyle/checkstyle.xml</configLocation>
<groupId>io.jsonwebtoken</groupId> <suppressionsLocation>config/checkstyle/suppressions.xml</suppressionsLocation>
<artifactId>jjwt</artifactId> <suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
<version>${jjwt.version}</version> </configuration>
</dependency> </plugin>
<dependency> <plugin>
<groupId>com.google.guava</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>guava</artifactId> <artifactId>maven-pmd-plugin</artifactId>
<version>${guava.version}</version> <version>3.14.0</version>
</dependency> <configuration>
<dependency> <targetJdk>15</targetJdk>
<groupId>commons-io</groupId> <failurePriority>1</failurePriority><!-- 5 means fail even on the lowest priority, 0 means never fail -->
<artifactId>commons-io</artifactId> <rulesets>
<version>${commons-io.version}</version> <!--suppress UnresolvedMavenProperty -->
</dependency> <ruleset>${maven.multiModuleProjectDirectory}/config/pmd/pmd-ruleset.xml</ruleset>
<dependency> </rulesets>
<groupId>org.apache.commons</groupId> <failOnViolation>true</failOnViolation>
<artifactId>commons-text</artifactId> <printFailingErrors>true</printFailingErrors>
<version>${commons-text.version}</version> </configuration>
</dependency> <executions>
<dependency> <execution>
<groupId>org.bitbucket.b_c</groupId> <goals>
<artifactId>jose4j</artifactId> <goal>check</goal>
<version>${jose4j.version}</version> </goals>
</dependency> </execution>
<dependency> </executions>
<groupId>org.webjars</groupId> </plugin>
<artifactId>bootstrap</artifactId> </plugins>
<version>${bootstrap.version}</version> </build>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>${wiremock.version}</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${webdriver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>9.3.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles> <profiles>
<profile>
<id>local-server</id>
</profile>
<profile>
<id>start-server</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>reserve-container-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>webgoat.port</portName>
<portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>0.9</version>
<executions>
<execution>
<id>start-jar</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<workingDir>${project.build.directory}</workingDir>
<arguments>
<argument>java</argument>
<argument>-jar</argument>
<argument>-Dlogging.pattern.console=</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>-Dwebwolf.port=${webwolf.port}</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang.reflect=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.text=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.desktop/java.beans=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.desktop/java.awt.font=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>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>
${project.build.directory}/webgoat-${project.version}.jar
</argument>
</arguments>
<waitForInterrupt>false</waitForInterrupt>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/</healthcheckUrl>
</configuration>
</execution>
<execution>
<id>stop-jar-process</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop-all</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile> <profile>
<id>owasp</id> <id>owasp</id>
<activation> <activation>
@ -351,11 +243,11 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>6.5.1</version> <version>6.1.3</version>
<configuration> <configuration>
<failBuildOnCVSS>7</failBuildOnCVSS> <failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>false</skipProvidedScope> <skipProvidedScope>true</skipProvidedScope>
<skipRuntimeScope>false</skipRuntimeScope> <skipRuntimeScope>true</skipRuntimeScope>
<suppressionFiles> <suppressionFiles>
<!--suppress UnresolvedMavenProperty --> <!--suppress UnresolvedMavenProperty -->
<suppressionFile> <suppressionFile>
@ -376,290 +268,6 @@
</profile> </profile>
</profiles> </profiles>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
</dependency>
<dependency>
<groupId>xml-resolver</groupId>
<artifactId>xml-resolver</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludeDevtools>true</excludeDevtools>
<executable>true</executable>
<mainClass>org.owasp.webgoat.server.StartWebGoat</mainClass>
<!-- See http://docs.spring.io/spring-boot/docs/current/reference/html/howto-build.html#howto-extract-specific-libraries-when-an-executable-jar-runs -->
<requiresUnpack>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-integration-test-source-as-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables>
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
<includes>**/*IntegrationTest.java</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<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
</argLine>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
<suppressionsLocation>config/checkstyle/suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>restrict-log4j-versions</id>
<phase>validate</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes combine.children="append">
<exclude>org.apache.logging.log4j:log4j-core</exclude>
</excludes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories> <repositories>
<repository> <repository>
<id>central</id> <id>central</id>
@ -679,4 +287,5 @@
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
</project> </project>

View File

@ -1,112 +0,0 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ChallengeIntegrationTest extends IntegrationTest {
@Test
public void testChallenge1() {
startLesson("Challenge1");
byte[] resultBytes =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/challenge/logo"))
.then()
.statusCode(200)
.extract().asByteArray();
String pincode = new String(Arrays.copyOfRange(resultBytes, 81216, 81220));
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("/WebGoat/challenge/1"), params, true);
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/1"))
.then()
.statusCode(200)
.extract().asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/1");
List<String> capturefFlags =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract().jsonPath()
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
assertTrue(capturefFlags.contains("Admin lost password"));
}
@Test
public void testChallenge5() {
startLesson("Challenge5");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username_login", "Larry");
params.put("password_login", "1' or '1'='1");
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/5"))
.then()
.statusCode(200)
.extract().asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/5");
List<String> capturefFlags =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract().jsonPath()
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
assertTrue(capturefFlags.contains("Without password"));
}
}

View File

@ -1,88 +0,0 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
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.InputStream;
import java.util.Properties;
public class LabelAndHintTest extends IntegrationTest {
@Test
public void testSingleLabel() {
Assertions.assertTrue(true);
JsonPath jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","en")
.cookie("JSESSIONID", getWebGoatCookie())
.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("\'http-basics.close\'"));
}
@Test
public void testLabels() {
Properties propsDefault = getProperties("");
System.out.println("Working Directory = " + System.getProperty("user.dir"));
checkLang(propsDefault,"nl");
checkLang(propsDefault,"de");
checkLang(propsDefault,"fr");
checkLang(propsDefault,"ru");
}
private Properties getProperties(String lang) {
Properties prop = null;
if (lang == null || lang.equals("")) { lang = ""; } else { lang = "_"+lang; }
try (InputStream input = new FileInputStream("src/main/resources/i18n/messages"+lang+".properties")) {
prop = new Properties();
// load a properties file
prop.load(input);
} catch (Exception e) {
e.printStackTrace();
}
return prop;
}
private void checkLang(Properties propsDefault, String lang) {
JsonPath jsonPath = getLabels(lang);
Properties propsLang = getProperties(lang);
for (String key: propsLang.stringPropertyNames()) {
if (!propsDefault.containsKey(key)) {
System.out.println("key: " + key + " in (" +lang+") is missing from default properties");
Assertions.fail();
}
if (!jsonPath.getString("\'"+key+"\'").equals(propsLang.get(key))) {
System.out.println("key: " + key + " in (" +lang+") has incorrect translation in label service");
System.out.println("actual:"+jsonPath.getString("\'"+key+"\'"));
System.out.println("expected: "+propsLang.getProperty(key));
System.out.println();
//Assertions.fail();
}
}
}
private JsonPath getLabels(String lang) {
return RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language",lang)
.cookie("JSESSIONID", getWebGoatCookie())
//.log().headers()
.get(url("service/labels.mvc"))
.then()
//.log().all()
.statusCode(200).extract().jsonPath();
}
}

View File

@ -1,68 +0,0 @@
package org.owasp.webgoat.container;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.service.RestartLessonService;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.function.Function;
@Configuration
@RequiredArgsConstructor
@Slf4j
public class DatabaseConfiguration {
private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean
@Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(properties.getDriverClassName());
dataSource.setUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
/**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users and 1 for lesson
* specific tables we use. This way we clean the data in the lesson database quite easily see {@link RestartLessonService#restartLesson()}
* for how we clean the lesson related tables.
*/
@Bean(initMethod = "migrate")
public Flyway flyWayContainer() {
return Flyway
.configure()
.configuration(Map.of("driver", properties.getDriverClassName()))
.dataSource(dataSource())
.schemas("container")
.locations("db/container")
.load();
}
@Bean
public Function<String, Flyway> flywayLessons(LessonDataSource lessonDataSource) {
return schema -> Flyway
.configure()
.configuration(Map.of("driver", properties.getDriverClassName()))
.schemas(schema)
.dataSource(lessonDataSource)
.locations("lessons")
.load();
}
@Bean
public LessonDataSource lessonDataSource() {
return new LessonDataSource(dataSource());
}
}

View File

@ -1,21 +0,0 @@
package org.owasp.webgoat.container;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequiredArgsConstructor
public class WebWolfRedirect {
private final ApplicationContext applicationContext;
@GetMapping("/WebWolf")
public ModelAndView openWebWolf() {
var url = applicationContext.getEnvironment().getProperty("webwolf.url");
return new ModelAndView("redirect:" + url + "/home");
}
}

View File

@ -1,12 +0,0 @@
package org.owasp.webgoat.container.lessons;
import org.owasp.webgoat.container.users.WebGoatUser;
/**
* Interface for initialization of a lesson. It is called when a new user is added to WebGoat and when a users
* reset a lesson. Make sure to clean beforehand and then re-initialize the lesson.
*/
public interface Initializeable {
void initialize(WebGoatUser webGoatUser);
}

View File

@ -1,46 +0,0 @@
package org.owasp.webgoat.container.lessons;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
@Component
@Slf4j
public class LessonScanner {
private static final Pattern lessonPattern = Pattern.compile("^.*/lessons/([^/]*)/.*$");
@Getter
private final Set<String> lessons = new HashSet<>();
public LessonScanner(ResourcePatternResolver resourcePatternResolver) {
try {
var resources = resourcePatternResolver.getResources("classpath:/lessons/*/*");
for (var resource : resources) {
//WG can run as a fat jar or as directly from file system we need to support both so use the URL
var url = resource.getURL();
var matcher = lessonPattern.matcher(url.toString());
if (matcher.matches()) {
lessons.add(matcher.group(1));
}
}
log.debug("Found {} lessons", lessons.size());
} catch (IOException e) {
log.warn("No lessons found...");
}
}
public List<String> applyPattern(String pattern) {
return lessons.stream().map(lesson -> String.format(pattern, lesson)).toList();
}
}

View File

@ -1,19 +0,0 @@
package org.owasp.webgoat.container.service;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController("/environment")
@RequiredArgsConstructor
public class EnvironmentService {
private final ApplicationContext context;
@GetMapping("/server-directory")
public String homeDirectory() {
return context.getEnvironment().getProperty("webgoat.server.directory");
}
}

View File

@ -1,59 +0,0 @@
package org.owasp.webgoat.container.service;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* <p>LessonProgressService class.</p>
*
* @author webgoat
*/
@Controller
@RequiredArgsConstructor
public class LessonProgressService {
private final UserTrackerRepository userTrackerRepository;
private final WebSession webSession;
/**
* Endpoint for fetching the complete lesson overview which informs the user about whether all the assignments are solved.
* Used as the last page of the lesson to generate a lesson overview.
*
* @return list of assignments
*/
@RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json")
@ResponseBody
public List<LessonOverview> lessonOverview() {
var userTracker = userTrackerRepository.findByUser(webSession.getUserName());
var currentLesson = webSession.getCurrentLesson();
if (currentLesson != null) {
var lessonTracker = userTracker.getLessonTracker(currentLesson);
return lessonTracker.getLessonOverview().entrySet().stream()
.map(entry -> new LessonOverview(entry.getKey(), entry.getValue()))
.toList();
}
return List.of();
}
@AllArgsConstructor
@Getter
//Jackson does not really like returning a map of <Assignment, Boolean> directly, see http://stackoverflow.com/questions/11628698/can-we-make-object-as-key-in-map-when-using-json
//so creating intermediate object is the easiest solution
private static class LessonOverview {
private Assignment assignment;
private Boolean solved;
}
}

View File

@ -1,33 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.owasp.webgoat.container.service;
import lombok.RequiredArgsConstructor;
import org.owasp.webgoat.container.i18n.Messages;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class SessionService {
private final WebSession webSession;
private final RestartLessonService restartLessonService;
private final Messages messages;
@RequestMapping(path = "/service/enable-security.mvc", produces = "application/json")
@ResponseBody
public String applySecurity() {
webSession.toggleSecurity();
restartLessonService.restartLesson();
var msg = webSession.isSecurityEnabled() ? "security.enabled" : "security.disabled";
return messages.getMessage(msg);
}
}

View File

@ -1,36 +0,0 @@
package org.owasp.webgoat.lessons.challenges.challenge1;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
import java.security.SecureRandom;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
@RestController
public class ImageServlet extends HttpServlet {
private static final long serialVersionUID = 9132775506936676850L;
static final public int PINCODE = new SecureRandom().nextInt(10000);
@RequestMapping(method = {GET, POST}, value = "/challenge/logo", produces = MediaType.IMAGE_PNG_VALUE)
@ResponseBody
public byte[] logo() throws IOException {
byte[] in = new ClassPathResource("lessons/challenges/images/webgoat2.png").getInputStream().readAllBytes();
String pincode = String.format("%04d", PINCODE);
in[81216]=(byte) pincode.charAt(0);
in[81217]=(byte) pincode.charAt(1);
in[81218]=(byte) pincode.charAt(2);
in[81219]=(byte) pincode.charAt(3);
return in;
}
}

View File

@ -1,10 +0,0 @@
package org.owasp.webgoat.server;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.owasp.webgoat.server")
public class ParentConfig {
}

View File

@ -1,82 +0,0 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.server;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.WebGoat;
import org.owasp.webgoat.webwolf.WebWolf;
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.util.SocketUtils;
import java.lang.reflect.Method;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
@Slf4j
public class StartWebGoat {
public static final String WEBGOAT_PORT = "webgoat.port";
public static final String WEBWOLF_PORT = "webwolf.port";
private static final int MAX_PORT = 9999;
public static void main(String[] args) {
setEnvironmentVariableForPort(WEBGOAT_PORT, "8080");
setEnvironmentVariableForPort(WEBWOLF_PORT, "9090");
new SpringApplicationBuilder().parent(ParentConfig.class)
.web(WebApplicationType.NONE).bannerMode(Banner.Mode.OFF)
.child(WebGoat.class)
.web(WebApplicationType.SERVLET)
.sibling(WebWolf.class).bannerMode(Banner.Mode.OFF)
.web(WebApplicationType.SERVLET)
.run(args);
}
private static void setEnvironmentVariableForPort(String name, String defaultValue) {
ofNullable(System.getProperty(name))
.or(() -> of(defaultValue))
.map(Integer::parseInt)
.map(port -> findPort(port))
.ifPresent(port -> System.setProperty(name, port));
}
public static String findPort(int port) {
try {
if (port == MAX_PORT) {
log.error("No free port found from 8080 - {}", MAX_PORT);
return "" + port;
}
return "" + SocketUtils.findAvailableTcpPort(port, port);
} catch (IllegalStateException var4) {
return findPort(port + 1);
}
}
}

View File

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

View File

@ -1,44 +0,0 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.webwolf;
import org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository;
import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("org.owasp.webgoat.webwolf")
@PropertySource("classpath:application-webwolf.properties")
@EnableAutoConfiguration
public class WebWolf {
@Bean
public HttpTraceRepository traceRepository() {
return new WebWolfTraceRepository();
}
}

View File

@ -1,6 +0,0 @@
__ __ _ _____ _
\ \ / / | | / ____| | |
\ \ /\ / / ___ | |__ | | __ ___ __ _ | |_
\ \/ \/ / / _ \ | '_ \ | | |_ | / _ \ / _' | | __|
\ /\ / | __/ | |_) | | |__| | | (_) | | (_| | | |_
\/ \/ \___| |_.__/ \_____| \___/ \__,_| \__|

View File

@ -1,9 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:lessons/challenges/documentation/Challenge_introduction.adoc"></div>
</div>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,36 +0,0 @@
== Step 1: writing content
Each lesson can consist of multiple pages with content (text) to explain the vulnerability at hand. The content
is written in AsciiDoc[https://asciidoctor.org/docs/asciidoc-writers-guide/] which makes it very easy to write content (if you know Markdown, you know AsciiDoc).
You can find excellent tutorials online for the AsciiDoc syntax. We are just showing a basic overview below.
Below we will describe some constructs often used within WebGoat.
=== Sub-heading
Check AsciiDoc for syntax, but more = means smaller headings. You can *bold* text and other things.
=== Structuring files
You should set up all content to these *.adoc files. The AsciiDoc files reside in the
directory `/src/main/resources/{lesson}/documentation/`.
=== Images
Images can be referenced below, including setting style (recommended to use lesson-image as the style). The root is `/src/main/resources/{lesson}/images`
image::images/firefox-proxy-config.png[Firefox Proxy Config,510,634,style="lesson-image"]
=== Code block
Write code blocks as follows:
```
[source]
----
public class A {
private String test;
}
----
```

View File

@ -1,34 +0,0 @@
=== Step 3: Write glue html page
We mentioned a lesson could consist of multiple assignments, WebGoat picks them up automatically, and the UI displays
a navigation bar on top of every lesson. A page with an assignment will be red initially and will become
green when the user solves the assignment. To make this work we need to add:
[source]
----
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:lessons/lesson_template/documentation/
lesson-template-intro.adoc"></div>
</div>
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:lessons/lesson_template/documentation/
lesson-template-content.adoc"></div>
</div>
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:lessons/lesson_template/documentation/
lesson-template-lesson-class.adoc"></div>
</div>
</html>
----
This file needs to be places in: `/src/main/resources/{lesson}/html/`. The name of the file should be the same as
the Java class we created in step 2.
The snippet above will create three separate pages (navigation bar) with the adoc pages we created to create this lesson.
That's it we create a basic lesson with only content. To make it all work, you need to make the lesson available in
WebGoat.
That's it. Start WebGoat, and your lesson will appear in the menu.

View File

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:lessons/webgoat_introduction/documentation/Introduction.adoc"></div>
</div>
</html>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -1,10 +0,0 @@
package org.owasp.webgoat.container;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication(scanBasePackages = "org.owasp.webgoat.container")
@PropertySource("classpath:application-webgoat.properties")
public class WebGoatApplication {
}

View File

@ -1,10 +0,0 @@
package org.owasp.webgoat.webwolf;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication(scanBasePackages = "org.owasp.webgoat.webwolf")
@PropertySource("classpath:application-webwolf.properties")
public class WebWolfApplication {
}

View File

@ -1,8 +0,0 @@
webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
spring.flyway.locations=classpath:/db/container
spring.main.banner-mode=off
spring.jpa.properties.hibernate.default_schema=CONTAINER
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver

8
webgoat-container/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
target/
.idea/
*.iml
/src/main/webapp/plugin_lessons/*.jar
/src/main/webapp/plugin_extracted/*
dependency-reduced-pom.xml
src/main/webapp/users/guest.org.owasp.webgoat.lessons.BackDoors.props
/src/main/webapp/WEB-INF/lib/*.jar

101
webgoat-container/pom.xml Normal file
View File

@ -0,0 +1,101 @@
<?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">
<name>webgoat-container</name>
<modelVersion>4.0.0</modelVersion>
<artifactId>webgoat-container</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.3-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -27,7 +27,7 @@
* for free software projects. * for free software projects.
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
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;
@ -48,7 +48,6 @@ public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoi
super(loginFormUrl); super(loginFormUrl);
} }
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
if (request.getHeader("x-requested-with") != null) { if (request.getHeader("x-requested-with") != null) {
response.sendError(401, authException.getMessage()); response.sendError(401, authException.getMessage());

View File

@ -29,18 +29,13 @@
* @since December 12, 2015 * @since December 12, 2015
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
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;
import org.owasp.webgoat.container.asciidoc.OperatingSystemMacro; import org.owasp.webgoat.asciidoc.*;
import org.owasp.webgoat.container.asciidoc.UsernameMacro; import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.container.asciidoc.WebGoatTmpDirMacro;
import org.owasp.webgoat.container.asciidoc.WebGoatVersionMacro;
import org.owasp.webgoat.container.asciidoc.WebWolfMacro;
import org.owasp.webgoat.container.asciidoc.WebWolfRootMacro;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource; import org.thymeleaf.templateresource.ITemplateResource;
@ -68,34 +63,55 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
private static final Asciidoctor asciidoctor = create(); private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:"; private static final String PREFIX = "doc:";
private final ResourceLoader resourceLoader; private final Language language;
public AsciiDoctorTemplateResolver(ResourceLoader resourceLoader) { public AsciiDoctorTemplateResolver(Language language) {
this.resourceLoader = resourceLoader; this.language = language;
setResolvablePatterns(Set.of(PREFIX + "*")); setResolvablePatterns(Set.of(PREFIX + "*"));
} }
@Override @Override
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length()); var templateName = resourceName.substring(PREFIX.length());
try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) {
if (is == null) {
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
return new StringTemplateResource("");
} else {
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
extensionRegistry.inlineMacro("username", UsernameMacro.class);
try (InputStream is = resourceLoader.getResource("classpath:/" + templateName).getInputStream()) { StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry(); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); return new StringTemplateResource(writer.getBuffer().toString());
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class); }
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
extensionRegistry.inlineMacro("username", UsernameMacro.class);
StringWriter writer = new StringWriter();
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new StringTemplateResource(writer.getBuffer().toString());
} catch (IOException e) { } catch (IOException e) {
return new StringTemplateResource("<div>Unable to find documentation for: " + templateName + " </div>"); //no html yet
return new StringTemplateResource("");
} }
} }
/**
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
*/
private String computeResourceName(String resourceName, String language) {
return String.format("lessonPlans/%s/%s", language, resourceName);
}
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
}
return is;
}
private Map<String, Object> createAttributes() { private Map<String, Object> createAttributes() {
Map<String, Object> attributes = new HashMap<>(); Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "coderay"); attributes.put("source-highlighter", "coderay");

View File

@ -0,0 +1,56 @@
package org.owasp.webgoat;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.owasp.webgoat.service.RestartLessonService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@Configuration
public class DatabaseConfiguration {
private String driverClassName;
public DatabaseConfiguration(@Value("${spring.datasource.driver-class-name}") String driverClassName) {
this.driverClassName = driverClassName;
}
/**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users and 1 for lesson
* specific tables we use. This way we clean the data in the lesson database quite easily see {@link RestartLessonService#restartLesson()}
* for how we clean the lesson related tables.
*/
@Bean(initMethod = "migrate")
public Flyway flyWayContainer(DataSource dataSource) {
return Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.dataSource(dataSource)
.schemas("container")
.locations("db/container")
.load();
}
@Bean
public Function<String, Flyway> flywayLessons(LessonDataSource lessonDataSource) {
return schema -> Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.schemas(schema)
.dataSource(lessonDataSource)
.load();
}
@Bean
public LessonDataSource lessonDataSource(DataSource dataSource) {
return new LessonDataSource(dataSource);
}
}

View File

@ -1,12 +1,16 @@
package org.owasp.webgoat.container; package org.owasp.webgoat;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.session.Course;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** /**
* ************************************************************************************************* * *************************************************************************************************
* <p> * <p>
@ -51,7 +55,7 @@ public class HammerHead {
* Entry point for WebGoat, redirects to the first lesson found within the course. * Entry point for WebGoat, redirects to the first lesson found within the course.
*/ */
@RequestMapping(path = "/attack", method = {RequestMethod.GET, RequestMethod.POST}) @RequestMapping(path = "/attack", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView attack() { public ModelAndView attack(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink()); return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink());
} }
} }

View File

@ -1,6 +1,6 @@
package org.owasp.webgoat.container; package org.owasp.webgoat;
import org.owasp.webgoat.container.lessons.LessonConnectionInvocationHandler; import org.owasp.webgoat.lessons.LessonConnectionInvocationHandler;
import org.springframework.jdbc.datasource.ConnectionProxy; import org.springframework.jdbc.datasource.ConnectionProxy;
import javax.sql.DataSource; import javax.sql.DataSource;

View File

@ -29,9 +29,8 @@
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
@ -48,12 +47,11 @@ import java.util.Set;
* Dynamically resolve a lesson. In the html file this can be invoked as: * Dynamically resolve a lesson. In the html file this can be invoked as:
* *
* <code> * <code>
* <div th:case="true" th:replace="lesson:__${lesson.class.simpleName}__"></div> * <div th:case="true" th:replace="lesson:__${lesson.class.simpleName}__"></div>
* </code> * </code>
* <p> *
* Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory * Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory
*/ */
@Slf4j
public class LessonTemplateResolver extends FileTemplateResolver { public class LessonTemplateResolver extends FileTemplateResolver {
private static final String PREFIX = "lesson:"; private static final String PREFIX = "lesson:";
@ -67,16 +65,16 @@ public class LessonTemplateResolver extends FileTemplateResolver {
@Override @Override
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length()); var templateName = resourceName.substring(PREFIX.length());;
byte[] resource = resources.get(templateName); byte[] resource = resources.get(templateName);
if (resource == null) { if (resource == null) {
try { try {
resource = resourceLoader.getResource("classpath:/" + templateName).getInputStream().readAllBytes(); resource = resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream().readAllBytes();
} catch (IOException e) { } catch (IOException e) {
log.error("Unable to find lesson HTML: {}", template); e.printStackTrace();
} }
resources.put(templateName, resource); resources.put(resourceName, resource);
} }
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8)); return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
} }
} }

View File

@ -29,51 +29,39 @@
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
import lombok.RequiredArgsConstructor; import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.container.i18n.Language; import org.owasp.webgoat.i18n.Messages;
import org.owasp.webgoat.container.i18n.Messages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.session.LabelDebugger;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.session.LabelDebugger;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.IEngineConfiguration; import org.thymeleaf.TemplateEngine;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver; import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* Configuration for Spring MVC * Configuration for Spring MVC
*/ */
@Configuration @Configuration
@RequiredArgsConstructor
public class MvcConfiguration implements WebMvcConfigurer { public class MvcConfiguration implements WebMvcConfigurer {
private static final String UTF8 = "UTF-8"; private static final String UTF8 = "UTF-8";
private final LessonScanner lessonScanner;
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
@ -81,55 +69,30 @@ public class MvcConfiguration implements WebMvcConfigurer {
registry.addViewController("/lesson_content").setViewName("lesson_content"); registry.addViewController("/lesson_content").setViewName("lesson_content");
registry.addViewController("/start.mvc").setViewName("main_new"); registry.addViewController("/start.mvc").setViewName("main_new");
registry.addViewController("/scoreboard").setViewName("scoreboard"); registry.addViewController("/scoreboard").setViewName("scoreboard");
//registry.addViewController("/list_users").setViewName("list_users");
} }
@Bean @Bean
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) { public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver(); ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine); resolver.setTemplateEngine(thymeleafTemplateEngine);
resolver.setCharacterEncoding(StandardCharsets.UTF_8.displayName()); resolver.setCharacterEncoding("UTF-8");
return resolver; return resolver;
} }
/**
* Responsible for loading lesson templates based on Thymeleaf, for example:
*
* <div th:include="/lessons/spoofcookie/templates/spoofcookieform.html" id="content"></div>
*/
@Bean
public ITemplateResolver lessonThymeleafTemplateResolver(ResourceLoader resourceLoader) {
var resolver = new FileTemplateResolver() {
@Override
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
try (var is = resourceLoader.getResource("classpath:" + resourceName).getInputStream()) {
return new StringTemplateResource(new String(is.readAllBytes(), StandardCharsets.UTF_8));
} catch (IOException e) {
return null;
}
}
};
resolver.setOrder(1);
return resolver;
}
/**
* Loads all normal WebGoat specific Thymeleaf templates
*/
@Bean @Bean
public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/webgoat/templates/"); resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html"); resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML); resolver.setTemplateMode(TemplateMode.HTML);
resolver.setOrder(2); resolver.setOrder(2);
resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8); resolver.setCharacterEncoding(UTF8);
resolver.setApplicationContext(applicationContext); resolver.setApplicationContext(applicationContext);
return resolver; return resolver;
} }
/**
* Loads the html for the complete lesson, see lesson_content.html
*/
@Bean @Bean
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) { public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader); LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
@ -139,12 +102,9 @@ public class MvcConfiguration implements WebMvcConfigurer {
return resolver; return resolver;
} }
/**
* Loads the lesson asciidoc.
*/
@Bean @Bean
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(ResourceLoader resourceLoader) { public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(resourceLoader); AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setOrder(1); resolver.setOrder(1);
resolver.setCharacterEncoding(UTF8); resolver.setCharacterEncoding(UTF8);
@ -154,37 +114,26 @@ public class MvcConfiguration implements WebMvcConfigurer {
@Bean @Bean
public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver, public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver,
LessonTemplateResolver lessonTemplateResolver, LessonTemplateResolver lessonTemplateResolver,
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver, AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
ITemplateResolver lessonThymeleafTemplateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine(); SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true); engine.setEnableSpringELCompiler(true);
engine.addDialect(new SpringSecurityDialect()); engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolvers( engine.setTemplateResolvers(
Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, lessonThymeleafTemplateResolver, springThymeleafTemplateResolver)); Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver));
return engine; return engine;
} }
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
//WebGoat internal registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/webgoat/static/css/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/");
registry.addResourceHandler("/js/**") registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/");
.addResourceLocations("classpath:/webgoat/static/js/"); registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/");
registry.addResourceHandler("/plugins/**").addResourceLocations("classpath:/webgoat/static/plugins/");
registry.addResourceHandler("/fonts/**").addResourceLocations("classpath:/webgoat/static/fonts/");
//WebGoat lessons
registry.addResourceHandler("/images/**").addResourceLocations(lessonScanner.applyPattern("classpath:/lessons/%s/images/").toArray(String[]::new));
registry.addResourceHandler("/lesson_js/**").addResourceLocations(lessonScanner.applyPattern("classpath:/lessons/%s/js/").toArray(String[]::new));
registry.addResourceHandler("/lesson_css/**").addResourceLocations(lessonScanner.applyPattern("classpath:/lessons/%s/css/").toArray(String[]::new));
registry.addResourceHandler("/lesson_templates/**").addResourceLocations(lessonScanner.applyPattern("classpath:/lessons/%s/templates/").toArray(String[]::new));
registry.addResourceHandler("/video/**").addResourceLocations(lessonScanner.applyPattern("classpath:/lessons/%s/video/").toArray(String[]::new));
} }
@Bean @Bean
public PluginMessages pluginMessages(Messages messages, Language language, public PluginMessages pluginMessages(Messages messages, Language language) {
ResourcePatternResolver resourcePatternResolver) { PluginMessages pluginMessages = new PluginMessages(messages, language);
PluginMessages pluginMessages = new PluginMessages(messages, language, resourcePatternResolver);
pluginMessages.setDefaultEncoding("UTF-8"); pluginMessages.setDefaultEncoding("UTF-8");
pluginMessages.setBasenames("i18n/WebGoatLabels"); pluginMessages.setBasenames("i18n/WebGoatLabels");
pluginMessages.setFallbackToSystemLocale(false); pluginMessages.setFallbackToSystemLocale(false);
@ -207,12 +156,13 @@ public class MvcConfiguration implements WebMvcConfigurer {
@Bean @Bean
public LocaleResolver localeResolver() { public LocaleResolver localeResolver() {
return new SessionLocaleResolver(); SessionLocaleResolver slr = new SessionLocaleResolver();
return slr;
} }
@Bean @Bean
public LabelDebugger labelDebugger() { public LabelDebugger labelDebugger() {
return new LabelDebugger(); return new LabelDebugger();
} }
} }

View File

@ -29,16 +29,13 @@
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@ -46,9 +43,6 @@ import org.springframework.web.client.RestTemplate;
import java.io.File; import java.io.File;
@Configuration @Configuration
@ComponentScan(basePackages = { "org.owasp.webgoat.container", "org.owasp.webgoat.lessons"})
@PropertySource("classpath:application-webgoat.properties")
@EnableAutoConfiguration
public class WebGoat { public class WebGoat {
@Bean(name = "pluginTargetDirectory") @Bean(name = "pluginTargetDirectory")

View File

@ -28,10 +28,10 @@
* @since December 12, 2015 * @since December 12, 2015
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.users.UserService; import org.owasp.webgoat.users.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -77,7 +77,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService); auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
} }
@Bean @Bean
@ -97,4 +97,4 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public NoOpPasswordEncoder passwordEncoder() { public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
} }
} }

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;

View File

@ -1,8 +1,8 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.owasp.webgoat.container.users.WebGoatUser; import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Map; import java.util.Map;
@ -21,8 +21,8 @@ public class UsernameMacro extends InlineMacroProcessor {
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) { public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var auth = SecurityContextHolder.getContext().getAuthentication(); var auth = SecurityContextHolder.getContext().getAuthentication();
var username = "unknown"; var username = "unknown";
if (auth.getPrincipal() instanceof WebGoatUser webGoatUser) { if (auth.getPrincipal() instanceof WebGoatUser) {
username = webGoatUser.getUsername(); username = ((WebGoatUser) auth.getPrincipal()).getUsername();
} }
//see https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used //see https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
@ -27,7 +27,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
@Override @Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) { public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv(); var env = EnvironmentExposure.getEnv();
var hostname = determineHost(env.getProperty("webwolf.port")); var hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
var target = (String) attributes.getOrDefault("target", "home"); var target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target; var href = hostname + "/" + target;
@ -44,7 +44,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
} }
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) { private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().anyMatch(a -> a.equals("noLink")); return attributes.values().stream().filter(a -> a.equals("noLink")).findFirst().isPresent();
} }
/** /**
@ -54,9 +54,9 @@ public class WebWolfMacro extends InlineMacroProcessor {
* You do not have to use the indicated hostname, but if you do, you should define two hosts aliases * You do not have to use the indicated hostname, but if you do, you should define two hosts aliases
* 127.0.0.1 www.webgoat.local www.webwolf.local * 127.0.0.1 www.webgoat.local www.webwolf.local
*/ */
private String determineHost(String port) { private String determineHost(String host, String port) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String host = request.getHeader("Host"); host = request.getHeader("Host");
int semicolonIndex = host.indexOf(":"); int semicolonIndex = host.indexOf(":");
if (semicolonIndex == -1 || host.endsWith(":80")) { if (semicolonIndex == -1 || host.endsWith(":80")) {
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local"); host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.asciidoc;
import java.util.Map; import java.util.Map;
@ -18,7 +18,6 @@ public class WebWolfRootMacro extends WebWolfMacro {
super(macroName, config); super(macroName, config);
} }
@Override
protected boolean includeWebWolfContext() { protected boolean includeWebWolfContext() {
return false; return false;
} }

View File

@ -23,17 +23,16 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.assignments;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Initializeable; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.users.UserTrackerRepository;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
public abstract class AssignmentEndpoint implements Initializeable { public abstract class AssignmentEndpoint {
@Autowired @Autowired
private WebSession webSession; private WebSession webSession;
@ -84,8 +83,4 @@ public abstract class AssignmentEndpoint implements Initializeable {
protected AttackResult.AttackResultBuilder informationMessage(AssignmentEndpoint assignment) { protected AttackResult.AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return AttackResult.builder(messages).lessonCompleted(false).assignment(assignment); return AttackResult.builder(messages).lessonCompleted(false).assignment(assignment);
} }
@Override
public void initialize(WebGoatUser user) {
}
} }

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.assignments;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.assignments;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -23,12 +23,11 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.assignments;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.apache.commons.lang3.StringEscapeUtils;
import org.owasp.webgoat.i18n.PluginMessages;
import static org.apache.commons.text.StringEscapeUtils.escapeJson;
public class AttackResult { public class AttackResult {
@ -108,8 +107,8 @@ public class AttackResult {
public AttackResult(boolean lessonCompleted, String feedback, String output, String assignment, boolean attemptWasMade) { public AttackResult(boolean lessonCompleted, String feedback, String output, String assignment, boolean attemptWasMade) {
this.lessonCompleted = lessonCompleted; this.lessonCompleted = lessonCompleted;
this.feedback = escapeJson(feedback); this.feedback = StringEscapeUtils.escapeJson(feedback);
this.output = escapeJson(output); this.output = StringEscapeUtils.escapeJson(output);
this.assignment = assignment; this.assignment = assignment;
this.attemptWasMade = attemptWasMade; this.attemptWasMade = attemptWasMade;
} }

View File

@ -20,11 +20,11 @@
* 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.container.assignments; package org.owasp.webgoat.assignments;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.users.UserTrackerRepository;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
@ -51,8 +51,8 @@ public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
@Override @Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (o instanceof AttackResult attackResult) { if (o != null && o instanceof AttackResult) {
trackProgress(attackResult); trackProgress((AttackResult) o);
} }
return o; return o;
} }

View File

@ -29,16 +29,21 @@
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat.container.controller; package org.owasp.webgoat.controller;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;
@Controller @Controller
@ -47,7 +52,7 @@ public class StartLesson {
private final WebSession ws; private final WebSession ws;
private final Course course; private final Course course;
public StartLesson(WebSession ws, Course course) { public StartLesson(final WebSession ws, final Course course) {
this.ws = ws; this.ws = ws;
this.course = course; this.course = course;
} }
@ -59,30 +64,29 @@ public class StartLesson {
*/ */
@RequestMapping(path = "startlesson.mvc", method = {RequestMethod.GET, RequestMethod.POST}) @RequestMapping(path = "startlesson.mvc", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView start() { public ModelAndView start() {
var model = new ModelAndView(); ModelAndView model = new ModelAndView();
model.addObject("course", course); model.addObject("course", course);
model.addObject("lesson", ws.getCurrentLesson()); model.addObject("lesson", ws.getCurrentLesson());
model.setViewName("lesson_content"); model.setViewName("lesson_content");
return model; return model;
} }
@RequestMapping(value = {"*.lesson"}, produces = "text/html") @RequestMapping(value = {"*.lesson"}, produces = "text/html")
public ModelAndView lessonPage(HttpServletRequest request) { public ModelAndView lessonPage(HttpServletRequest request) {
var model = new ModelAndView("lesson_content"); // I will set here the thymeleaf fragment location based on the resource requested.
var path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson ModelAndView model = new ModelAndView();
var lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson")); SecurityContext context = SecurityContextHolder.getContext(); //TODO this should work with the security roles of Spring
//GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next();
course.getLessons() String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson
.stream() String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson"));
List<? extends Lesson> lessons = course.getLessons();
Optional<? extends Lesson> lesson = lessons.stream()
.filter(l -> l.getId().equals(lessonName)) .filter(l -> l.getId().equals(lessonName))
.findFirst() .findFirst();
.ifPresent(lesson -> { ws.setCurrentLesson(lesson.get());
ws.setCurrentLesson(lesson); model.setViewName("lesson_content");
model.addObject("lesson", lesson); model.addObject("lesson", lesson.get());
});
return model; return model;
} }

View File

@ -29,10 +29,11 @@
* @version $Id: $Id * @version $Id: $Id
*/ */
package org.owasp.webgoat.container.controller; package org.owasp.webgoat.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -55,7 +56,7 @@ public class Welcome {
* @param request a {@link javax.servlet.http.HttpServletRequest} object. * @param request a {@link javax.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"}) @RequestMapping(path = {"welcome.mvc", "/"}, method = RequestMethod.GET)
public ModelAndView welcome(HttpServletRequest request) { public ModelAndView welcome(HttpServletRequest request) {
// set the welcome attribute // set the welcome attribute
@ -68,6 +69,8 @@ public class Welcome {
//go ahead and send them to webgoat (skip the welcome page) //go ahead and send them to webgoat (skip the welcome page)
ModelAndView model = new ModelAndView(); ModelAndView model = new ModelAndView();
//model.setViewName("welcome");
//model.setViewName("main_new");
model.setViewName("forward:/attack?start=true"); model.setViewName("forward:/attack?start=true");
return model; return model;
} }

View File

@ -23,7 +23,7 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;

View File

@ -23,7 +23,7 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;

View File

@ -23,12 +23,14 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.i18n;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
/** /**
@ -40,15 +42,12 @@ import java.util.Properties;
public class PluginMessages extends ReloadableResourceBundleMessageSource { public class PluginMessages extends ReloadableResourceBundleMessageSource {
private static final String PROPERTIES_SUFFIX = ".properties"; private static final String PROPERTIES_SUFFIX = ".properties";
private final Language language; private Language language;
private final ResourcePatternResolver resourcePatternResolver;
public PluginMessages(Messages messages, Language language) {
public PluginMessages(Messages messages, Language language, ResourcePatternResolver resourcePatternResolver) {
this.language = language; this.language = language;
this.setParentMessageSource(messages); this.setParentMessageSource(messages);
this.setBasename("WebGoatLabels"); this.setBasename("WebGoatLabels");
this.resourcePatternResolver = resourcePatternResolver;
} }
@Override @Override
@ -56,15 +55,16 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
Properties properties = new Properties(); Properties properties = new Properties();
long lastModified = System.currentTimeMillis(); long lastModified = System.currentTimeMillis();
Enumeration<URL> resources = null;
try { try {
var resources = resourcePatternResolver.getResources("classpath:/lessons/**/i18n" + resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
"/WebGoatLabels" + PROPERTIES_SUFFIX); while (resources.hasMoreElements()) {
for (var resource : resources) { URL resource = resources.nextElement();
String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, ""); String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder); PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
properties.putAll(holder.getProperties()); properties.putAll(holder.getProperties());
} }
} catch (IOException e) { } catch (IOException | URISyntaxException e) {
logger.error("Unable to read plugin message", e); logger.error("Unable to read plugin message", e);
} }

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.lessons;
import lombok.*; import lombok.*;
@ -66,4 +66,14 @@ public class Assignment {
this.hints = hints; this.hints = hints;
} }
/**
* Set path is here to overwrite stored paths.
* Since a stored path can no longer be used in a lesson while
* the lesson (name) itself is still part of the lesson.
*
* @param pathName the path
*/
public void setPath(String pathName) {
this.path = pathName;
}
} }

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.lessons;
import lombok.Getter; import lombok.Getter;
@ -39,19 +39,36 @@ public enum Category {
INTRODUCTION("Introduction", 5), INTRODUCTION("Introduction", 5),
GENERAL("General", 100), GENERAL("General", 100),
A1("(A1) Broken Access Control", 301), INJECTION("(A1) Injection", 300),
A2("(A2) Cryptographic Failures", 302), AUTHENTICATION("(A2) Broken Authentication", 302),
A3("(A3) Injection", 303), INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", 303),
XXE("(A4) XML External Entities (XXE)", 304),
A5("(A5) Security Misconfiguration", 305), ACCESS_CONTROL("(A5) Broken Access Control", 305),
A6("(A6) Vuln & Outdated Components", 306),
A7("(A7) Identity & Auth Failure", 307),
A8("(A8) Software & Data Integrity", 308),
A9("(A9) Security Logging Failures", 309),
A10("(A10) Server-side Request Forgery", 310),
CLIENT_SIDE("Client side", 1700), XSS("(A7) Cross-Site Scripting (XSS)", 307),
INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", 308),
VULNERABLE_COMPONENTS("(A9) Vulnerable Components", 309),
SESSION_MANAGEMENT("(A10) Session Management Flaws", 310),
REQUEST_FORGERIES("(A8:2013) Request Forgeries", 318),
REQ_FORGERIES("Request Forgeries", 450),
INSECURE_CONFIGURATION("Insecure Configuration", 600),
INSECURE_STORAGE("Insecure Storage", 800),
AJAX_SECURITY("AJAX Security", 1000),
BUFFER_OVERFLOW("Buffer Overflows", 1100),
CODE_QUALITY("Code Quality", 1200),
CONCURRENCY("Concurrency", 1300),
ERROR_HANDLING("Improper Error Handling", 1400),
DOS("Denial of Service", 1500),
MALICIOUS_EXECUTION("Malicious Execution", 1600),
CLIENT_SIDE("Client side", 1700),
WEB_SERVICES("Web Services", 1900),
ADMIN_FUNCTIONS("Admin Functions", 2000),
CHALLENGE("Challenges", 3000); CHALLENGE("Challenges", 3000);
@Getter @Getter

View File

@ -20,14 +20,14 @@
* 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.container.lessons; package org.owasp.webgoat.lessons;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.session.Course;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -67,11 +67,9 @@ public class CourseConfiguration {
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName()); var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
if (CollectionUtils.isEmpty(endpoints)) { if (CollectionUtils.isEmpty(endpoints)) {
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle()); log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
return new ArrayList<>(); return new ArrayList();
} }
return endpoints.stream() return endpoints.stream().map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass()))).collect(toList());
.map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass())))
.toList();
} }
private String getPath(Class<? extends AssignmentEndpoint> e) { private String getPath(Class<? extends AssignmentEndpoint> e) {

View File

@ -25,7 +25,7 @@
* *
*/ */
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.lessons;
import lombok.Value; import lombok.Value;

View File

@ -20,10 +20,11 @@
* 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.container.lessons; package org.owasp.webgoat.lessons;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.Singular;
import java.util.List; import java.util.List;
@ -38,7 +39,7 @@ public abstract class Lesson {
/** /**
* Constructor for the Lesson object * Constructor for the Lesson object
*/ */
protected Lesson() { public Lesson() {
id = ++count; id = ++count;
} }
@ -65,7 +66,7 @@ public abstract class Lesson {
/** /**
* <p>getDefaultCategory.</p> * <p>getDefaultCategory.</p>
* *
* @return a {@link org.owasp.webgoat.container.lessons.Category} object. * @return a {@link org.owasp.webgoat.lessons.Category} object.
*/ */
protected abstract Category getDefaultCategory(); protected abstract Category getDefaultCategory();
@ -121,16 +122,4 @@ public abstract class Lesson {
public final String getId() { public final String getId() {
return this.getClass().getSimpleName(); return this.getClass().getSimpleName();
} }
public final String getPackage() {
var packageName = this.getClass().getPackageName();
//package name is the direct package name below lessons (any subpackage will be removed)
return packageName.replaceAll("org.owasp.webgoat.lessons.", "").replaceAll("\\..*", "");
}
} }

View File

@ -1,7 +1,6 @@
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.lessons;
import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.users.WebGoatUser;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
@ -13,7 +12,6 @@ import java.sql.Connection;
* Handler which sets the correct schema for the currently bounded user. This way users are not seeing each other * 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. * 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;
@ -25,10 +23,9 @@ public class LessonConnectionInvocationHandler implements InvocationHandler {
@Override @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
var authentication = SecurityContextHolder.getContext().getAuthentication(); var authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof WebGoatUser user) { if (authentication != null && authentication.getPrincipal() instanceof WebGoatUser) {
try (var statement = targetConnection.createStatement()) { var user = (WebGoatUser) authentication.getPrincipal();
statement.execute("SET SCHEMA \"" + user.getUsername() + "\""); targetConnection.createStatement().execute("SET SCHEMA \"" + user.getUsername() + "\"");
}
} }
try { try {
return method.invoke(targetConnection, args); return method.invoke(targetConnection, args);

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.lessons;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

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