Compare commits

..

4 Commits

Author SHA1 Message Date
c24771cf67 WIP 2021-03-30 10:27:58 +02:00
e4a8820b6b WIP 2021-03-30 10:22:55 +02:00
e4d69d257a WIP 2021-03-30 08:05:45 +02:00
efe4a87556 Replace ${revision} with real version as Maven
The CI pipeline should take care of this.
2021-03-30 08:05:34 +02:00
277 changed files with 2182 additions and 1789 deletions

View File

@ -1,25 +1,9 @@
name: "Build"
on:
pull_request:
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
push:
branches:
- master
- develop
- release/*
branches: [ '*' ]
tags-ignore:
- '*'
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
jobs:
build:
@ -27,17 +11,16 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
java: [15]
java: [11, 15]
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
uses: actions/setup-java@v1
with:
distribution: 'zulu'
java-version: ${{ matrix.java }}
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.5
uses: actions/cache@v2.1.4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

View File

@ -4,118 +4,112 @@ on:
tags:
- v*
jobs:
release:
name: Release WebGoat
runs-on: ubuntu-latest
environment:
name: release
steps:
- uses: actions/checkout@v2.3.4
- name: "Get tag name"
id: tag
uses: dawidd6/action-get-tag@v1
- name: Set up JDK 15
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: 15
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: "Set labels for ${{ github.ref }}"
run: |
echo "WEBGOAT_TAG_VERSION=${{ steps.tag.outputs.tag }}" >> $GITHUB_ENV
WEBGOAT_MAVEN_VERSION=${{ steps.tag.outputs.tag }}
echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
- name: Build with Maven
run: |
mvn versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }}
mvn clean install -DskipTests
- name: "Create release"
uses: softprops/action-gh-release@v1
with:
draft: false
files: |
webgoat-server/target/webgoat-server-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
webwolf/target/webwolf-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: |
## Version ${{ steps.tag.outputs.tag }}
### New functionality
- test
### Bug fixes
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
## Contributors
Special thanks to the following contributors providing us with a pull request:
- Person 1
- Person 2
And everyone who provided feedback through Github.
Team WebGoat
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU"
uses: docker/setup-qemu-action@v1.1.0
- name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v1
- name: "Login to dockerhub"
uses: docker/login-action@v1.9.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push"
uses: docker/build-push-action@v2.4.0
with:
context: ./docker
file: docker/Dockerfile
push: false #todo enable
platforms: linux/amd64
tags: |
webgoat/goatandwolf:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/goatandwolf:latest
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Image digest"
run: echo ${{ steps.docker_build.outputs.digest }}
# release:
# name: Release WebGoat
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
#
# - name: "Get tag name"
# id: tag
# uses: dawidd6/action-get-tag@v1
#
# - name: Set up JDK 11
# uses: actions/setup-java@v1
# with:
# java-version: 11
# architecture: x64
#
# - name: Cache Maven packages
# uses: actions/cache@v2.1.4
# with:
# path: ~/.m2
# key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
# restore-keys: ${{ runner.os }}-m2
#
# - name: "Set labels for ${{ github.ref }}"
# run: |
# echo "WEBGOAT_TAG_VERSION=${{ steps.tag.outputs.tag }}" >> $GITHUB_ENV
# WEBGOAT_MAVEN_VERSION=${{ steps.tag.outputs.tag }}
# echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
# - name: Build with Maven
# run: |
# mvn versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }}
# mvn clean install -DskipTests
#
# - name: "Create release"
# uses: softprops/action-gh-release@v1
# with:
# draft: false
# files: |
# webgoat-server/target/webgoat-server-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
# webwolf/target/webwolf-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
# body: |
# ## Version ${{ steps.tag.outputs.tag }}
#
# ### New functionality
#
# - test
#
# ### Bug fixes
#
# - [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
#
#
# ## Contributors
#
# Special thanks to the following contributors providing us with a pull request:
#
# - Person 1
# - Person 2
#
# And everyone who provided feedback through Github.
#
#
# Team WebGoat
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#
# - name: "Set up QEMU"
# uses: docker/setup-qemu-action@v1
#
# - name: "Set up Docker Buildx"
# uses: docker/setup-buildx-action@v1
#
# - name: "Login to dockerhub"
# uses: docker/login-action@v1
# with:
# username: ${{ secrets.DOCKERHUB_USERNAME }}
# password: ${{ secrets.DOCKERHUB_TOKEN }}
#
# - name: "Build and push"
# uses: docker/build-push-action@v2
# with:
# context: ./docker
# file: docker/Dockerfile
# push: false #todo enable
# platforms: linux/amd64
# tags: |
# webgoat/goatandwolf:${{ env.WEBGOAT_TAG_VERSION }}
# webgoat/goatandwolf:latest
# build-args: |
# webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
#
# - name: "Image digest"
# run: echo ${{ steps.docker_build.outputs.digest }}
new_version:
name: Update development version
needs: [ release ]
# needs: [ release ]
runs-on: ubuntu-latest
environment:
name: release
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v2
with:
ref: develop
token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }}
- name: Set up JDK 15
uses: actions/setup-java@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 15
java-version: 11
architecture: x64
- name: Set version to next snapshot
@ -124,8 +118,6 @@ jobs:
- name: Commit pom.xml
run: |
git config user.name webgoat-github
git config user.email owasp.webgoat@gmail.com
find . -name 'pom.xml' | xargs git add
git commit -m "Updating to the new development version"
git push

View File

@ -6,8 +6,8 @@ jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.1.0
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'
pr-message: 'Thanks so much for your contribution, really appreciated! We will have a look and merge it if everything checks out!'
pr-message: 'Thanks so much for your contribution, really appreciated! We will have a look and merge it if everything checks out!'

View File

@ -1,2 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.2.5/apache-maven-3.2.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar

View File

@ -38,14 +38,40 @@ Every release is also published on [DockerHub]((https://hub.docker.com/r/webgoat
The easiest way to start WebGoat as a Docker container is to use the all-in-one docker container. This is a docker image that has WebGoat and WebWolf running inside.
```shell
docker run -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf
docker run -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf
```
WebGoat will be located at: http://127.0.0.1:8080/WebGoat
WebWolf will be located at: http://127.0.0.1:9090/WebWolf
**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 important for the validity of JWT tokens used in certain exercises.
### Using docker stack deploy
Another way to deply WebGoat and WebWolf in a more advanced way is to use a compose-file in a docker stack deploy.
You can define which containers should run in which combinations and define all of this in a yaml file.
An example of such a file is: [goat-with-reverseproxy.yaml](goat-with-reverseproxy.yaml)
This sets up an nginx webserver as reverse proxy to WebGoat and WebWolf. You can change the timezone by adjusting the value in the yaml file.
```shell
docker stack init
docker stack deploy --compose-file goat-with-reverseproxy.yaml webgoatdemo
```
Add the following entries in your local hosts file:
```shell
127.0.0.1 www.webgoat.local www.webwolf.localhost
```
You can use the overall start page: http://www.webgoat.local or:
WebGoat will be located at: http://www.webgoat.local/WebGoat
WebWolf will be located at: http://www.webwolf.local/WebWolf
**Important**: the current directory on your host will be mapped into the container for keeping state.
## 2. Standalone
@ -56,7 +82,7 @@ java -jar webgoat-server-8.1.0.jar [--server.port=8080] [--server.address=localh
java -jar webwolf-8.1.0.jar [--server.port=9090] [--server.address=localhost]
```
The latest version of WebGoat needs Java 15 or above. By default, WebGoat and Webwolf start on port 8080, 9000 and 9090 with the environment variable WEBGOAT_PORT, WEBGOAT_HSQLPORT and WEBWOLF_PORT you can set different values.
The latest version of WebGoat needs Java 11 or above. By default WebGoat and WebWolf start on port 8080,9000 and 9090 with the environment variable WEBGOAT_PORT, WEBWOLF_PORT and WEBGOAT_HSQLPORT you can set different values.
```Shell
export WEBGOAT_PORT=18080
export WEBGOAT_HSQLPORT=19001
@ -64,15 +90,14 @@ export WEBWOLF_PORT=19090
java -jar webgoat-server-8.1.0.jar
java -jar webwolf-8.1.0.jar
```
Use `set` instead of export if you're using Windows cmd.
Use set in stead of export on Windows cmd.
## 3. Run from the sources
### Prerequisites:
* Java 15
* Java 11
* Maven > 3.2.1
* Your favorite IDE
* Git, or Git support in your IDE
@ -99,7 +124,7 @@ mvn -pl webgoat-server spring-boot:run
... 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 IP address add the following variable to WebGoat/webgoat-container/src/main/resources/application.properties file
```
server.address=x.x.x.x
@ -107,15 +132,15 @@ server.address=x.x.x.x
## 4. Run with custom menu
For specialist only. There is a way to set up WebGoat with a personalized menu. You can leave out some menu categories or individual lessons by setting certain environment variables.
For specialist only. There is a way to set up WebGoat with a personalized menu. You can leave out some menu categories or individual lessons by setting environment variables.
For instance running as a jar on a Linux/macOS it will look like this:
For instance running as a jar on a Linux/MacOS it will look like:
```Shell
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar webgoat-server/target/webgoat-server-v8.2.0-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:
```Shell
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

@ -1,44 +1,5 @@
# WebGoat release notes
## Version 8.2.0
### New functionality
- Add new zip slip lesson (part of path traversal)
- SQL lessons are now separate for each user, database are now per user and no longer shared across users
- Moved to Java 15 & Spring Boot 2.4 & moved to JUnit 5
### Bug fixes
- [#974 SQL injection Intro 5 not solvable](https://github.com/WebGoat/WebGoat/issues/974)
- [#962 SQL-Lesson 5 (Advanced) Solvable with wrong anwser](https://github.com/WebGoat/WebGoat/issues/962)
- [#961 SQl-Injection lesson 4 not deleting created row](https://github.com/WebGoat/WebGoat/issues/961)
- [#949 Challenge: Admin password reset always solvable](https://github.com/WebGoat/WebGoat/issues/949)
- [#923 - Upgrade to Java 15](https://github.com/WebGoat/WebGoat/issues/923)
- [#922 - Vulnerable components lesson](https://github.com/WebGoat/WebGoat/issues/922)
- [#891 - Update the OWASP website with the new all-in-one Docker container](https://github.com/WebGoat/WebGoat/issues/891)
- [#844 - Suggestion: Update navigation](https://github.com/WebGoat/WebGoat/issues/844)
- [#843 - Bypass front-end restrictions: Field restrictions - confusing text in form](https://github.com/WebGoat/WebGoat/issues/843)
- [#841 - XSS - Reflected XSS confusing instruction and success messages](https://github.com/WebGoat/WebGoat/issues/841)
- [#839 - SQL Injection (mitigation) Order by clause confusing](https://github.com/WebGoat/WebGoat/issues/839)
- [#838 - SQL mitigation (filtering) can only be passed by updating table](https://github.com/WebGoat/WebGoat/issues/838)
## Contributors
Special thanks to the following contributors providing us with a pull request:
- nicholas-quirk
- VijoPlays
- aolle
- trollingHeifer
- maximmasiutin
- toshihue
- avivmu
- KellyMarchewa
- NatasG
- gabe-sky
## Version 8.1.0
### New functionality

12
buildspec.yml Normal file
View File

@ -0,0 +1,12 @@
version: 0.1
phases:
build:
commands:
- mvn package
artifacts:
files:
- webgoat-server/target/webgoat-server-8.0-SNAPSHOT.jar
discard-paths: yes

13
docker-compose-local.yml Normal file
View File

@ -0,0 +1,13 @@
version: '2.1'
services:
webgoat:
image: webgoat/webgoat-v8.0.0.snapshot
extends:
file: docker-compose.yml
service: webgoat
webwolf:
extends:
file: docker-compose.yml
service: webwolf
image: webgoat/webwolf-v8.0.0.snapshot

View File

@ -0,0 +1,40 @@
version: '2.0'
services:
webgoat:
image: webgoat/webgoat-8.0
user: webgoat
environment:
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
- spring.datasource.username=webgoat
- spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect
- webgoat.server.directory=/home/webgoat/.webgoat/
- webgoat.user.directory=/home/webgoat/.webgoat/
ports:
- "8080:8080"
webwolf:
image: webgoat/webwolf
environment:
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
- spring.datasource.username=webgoat
- spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect
ports:
- "9090:9090"
webgoat_db:
image: postgres:10.12
# Uncomment to store the state of the database on the host.
# volumes:
# - ./database:/var/lib/postgresql
environment:
- POSTGRES_PASSWORD=webgoat
- POSTGRES_USER=webgoat
- POSTGRES_DB=webgoat
ports:
- "5432:5432"

22
docker-compose.yml Normal file
View File

@ -0,0 +1,22 @@
version: '3'
services:
webgoat:
image: webgoat/webgoat-8.0
environment:
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
- TZ=Europe/Amsterdam
ports:
- "8080:8080"
- "9001:9001"
volumes:
- .:/home/webgoat/.webgoat
working_dir: /home/webgoat
webwolf:
image: webgoat/webwolf
ports:
- "9090:9090"
command: --spring.datasource.url=jdbc:hsqldb:hsql://webgoat:9001/webgoat --server.address=0.0.0.0
depends_on:
- webgoat

1
docker/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.jar

View File

@ -1,19 +1,22 @@
FROM openjdk:15.0.2-slim
FROM openjdk:11.0.1-jre-slim-stretch
ARG webgoat_version=8.2.0-SNAPSHOT
ARG webgoat_version=v8.2.0-SNAPSHOT
ENV webgoat_version_env=${webgoat_version}
RUN apt-get update
RUN useradd -ms /bin/bash webgoat
RUN apt-get update && apt-get install
RUN useradd --home-dir /home/webgoat --create-home -U webgoat
RUN cd /home/webgoat/;
RUN chgrp -R 0 /home/webgoat
RUN chmod -R g=u /home/webgoat
RUN apt-get -y install apt-utils nginx
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-${webgoat_version}.jar /home/webgoat/webgoat.jar
COPY --chown=webgoat target/webwolf-${webgoat_version}.jar /home/webgoat/webwolf.jar
COPY --chown=webgoat start.sh /home/webgoat
COPY nginx.conf /etc/nginx/nginx.conf
COPY index.html /usr/share/nginx/html/
COPY webgoat-server-${webgoat_version}.jar /home/webgoat/webgoat.jar
COPY webwolf-${webgoat_version}.jar /home/webgoat/webwolf.jar
COPY start.sh /home/webgoat
EXPOSE 8080
EXPOSE 9090

View File

@ -2,12 +2,8 @@
## Docker build
```shell
docker build --no-cache --build-arg webgoat_version=8.2.0-SNAPSHOT -t webgoat/goatandwolf:latest .
```
docker build --no-cache --build-arg webgoat_version=v8.2.0-SNAPSHOT -t webgoat/goatandwolf:latest .
## Docker run
```shell
docker run -p 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:latest
```
docker run -d -p 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:latest

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
<dependencies>
@ -18,14 +18,14 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<version>1.8</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"/>
<copy file="../webgoat-server/target/webgoat-server-${project.version}.jar" tofile="webgoat-server-${project.version}.jar"/>
<copy file="../webwolf/target/webwolf-${project.version}.jar" tofile="webwolf-${project.version}.jar"/>
</target>
</configuration>
<goals>

View File

@ -3,14 +3,10 @@
cd /home/webgoat
service nginx start
sleep 1
echo "Starting WebGoat..."
java -Duser.home=/home/webgoat -Dfile.encoding=UTF-8 -jar webgoat.jar --webgoat.build.version=$1 --server.address=0.0.0.0 > webgoat.log &
sleep 10
echo "Starting WebWolf..."
java -Duser.home=/home/webgoat -Dfile.encoding=UTF-8 -jar webwolf.jar --webgoat.build.version=$1 --server.address=0.0.0.0 > webwolf.log &
echo "Browse to http://localhost" to get started >> webgoat.log
tail -300f webgoat.log

View File

@ -0,0 +1,43 @@
version: '3'
networks:
webwolflocal:
services:
webgoat:
hostname: www.webgoat.local
image: webgoat/webgoat-8.0
environment:
- WEBGOAT_PORT=8080
- WEBGOAT_SSLENABLED=false
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
- TZ=Europe/Amsterdam
volumes:
- .:/home/webgoat/.webgoat
working_dir: /home/webgoat
command: --server.address=0.0.0.0
networks:
webwolflocal:
aliases:
- goat.webgoat.local
webwolf:
image: webgoat/webwolf
environment:
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
- TZ=Europe/Amsterdam
command: --spring.datasource.url=jdbc:hsqldb:hsql://webgoat:9001/webgoat --server.address=0.0.0.0
networks:
webwolflocal:
aliases:
- wolf.webwolf.local
depends_on:
- webgoat
reverseproxy:
hostname: www.webwolf.local
image: webgoat/reverseproxy
networks:
webwolflocal:
aliases:
- www.webwolf.local
ports:
- 80:80

View File

@ -0,0 +1,31 @@
# AWS
- This contains the various platform Quick Starts for Getting WebGoat Deployed into AWS.
- This IaaS quickstart uses AWS CloudFormation to perform most of the provisioning
- This IaaS quickstart is composed of three independent bundles
- Code pipeline and Build
- Deploying to EC2
- Deploying to ECS
It is Assumed:
- You have an AWS Account
- You know what an S3 bucket is
- You have seen the IAM console and have permissions to create IAM Roles
## Code Pipeline and Build
This Quickstart is for those that just want to perform builds with AWS. It Triggers off of Github to perform builds of `webgoat-server`
## EC2
(WIP) This uses AWS CodePipeline, CodeBuild, and CodeDeploy to land WebGoat to Running EC2 instances
## ECS
(WIP) This uses AWS CodePipeline, CodeBuild, ECR, to land a container onto an ECS cluster

View File

@ -0,0 +1,101 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "IAM Roles for Code Build WebGoat IaaS Quickstart",
"Parameters": {
"qsS3BucketName": {
"Description": "Name of the S3 Bucket for artifacts",
"Type": "String",
"MinLength": "1"
},
"qsRoleName": {
"Description": "Name of the IAM role that CodeBuild Will Use",
"Type": "String",
"Default": "SimpleCodeBuildRole",
"MinLength": "1"
}
},
"Resources": {
"qsCodeBuildRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"codebuild.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/webgoat/",
"RoleName": {
"Ref": "qsRoleName"
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/AWSCodeCommitFullAccess",
"arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess",
"arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess"
],
"Policies": [
{
"PolicyName": "CloudWatchLogs",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
{"Fn::Join": [ "",["arn:aws:logs:*:", { "Ref": "AWS::AccountId" }, ":log-group:/aws/codebuild*" ] ]}
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
}
]
}
},
{
"PolicyName": "S3buckets",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "qsS3BucketName"
},
"*"
]
]
},
"arn:aws:s3:::codepipeline-*"
],
"Action": [
"s3:Put*",
"s3:Get*",
"s3:List*"
]
}
]
}
}
]
}
}
}
}

View File

@ -0,0 +1,127 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "IAM Role for Code Pipeline WebGoat IaaS Quickstart",
"Parameters": {
"qsS3BucketName": {
"Description": "Name of the S3 Bucket for artifacts",
"Type": "String",
"MinLength": "1"
},
"qsRoleName": {
"Description": "Name of the IAM role that CodePipeline Will Use",
"Type": "String",
"Default": "SimpleCodePipelineRole",
"MinLength": "1"
}
},
"Resources": {
"qsCodePipelineRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "codepipeline.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"Path": "/webgoat/",
"RoleName": {
"Ref": "qsRoleName"
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/AWSCodeCommitFullAccess",
"arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess",
"arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess"
],
"Policies": [
{
"PolicyName": "CloudWatchLogsPipeline",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
{"Fn::Join": [ "",["arn:aws:logs:*:", { "Ref": "AWS::AccountId" }, ":log-group:/aws/*" ] ]}
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
}
]
}
},
{
"PolicyName": "MiscComputeOpen",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": "*",
"Action": [
"lambda:InvokeFunction",
"lambda:ListFunctions",
"elasticbeanstalk:*",
"ec2:*",
"elasticloadbalancing:*",
"autoscaling:*",
"cloudwatch:*",
"s3:*",
"sns:*",
"cloudformation:*",
"rds:*",
"sqs:*",
"ecs:*",
"iam:PassRole"
]
}
]
}
},
{
"PolicyName": "S3buckets",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "qsS3BucketName"
},
"*"
]
]
},
"arn:aws:s3:::codepipeline-*",
"arn:aws:s3:::elasticbeanstalk*"
],
"Action": [
"s3:Put*",
"s3:Get*",
"s3:List*"
]
}
]
}
}
]
}
}
}
}

View File

@ -0,0 +1,123 @@
AWSTemplateFormatVersion: "2010-09-09"
Description: >
AWS Cloud Formation for creating an AWS CodePipeline that checks a git repo for changes and then performs a build using code build
Parameters:
qsPipelineName:
Description: The name of the AWS Code Pipeline
Type: String
Default: WG-pipeline
MinLength: 1
qsPipelineRoleARN:
Description: The complete ARN to the IAM role that code pipeline should use
Type: String
MinLength: 1
qsCodeRepo:
Description: The Repository
Type: String
MinLength: 1
qsRepoBranch:
Description: The Branch in the Repository
Type: String
MinLength: 1
qsGitHubUser:
Description: The GitHub User Id
Type: String
MinLength: 1
qsGitHubAPIToken:
Description: The GitHub Personal Access token do not use password
NoEcho: true
Type: String
MinLength: 1
qsS3PipelineArtifacts:
Description: Where Code Pipeline will state artifacts in S3
Type: String
MinLength: 1
qsS3CodeBuildArtifacts:
Description: Where Code Build will upload Artifacts can be same as codepipeline
Type: String
MinLength: 1
qsCodeBuildName:
Description: Name of the AWS Code Build
Type: String
Default: WG-mvnBuilder
MinLength: 1
qsKMSKeyARN:
Description: The KMS ARN that the IAM Role is allowed to use
Type: String
MinLength: 1
qsCodeRoleArn:
Description: The IAM Role ARN for CodePipeline and CodeDeploy
Type: String
MinLength: 1
Resources:
stkcbrCodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: CODEPIPELINE
Description: Builds WebGoat Jar using build file in repo
EncryptionKey: !Ref 'qsKMSKeyARN'
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/java:openjdk-8
Type: LINUX_CONTAINER
Name: !Ref 'qsCodeBuildName'
ServiceRole: !Ref 'qsCodeRoleArn'
TimeoutInMinutes: 10
Source:
Type: CODEPIPELINE
stkcplPipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Ref 'qsPipelineName'
RoleArn: !Ref 'qsPipelineRoleARN'
ArtifactStore:
Location: !Ref 'qsS3PipelineArtifacts'
Type: S3
Stages:
- Name: CodeRepo
Actions:
- Name: CodeSource
ActionTypeId:
Category: Source
Owner: ThirdParty
Provider: GitHub
Version: 1
Configuration:
Branch: !Ref 'qsRepoBranch'
Repo: !Ref 'qsCodeRepo'
Owner: !Ref 'qsGitHubUser'
OAuthToken: !Ref 'qsGitHubAPIToken'
OutputArtifacts:
- Name: MySource
RunOrder: '1'
- Name: Build
Actions:
- Name: CodeBuild
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
InputArtifacts:
- Name: MySource
Configuration:
ProjectName: !Ref stkcbrCodeBuild
OutputArtifacts:
- Name: MyBuild
RunOrder: '2'

View File

@ -0,0 +1,64 @@
# Serverless MVN builds Featuring AWS
This Quick Start forms the basis for the other AWS quickstarts. This only BUILDS the `webgoat-server` spring boot jar. If you want to also run it on AWS skip to the other AWS quickstarts
Before you Begin
1. Do you have an AWS Account?
2. Can you create an S3 Bucket?
3. Can you create a KMS Key?
4. Do you know what Cloud Formation is?
5. Do you have enough permissions to do any real work in said AWS Account?
If you said no to any of those...hop over to [docs](https://aws.amazon.com/documentation/) and learn (but don't do) how to create those.
You will also need:
1. A GitHub Account
2. Fork of WebGoat
3. Personal access Token with `Admin:repo_hook` and `repo`
## Create Pre-requisites
First pick an AWS region and stick with it for ALL the quickstarts. This one was mostly executed on US-east-1/2 but any region with KMS, CodePipeline, and CodeBuild will work. eu-Central-1, ap-southeast-1 and sa-east-1 have reported success also.
1. Create an S3 bucket and call it something meaningfull like `webgoat-stash-username` or something or use an existing bucket you have access to.
2. Create a KMS Key. Make sure you are a key administrator so you can add key users later.
## Deploy IAM role Cloud Formation Stacks
In this folder there are two json cloudformation templates:
-`01_IAM_codebuild.json`
-`01_IAM_codepipeline.json`
You will use the CloudFormation templates to create two roles. One for CodePipeline and the Other for CodeBuild. You will use the name of the bucket you just created as a parameter.
## Update KMS Key
Access the KMS key you created earlier...add the two IAM roles you just created and Key Users
## Finally the Pipeline
You will use the yaml cloudformation template `01_codepiplinebuild.yml` to create the code building pipeline.
Some of the parameters you will need to pass:
1. The S3 bucket (twice)
2. The Github Branch name (master? develop? yourbranchname?)
3. The Github user (if you forked it would be your username)
4. You personal access token for GitHub
5. The name or the repo (WebGoat! ...unless you renamed and did a whole bunch of fancy git magic)
6. The ARN of the KMS key
7. The ARN of the role for the codebuild for parameter qsCodeRoleArn
8. The ARN for codepipeline
If this Stack successfully deploys a build will begin based on the latest commit automatically. You will have a funky named zip file (without the .zip ending) in a folder in the S3 bucket in a few minutes.
Congratulations. You just Deployed a two step AWS Codepipeline that looks for codechanges and then performs a build.
... ON to the next AWS Quickstart

View File

@ -0,0 +1,80 @@
# GKE - DockerHub
This Quickstart shows how to create a Kubernettes Cluster using Google Cloud Platform's [GKE](https://cloud.google.com/container-engine/) and WebGoat's Docker [Image](https://hub.docker.com/r/webgoat/webgoat-8.0/).
To be Successfull with this Quickstart
1. You have a Google Cloud Platform account and have enough access rights to create Compute Engine and Container Engine Resources
2. You know how to `git clone`
3. You have the gcloud SDK install and initialized somewhere ( do not use the google cloud shell)
Remeber to perform a 'gcloud auth login' before using the gcloud commands below.
## Create Kubernettes Cluster
You can create a cluster using the Google Cloud Console. The Default settings will suffice. For this QuickStart the cluster name used is `owaspbasiccluster`. The `PROJECTNAME` is whatever your project is. The `REGION` is a region/zone near you.
If you want to use the gcloud sdk from a properly initialized gcloud commandline environment use the following command
```
gcloud container --project "PROJECTNAME" clusters create "owaspbasiccluster" --zone "REGION" --machine-type "n1-standard-1" --image-type "COS" --disk-size "100" --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append","https://www.googleapis.com/auth/source.read_only" --num-nodes "3" --network "default" --enable-cloud-logging --no-enable-cloud-monitoring
```
The command creates a similar cluster with more of the options set explicitly.
## Set up Kubectl
Using the commandline gcloud SDK environment you need to set-up 'kubectl'
If you have not already installed 'Kubectl' you can do so with the following command using `gcloud`
- `gcloud components install kubectl`
Then you just run:
- `gcloud container clusters get-credentials owaspbasiccluster --zone REGION --project PROJECTNAME`
## Deploy WebGoat Deployment
Time to deploy the latest DockerImage for WebGoat!
Let's First Make a namespace for this:
- `kubectl create namespace webgoat`
Now it is time to make the magic happen!
- `kubectl create -f /where_you_git_cloned_webgoat/platformQuickStart/GCP/GKE-Docker/webgoat_noDNSnoTLS.yml`
This should complete with no errors.
Use the following command to see information/status about the deployment
- `kubectl describe deployment webgoat-dpl --namespace=webgoat`
After a few minutes the service endpoint should be ready. You can check the status with
- `kubectl describe service webgoatsvc --namespace=webgoat`
In the output you should see a message like "Created load..." after a "Creating load..." which means that the public facing loadbalancer (even thou there is just one container running!) is ready.
If you want to see the Kubernetes dashboard you can run `kubectl proxy` (in a new terminal window) and then navigate to http://localhost:8001/ui .
## Test Deployment
From the previous `describe service` command the `LoadBalancer Ingress:` line should have the external IP. The line below should give the port.
So.....
[IP]:[PORT]/WebGoat in your browser!
DONE

View File

@ -0,0 +1,4 @@
CURTAG=webgoat/webgoat-8.0
DEST_TAG=gcr.io/astech-training/raging-wire-webgoat
CLUSTER_NAME=raging-wire-webgoat
PORT_NUM=8080

View File

@ -0,0 +1,4 @@
CURTAG=webgoat/webgoat-8.0
DEST_TAG=gcr.io/your-gke-project/your-webgoat-tag
CLUSTER_NAME=your-cluster-name
PORT_NUM=8080

View File

@ -0,0 +1,39 @@
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webgoatapp
name: webgoatsvc
namespace: webgoat
spec:
ports:
-
port: 8080
protocol: TCP
selector:
app: webgoatapp
type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webgoat-dpl
namespace: webgoat
spec:
replicas: 1
template:
metadata:
name: webgoatapp
labels:
app: webgoatapp
spec:
containers:
-
image: webgoat/webgoat-8.0
name: webgoat
ports:
-
containerPort: 8080

View File

@ -0,0 +1,17 @@
# WebGoat on GCP!
This folder contains sub folders for the various ways you could deploy WebGoat on Google Cloud Platform
It is assumed:
1. You have a Google Cloud Platform Account
2. You can use Git
3. You can use a Linux/Mac/Google Cloud Shell
## GKE Docker
Uses GKE to run the latest DockerHub version of WebGoat8
## AppEngine
WIP

View File

@ -0,0 +1,22 @@
# OWASP WebGoat Platform Quick Starts
Want to Run WebGoat? Want to run WebGoat in the Cloud? Don't want to be cloud Expert?
Do we have a solution for you!
Additionally, Each IaaS/PaaS will have their deployment steps broken down giving the *app-guy-new-to-cloud* an opportunity to learn how said platform works.
## AWS
Multi-Part Quickstart. Starts with simple pipeline that just builds code to a deploying onto EC2 instances and then containers using ECS/ECR
## GCP
Get WebGoat Running on GKE and AppEngine

22
pom.xml
View File

@ -6,17 +6,13 @@
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<packaging>pom</packaging>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
<name>WebGoat Parent Pom</name>
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
<inceptionYear>2006</inceptionYear>
<url>https://github.com/WebGoat/WebGoat</url>
<prerequisites>
<maven>3.2.5</maven>
</prerequisites>
<organization>
<name>OWASP</name>
<url>https://github.com/WebGoat/WebGoat/</url>
@ -119,8 +115,8 @@
<!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- This build number will be ubdated by Travis-CI -->
<build.number>build</build.number>
@ -138,7 +134,6 @@
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
<java.version>15</java.version>
</properties>
<modules>
@ -193,17 +188,16 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>15</source>
<target>15</target>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<version>3.1.0</version>
<configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
@ -218,7 +212,7 @@
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<configuration>
<targetJdk>15</targetJdk>
<targetJdk>11</targetJdk>
<failurePriority>1</failurePriority><!-- 5 means fail even on the lowest priority, 0 means never fail -->
<rulesets>
<!--suppress UnresolvedMavenProperty -->
@ -249,7 +243,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.1.3</version>
<version>5.3.2</version>
<configuration>
<failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>true</skipProvidedScope>

34
scripts/build-all.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
cd ..
nc -zv 127.0.0.1 8080 2>/dev/null
SUCCESS=$?
nc -zv 127.0.0.1 9090 2>/dev/null
SUCCESS=${SUCCESS}$?
if [[ "${SUCCESS}" -eq 0 ]] ; then
echo "WebGoat and or WebWolf are still running, please stop them first otherwise unit tests might fail!"
exit 127
fi
sh mvnw clean install
if [[ "$?" -ne 0 ]] ; then
exit y$?
fi
cd -
sh build_docker.sh
if [[ "$?" -ne 0 ]] ; then
exit y$?
fi
while true; do
read -p "Do you want to run docker-compose?" yn
case ${yn} in
[Yy]* ) sh clean-run-docker-compose.sh; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done

10
scripts/build_docker.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
WEBGOAT_HOME=$(pwd)/../
cd "${WEBGOAT_HOME}"/webgoat-server
docker build -t webgoat/webgoat-v8.0.0.snapshot .
cd "${WEBGOAT_HOME}"/webwolf
docker build -t webgoat/webwolf-v8.0.0.snapshot .

View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
cd ..
docker-compose rm -f
docker-compose -f docker-compose-local.yml up

16
scripts/deploy-webgoat.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
docker login -u $DOCKER_USER -p $DOCKER_PASS
export REPO=webgoat/goatandwolf
cd ..
cd docker
ls target/
if [ ! -z "${TRAVIS_TAG}" ]; then
# If we push a tag to master this will update the LATEST Docker image and tag with the version number
docker build --build-arg webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} .
docker push $REPO
else
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
fi

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
cd ..
docker-compose up

18
scripts/start.sh Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
DATABASE_PORT=9001
checkDatabaseAvailable(){
#for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)
local started = $(netstat -lnt | grep ${DATABASE_PORT})
echo $?
}
#java -Djava.security.egd=file:/dev/./urandom -jar home/webgoat/webgoat.jar --server.address=0.0.0.0
$(checkDatabaseAvailable)
#java -Djava.security.egd=file:/dev/./urandom -jar /home/webwolf/webwolf.jar --server.port=9090 --server.address=0.0.0.0

View File

@ -9,7 +9,7 @@
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
<build>
@ -70,11 +70,17 @@
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>2.4.3</version>
<version>1.5.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<artifactId>HikariCP</artifactId>
<groupId>com.zaxxer</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
@ -97,6 +103,8 @@
<artifactId>hsqldb</artifactId>
</dependency>
<!-- ************* END spring MVC and related dependencies ************** -->
<!-- ************* START: Dependencies for Unit and Integration Testing ************** -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -105,8 +113,19 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<!-- <version>4.1.3.RELEASE</version>-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<type>jar</type>
<scope>test</scope>
</dependency>
<!-- ************* END: Dependencies for Unit and Integration Testing ************** -->
<!-- ************* END: <dependencies> ************** -->
</dependencies>
</project>

View File

@ -84,7 +84,6 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
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());

View File

@ -1,56 +0,0 @@
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

@ -0,0 +1,50 @@
package org.owasp.webgoat;
import org.flywaydb.core.Flyway;
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 org.springframework.context.annotation.DependsOn;
import javax.sql.DataSource;
import java.util.Map;
/**
* 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.
*/
@Configuration
public class DatabaseInitialization {
private final DataSource dataSource;
private String driverClassName;
public DatabaseInitialization(DataSource dataSource,
@Value("${spring.datasource.driver-class-name}") String driverClassName) {
this.dataSource = dataSource;
this.driverClassName = driverClassName;
}
@Bean(initMethod = "migrate")
public Flyway flyWayContainer() {
return Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.dataSource(dataSource)
.schemas("container")
.locations("db/container")
.load();
}
@Bean(initMethod = "migrate")
@DependsOn("flyWayContainer")
public Flyway flywayLessons() {
return Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.dataSource(dataSource)
.load();
}
}

View File

@ -1,70 +0,0 @@
package org.owasp.webgoat;
import org.owasp.webgoat.lessons.LessonConnectionInvocationHandler;
import org.springframework.jdbc.datasource.ConnectionProxy;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
public class LessonDataSource implements DataSource {
private final DataSource originalDataSource;
public LessonDataSource(DataSource dataSource) {
this.originalDataSource = dataSource;
}
@Override
public Connection getConnection() throws SQLException {
var targetConnection = originalDataSource.getConnection();
return (Connection) Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader(),
new Class[]{ConnectionProxy.class},
new LessonConnectionInvocationHandler(targetConnection));
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return originalDataSource.getConnection(username, password);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return originalDataSource.getLogWriter();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
originalDataSource.setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
originalDataSource.setLoginTimeout(seconds);
}
@Override
public int getLoginTimeout() throws SQLException {
return originalDataSource.getLoginTimeout();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return originalDataSource.getParentLogger();
}
@Override
public <T> T unwrap(Class<T> clazz) throws SQLException {
return originalDataSource.unwrap(clazz);
}
@Override
public boolean isWrapperFor(Class<?> clazz) throws SQLException {
return originalDataSource.isWrapperFor(clazz);
}
}

View File

@ -1,25 +1,18 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
import java.util.Map;
public class OperatingSystemMacro extends InlineMacroProcessor {
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
public OperatingSystemMacro(String macroName) {
super(macroName);
}
public class OperatingSystemMacro extends InlineMacroProcessor {
public OperatingSystemMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var osName = System.getProperty("os.name");
//see https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", osName);
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return System.getProperty("os.name");
}
}

View File

@ -1,31 +0,0 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Map;
public class UsernameMacro extends InlineMacroProcessor {
public UsernameMacro(String macroName) {
super(macroName);
}
public UsernameMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var auth = SecurityContextHolder.getContext().getAuthentication();
var username = "unknown";
if (auth.getPrincipal() instanceof WebGoatUser) {
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
return createPhraseNode(contentNode, "quoted", username);
}
}

View File

@ -1,26 +1,17 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import java.util.Map;
public class WebGoatTmpDirMacro extends InlineMacroProcessor {
public WebGoatTmpDirMacro(String macroName) {
super(macroName);
}
public WebGoatTmpDirMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
//see https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", env);
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
}
}

View File

@ -1,25 +1,17 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import java.util.Map;
public class WebGoatVersionMacro extends InlineMacroProcessor {
public WebGoatVersionMacro(String macroName) {
super(macroName);
}
public WebGoatVersionMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var webgoatVersion = EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
//see https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", webgoatVersion);
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
}
}

View File

@ -1,46 +1,35 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.core.env.Environment;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* Usage in asciidoc:
* <p>
* webWolfLink:here[] will display a href with here as text
* webWolfLink:landing[noLink] will display the complete url, for example: http://WW_HOST:WW_PORT/landing
*/
public class WebWolfMacro extends InlineMacroProcessor {
public WebWolfMacro(String macroName) {
super(macroName);
}
public WebWolfMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv();
var hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
var target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target;
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
Environment env = EnvironmentExposure.getEnv();
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
//are we using noLink in webWolfLink:landing[noLink]? Then display link with full href
if (displayCompleteLinkNoFormatting(attributes)) {
linkText = href;
return hostname + (hostname.endsWith("/") ? "" : "/") + target;
}
var options = new HashMap<String, Object>();
options.put("type", ":link");
options.put("target", href);
attributes.put("window", "_blank");
return createPhraseNode(contentNode, "anchor", linkText, attributes, options).convert();
return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>";
}
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
@ -48,9 +37,9 @@ public class WebWolfMacro extends InlineMacroProcessor {
}
/**
* Determine the host from the hostname and ports that were used.
* Determine the host from the hostname and ports that were used.
* The purpose is to make it possible to use the application behind a reverse proxy. For instance in the docker
* compose/stack version with webgoat webwolf and nginx proxy.
* compose/stack version with webgoat webwolf and nginx proxy.
* You do not have to use the indicated hostname, but if you do, you should define two hosts aliases
* 127.0.0.1 www.webgoat.local www.webwolf.local
*/
@ -58,11 +47,11 @@ public class WebWolfMacro extends InlineMacroProcessor {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
host = request.getHeader("Host");
int semicolonIndex = host.indexOf(":");
if (semicolonIndex == -1 || host.endsWith(":80")) {
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
if (semicolonIndex==-1 || host.endsWith(":80")) {
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
} else {
host = host.substring(0, semicolonIndex);
host = host.concat(":").concat(port);
host = host.substring(0, semicolonIndex);
host = host.concat(":").concat(port);
}
return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : "");
}

View File

@ -10,10 +10,6 @@ import java.util.Map;
*/
public class WebWolfRootMacro extends WebWolfMacro {
public WebWolfRootMacro(String macroName) {
super(macroName);
}
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}

View File

@ -1,36 +0,0 @@
package org.owasp.webgoat.lessons;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
/**
* 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.
*/
public class LessonConnectionInvocationHandler implements InvocationHandler {
private final Connection targetConnection;
public LessonConnectionInvocationHandler(Connection targetConnection) {
this.targetConnection = targetConnection;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
var authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof WebGoatUser) {
var user = (WebGoatUser) authentication.getPrincipal();
targetConnection.createStatement().execute("SET SCHEMA \"" + user.getUsername() + "\"");
}
try {
return method.invoke(targetConnection, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}

View File

@ -36,8 +36,6 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.util.function.Function;
@Controller
@AllArgsConstructor
@Slf4j
@ -45,7 +43,7 @@ public class RestartLessonService {
private final WebSession webSession;
private final UserTrackerRepository userTrackerRepository;
private final Function<String, Flyway> flywayLessons;
private final Flyway flywayLessons;
@RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text")
@ResponseStatus(value = HttpStatus.OK)
@ -57,8 +55,7 @@ public class RestartLessonService {
userTracker.reset(al);
userTrackerRepository.save(userTracker);
var flyway = flywayLessons.apply(webSession.getUserName());
flyway.clean();
flyway.migrate();
flywayLessons.clean();
flywayLessons.migrate();
}
}

View File

@ -14,6 +14,4 @@ public interface UserRepository extends JpaRepository<WebGoatUser, String> {
List<WebGoatUser> findAll();
boolean existsByUsername(String username);
}

View File

@ -1,16 +1,11 @@
package org.owasp.webgoat.users;
import lombok.AllArgsConstructor;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.owasp.webgoat.session.WebSession;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.function.Function;
/**
* @author nbaars
@ -22,8 +17,6 @@ public class UserService implements UserDetailsService {
private final UserRepository userRepository;
private final UserTrackerRepository userTrackerRepository;
private final JdbcTemplate jdbcTemplate;
private final Function<String, Flyway> flywayLessons;
@Override
public WebGoatUser loadUserByUsername(String username) throws UsernameNotFoundException {
@ -38,18 +31,24 @@ public class UserService implements UserDetailsService {
public void addUser(String username, String password) {
//get user if there exists one by the name
var userAlreadyExists = userRepository.existsByUsername(username);
var webGoatUser = userRepository.save(new WebGoatUser(username, password));
if (!userAlreadyExists) {
userTrackerRepository.save(new UserTracker(username)); //if user previously existed it will not get another tracker
createLessonsForUser(webGoatUser);
WebGoatUser webGoatUser = userRepository.findByUsername(username);
//if user exists it will be updated, otherwise created
userRepository.save(new WebGoatUser(username, password));
//if user previously existed it will not get another tracker
if (webGoatUser == null) {
userTrackerRepository.save(new UserTracker(username));
}
}
private void createLessonsForUser(WebGoatUser webGoatUser) {
jdbcTemplate.execute("CREATE SCHEMA \"" + webGoatUser.getUsername() + "\" authorization dba");
flywayLessons.apply(webGoatUser.getUsername()).migrate();
public void addUser(String username, String password, String role) {
//get user if there exists one by the name
WebGoatUser webGoatUser = userRepository.findByUsername(username);
//if user exists it will be updated, otherwise created
userRepository.save(new WebGoatUser(username, password, role));
//if user previously existed it will not get another tracker
if (webGoatUser == null) {
userTrackerRepository.save(new UserTracker(username));
}
}
public List<WebGoatUser> getAllUsers() {

View File

@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@ -15,19 +14,14 @@ import java.sql.SQLException;
@SpringBootApplication
public class TestApplication {
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
/**
* We define our own datasource, otherwise we end up with Hikari one which for some lessons will
* throw an error (feature not supported)
*/
@Bean
@ConditionalOnProperty(prefix = "webgoat.start", name = "hsqldb", havingValue = "false")
@Primary
public DataSource dataSource(@Value("${spring.datasource.url}") String url) throws SQLException {
DriverManager.registerDriver(new JDBCDriver());
return new DriverManagerDataSource(url);
}
}

View File

@ -38,7 +38,6 @@ import org.springframework.web.servlet.i18n.FixedLocaleResolver;
import java.util.Locale;
//Do not remove is the base class for all assignments tests
public class AssignmentEndpointTest {
@Mock
@ -60,6 +59,7 @@ public class AssignmentEndpointTest {
public void init(AssignmentEndpoint a) {
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository);
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
ReflectionTestUtils.setField(a, "webSession", webSession);
ReflectionTestUtils.setField(a, "messages", pluginMessages);

View File

@ -1,8 +1,6 @@
package org.owasp.webgoat.plugins;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.Before;
import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.WebSession;
@ -14,9 +12,7 @@ import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import javax.annotation.PostConstruct;
import java.util.Locale;
import java.util.function.Function;
import static org.mockito.Mockito.when;
@ -35,25 +31,16 @@ public abstract class LessonTest {
protected WebApplicationContext wac;
@Autowired
protected PluginMessages messages;
@Autowired
private Function<String, Flyway> flywayLessons;
@MockBean
protected WebSession webSession;
@MockBean
private Language language;
@BeforeEach
void init() {
@Before
public void init() {
when(webSession.getUserName()).thenReturn("unit-test");
when(language.getLocale()).thenReturn(Locale.getDefault());
}
@PostConstruct
public void createFlywayLessonTables() {
flywayLessons.apply("PUBLIC").migrate();
}
}

View File

@ -0,0 +1,32 @@
package org.owasp.webgoat.plugins;
public class PluginTest {
// @Test
// public void pathShouldBeRewrittenInHtmlFile() throws Exception {
// Path tmpDir = PluginTestHelper.createTmpDir();
// Path pluginSourcePath = PluginTestHelper.pathForLoading();
// Plugin plugin = PluginTestHelper.createPluginFor(TestPlugin.class);
// Path htmlFile = Paths.get(pluginSourcePath.toString(), "lessonSolutions", "rewrite_test.html");
// plugin.loadFiles(Arrays.asList(htmlFile), true);
// plugin.rewritePaths(tmpDir);
// List<String> allLines = Files.readAllLines(htmlFile, StandardCharsets.UTF_8);
//
// assertThat(allLines,
// hasItem(containsString("plugin/TestPlugin/lessonSolutions/en/TestPlugin_files/image001.png")));
// }
//
// @Test
// public void shouldNotRewriteOtherLinks() throws Exception {
// Path tmpDir = PluginTestHelper.createTmpDir();
// Path pluginSourcePath = PluginTestHelper.pathForLoading();
// Plugin plugin = PluginTestHelper.createPluginFor(TestPlugin.class);
// Path htmlFile = Paths.get(pluginSourcePath.toString(), "lessonSolutions", "rewrite_test.html");
// plugin.loadFiles(Arrays.asList(htmlFile), true);
// plugin.rewritePaths(tmpDir);
// List<String> allLines = Files.readAllLines(htmlFile, StandardCharsets.UTF_8);
//
// assertThat(allLines,
// hasItem(containsString("Unknown_files/image001.png")));
// }
}

View File

@ -2,25 +2,28 @@ package org.owasp.webgoat.service;
import com.beust.jcommander.internal.Lists;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.lessons.Assignment;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.session.WebSession;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.List;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.service.HintService.URL_HINTS_MVC;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
@RunWith(MockitoJUnitRunner.class)
public class HintServiceTest {
private MockMvc mockMvc;
@ -31,13 +34,13 @@ public class HintServiceTest {
@Mock
private Assignment assignment;
@BeforeEach
void setup() {
@Before
public void setup() {
this.mockMvc = standaloneSetup(new HintService(websession)).build();
}
@Test
void hintsPerAssignment() throws Exception {
public void hintsPerAssignment() throws Exception {
Assignment assignment = Mockito.mock(Assignment.class);
when(assignment.getPath()).thenReturn("/HttpBasics/attack1");
when(assignment.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2"));

View File

@ -1,15 +1,16 @@
package org.owasp.webgoat.service;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.assignments.LessonTrackerInterceptor;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.users.UserService;
import org.owasp.webgoat.users.UserTrackerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -47,21 +48,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @since November 29, 2016
*/
@WebMvcTest(value = {LabelService.class})
@ActiveProfiles({"test", "webgoat"})
class LabelServiceTest {
@RunWith(SpringRunner.class)
public class LabelServiceTest {
@Autowired
public MockMvc mockMvc;
@MockBean
private UserService userService;
@MockBean
private UserTrackerRepository userTrackerRepository;
@MockBean
private LessonTrackerInterceptor lessonTrackerInterceptor;
@Test
@WithMockUser(username = "guest", password = "guest")
void withoutLocale() throws Exception {
public void withoutLocale() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get(URL_LABELS_MVC))
.andExpect(status().isOk())
.andExpect(jsonPath("password", CoreMatchers.is("Password")));
@ -69,7 +64,7 @@ class LabelServiceTest {
@Test
@WithMockUser(username = "guest", password = "guest")
void withLocale() throws Exception {
public void withLocale() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get(URL_LABELS_MVC).param("lang", "nl"))
.andExpect(status().isOk())
.andExpect(jsonPath("password", CoreMatchers.is("Wachtwoord")));

View File

@ -23,12 +23,12 @@ package org.owasp.webgoat.service;
import com.beust.jcommander.internal.Lists;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.Course;
@ -39,8 +39,6 @@ import org.owasp.webgoat.users.UserTrackerRepository;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.Arrays;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.service.LessonMenuService.URL_LESSONMENU_MVC;
@ -49,7 +47,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
import java.util.Arrays;
@RunWith(MockitoJUnitRunner.class)
public class LessonMenuServiceTest {
@Mock(lenient=true)
@ -64,13 +64,13 @@ public class LessonMenuServiceTest {
private WebSession webSession;
private MockMvc mockMvc;
@BeforeEach
void setup() {
@Before
public void setup() {
this.mockMvc = standaloneSetup(new LessonMenuService(course, webSession, userTrackerRepository, Arrays.asList("none"), Arrays.asList("none"))).build();
}
@Test
void lessonsShouldBeOrdered() throws Exception {
public void lessonsShouldBeOrdered() throws Exception {
Lesson l1 = Mockito.mock(Lesson.class);
Lesson l2 = Mockito.mock(Lesson.class);
when(l1.getTitle()).thenReturn("ZA");
@ -88,7 +88,7 @@ public class LessonMenuServiceTest {
}
@Test
void lessonCompleted() throws Exception {
public void lessonCompleted() throws Exception {
Lesson l1 = Mockito.mock(Lesson.class);
when(l1.getTitle()).thenReturn("ZA");
when(lessonTracker.isLessonSolved()).thenReturn(true);

View File

@ -1,11 +1,11 @@
package org.owasp.webgoat.service;
import org.assertj.core.util.Maps;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.session.WebSession;
@ -54,8 +54,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @version $Id: $Id
* @since November 25, 2016
*/
@ExtendWith(MockitoExtension.class)
class LessonProgressServiceTest {
@RunWith(MockitoJUnitRunner.class)
public class LessonProgressServiceTest {
private MockMvc mockMvc;
@ -70,8 +70,8 @@ class LessonProgressServiceTest {
@Mock
private WebSession websession;
@BeforeEach
void setup() {
@Before
public void setup() {
Assignment assignment = new Assignment("test", "test", List.of());
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
@ -82,7 +82,7 @@ class LessonProgressServiceTest {
}
@Test
void jsonLessonOverview() throws Exception {
public void jsonLessonOverview() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.get("/service/lessonoverview.mvc").accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].assignment.name", is("test")))

View File

@ -1,10 +1,10 @@
package org.owasp.webgoat.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.Course;
@ -26,7 +26,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
@RunWith(MockitoJUnitRunner.class)
public class ReportCardServiceTest {
private MockMvc mockMvc;
@ -45,15 +45,15 @@ public class ReportCardServiceTest {
@Mock
private PluginMessages pluginMessages;
@BeforeEach
void setup() {
@Before
public void setup() {
this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course, pluginMessages)).build();
when(pluginMessages.getMessage(anyString())).thenReturn("Test");
}
@Test
@WithMockUser(username = "guest", password = "guest")
void withLessons() throws Exception {
public void withLessons() throws Exception {
when(lesson.getTitle()).thenReturn("Test");
when(course.getTotalOfLessons()).thenReturn(1);
when(course.getTotalOfAssignments()).thenReturn(10);

View File

@ -0,0 +1,38 @@
package org.owasp.webgoat.session;
/**
* ************************************************************************************************
* 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 - 2014 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>
*
* @author nbaars
* @version $Id: $Id
* @since November 26, 2016
*/
public class CourseTest {
public void number() {
}
}

View File

@ -1,43 +1,45 @@
package org.owasp.webgoat.session;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.Test;
class LabelDebuggerTest {
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class LabelDebuggerTest {
@Test
void testSetEnabledTrue() {
public void testSetEnabledTrue() throws Exception {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(true);
Assertions.assertThat(ld.isEnabled()).isTrue();
assertTrue(ld.isEnabled());
}
@Test
void testSetEnabledFalse() {
public void testSetEnabledFalse() throws Exception {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(false);
Assertions.assertThat((ld.isEnabled())).isFalse();
assertFalse(ld.isEnabled());
}
@Test
void testSetEnabledNullThrowsException() {
public void testSetEnabledNullThrowsException() {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(true);
Assertions.assertThat((ld.isEnabled())).isTrue();
assertTrue(ld.isEnabled());
}
@Test
void testEnableIsTrue() {
public void testEnableIsTrue() {
LabelDebugger ld = new LabelDebugger();
ld.enable();
Assertions.assertThat((ld.isEnabled())).isTrue();
assertTrue(ld.isEnabled());
}
@Test
void testDisableIsFalse() {
public void testDisableIsFalse() {
LabelDebugger ld = new LabelDebugger();
ld.disable();
Assertions.assertThat((ld.isEnabled())).isFalse();
assertFalse(ld.isEnabled());
}

View File

@ -1,7 +1,6 @@
package org.owasp.webgoat.session;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.users.LessonTracker;
@ -10,6 +9,7 @@ import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -42,20 +42,20 @@ import static org.mockito.Mockito.when;
* @version $Id: $Id
* @since November 25, 2016
*/
class LessonTrackerTest {
public class LessonTrackerTest {
@Test
void allAssignmentsSolvedShouldMarkLessonAsComplete() {
public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
Lesson lesson = mock(Lesson.class);
when(lesson.getAssignments()).thenReturn(List.of(new Assignment("assignment", "assignment", List.of(""))));
LessonTracker lessonTracker = new LessonTracker(lesson);
lessonTracker.assignmentSolved("assignment");
Assertions.assertThat(lessonTracker.isLessonSolved()).isTrue();
assertTrue(lessonTracker.isLessonSolved());
}
@Test
void noAssignmentsSolvedShouldMarkLessonAsInComplete() {
public void noAssignmentsSolvedShouldMarkLessonAsInComplete() {
Lesson lesson = mock(Lesson.class);
Assignment a1 = new Assignment("a1");
Assignment a2 = new Assignment("a2");
@ -70,7 +70,7 @@ class LessonTrackerTest {
}
@Test
void solvingSameAssignmentShouldNotAddItTwice() {
public void solvingSameAssignmentShouldNotAddItTwice() {
Lesson lesson = mock(Lesson.class);
Assignment a1 = new Assignment("a1");
List<Assignment> assignments = List.of(a1);

View File

@ -1,20 +1,23 @@
package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
@DataJpaTest
@RunWith(SpringRunner.class)
@ActiveProfiles({"test", "webgoat"})
class UserRepositoryTest {
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void userShouldBeSaved() {
public void userShouldBeSaved() {
WebGoatUser user = new WebGoatUser("test", "password");
userRepository.saveAndFlush(user);

View File

@ -1,37 +1,27 @@
package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.jdbc.core.JdbcTemplate;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.function.Function;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private UserTrackerRepository userTrackerRepository;
@Mock
private JdbcTemplate jdbcTemplate;
@Mock
private Function<String, Flyway> flywayLessons;
@Test
void shouldThrowExceptionWhenUserIsNotFound() {
@Test(expected = UsernameNotFoundException.class)
public void shouldThrowExceptionWhenUserIsNotFound() {
when(userRepository.findByUsername(any())).thenReturn(null);
UserService userService = new UserService(userRepository, userTrackerRepository, jdbcTemplate, flywayLessons);
Assertions.assertThatThrownBy(() -> userService.loadUserByUsername("unknown")).isInstanceOf(UsernameNotFoundException.class);
UserService userService = new UserService(userRepository, userTrackerRepository);
userService.loadUserByUsername("unknown");
}
}

View File

@ -2,19 +2,22 @@ package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.Lesson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@DataJpaTest
@RunWith(SpringRunner.class)
@ActiveProfiles({"test", "webgoat"})
class UserTrackerRepositoryTest {
public class UserTrackerRepositoryTest {
private class TestLesson extends Lesson {
@ -39,8 +42,9 @@ class UserTrackerRepositoryTest {
private UserTrackerRepository userTrackerRepository;
@Test
void saveUserTracker() {
public void saveUserTracker() {
UserTracker userTracker = new UserTracker("test");
LessonTracker lessonTracker = userTracker.getLessonTracker(new TestLesson());
userTrackerRepository.save(userTracker);
@ -49,7 +53,7 @@ class UserTrackerRepositoryTest {
}
@Test
void solvedAssignmentsShouldBeSaved() {
public void solvedAssignmentsShouldBeSaved() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);
@ -64,7 +68,7 @@ class UserTrackerRepositoryTest {
}
@Test
void saveAndLoadShouldHaveCorrectNumberOfAttempts() {
public void saveAndLoadShouldHaveCorrectNumberOfAttemtps() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);

View File

@ -1,25 +1,26 @@
package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class UserValidatorTest {
@RunWith(MockitoJUnitRunner.class)
public class UserValidatorTest {
@Mock
private UserRepository userRepository;
@Test
void passwordsShouldMatch() {
public void passwordsShouldMatch() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test1234");
@ -27,11 +28,11 @@ class UserValidatorTest {
userForm.setMatchingPassword("test1234");
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isFalse();
assertFalse(errors.hasErrors());
}
@Test
void shouldGiveErrorWhenPasswordsDoNotMatch() {
public void shouldGiveErrorWhenPasswordsDoNotMatch() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test1234");
@ -39,12 +40,12 @@ class UserValidatorTest {
userForm.setMatchingPassword("test1234");
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isTrue();
assertTrue(errors.hasErrors());
assertThat(errors.getFieldError("matchingPassword").getCode()).isEqualTo("password.diff");
}
@Test
void shouldGiveErrorWhenUserAlreadyExists() {
public void shouldGiveErrorWhenUserAlreadyExists() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test12345");
@ -53,7 +54,7 @@ class UserValidatorTest {
when(userRepository.findByUsername(anyString())).thenReturn(new WebGoatUser("test1245", "password"));
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isTrue();
assertTrue(errors.hasErrors());
assertThat(errors.getFieldError("username").getCode()).isEqualTo("username.duplicate");
}

View File

@ -0,0 +1,20 @@
package org.owasp.webgoat.util;
public class LabelManagerImplTest {
// @Test
// public void shouldSerialize() throws IOException {
// LabelManagerImpl labelManager = new LabelManagerImpl(null, new LabelDebugger());
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// ObjectOutputStream out = new ObjectOutputStream(bos);
// out.writeObject(labelManager);
// }
//
// @Test
// public void shouldSerializeWithLabelProvider() throws IOException {
// LabelManagerImpl labelManager = new LabelManagerImpl(new LabelProvider(), new LabelDebugger());
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// ObjectOutputStream out = new ObjectOutputStream(bos);
// out.writeObject(labelManager);
// }
}

View File

@ -3,4 +3,3 @@ webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
webgoat.start.hsqldb=false
spring.flyway.locations=classpath:/db/container
spring.main.banner-mode=off

View File

@ -0,0 +1,35 @@
# Setup a Linux box headless which will start WebGoat and WebWolf helpful image to give away during training
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network :forwarded_port, guest: 8080, host: 8080
config.vm.network :forwarded_port, guest: 9090, host: 9090
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = "4096"
vb.cpus = 2
vb.name = "WebGoat-Training"
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
end
config.vm.provider "vmware_fusion" do |vf|
vf.gui = false
vf.vmx["memsize"] = 4096
vf.vmx["numvcpus"] = 2
vf.vmx["displayname"] = "WebGoat-Training"
end
config.vm.provision "shell", inline: <<-SHELL
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webgoat-server-8.0.0.M25.jar
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webwolf-8.0.0.M25.jar
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
sudo apt-get install openjdk-11-jre -y
SHELL
config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL
java -jar webgoat-server-8.0.0.M25.jar --server.address=0.0.0.0 &
sleep 40s
java -jar webwolf-8.0.0.M25.jar --server.address=0.0.0.0 &
SHELL
end

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
<dependencies>
@ -18,7 +18,7 @@
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>4.3.1</version>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -10,25 +10,25 @@ import org.owasp.webgoat.deserialization.SerializationHelper;
public class DeserializationTest extends IntegrationTest {
private static String OS = System.getProperty("os.name").toLowerCase();
private static String OS = System.getProperty("os.name").toLowerCase();
@Test
public void runTests() throws IOException {
startLesson("InsecureDeserialization");
Map<String, Object> params = new HashMap<>();
params.clear();
if (OS.indexOf("win") > -1) {
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5")));
if (OS.indexOf("win")>-1) {
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5")));
} else {
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
}
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
checkAssignment(url("/WebGoat/InsecureDeserialization/task"),params,true);
checkResults("/InsecureDeserialization/");
}
}

View File

@ -7,8 +7,8 @@ import lombok.extern.slf4j.Slf4j;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.owasp.webwolf.WebWolf;
import org.springframework.boot.builder.SpringApplicationBuilder;

View File

@ -1,7 +1,14 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import lombok.SneakyThrows;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach;
@ -11,49 +18,38 @@ import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.security.core.token.Sha512DigestUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import io.restassured.RestAssured;
import lombok.SneakyThrows;
public class PathTraversalTest extends IntegrationTest {
//the JUnit5 way
//the JUnit5 way
@TempDir
Path tempDir;
private File fileToUpload = null;
@BeforeEach
@SneakyThrows
public void init() {
fileToUpload = Files.createFile(
fileToUpload = Files.createFile(
tempDir.resolve("test.jpg")).toFile();
Files.write(fileToUpload.toPath(), "This is a test".getBytes());
startLesson("PathTraversal");
Files.write(fileToUpload.toPath(), "This is a test" .getBytes());
startLesson("PathTraversal");
}
@TestFactory
Iterable<DynamicTest> testPathTraversal() {
return Arrays.asList(
dynamicTest("assignment 1 - profile upload", () -> assignment1()),
dynamicTest("assignment 2 - profile upload fix", () -> assignment2()),
dynamicTest("assignment 3 - profile upload remove user input", () -> assignment3()),
dynamicTest("assignment 4 - profile upload random pic", () -> assignment4()),
dynamicTest("assignment 5 - zip slip", () -> assignment5())
);
return Arrays.asList(
dynamicTest("assignment 1 - profile upload",()-> assignment1()),
dynamicTest("assignment 2 - profile upload fix",()-> assignment2()),
dynamicTest("assignment 3 - profile upload remove user input",()-> assignment3()),
dynamicTest("assignment 4 - profile upload random pic",()-> assignment4())
);
}
public void assignment1() throws IOException {
MatcherAssert.assertThat(
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
@ -67,7 +63,7 @@ public class PathTraversalTest extends IntegrationTest {
}
public void assignment2() throws IOException {
MatcherAssert.assertThat(
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
@ -81,7 +77,7 @@ public class PathTraversalTest extends IntegrationTest {
}
public void assignment3() throws IOException {
MatcherAssert.assertThat(
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
@ -92,7 +88,6 @@ public class PathTraversalTest extends IntegrationTest {
.statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true));
}
public void assignment4() throws IOException {
var uri = "/WebGoat/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
RestAssured.given().urlEncodingEnabled(false)
@ -106,34 +101,10 @@ public class PathTraversalTest extends IntegrationTest {
checkAssignment("/WebGoat/PathTraversal/random", Map.of("secret", Sha512DigestUtils.shaHex(getWebgoatUser())), true);
}
public void assignment5() throws IOException {
var webGoatHome = System.getProperty("user.dir") + "/target/.webgoat/PathTraversal/" + getWebgoatUser();
webGoatHome = webGoatHome.replaceAll("^[a-zA-Z]:", ""); //Remove C: from the home directory on Windows
var webGoatDirectory = new File(webGoatHome);
var zipFile = new File(webGoatDirectory, "upload.zip");
try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory.toString() + "/image.jpg");
zos.putNextEntry(e);
zos.write("test".getBytes(StandardCharsets.UTF_8));
}
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
.post("/WebGoat/PathTraversal/zip-slip")
.then()
.statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true));
}
@AfterEach
public void shutdown() {
//this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete
checkResults("/PathTraversal");
//this will run only once after the list of dynamic tests has run, this is to test if the lesson is marked complete
checkResults("/PathTraversal");
}
}

View File

@ -48,7 +48,7 @@ public class ProgressRaceConditionTest extends IntegrationTest {
throw new IllegalStateException(e);
}
}).count();
System.err.println("counted status 500: "+countStatusCode500);
System.out.println("counted status 500: "+countStatusCode500);
Assertions.assertThat(countStatusCode500).isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS/NUMBER_OF_PARALLEL_THREADS)));
}
}

View File

@ -50,8 +50,8 @@ public class SeleniumTest extends IntegrationTest {
driver.findElement(By.name("agree")).click();
driver.findElement(By.className("btn-primary")).click();
}
} catch (Exception e) {
System.err.println("Selenium test failed "+System.getProperty("webdriver.gecko.driver")+", message: "+e.getMessage());
} catch (IllegalStateException e) {
System.err.println("Web driver not found here: "+System.getProperty("webdriver.gecko.driver"));
}
}

View File

@ -43,6 +43,10 @@ public class SqlInjectionLessonTest extends IntegrationTest {
params.put("query", sql_4_add);
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
params.clear();
params.put("query", sql_4_drop);
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, false);
params.clear();
params.put("query", sql_5);
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
</project>

View File

@ -27,7 +27,7 @@ package org.owasp.webgoat.auth_bypass;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
@ -43,12 +43,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
@RunWith(MockitoJUnitRunner.class)
public class BypassVerificationTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
@Before
public void setup() {
VerifyAccount verifyAccount = new VerifyAccount();
init(verifyAccount);

View File

@ -6,6 +6,6 @@
<parent>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
</project>

View File

@ -24,10 +24,7 @@ package org.owasp.webgoat.bypass_restrictions;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@RestController
public class BypassRestrictionsFrontendValidation extends AssignmentEndpoint {

View File

@ -1,11 +1,11 @@
package org.owasp.webgoat.bypass_restrictions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@ -18,20 +18,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author nbaars
* @since 6/16/17.
*/
@ExtendWith(SpringExtension.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class BypassRestrictionsFrontendValidationTest extends LessonTest {
@Autowired
private BypassRestrictions bypassRestrictions;
@BeforeEach
@Before
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(bypassRestrictions);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
void noChangesShouldNotPassTheLesson() throws Exception {
public void noChangesShouldNotPassTheLesson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "123")
@ -45,7 +45,7 @@ public class BypassRestrictionsFrontendValidationTest extends LessonTest {
}
@Test
void bypassAllFieldShouldPass() throws Exception {
public void bypassAllFieldShouldPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abcd")
.param("field2", "1234")
@ -59,7 +59,7 @@ public class BypassRestrictionsFrontendValidationTest extends LessonTest {
}
@Test
void notBypassingAllFieldShouldNotPass() throws Exception {
public void notBypassingAllFieldShouldNotPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "1234")

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
@ -14,7 +14,7 @@
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -24,8 +24,15 @@
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>4.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<type>jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -22,8 +22,13 @@
package org.owasp.webgoat.challenges;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import javax.annotation.PostConstruct;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.WebSession;
@ -37,11 +42,8 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author nbaars

View File

@ -4,10 +4,7 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.challenges.Flag;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;

View File

@ -1,16 +1,17 @@
package org.owasp.webgoat.challenges.challenge1;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.security.SecureRandom;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.SecureRandom;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
@WebServlet(name = "ImageServlet", urlPatterns = "/challenge/logo")
public class ImageServlet extends HttpServlet {

View File

@ -23,7 +23,6 @@
package org.owasp.webgoat.challenges.challenge5;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.LessonDataSource;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.challenges.Flag;
@ -41,9 +40,9 @@ import java.sql.ResultSet;
@Slf4j
public class Assignment5 extends AssignmentEndpoint {
private final LessonDataSource dataSource;
private final DataSource dataSource;
public Assignment5(LessonDataSource dataSource) {
public Assignment5(DataSource dataSource) {
this.dataSource = dataSource;
}

View File

@ -12,12 +12,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;

View File

@ -1,11 +1,12 @@
package org.owasp.webgoat.challenges.challenge7;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.io.*;
/**
* MD5 hash generator.
* More information about this class is available from <a target="_top" href=

View File

@ -23,10 +23,10 @@
package org.owasp.webgoat.challenges;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.challenges.challenge1.Assignment1;
import org.owasp.webgoat.challenges.challenge1.ImageServlet;
@ -35,6 +35,8 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.net.InetAddress;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.challenges.SolutionConstants.PASSWORD;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ -42,13 +44,13 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal
* @author nbaars
* @since 5/2/17.
*/
@ExtendWith(MockitoExtension.class)
class Assignment1Test extends AssignmentEndpointTest {
@RunWith(MockitoJUnitRunner.class)
public class Assignment1Test extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
void setup() {
@Before
public void setup() {
Assignment1 assignment1 = new Assignment1();
init(assignment1);
new Flag().initFlags();
@ -56,7 +58,7 @@ class Assignment1Test extends AssignmentEndpointTest {
}
@Test
void success() throws Exception {
public void success() throws Exception {
InetAddress addr = InetAddress.getLocalHost();
String host = addr.getHostAddress();
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
@ -68,7 +70,7 @@ class Assignment1Test extends AssignmentEndpointTest {
}
@Test
void wrongPassword() throws Exception {
public void wrongPassword() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
.param("username", "admin")
.param("password", "wrong"))

View File

@ -6,6 +6,6 @@
<parent>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
</project>

View File

@ -25,10 +25,7 @@ package org.owasp.webgoat.chrome_dev_tools;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.UserSessionData;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* This is just a class used to make the the HTTP request.

View File

@ -26,10 +26,7 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* Assignment where the user has to look through an HTTP Request

View File

@ -1,15 +1,17 @@
package org.owasp.webgoat.chrome_dev_tools;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -18,13 +20,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author Benedikt Stuhrmann
* @since 13/03/19.
*/
@ExtendWith(SpringExtension.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class ChromeDevToolsTest extends LessonTest {
@Autowired
private ChromeDevTools cdt;
@BeforeEach
@Before
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(cdt);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();

View File

@ -6,6 +6,6 @@
<parent>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId>
<version>8.2.0</version>
<version>8.2.0-SNAPSHOT</version>
</parent>
</project>

View File

@ -2,11 +2,7 @@ package org.owasp.webgoat.cia;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@RestController
public class CIAQuiz extends AssignmentEndpoint {

View File

@ -1,11 +1,11 @@
package org.owasp.webgoat.cia;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@ -19,13 +19,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author Benedikt Stuhrmann
* @since 13/03/19.
*/
@ExtendWith(SpringExtension.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class CIAQuizTest extends LessonTest {
@Autowired
private CIA cia;
@BeforeEach
@Before
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(cia);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();

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