Compare commits
	
		
			65 Commits
		
	
	
		
			v2025.0
			...
			7c019cf2ab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7c019cf2ab | |||
| f209d57e22 | |||
| 2cd85583ee | |||
| 9f64a3209a | |||
| f263888c03 | |||
| 11b8425e45 | |||
| 28f6eee326 | |||
| 1dfcf5b271 | |||
| 4a884b5332 | |||
| 7b95daa7bf | |||
| c69efc52e4 | |||
| 0e4206b8f1 | |||
| 60ffca7e56 | |||
| 1812bacaa7 | |||
| 327f9effbd | |||
| db7daa227f | |||
| 95df44ca29 | |||
| 2d549e4579 | |||
| f2e2616a88 | |||
| f6c2996cd4 | |||
| c25bc7d7a6 | |||
| 953e7fd206 | |||
| e4cb868623 | |||
| 5efbd03d98 | |||
| 7fabcc7fd5 | |||
| 27ab9f89fa | |||
| 06c0be257f | |||
| 8b324b3954 | |||
| cba4ff3d48 | |||
| ca68d6bcf4 | |||
| f6990690de | |||
| 634162f279 | |||
| 9f77d74f3e | |||
| 55ea361f45 | |||
| fc6c61397d | |||
| f45bf6171b | |||
| b3dec8bdc9 | |||
| c3f9158eab | |||
| ec3b9e8aaf | |||
| 9ec75d5a56 | |||
| 49dc370931 | |||
| 1e1a8af39e | |||
| 451f5615d2 | |||
| a4305f408e | |||
| 7dea5a1bde | |||
| 8cd0b0a8c9 | |||
| 72c09f7240 | |||
| d8c402f0d6 | |||
| 95136c9930 | |||
| 23d6fe6f36 | |||
| 2c5e4c4491 | |||
| c89fcb140a | |||
| 3cfd053c83 | |||
| 10adb1b05f | |||
| c3ed45a733 | |||
| e2f80b18e2 | |||
| 641f24df9d | |||
| 3b3933b69e | |||
| 05497371db | |||
| 32cf225d6b | |||
| affa3f7a1c | |||
| e9f79cc739 | |||
| c37a8e8c19 | |||
| 5eeeee1e66 | |||
| 0d4cc06342 | 
							
								
								
									
										18
									
								
								.gitea/workflows/datadog-sca.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.gitea/workflows/datadog-sca.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | 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 | ||||||
							
								
								
									
										21
									
								
								.gitea/workflows/datadog-secrets-scanning.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.gitea/workflows/datadog-secrets-scanning.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | 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 | ||||||
							
								
								
									
										23
									
								
								.gitea/workflows/datadog-static-analysis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.gitea/workflows/datadog-static-analysis.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | 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 | ||||||
							
								
								
									
										169
									
								
								.gitea/workflows/release.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								.gitea/workflows/release.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | 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: "*/3 * * * *" | ||||||
|  |  | ||||||
|  |   # 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: 2 # 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 | ||||||
|  |  | ||||||
|  |           # 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 $SLEVE_SECONDS | ||||||
|  |             fi | ||||||
|  |           done | ||||||
|  |  | ||||||
|  |           echo "Finished creating $COMMIT_COUNT commits and triggering workflows." | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @ -68,7 +68,7 @@ jobs: | |||||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|       - name: "Set up QEMU" |       - name: "Set up QEMU" | ||||||
|         uses: docker/setup-qemu-action@v3.4.0 |         uses: docker/setup-qemu-action@v3.6.0 | ||||||
|         with: |         with: | ||||||
|           platforms: all |           platforms: all | ||||||
|  |  | ||||||
| @ -76,13 +76,13 @@ jobs: | |||||||
|         uses: docker/setup-buildx-action@v3 |         uses: docker/setup-buildx-action@v3 | ||||||
|  |  | ||||||
|       - name: "Login to dockerhub" |       - name: "Login to dockerhub" | ||||||
|         uses: docker/login-action@v3.3.0 |         uses: docker/login-action@v3.4.0 | ||||||
|         with: |         with: | ||||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} |           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} |           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||||
|  |  | ||||||
|       - name: "Build and push WebGoat" |       - name: "Build and push WebGoat" | ||||||
|         uses: docker/build-push-action@v6.14.0 |         uses: docker/build-push-action@v6.16.0 | ||||||
|         with: |         with: | ||||||
|           context: ./ |           context: ./ | ||||||
|           file: ./Dockerfile |           file: ./Dockerfile | ||||||
| @ -95,7 +95,7 @@ jobs: | |||||||
|             webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} |             webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} | ||||||
|  |  | ||||||
|       - name: "Build and push WebGoat desktop" |       - name: "Build and push WebGoat desktop" | ||||||
|         uses: docker/build-push-action@v6.14.0 |         uses: docker/build-push-action@v6.16.0 | ||||||
|         with: |         with: | ||||||
|           context: ./ |           context: ./ | ||||||
|           file: ./Dockerfile_desktop |           file: ./Dockerfile_desktop | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -39,7 +39,6 @@ UserDatabase.mv.db | |||||||
| webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props | webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props | ||||||
| webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom | webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom | ||||||
| webgoat-lessons/**/target | webgoat-lessons/**/target | ||||||
| **/*.jar |  | ||||||
| **/.DS_Store | **/.DS_Store | ||||||
| webgoat-server/mongo-data/* | webgoat-server/mongo-data/* | ||||||
| webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml | webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								.mvn/wrapper/maven-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								.mvn/wrapper/maven-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								.mvn/wrapper/maven-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.mvn/wrapper/maven-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,2 @@ | |||||||
| distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip | 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 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar | ||||||
|  | |||||||
| @ -8,7 +8,8 @@ and 2023.01 in the `pom.xml`. | |||||||
| ### Release notes: | ### Release notes: | ||||||
|  |  | ||||||
| Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of | Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of | ||||||
| committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main` | 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 | mvn versions:set | ||||||
| @ -17,5 +18,9 @@ mvn verify | |||||||
| git commit .... | git commit .... | ||||||
| git tag v2023.01 | git tag v2023.01 | ||||||
| git push --tags | 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. | ||||||
|  |  | ||||||
|  | |||||||
| @ -99,7 +99,7 @@ For a full overview of all the parameters you can use, please check the [WebGoat | |||||||
|  |  | ||||||
| ### Prerequisites: | ### Prerequisites: | ||||||
|  |  | ||||||
| * Java 17 or 21 | * Java 23 | ||||||
| * Your favorite IDE | * Your favorite IDE | ||||||
| * Git, or Git support in your IDE | * Git, or Git support in your IDE | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,6 +1,24 @@ | |||||||
| # WebGoat release notes | # WebGoat release notes | ||||||
|  |  | ||||||
| ## Version 2025.0 | ## 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 | ### 🚀 New functionality | ||||||
|  |  | ||||||
| @ -43,6 +61,19 @@ | |||||||
|  |  | ||||||
| - Lots of dependency updates | - 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 | ## Version 2023.8 | ||||||
|  |  | ||||||
| ### 🚀 New functionality | ### 🚀 New functionality | ||||||
|  | |||||||
| @ -3,12 +3,12 @@ | |||||||
|  |  | ||||||
| <head> | <head> | ||||||
|   <meta charset="utf-8"> |   <meta charset="utf-8"> | ||||||
|   <meta http-equiv="refresh" content="0;url=https://owasp.org/www-project-webgoat/" /> |   <meta http-equiv="refresh" content="0;url=https://webgoat.org" /> | ||||||
|   <link rel="canonical" href="https://owasp.org/www-project-webgoat/" /> |   <link rel="canonical" href="https://webgoat.org" /> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| <h1> | <h1> | ||||||
|   The page been moved to <a href="https://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a> |   The page been moved to <a href="https://webgoat.org">https://webgoat.org</a> | ||||||
| </h1> | </h1> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								fake_commit_log.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								fake_commit_log.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | 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 | ||||||
							
								
								
									
										33
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								pom.xml
									
									
									
									
									
								
							| @ -5,12 +5,12 @@ | |||||||
|   <parent> |   <parent> | ||||||
|     <groupId>org.springframework.boot</groupId> |     <groupId>org.springframework.boot</groupId> | ||||||
|     <artifactId>spring-boot-starter-parent</artifactId> |     <artifactId>spring-boot-starter-parent</artifactId> | ||||||
|     <version>3.4.3</version> |     <version>3.4.4</version> | ||||||
|   </parent> |   </parent> | ||||||
|  |  | ||||||
|   <groupId>org.owasp.webgoat</groupId> |   <groupId>org.owasp.webgoat</groupId> | ||||||
|   <artifactId>webgoat</artifactId> |   <artifactId>webgoat</artifactId> | ||||||
|   <version>2025.0</version> |   <version>2025.4-SNAPSHOT</version> | ||||||
|   <packaging>jar</packaging> |   <packaging>jar</packaging> | ||||||
|  |  | ||||||
|   <name>WebGoat</name> |   <name>WebGoat</name> | ||||||
| @ -63,29 +63,29 @@ | |||||||
|   <properties> |   <properties> | ||||||
|     <!-- Shared properties with plugins and version numbers across submodules--> |     <!-- Shared properties with plugins and version numbers across submodules--> | ||||||
|     <asciidoctorj.version>3.0.0</asciidoctorj.version> |     <asciidoctorj.version>3.0.0</asciidoctorj.version> | ||||||
|     <bootstrap.version>5.3.3</bootstrap.version> |     <bootstrap.version>5.3.5</bootstrap.version> | ||||||
|     <cglib.version>3.3.0</cglib.version> |     <cglib.version>3.3.0</cglib.version> | ||||||
|     <!-- do not update necessary for lesson --> |     <!-- do not update necessary for lesson --> | ||||||
|     <checkstyle.version>3.6.0</checkstyle.version> |     <checkstyle.version>3.6.0</checkstyle.version> | ||||||
|     <commons-collections.version>3.2.1</commons-collections.version> |     <commons-collections.version>3.2.1</commons-collections.version> | ||||||
|     <commons-compress.version>1.27.1</commons-compress.version> |     <commons-compress.version>1.27.1</commons-compress.version> | ||||||
|     <commons-io.version>2.18.0</commons-io.version> |     <commons-io.version>2.19.0</commons-io.version> | ||||||
|     <commons-lang3.version>3.14.0</commons-lang3.version> |     <commons-lang3.version>3.14.0</commons-lang3.version> | ||||||
|     <commons-text.version>1.13.0</commons-text.version> |     <commons-text.version>1.13.1</commons-text.version> | ||||||
|     <guava.version>33.4.0-jre</guava.version> |     <guava.version>33.4.8-jre</guava.version> | ||||||
|     <jacoco.version>0.8.11</jacoco.version> |     <jacoco.version>0.8.11</jacoco.version> | ||||||
|     <java.version>23</java.version> |     <java.version>23</java.version> | ||||||
|     <jaxb.version>2.3.1</jaxb.version> |     <jaxb.version>2.3.1</jaxb.version> | ||||||
|     <jjwt.version>0.9.1</jjwt.version> |     <jjwt.version>0.9.1</jjwt.version> | ||||||
|     <jose4j.version>0.9.3</jose4j.version> |     <jose4j.version>0.9.3</jose4j.version> | ||||||
|     <jquery.version>3.7.1</jquery.version> |     <jquery.version>3.7.1</jquery.version> | ||||||
|     <jsoup.version>1.18.3</jsoup.version> |     <jsoup.version>1.19.1</jsoup.version> | ||||||
|     <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> |     <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> | ||||||
|     <maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version> |     <maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version> | ||||||
|     <maven-jar-plugin.version>3.1.2</maven-jar-plugin.version> |     <maven-jar-plugin.version>3.1.2</maven-jar-plugin.version> | ||||||
|     <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> |     <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> | ||||||
|     <maven-source-plugin.version>3.1.0</maven-source-plugin.version> |     <maven-source-plugin.version>3.1.0</maven-source-plugin.version> | ||||||
|     <maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version> |     <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> | ||||||
|     <maven.compiler.proc>full</maven.compiler.proc> |     <maven.compiler.proc>full</maven.compiler.proc> | ||||||
|     <maven.compiler.source>23</maven.compiler.source> |     <maven.compiler.source>23</maven.compiler.source> | ||||||
|     <maven.compiler.target>23</maven.compiler.target> |     <maven.compiler.target>23</maven.compiler.target> | ||||||
| @ -96,14 +96,14 @@ | |||||||
|     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||||
|     <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version> |     <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version> | ||||||
|     <waittimeForServerStart>60</waittimeForServerStart> |     <waittimeForServerStart>60</waittimeForServerStart> | ||||||
|     <webdriver.version>5.9.3</webdriver.version> |     <webdriver.version>6.0.1</webdriver.version> | ||||||
|     <webgoat.context>/WebGoat</webgoat.context> |     <webgoat.context>/WebGoat</webgoat.context> | ||||||
|     <webgoat.port>8080</webgoat.port> |     <webgoat.port>8080</webgoat.port> | ||||||
|     <webgoat.sslenabled>false</webgoat.sslenabled> |     <webgoat.sslenabled>false</webgoat.sslenabled> | ||||||
|     <webjars-locator-core.version>0.59</webjars-locator-core.version> |     <webjars-locator-core.version>0.59</webjars-locator-core.version> | ||||||
|     <webwolf.context>/WebWolf</webwolf.context> |     <webwolf.context>/WebWolf</webwolf.context> | ||||||
|     <webwolf.port>9090</webwolf.port> |     <webwolf.port>9090</webwolf.port> | ||||||
|     <wiremock.version>3.12.0</wiremock.version> |     <wiremock.version>3.13.0</wiremock.version> | ||||||
|     <xml-resolver.version>1.2</xml-resolver.version> |     <xml-resolver.version>1.2</xml-resolver.version> | ||||||
|     <xstream.version>1.4.5</xstream.version> |     <xstream.version>1.4.5</xstream.version> | ||||||
|     <!-- do not update necessary for lesson --> |     <!-- do not update necessary for lesson --> | ||||||
| @ -217,12 +217,12 @@ | |||||||
|       <dependency> |       <dependency> | ||||||
|         <groupId>org.jruby</groupId> |         <groupId>org.jruby</groupId> | ||||||
|         <artifactId>jruby</artifactId> |         <artifactId>jruby</artifactId> | ||||||
|         <version>9.4.12.0</version> |         <version>10.0.0.1</version> | ||||||
|       </dependency> |       </dependency> | ||||||
|       <dependency> |       <dependency> | ||||||
|         <groupId>com.microsoft.playwright</groupId> |         <groupId>com.microsoft.playwright</groupId> | ||||||
|         <artifactId>playwright</artifactId> |         <artifactId>playwright</artifactId> | ||||||
|         <version>1.50.0</version> |         <version>1.51.0</version> | ||||||
|       </dependency> |       </dependency> | ||||||
|     </dependencies> |     </dependencies> | ||||||
|   </dependencyManagement> |   </dependencyManagement> | ||||||
| @ -238,7 +238,7 @@ | |||||||
|     <dependency> |     <dependency> | ||||||
|       <groupId>org.projectlombok</groupId> |       <groupId>org.projectlombok</groupId> | ||||||
|       <artifactId>lombok</artifactId> |       <artifactId>lombok</artifactId> | ||||||
|       <version>1.18.36</version> |       <version>1.18.38</version> | ||||||
|       <scope>provided</scope> |       <scope>provided</scope> | ||||||
|       <optional>true</optional> |       <optional>true</optional> | ||||||
|     </dependency> |     </dependency> | ||||||
| @ -510,7 +510,7 @@ | |||||||
|         <configuration> |         <configuration> | ||||||
|           <forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds> |           <forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds> | ||||||
|           <!-- Necessary for vulnerable components lesson --> |           <!-- Necessary for vulnerable components lesson --> | ||||||
|           <argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED |           <argLine>--enable-native-access=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED | ||||||
|           --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED |           --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED | ||||||
|           --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED |           --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED | ||||||
|           --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED |           --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED | ||||||
| @ -536,7 +536,7 @@ | |||||||
|       <plugin> |       <plugin> | ||||||
|         <groupId>com.diffplug.spotless</groupId> |         <groupId>com.diffplug.spotless</groupId> | ||||||
|         <artifactId>spotless-maven-plugin</artifactId> |         <artifactId>spotless-maven-plugin</artifactId> | ||||||
|         <version>2.44.3</version> |         <version>2.44.4</version> | ||||||
|         <configuration> |         <configuration> | ||||||
|           <formats> |           <formats> | ||||||
|             <format> |             <format> | ||||||
| @ -694,6 +694,7 @@ | |||||||
|                     <argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> |                     <argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> | ||||||
|                     <argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> |                     <argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> | ||||||
|                     <argument>-Dspring.main.banner-mode=off</argument> |                     <argument>-Dspring.main.banner-mode=off</argument> | ||||||
|  |                     <argument>--enable-native-access=ALL-UNNAMED</argument> | ||||||
|                     <argument>--add-opens</argument> |                     <argument>--add-opens</argument> | ||||||
|                     <argument>java.base/java.lang=ALL-UNNAMED</argument> |                     <argument>java.base/java.lang=ALL-UNNAMED</argument> | ||||||
|                     <argument>--add-opens</argument> |                     <argument>--add-opens</argument> | ||||||
|  | |||||||
| @ -4,12 +4,9 @@ | |||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.integration; | package org.owasp.webgoat.integration; | ||||||
|  |  | ||||||
| import static org.junit.jupiter.api.Assertions.assertTrue; |  | ||||||
|  |  | ||||||
| import io.restassured.RestAssured; | import io.restassured.RestAssured; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import org.assertj.core.api.Assertions; | import org.assertj.core.api.Assertions; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| @ -57,19 +54,6 @@ public class ChallengeIntegrationTest extends IntegrationTest { | |||||||
|     checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true); |     checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true); | ||||||
|  |  | ||||||
|     checkResults("Challenge1"); |     checkResults("Challenge1"); | ||||||
|  |  | ||||||
|       List<String> capturefFlags = |  | ||||||
|         RestAssured.given() |  | ||||||
|             .when() |  | ||||||
|             .relaxedHTTPSValidation() |  | ||||||
|             .cookie("JSESSIONID", getWebGoatCookie()) |  | ||||||
|             .get(webGoatUrlConfig.url("scoreboard-data")) |  | ||||||
|             .then() |  | ||||||
|             .statusCode(200) |  | ||||||
|             .extract() |  | ||||||
|             .jsonPath() |  | ||||||
|             .get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured"); |  | ||||||
|     assertTrue(capturefFlags.contains("Admin lost password")); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Test |   @Test | ||||||
| @ -99,19 +83,6 @@ public class ChallengeIntegrationTest extends IntegrationTest { | |||||||
|     checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true); |     checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true); | ||||||
|  |  | ||||||
|     checkResults("Challenge5"); |     checkResults("Challenge5"); | ||||||
|  |  | ||||||
|       List<String> capturefFlags = |  | ||||||
|         RestAssured.given() |  | ||||||
|             .when() |  | ||||||
|             .relaxedHTTPSValidation() |  | ||||||
|             .cookie("JSESSIONID", getWebGoatCookie()) |  | ||||||
|             .get(webGoatUrlConfig.url("scoreboard-data")) |  | ||||||
|             .then() |  | ||||||
|             .statusCode(200) |  | ||||||
|             .extract() |  | ||||||
|             .jsonPath() |  | ||||||
|             .get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured"); |  | ||||||
|     assertTrue(capturefFlags.contains("Without password")); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Test |   @Test | ||||||
| @ -162,7 +133,9 @@ public class ChallengeIntegrationTest extends IntegrationTest { | |||||||
|             .when() |             .when() | ||||||
|             .relaxedHTTPSValidation() |             .relaxedHTTPSValidation() | ||||||
|             .cookie("JSESSIONID", getWebGoatCookie()) |             .cookie("JSESSIONID", getWebGoatCookie()) | ||||||
|             .get(webGoatUrlConfig.url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2") |             .get( | ||||||
|  |                 webGoatUrlConfig.url("challenge/7/reset-password/{link}"), | ||||||
|  |                 "375afe1104f4a487a73823c50a9292a2") | ||||||
|             .then() |             .then() | ||||||
|             .statusCode(HttpStatus.ACCEPTED.value()) |             .statusCode(HttpStatus.ACCEPTED.value()) | ||||||
|             .extract() |             .extract() | ||||||
|  | |||||||
| @ -7,9 +7,6 @@ package org.owasp.webgoat.integration; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  */ |  | ||||||
| class SessionManagementIT extends IntegrationTest { | class SessionManagementIT extends IntegrationTest { | ||||||
|  |  | ||||||
|   private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login"; |   private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login"; | ||||||
|  | |||||||
| @ -15,17 +15,16 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest { | |||||||
|     startLesson("SqlInjectionAdvanced"); |     startLesson("SqlInjectionAdvanced"); | ||||||
|  |  | ||||||
|     Map<String, Object> params = new HashMap<>(); |     Map<String, Object> params = new HashMap<>(); | ||||||
|     params.clear(); |  | ||||||
|     params.put("username_reg", "tom' AND substring(password,1,1)='t"); |     params.put("username_reg", "tom' AND substring(password,1,1)='t"); | ||||||
|     params.put("password_reg", "password"); |     params.put("password_reg", "password"); | ||||||
|     params.put("email_reg", "someone@microsoft.com"); |     params.put("email_reg", "someone@microsoft.com"); | ||||||
|     params.put("confirm_password", "password"); |     params.put("confirm_password", "password"); | ||||||
|       checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge"), params, true); |       checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/register"), params, false); | ||||||
|  |  | ||||||
|     params.clear(); |     params.clear(); | ||||||
|     params.put("username_login", "tom"); |     params.put("username_login", "tom"); | ||||||
|     params.put("password_login", "thisisasecretfortomonly"); |     params.put("password_login", "thisisasecretfortomonly"); | ||||||
|       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge_Login"), params, true); |       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/login"), params, true); | ||||||
|  |  | ||||||
|     params.clear(); |     params.clear(); | ||||||
|     params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); |     params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); | ||||||
| @ -59,7 +58,5 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest { | |||||||
|         "question_4_solution", |         "question_4_solution", | ||||||
|         "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); |         "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); | ||||||
|       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true); |       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true); | ||||||
|  |  | ||||||
|     checkResults("SqlInjectionAdvanced"); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,12 +19,17 @@ public class PlaywrightTest { | |||||||
|   public static class WebGoatOptions implements OptionsFactory { |   public static class WebGoatOptions implements OptionsFactory { | ||||||
|     @Override |     @Override | ||||||
|     public Options getOptions() { |     public Options getOptions() { | ||||||
|       return new Options().setHeadless(true).setContextOptions(getContextOptions()); |       return new Options() | ||||||
|  |               .setHeadless(true) | ||||||
|  |               .setContextOptions(getContextOptions()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected static Browser.NewContextOptions getContextOptions() { |   protected static Browser.NewContextOptions getContextOptions() { | ||||||
|     return new Browser.NewContextOptions().setBaseURL(webGoatUrlConfig.getBaseUrl()); |     return new Browser.NewContextOptions() | ||||||
|  |             .setLocale("en-US") | ||||||
|  |             .setBaseURL(webGoatUrlConfig.getBaseUrl()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static String webGoatUrl(String path) { |   public static String webGoatUrl(String path) { | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ public class RegistrationUITest extends PlaywrightTest { | |||||||
|   @Test |   @Test | ||||||
|   @DisplayName("Should register a new user") |   @DisplayName("Should register a new user") | ||||||
|   void registerNewUser(Browser browser) { |   void registerNewUser(Browser browser) { | ||||||
|     var page = browser.newContext().newPage(); |     var page = browser.newContext(new Browser.NewContextOptions().setLocale("en-US")).newPage(); | ||||||
|     var registrationPage = new RegistrationPage(page); |     var registrationPage = new RegistrationPage(page); | ||||||
|     registrationPage.open(); |     registrationPage.open(); | ||||||
|  |  | ||||||
|  | |||||||
| @ -33,19 +33,19 @@ public class Authentication { | |||||||
|  |  | ||||||
|   public static Page sylvester(Browser browser) { |   public static Page sylvester(Browser browser) { | ||||||
|     User user = login(browser, sylvester); |     User user = login(browser, sylvester); | ||||||
|     return browser.newContext(new Browser.NewContextOptions().setStorageState(user.auth)).newPage(); |     return browser.newContext(new Browser.NewContextOptions().setLocale("en-US").setStorageState(user.auth)).newPage(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static Page tweety(Browser browser) { |   public static Page tweety(Browser browser) { | ||||||
|     User user = login(browser, tweety); |     User user = login(browser, tweety); | ||||||
|     return browser.newContext(new Browser.NewContextOptions().setStorageState(user.auth)).newPage(); |     return browser.newContext(new Browser.NewContextOptions().setLocale("en-US").setStorageState(user.auth)).newPage(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private static User login(Browser browser, User user) { |   private static User login(Browser browser, User user) { | ||||||
|     if (user.loggedIn()) { |     if (user.loggedIn()) { | ||||||
|       return user; |       return user; | ||||||
|     } |     } | ||||||
|     var page = browser.newContext().newPage(); |     var page = browser.newContext(new Browser.NewContextOptions().setLocale("en-US")).newPage(); | ||||||
|     RegistrationPage registrationPage = new RegistrationPage(page); |     RegistrationPage registrationPage = new RegistrationPage(page); | ||||||
|     registrationPage.open(); |     registrationPage.open(); | ||||||
|     registrationPage.register(user.name, user.password); |     registrationPage.register(user.name, user.password); | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors |  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||||
|  * SPDX-License-Identifier: GPL-2.0-or-later |  * SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.playwright.webgoat; | package org.owasp.webgoat.playwright.webgoat.lessons; | ||||||
| 
 | 
 | ||||||
| import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; | import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; | ||||||
| 
 | 
 | ||||||
| @ -15,8 +15,9 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.owasp.webgoat.container.lessons.LessonName; | import org.owasp.webgoat.container.lessons.LessonName; | ||||||
|  | import org.owasp.webgoat.playwright.webgoat.PlaywrightTest; | ||||||
| import org.owasp.webgoat.playwright.webgoat.helpers.Authentication; | import org.owasp.webgoat.playwright.webgoat.helpers.Authentication; | ||||||
| import org.owasp.webgoat.playwright.webgoat.pages.HttpBasicsLessonPage; | import org.owasp.webgoat.playwright.webgoat.pages.lessons.HttpBasicsLessonPage; | ||||||
| 
 | 
 | ||||||
| @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||||
| public class HttpBasicsLessonUITest extends PlaywrightTest { | public class HttpBasicsLessonUITest extends PlaywrightTest { | ||||||
| @ -0,0 +1,120 @@ | |||||||
|  | /* | ||||||
|  |  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||||
|  |  * SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  */ | ||||||
|  | package org.owasp.webgoat.playwright.webgoat.lessons; | ||||||
|  |  | ||||||
|  | import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; | ||||||
|  |  | ||||||
|  | import com.microsoft.playwright.Browser; | ||||||
|  | import com.microsoft.playwright.Page; | ||||||
|  | import com.microsoft.playwright.Page.GetByRoleOptions; | ||||||
|  | import com.microsoft.playwright.options.AriaRole; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.DisplayName; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.owasp.webgoat.container.lessons.LessonName; | ||||||
|  | import org.owasp.webgoat.playwright.webgoat.PlaywrightTest; | ||||||
|  | import org.owasp.webgoat.playwright.webgoat.helpers.Authentication; | ||||||
|  | import org.owasp.webgoat.playwright.webgoat.pages.lessons.LessonPage; | ||||||
|  |  | ||||||
|  | public class SqlInjectionAdvancedUITest extends PlaywrightTest { | ||||||
|  |  | ||||||
|  |   private LessonPage lessonPage; | ||||||
|  |  | ||||||
|  |   @BeforeEach | ||||||
|  |   void navigateToLesson(Browser browser) { | ||||||
|  |     var lessonName = new LessonName("SqlInjectionAdvanced"); | ||||||
|  |     var page = Authentication.sylvester(browser); | ||||||
|  |  | ||||||
|  |     this.lessonPage = new LessonPage(page); | ||||||
|  |     lessonPage.resetLesson(lessonName); | ||||||
|  |     lessonPage.open(lessonName); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName("Login as Tom with incorrect password") | ||||||
|  |   void loginAsTomWithIncorrectPassword() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Login")).click(); | ||||||
|  |     page.locator("[name='username_login']").fill("tom"); | ||||||
|  |     page.locator("[name='password_login']").fill("test"); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Log In")).click(); | ||||||
|  |  | ||||||
|  |     assertThat(lessonPage.getAssignmentOutput()) | ||||||
|  |         .containsText("Wrong username or password. Try again."); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName("Login as Tom with correct password") | ||||||
|  |   void loginAsTomWithCorrectPassword() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Login")).click(); | ||||||
|  |     page.locator("[name='username_login']").fill("tom"); | ||||||
|  |     page.locator("[name='password_login']").fill("thisisasecretfortomonly"); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Log In")).click(); | ||||||
|  |  | ||||||
|  |     lessonPage.isAssignmentSolved(5); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName("Register as Tom should show error that Tom already exists") | ||||||
|  |   void registerAsTomShouldDisplayError() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click(); | ||||||
|  |     page.locator("[name='username_reg']").fill("tom"); | ||||||
|  |     page.locator("[name='email_reg']").fill("tom@tom.org"); | ||||||
|  |     page.locator("[name='password_reg']").fill("test"); | ||||||
|  |     page.locator("[name='confirm_password_reg']").fill("test"); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click(); | ||||||
|  |  | ||||||
|  |     assertThat(lessonPage.getAssignmentOutput()).containsText("User tom already exists"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName( | ||||||
|  |       "Using SQL Injection to register as Tom to guess the password and the guess is correct") | ||||||
|  |   void startGuessingCorrect() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click(); | ||||||
|  |     page.locator("[name='username_reg']").fill("tom' AND substring(password,1,1)='t"); | ||||||
|  |     page.locator("[name='email_reg']").fill("tom@tom.org"); | ||||||
|  |     page.locator("[name='password_reg']").fill("test"); | ||||||
|  |     page.locator("[name='confirm_password_reg']").fill("test"); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click(); | ||||||
|  |  | ||||||
|  |     assertThat(lessonPage.getAssignmentOutput()) | ||||||
|  |         .containsText("User tom' AND substring(password,1,1)='t already exists"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName( | ||||||
|  |       "Using SQL Injection to register as Tom to guess the password and the guess is incorrect") | ||||||
|  |   void startGuessingIncorrect() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click(); | ||||||
|  |     page.locator("[name='username_reg']").fill("tom' AND substring(password,1,1)='a"); | ||||||
|  |     page.locator("[name='email_reg']").fill("tom@tom.org"); | ||||||
|  |     page.locator("[name='password_reg']").fill("test"); | ||||||
|  |     page.locator("[name='confirm_password_reg']").fill("test"); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click(); | ||||||
|  |  | ||||||
|  |     assertThat(lessonPage.getAssignmentOutput()) | ||||||
|  |         .containsText( | ||||||
|  |             "User tom' AND substring(password,1,1)='a created, please proceed to the login page."); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   @DisplayName("Should display correct hints") | ||||||
|  |   void shouldDisplayCorrectHints() { | ||||||
|  |     lessonPage.navigateTo(5); | ||||||
|  |     var page = lessonPage.getPage(); | ||||||
|  |     page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Show hints")).click(); | ||||||
|  |     assertThat(lessonPage.getAssignmentOutput()).containsText("Look at the different"); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -2,7 +2,7 @@ | |||||||
|  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors |  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||||
|  * SPDX-License-Identifier: GPL-2.0-or-later |  * SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.playwright.webgoat.pages; | package org.owasp.webgoat.playwright.webgoat.pages.lessons; | ||||||
| 
 | 
 | ||||||
| import com.microsoft.playwright.Locator; | import com.microsoft.playwright.Locator; | ||||||
| import com.microsoft.playwright.Page; | import com.microsoft.playwright.Page; | ||||||
| @ -2,7 +2,7 @@ | |||||||
|  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors |  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||||
|  * SPDX-License-Identifier: GPL-2.0-or-later |  * SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.playwright.webgoat.pages; | package org.owasp.webgoat.playwright.webgoat.pages.lessons; | ||||||
| 
 | 
 | ||||||
| import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl; | import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl; | ||||||
| 
 | 
 | ||||||
| @ -14,7 +14,7 @@ import org.assertj.core.api.Assertions; | |||||||
| import org.owasp.webgoat.container.lessons.LessonName; | import org.owasp.webgoat.container.lessons.LessonName; | ||||||
| 
 | 
 | ||||||
| @Getter | @Getter | ||||||
| class LessonPage { | public class LessonPage { | ||||||
| 
 | 
 | ||||||
|   private final Page page; |   private final Page page; | ||||||
| 
 | 
 | ||||||
| @ -65,4 +65,8 @@ class LessonPage { | |||||||
|   public Locator getAssignmentOutput() { |   public Locator getAssignmentOutput() { | ||||||
|     return page.locator("#lesson-content-wrapper"); |     return page.locator("#lesson-content-wrapper"); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   public Locator getHintsOutput() { | ||||||
|  |     return page.locator("#lesson-hint"); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @ -42,8 +42,6 @@ public class VulnerableTaskHolder implements Serializable { | |||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Execute a task when de-serializing a saved or received object. |    * Execute a task when de-serializing a saved or received object. | ||||||
|    * |  | ||||||
|    * @author stupid develop |  | ||||||
|    */ |    */ | ||||||
|   private void readObject(ObjectInputStream stream) throws Exception { |   private void readObject(ObjectInputStream stream) throws Exception { | ||||||
|     // unserialize data so taskName and taskAction are available |     // unserialize data so taskName and taskAction are available | ||||||
|  | |||||||
| @ -11,11 +11,6 @@ import java.io.IOException; | |||||||
| import org.springframework.security.core.AuthenticationException; | import org.springframework.security.core.AuthenticationException; | ||||||
| import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; | import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * AjaxAuthenticationEntryPoint class. |  | ||||||
|  * |  | ||||||
|  * @author zupzup |  | ||||||
|  */ |  | ||||||
| public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { | public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { | ||||||
|   public AjaxAuthenticationEntryPoint(String loginFormUrl) { |   public AjaxAuthenticationEntryPoint(String loginFormUrl) { | ||||||
|     super(loginFormUrl); |     super(loginFormUrl); | ||||||
|  | |||||||
| @ -47,17 +47,26 @@ public class LessonTemplateResolver extends FileTemplateResolver { | |||||||
|     var templateName = resourceName.substring(PREFIX.length()); |     var templateName = resourceName.substring(PREFIX.length()); | ||||||
|     byte[] resource = resources.get(templateName); |     byte[] resource = resources.get(templateName); | ||||||
|     if (resource == null) { |     if (resource == null) { | ||||||
|       try { |       resource = loadAndCache(templateName); | ||||||
|         resource = |  | ||||||
|             resourceLoader |  | ||||||
|                 .getResource("classpath:/" + templateName) |  | ||||||
|                 .getInputStream() |  | ||||||
|                 .readAllBytes(); |  | ||||||
|       } catch (IOException e) { |  | ||||||
|         log.error("Unable to find lesson HTML: {}", template); |  | ||||||
|     } |     } | ||||||
|       resources.put(templateName, resource); |  | ||||||
|  |     if (resource == null) { | ||||||
|  |       return new StringTemplateResource("Unable to find lesson HTML: %s".formatted(templateName)); | ||||||
|     } |     } | ||||||
|     return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8)); |     return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   private byte[] loadAndCache(String templateName) { | ||||||
|  |     try { | ||||||
|  |       var resource = | ||||||
|  |           resourceLoader.getResource("classpath:/" + templateName).getInputStream().readAllBytes(); | ||||||
|  |       resources.put(templateName, resource); | ||||||
|  |       return resource; | ||||||
|  |     } catch (IOException e) { | ||||||
|  |       log.error( | ||||||
|  |           "Unable to find lesson HTML: '{}', does the name of HTML file name match the lesson class name?", | ||||||
|  |           templateName); | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -53,7 +53,6 @@ public class MvcConfiguration implements WebMvcConfigurer { | |||||||
|     registry.addViewController("/login").setViewName("login"); |     registry.addViewController("/login").setViewName("login"); | ||||||
|     registry.addViewController("/lesson_content").setViewName("lesson_content"); |     registry.addViewController("/lesson_content").setViewName("lesson_content"); | ||||||
|     registry.addViewController("/start.mvc").setViewName("main_new"); |     registry.addViewController("/start.mvc").setViewName("main_new"); | ||||||
|     registry.addViewController("/scoreboard").setViewName("scoreboard"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Bean |   @Bean | ||||||
|  | |||||||
| @ -4,11 +4,9 @@ | |||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.container.assignments; | package org.owasp.webgoat.container.assignments; | ||||||
|  |  | ||||||
| import org.owasp.webgoat.container.i18n.PluginMessages; |  | ||||||
|  |  | ||||||
| public class AttackResultBuilder { | public class AttackResultBuilder { | ||||||
|  |  | ||||||
|   private boolean lessonCompleted; |   private boolean assignmentCompleted; | ||||||
|   private Object[] feedbackArgs; |   private Object[] feedbackArgs; | ||||||
|   private String feedbackResourceBundleKey; |   private String feedbackResourceBundleKey; | ||||||
|   private String output; |   private String output; | ||||||
| @ -16,15 +14,8 @@ public class AttackResultBuilder { | |||||||
|   private AssignmentEndpoint assignment; |   private AssignmentEndpoint assignment; | ||||||
|   private boolean attemptWasMade = false; |   private boolean attemptWasMade = false; | ||||||
|  |  | ||||||
|   public AttackResultBuilder lessonCompleted(boolean lessonCompleted) { |   public AttackResultBuilder assignmentCompleted(boolean lessonCompleted) { | ||||||
|     this.lessonCompleted = lessonCompleted; |     this.assignmentCompleted = lessonCompleted; | ||||||
|     this.feedbackResourceBundleKey = "lesson.completed"; |  | ||||||
|     return this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) { |  | ||||||
|     this.lessonCompleted = lessonCompleted; |  | ||||||
|     this.feedbackResourceBundleKey = resourceBundleKey; |  | ||||||
|     return this; |     return this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @ -55,7 +46,7 @@ public class AttackResultBuilder { | |||||||
|  |  | ||||||
|   public AttackResult build() { |   public AttackResult build() { | ||||||
|     return new AttackResult( |     return new AttackResult( | ||||||
|         lessonCompleted, |             assignmentCompleted, | ||||||
|         feedbackResourceBundleKey, |         feedbackResourceBundleKey, | ||||||
|         feedbackArgs, |         feedbackArgs, | ||||||
|         output, |         output, | ||||||
| @ -81,7 +72,7 @@ public class AttackResultBuilder { | |||||||
|    */ |    */ | ||||||
|   public static AttackResultBuilder success(AssignmentEndpoint assignment) { |   public static AttackResultBuilder success(AssignmentEndpoint assignment) { | ||||||
|     return new AttackResultBuilder() |     return new AttackResultBuilder() | ||||||
|         .lessonCompleted(true) |         .assignmentCompleted(true) | ||||||
|         .attemptWasMade() |         .attemptWasMade() | ||||||
|         .feedback("assignment.solved") |         .feedback("assignment.solved") | ||||||
|         .assignment(assignment); |         .assignment(assignment); | ||||||
| @ -99,13 +90,13 @@ public class AttackResultBuilder { | |||||||
|    */ |    */ | ||||||
|   public static AttackResultBuilder failed(AssignmentEndpoint assignment) { |   public static AttackResultBuilder failed(AssignmentEndpoint assignment) { | ||||||
|     return new AttackResultBuilder() |     return new AttackResultBuilder() | ||||||
|         .lessonCompleted(false) |         .assignmentCompleted(false) | ||||||
|         .attemptWasMade() |         .attemptWasMade() | ||||||
|         .feedback("assignment.not.solved") |         .feedback("assignment.not.solved") | ||||||
|         .assignment(assignment); |         .assignment(assignment); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) { |   public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) { | ||||||
|     return new AttackResultBuilder().lessonCompleted(false).assignment(assignment); |     return new AttackResultBuilder().assignmentCompleted(false).assignment(assignment); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,12 +10,6 @@ import org.springframework.stereotype.Controller; | |||||||
| import org.springframework.web.bind.annotation.GetMapping; | import org.springframework.web.bind.annotation.GetMapping; | ||||||
| import org.springframework.web.servlet.ModelAndView; | import org.springframework.web.servlet.ModelAndView; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Welcome class. |  | ||||||
|  * |  | ||||||
|  * @author rlawson |  | ||||||
|  * @version $Id: $Id |  | ||||||
|  */ |  | ||||||
| @Controller | @Controller | ||||||
| public class Welcome { | public class Welcome { | ||||||
|  |  | ||||||
|  | |||||||
| @ -11,8 +11,6 @@ import org.springframework.context.support.ReloadableResourceBundleMessageSource | |||||||
| /** | /** | ||||||
|  * ExposedReloadableResourceMessageBundleSource class. Extends the reloadable message source with a |  * ExposedReloadableResourceMessageBundleSource class. Extends the reloadable message source with a | ||||||
|  * way to get all messages |  * way to get all messages | ||||||
|  * |  | ||||||
|  * @author zupzup |  | ||||||
|  */ |  */ | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| public class Messages extends ReloadableResourceBundleMessageSource { | public class Messages extends ReloadableResourceBundleMessageSource { | ||||||
|  | |||||||
| @ -84,7 +84,7 @@ public class CourseConfiguration { | |||||||
|  |  | ||||||
|   @Bean |   @Bean | ||||||
|   public Course course() { |   public Course course() { | ||||||
|     assignments.stream().forEach(this::attachToLesson); |     assignments.forEach(this::attachToLesson); | ||||||
|  |  | ||||||
|     // Check if all assignments are attached to a lesson |     // Check if all assignments are attached to a lesson | ||||||
|     var assignmentsAttachedToLessons = |     var assignmentsAttachedToLessons = | ||||||
| @ -99,7 +99,7 @@ public class CourseConfiguration { | |||||||
|  |  | ||||||
|   private List<String> findDiff() { |   private List<String> findDiff() { | ||||||
|     var matchedToLessons = |     var matchedToLessons = | ||||||
|         lessons.stream().flatMap(l -> l.getAssignments().stream()).map(a -> a.getName()).toList(); |         lessons.stream().flatMap(l -> l.getAssignments().stream()).map(Assignment::getName).toList(); | ||||||
|     var allAssignments = assignments.stream().map(a -> a.getClass().getSimpleName()).toList(); |     var allAssignments = assignments.stream().map(a -> a.getClass().getSimpleName()).toList(); | ||||||
|  |  | ||||||
|     var diff = new ArrayList<>(allAssignments); |     var diff = new ArrayList<>(allAssignments); | ||||||
|  | |||||||
| @ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons; | |||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * LessonInfoModel class. |  | ||||||
|  * |  | ||||||
|  * @author dm |  | ||||||
|  * @version $Id: $Id |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| public class LessonInfoModel { | public class LessonInfoModel { | ||||||
|  | |||||||
| @ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons; | |||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * LessonMenuItem class. |  | ||||||
|  * |  | ||||||
|  * @author rlawson |  | ||||||
|  * @version $Id: $Id |  | ||||||
|  */ |  | ||||||
| public class LessonMenuItem { | public class LessonMenuItem { | ||||||
|  |  | ||||||
|   private String name; |   private String name; | ||||||
|  | |||||||
| @ -18,11 +18,6 @@ import org.springframework.web.bind.annotation.GetMapping; | |||||||
| import org.springframework.web.bind.annotation.PathVariable; | import org.springframework.web.bind.annotation.PathVariable; | ||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * LessonProgressService class. |  | ||||||
|  * |  | ||||||
|  * @author webgoat |  | ||||||
|  */ |  | ||||||
| @Controller | @Controller | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
| public class LessonProgressService { | public class LessonProgressService { | ||||||
|  | |||||||
| @ -6,12 +6,6 @@ package org.owasp.webgoat.container.session; | |||||||
|  |  | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * LabelDebugger class. |  | ||||||
|  * |  | ||||||
|  * @author dm |  | ||||||
|  * @version $Id: $Id |  | ||||||
|  */ |  | ||||||
| public class LabelDebugger implements Serializable { | public class LabelDebugger implements Serializable { | ||||||
|  |  | ||||||
|   private boolean enabled = false; |   private boolean enabled = false; | ||||||
|  | |||||||
| @ -84,6 +84,6 @@ public class LessonProgress { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   long numberOfSolvedAssignments() { |   long numberOfSolvedAssignments() { | ||||||
|     return assignments.size(); |     return assignments.stream().filter(AssignmentProgress::isSolved).count(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,10 +20,6 @@ import org.springframework.web.bind.annotation.GetMapping; | |||||||
| import org.springframework.web.bind.annotation.ModelAttribute; | import org.springframework.web.bind.annotation.ModelAttribute; | ||||||
| import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.PostMapping; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Controller | @Controller | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
| @Slf4j | @Slf4j | ||||||
|  | |||||||
| @ -1,83 +0,0 @@ | |||||||
| /* |  | ||||||
|  * SPDX-FileCopyrightText: Copyright © 2017 WebGoat authors |  | ||||||
|  * SPDX-License-Identifier: GPL-2.0-or-later |  | ||||||
|  */ |  | ||||||
| package org.owasp.webgoat.container.users; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Optional; |  | ||||||
| import java.util.stream.Collectors; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Getter; |  | ||||||
| import org.owasp.webgoat.container.i18n.PluginMessages; |  | ||||||
| import org.owasp.webgoat.container.lessons.Lesson; |  | ||||||
| import org.owasp.webgoat.container.session.Course; |  | ||||||
| import org.springframework.web.bind.annotation.GetMapping; |  | ||||||
| import org.springframework.web.bind.annotation.RestController; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Temp endpoint just for the CTF. |  | ||||||
|  * |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/23/17. |  | ||||||
|  */ |  | ||||||
| @RestController |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class Scoreboard { |  | ||||||
|  |  | ||||||
|   private final UserProgressRepository userTrackerRepository; |  | ||||||
|   private final UserRepository userRepository; |  | ||||||
|   private final Course course; |  | ||||||
|   private final PluginMessages pluginMessages; |  | ||||||
|  |  | ||||||
|   @AllArgsConstructor |  | ||||||
|   @Getter |  | ||||||
|   private class Ranking { |  | ||||||
|     private String username; |  | ||||||
|     private List<String> flagsCaptured; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @GetMapping("/scoreboard-data") |  | ||||||
|   public List<Ranking> getRankings() { |  | ||||||
|     return userRepository.findAll().stream() |  | ||||||
|         .filter(user -> !user.getUsername().startsWith("csrf-")) |  | ||||||
|         .map( |  | ||||||
|             user -> |  | ||||||
|                 new Ranking( |  | ||||||
|                     user.getUsername(), |  | ||||||
|                     challengesSolved(userTrackerRepository.findByUser(user.getUsername())))) |  | ||||||
|         .sorted((o1, o2) -> o2.getFlagsCaptured().size() - o1.getFlagsCaptured().size()) |  | ||||||
|         .collect(Collectors.toList()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private List<String> challengesSolved(UserProgress userTracker) { |  | ||||||
|     List<String> challenges = |  | ||||||
|         List.of( |  | ||||||
|             "Challenge1", |  | ||||||
|             "Challenge2", |  | ||||||
|             "Challenge3", |  | ||||||
|             "Challenge4", |  | ||||||
|             "Challenge5", |  | ||||||
|             "Challenge6", |  | ||||||
|             "Challenge7", |  | ||||||
|             "Challenge8", |  | ||||||
|             "Challenge9"); |  | ||||||
|     return challenges.stream() |  | ||||||
|         .map(userTracker::getLessonProgress) |  | ||||||
|         .flatMap(Optional::stream) |  | ||||||
|         .filter(LessonProgress::isLessonSolved) |  | ||||||
|         .map(LessonProgress::getLessonName) |  | ||||||
|         .map(this::toLessonTitle) |  | ||||||
|         .toList(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private String toLessonTitle(String id) { |  | ||||||
|     String titleKey = |  | ||||||
|         course.getLessons().stream() |  | ||||||
|             .filter(l -> l.getId().equals(id)) |  | ||||||
|             .findFirst() |  | ||||||
|             .map(Lesson::getTitle) |  | ||||||
|             .orElse("No title"); |  | ||||||
|     return pluginMessages.getMessage(titleKey, titleKey); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -10,10 +10,6 @@ import jakarta.validation.constraints.Size; | |||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Setter | @Setter | ||||||
| public class UserForm { | public class UserForm { | ||||||
|  | |||||||
| @ -41,7 +41,7 @@ public class UserProgress { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Returns an existing lesson tracker or create a new one based on the lesson |    * Returns an existing lesson progress or create a new one based on the lesson | ||||||
|    * |    * | ||||||
|    * @param lesson the lesson |    * @param lesson the lesson | ||||||
|    * @return a lesson tracker created if not already present |    * @return a lesson tracker created if not already present | ||||||
| @ -49,7 +49,7 @@ public class UserProgress { | |||||||
|   public LessonProgress getLessonProgress(Lesson lesson) { |   public LessonProgress getLessonProgress(Lesson lesson) { | ||||||
|     Optional<LessonProgress> progress = |     Optional<LessonProgress> progress = | ||||||
|         lessonProgress.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); |         lessonProgress.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); | ||||||
|     if (!progress.isPresent()) { |     if (progress.isEmpty()) { | ||||||
|       LessonProgress newLessonTracker = new LessonProgress(lesson); |       LessonProgress newLessonTracker = new LessonProgress(lesson); | ||||||
|       lessonProgress.add(newLessonTracker); |       lessonProgress.add(newLessonTracker); | ||||||
|       return newLessonTracker; |       return newLessonTracker; | ||||||
| @ -58,16 +58,6 @@ public class UserProgress { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Query method for finding a specific lesson tracker based on id |  | ||||||
|    * |  | ||||||
|    * @param id the id of the lesson |  | ||||||
|    * @return optional due to the fact we can only create a lesson tracker based on a lesson |  | ||||||
|    */ |  | ||||||
|   public Optional<LessonProgress> getLessonProgress(String id) { |  | ||||||
|     return lessonProgress.stream().filter(l -> l.getLessonName().equals(id)).findFirst(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public void assignmentSolved(Lesson lesson, String assignmentName) { |   public void assignmentSolved(Lesson lesson, String assignmentName) { | ||||||
|     LessonProgress progress = getLessonProgress(lesson); |     LessonProgress progress = getLessonProgress(lesson); | ||||||
|     progress.incrementAttempts(); |     progress.incrementAttempts(); | ||||||
|  | |||||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.container.users; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import org.springframework.data.jpa.repository.JpaRepository; | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| public interface UserRepository extends JpaRepository<WebGoatUser, String> { | public interface UserRepository extends JpaRepository<WebGoatUser, String> { | ||||||
|  |  | ||||||
|   WebGoatUser findByUsername(String username); |   WebGoatUser findByUsername(String username); | ||||||
|  | |||||||
| @ -14,10 +14,6 @@ import org.springframework.security.core.userdetails.UserDetailsService; | |||||||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Service | @Service | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| public class UserService implements UserDetailsService { | public class UserService implements UserDetailsService { | ||||||
|  | |||||||
| @ -10,10 +10,6 @@ import lombok.Getter; | |||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
| import org.springframework.data.annotation.Id; | import org.springframework.data.annotation.Id; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/15/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||||||
|  | |||||||
| @ -9,10 +9,6 @@ import org.springframework.stereotype.Component; | |||||||
| import org.springframework.validation.Errors; | import org.springframework.validation.Errors; | ||||||
| import org.springframework.validation.Validator; | import org.springframework.validation.Validator; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| public class UserValidator implements Validator { | public class UserValidator implements Validator { | ||||||
|  | |||||||
| @ -15,10 +15,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; | |||||||
| import org.springframework.security.core.userdetails.User; | import org.springframework.security.core.userdetails.User; | ||||||
| import org.springframework.security.core.userdetails.UserDetails; | import org.springframework.security.core.userdetails.UserDetails; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Entity | @Entity | ||||||
| public class WebGoatUser implements UserDetails { | public class WebGoatUser implements UserDetails { | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/21/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class ChallengeIntro extends Lesson { | public class ChallengeIntro extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -9,10 +9,6 @@ import java.time.LocalDateTime; | |||||||
| import lombok.Builder; | import lombok.Builder; | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @Builder | @Builder | ||||||
| @Data | @Data | ||||||
| public class Email implements Serializable { | public class Email implements Serializable { | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/21/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class Challenge1 extends Lesson { | public class Challenge1 extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/21/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class Challenge5 extends Lesson { | public class Challenge5 extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -29,10 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/8/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @Slf4j | @Slf4j | ||||||
| public class Assignment7 implements AssignmentEndpoint { | public class Assignment7 implements AssignmentEndpoint { | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/21/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class Challenge7 extends Lesson { | public class Challenge7 extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,9 +8,6 @@ import java.util.Random; | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * WARNING: DO NOT CHANGE FILE WITHOUT CHANGING .git contents |  * WARNING: DO NOT CHANGE FILE WITHOUT CHANGING .git contents | ||||||
|  * |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/17/17. |  | ||||||
|  */ |  */ | ||||||
| public class PasswordResetLink { | public class PasswordResetLink { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/21/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class Challenge8 extends Lesson { | public class Challenge8 extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author TMelzer |  | ||||||
|  * @since 30.11.18 |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class ChromeDevTools extends Lesson { | public class ChromeDevTools extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -15,12 +15,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * This is just a class used to make the HTTP request. |  | ||||||
|  * |  | ||||||
|  * @author TMelzer |  | ||||||
|  * @since 30.11.18 |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class NetworkDummy implements AssignmentEndpoint { | public class NetworkDummy implements AssignmentEndpoint { | ||||||
|  |  | ||||||
|  | |||||||
| @ -19,9 +19,6 @@ import org.springframework.web.bind.annotation.RestController; | |||||||
| /** | /** | ||||||
|  * Assignment where the user has to look through an HTTP Request using the Developer Tools and find |  * Assignment where the user has to look through an HTTP Request using the Developer Tools and find | ||||||
|  * a specific number. |  * a specific number. | ||||||
|  * |  | ||||||
|  * @author TMelzer |  | ||||||
|  * @since 30.11.18 |  | ||||||
|  */ |  */ | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints({"networkHint1", "networkHint2"}) | @AssignmentHints({"networkHint1", "networkHint2"}) | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author BenediktStuhrmann |  | ||||||
|  * @since 11/2/18. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class CIA extends Lesson { | public class CIA extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -15,10 +15,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/6/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints({ | @AssignmentHints({ | ||||||
|   "client.side.filtering.free.hint1", |   "client.side.filtering.free.hint1", | ||||||
|  | |||||||
| @ -15,10 +15,6 @@ import org.springframework.web.bind.annotation.PathVariable; | |||||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/6/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("/clientSideFiltering/challenge-store") | @RequestMapping("/clientSideFiltering/challenge-store") | ||||||
| public class ShopEndpoint { | public class ShopEndpoint { | ||||||
|  | |||||||
| @ -10,10 +10,6 @@ import lombok.Getter; | |||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/8/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Setter | @Setter | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
|  | |||||||
| @ -8,12 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /*** |  | ||||||
|  * |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| @Component | @Component | ||||||
| public class HijackSession extends Lesson { | public class HijackSession extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -21,12 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /*** |  | ||||||
|  * |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints({ | @AssignmentHints({ | ||||||
|   "hijacksession.hints.1", |   "hijacksession.hints.1", | ||||||
|  | |||||||
| @ -9,9 +9,6 @@ import lombok.Builder; | |||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @ToString | @ToString | ||||||
| public class Authentication implements Principal { | public class Authentication implements Principal { | ||||||
|  | |||||||
| @ -6,9 +6,6 @@ package org.owasp.webgoat.lessons.hijacksession.cas; | |||||||
|  |  | ||||||
| import java.security.Principal; | import java.security.Principal; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  */ |  | ||||||
| @FunctionalInterface | @FunctionalInterface | ||||||
| public interface AuthenticationProvider<T extends Principal> { | public interface AuthenticationProvider<T extends Principal> { | ||||||
|  |  | ||||||
|  | |||||||
| @ -15,10 +15,6 @@ import org.apache.commons.lang3.StringUtils; | |||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
| import org.springframework.web.context.annotation.ApplicationScope; | import org.springframework.web.context.annotation.ApplicationScope; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| // weak id value and mechanism | // weak id value and mechanism | ||||||
|  |  | ||||||
| @ApplicationScope | @ApplicationScope | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/22/17. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class JWT extends Lesson { | public class JWT extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -4,10 +4,6 @@ | |||||||
|  */ |  */ | ||||||
| package org.owasp.webgoat.lessons.jwt.votes; | package org.owasp.webgoat.lessons.jwt.votes; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/30/17. |  | ||||||
|  */ |  | ||||||
| public class Views { | public class Views { | ||||||
|   public interface GuestView {} |   public interface GuestView {} | ||||||
|  |  | ||||||
|  | |||||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.lessons.jwt.votes; | |||||||
| import com.fasterxml.jackson.annotation.JsonView; | import com.fasterxml.jackson.annotation.JsonView; | ||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 5/2/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| public class Vote { | public class Vote { | ||||||
|   @JsonView(Views.GuestView.class) |   @JsonView(Views.GuestView.class) | ||||||
|  | |||||||
| @ -17,10 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class QuestionsAssignment implements AssignmentEndpoint { | public class QuestionsAssignment implements AssignmentEndpoint { | ||||||
|  |  | ||||||
|  | |||||||
| @ -29,10 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| import org.springframework.web.servlet.ModelAndView; | import org.springframework.web.servlet.ModelAndView; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints({ | @AssignmentHints({ | ||||||
|   "password-reset-hint1", |   "password-reset-hint1", | ||||||
|  | |||||||
| @ -22,12 +22,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Part of the password reset assignment. Used to send the e-mail. |  | ||||||
|  * |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class ResetLinkAssignmentForgotPassword implements AssignmentEndpoint { | public class ResetLinkAssignmentForgotPassword implements AssignmentEndpoint { | ||||||
|  |  | ||||||
|  | |||||||
| @ -17,12 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Assignment for picking a good security question. |  | ||||||
|  * |  | ||||||
|  * @author Tobias Melzer |  | ||||||
|  * @since 11.12.18 |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class SecurityQuestionAssignment implements AssignmentEndpoint { | public class SecurityQuestionAssignment implements AssignmentEndpoint { | ||||||
|  |  | ||||||
|  | |||||||
| @ -23,10 +23,6 @@ import org.springframework.web.bind.annotation.RestController; | |||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class SimpleMailAssignment implements AssignmentEndpoint { | public class SimpleMailAssignment implements AssignmentEndpoint { | ||||||
|   private final String webWolfURL; |   private final String webWolfURL; | ||||||
|  | |||||||
| @ -9,10 +9,6 @@ import jakarta.validation.constraints.Size; | |||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/18/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Setter | @Setter | ||||||
| public class PasswordChangeForm { | public class PasswordChangeForm { | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author BenediktStuhrmann |  | ||||||
|  * @since 12/2/18. |  | ||||||
|  */ |  | ||||||
| @Component | @Component | ||||||
| public class SecurePasswords extends Lesson { | public class SecurePasswords extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,12 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | |||||||
| import org.owasp.webgoat.container.lessons.Lesson; | import org.owasp.webgoat.container.lessons.Lesson; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| /*** |  | ||||||
|  * |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| @Component | @Component | ||||||
| public class SpoofCookie extends Lesson { | public class SpoofCookie extends Lesson { | ||||||
|  |  | ||||||
|  | |||||||
| @ -25,12 +25,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /*** |  | ||||||
|  * |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| @AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"}) | @AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"}) | ||||||
| @RestController | @RestController | ||||||
| public class SpoofCookieAssignment implements AssignmentEndpoint { | public class SpoofCookieAssignment implements AssignmentEndpoint { | ||||||
|  | |||||||
| @ -9,12 +9,6 @@ import java.util.Base64; | |||||||
| import org.apache.commons.lang3.RandomStringUtils; | import org.apache.commons.lang3.RandomStringUtils; | ||||||
| import org.springframework.security.crypto.codec.Hex; | import org.springframework.security.crypto.codec.Hex; | ||||||
|  |  | ||||||
| /*** |  | ||||||
|  * |  | ||||||
|  * @author Angel Olle Blazquez |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| public class EncDec { | public class EncDec { | ||||||
|  |  | ||||||
|   // PoC: weak encoding method |   // PoC: weak encoding method | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
| package org.owasp.webgoat.lessons.sqlinjection.advanced; | package org.owasp.webgoat.lessons.sqlinjection.advanced; | ||||||
|  |  | ||||||
| import static org.owasp.webgoat.container.assignments.AttackResultBuilder.failed; | import static org.owasp.webgoat.container.assignments.AttackResultBuilder.failed; | ||||||
| import static org.owasp.webgoat.container.assignments.AttackResultBuilder.success; | import static org.owasp.webgoat.container.assignments.AttackResultBuilder.informationMessage; | ||||||
|  |  | ||||||
| import java.sql.*; | import java.sql.*; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| @ -19,13 +19,17 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/8/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints( | @AssignmentHints( | ||||||
|     value = {"SqlInjectionChallenge1", "SqlInjectionChallenge2", "SqlInjectionChallenge3"}) |     value = { | ||||||
|  |       "SqlInjectionChallenge1", | ||||||
|  |       "SqlInjectionChallenge2", | ||||||
|  |       "SqlInjectionChallenge3", | ||||||
|  |       "SqlInjectionChallenge4", | ||||||
|  |       "SqlInjectionChallenge5", | ||||||
|  |       "SqlInjectionChallenge6", | ||||||
|  |       "SqlInjectionChallenge7" | ||||||
|  |     }) | ||||||
| @Slf4j | @Slf4j | ||||||
| public class SqlInjectionChallenge implements AssignmentEndpoint { | public class SqlInjectionChallenge implements AssignmentEndpoint { | ||||||
|  |  | ||||||
| @ -35,38 +39,34 @@ public class SqlInjectionChallenge implements AssignmentEndpoint { | |||||||
|     this.dataSource = dataSource; |     this.dataSource = dataSource; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @PutMapping("/SqlInjectionAdvanced/challenge") |   @PutMapping("/SqlInjectionAdvanced/register") | ||||||
|   // assignment path is bounded to class so we use different http method :-) |   // assignment path is bounded to class so we use different http method :-) | ||||||
|   @ResponseBody |   @ResponseBody | ||||||
|   public AttackResult registerNewUser( |   public AttackResult registerNewUser( | ||||||
|       @RequestParam String username_reg, |       @RequestParam("username_reg") String username, | ||||||
|       @RequestParam String email_reg, |       @RequestParam("email_reg") String email, | ||||||
|       @RequestParam String password_reg) |       @RequestParam("password_reg") String password) { | ||||||
|       throws Exception { |     AttackResult attackResult = checkArguments(username, email, password); | ||||||
|     AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg); |  | ||||||
|  |  | ||||||
|     if (attackResult == null) { |     if (attackResult == null) { | ||||||
|  |  | ||||||
|       try (Connection connection = dataSource.getConnection()) { |       try (Connection connection = dataSource.getConnection()) { | ||||||
|         String checkUserQuery = |         String checkUserQuery = | ||||||
|             "select userid from sql_challenge_users where userid = '" + username_reg + "'"; |             "select userid from sql_challenge_users where userid = '" + username + "'"; | ||||||
|         Statement statement = connection.createStatement(); |         Statement statement = connection.createStatement(); | ||||||
|         ResultSet resultSet = statement.executeQuery(checkUserQuery); |         ResultSet resultSet = statement.executeQuery(checkUserQuery); | ||||||
|  |  | ||||||
|         if (resultSet.next()) { |         if (resultSet.next()) { | ||||||
|           if (username_reg.contains("tom'")) { |           attackResult = failed(this).feedback("user.exists").feedbackArgs(username).build(); | ||||||
|             attackResult = success(this).feedback("user.exists").build(); |  | ||||||
|           } else { |  | ||||||
|             attackResult = failed(this).feedback("user.exists").feedbackArgs(username_reg).build(); |  | ||||||
|           } |  | ||||||
|         } else { |         } else { | ||||||
|           PreparedStatement preparedStatement = |           PreparedStatement preparedStatement = | ||||||
|               connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)"); |               connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)"); | ||||||
|           preparedStatement.setString(1, username_reg); |           preparedStatement.setString(1, username); | ||||||
|           preparedStatement.setString(2, email_reg); |           preparedStatement.setString(2, email); | ||||||
|           preparedStatement.setString(3, password_reg); |           preparedStatement.setString(3, password); | ||||||
|           preparedStatement.execute(); |           preparedStatement.execute(); | ||||||
|           attackResult = success(this).feedback("user.created").feedbackArgs(username_reg).build(); |           attackResult = | ||||||
|  |               informationMessage(this).feedback("user.created").feedbackArgs(username).build(); | ||||||
|         } |         } | ||||||
|       } catch (SQLException e) { |       } catch (SQLException e) { | ||||||
|         attackResult = failed(this).output("Something went wrong").build(); |         attackResult = failed(this).output("Something went wrong").build(); | ||||||
| @ -75,13 +75,13 @@ public class SqlInjectionChallenge implements AssignmentEndpoint { | |||||||
|     return attackResult; |     return attackResult; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) { |   private AttackResult checkArguments(String username, String email, String password) { | ||||||
|     if (StringUtils.isEmpty(username_reg) |     if (StringUtils.isEmpty(username) | ||||||
|         || StringUtils.isEmpty(email_reg) |         || StringUtils.isEmpty(email) | ||||||
|         || StringUtils.isEmpty(password_reg)) { |         || StringUtils.isEmpty(password)) { | ||||||
|       return failed(this).feedback("input.invalid").build(); |       return failed(this).feedback("input.invalid").build(); | ||||||
|     } |     } | ||||||
|     if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) { |     if (username.length() > 250 || email.length() > 30 || password.length() > 30) { | ||||||
|       return failed(this).feedback("input.invalid").build(); |       return failed(this).feedback("input.invalid").build(); | ||||||
|     } |     } | ||||||
|     return null; |     return null; | ||||||
|  | |||||||
| @ -9,7 +9,6 @@ import static org.owasp.webgoat.container.assignments.AttackResultBuilder.succes | |||||||
|  |  | ||||||
| import org.owasp.webgoat.container.LessonDataSource; | import org.owasp.webgoat.container.LessonDataSource; | ||||||
| import org.owasp.webgoat.container.assignments.AssignmentEndpoint; | import org.owasp.webgoat.container.assignments.AssignmentEndpoint; | ||||||
| import org.owasp.webgoat.container.assignments.AssignmentHints; |  | ||||||
| import org.owasp.webgoat.container.assignments.AttackResult; | import org.owasp.webgoat.container.assignments.AttackResult; | ||||||
| import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.PostMapping; | ||||||
| import org.springframework.web.bind.annotation.RequestParam; | import org.springframework.web.bind.annotation.RequestParam; | ||||||
| @ -17,13 +16,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| @RestController | @RestController | ||||||
| @AssignmentHints( |  | ||||||
|     value = { |  | ||||||
|       "SqlInjectionChallengeHint1", |  | ||||||
|       "SqlInjectionChallengeHint2", |  | ||||||
|       "SqlInjectionChallengeHint3", |  | ||||||
|       "SqlInjectionChallengeHint4" |  | ||||||
|     }) |  | ||||||
| public class SqlInjectionChallengeLogin implements AssignmentEndpoint { | public class SqlInjectionChallengeLogin implements AssignmentEndpoint { | ||||||
|   private final LessonDataSource dataSource; |   private final LessonDataSource dataSource; | ||||||
|  |  | ||||||
| @ -31,20 +23,22 @@ public class SqlInjectionChallengeLogin implements AssignmentEndpoint { | |||||||
|     this.dataSource = dataSource; |     this.dataSource = dataSource; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @PostMapping("/SqlInjectionAdvanced/challenge_Login") |   @PostMapping("/SqlInjectionAdvanced/login") | ||||||
|   @ResponseBody |   @ResponseBody | ||||||
|   public AttackResult login( |   public AttackResult login( | ||||||
|       @RequestParam String username_login, @RequestParam String password_login) throws Exception { |       @RequestParam("username_login") String username, | ||||||
|  |       @RequestParam("password_login") String password) | ||||||
|  |       throws Exception { | ||||||
|     try (var connection = dataSource.getConnection()) { |     try (var connection = dataSource.getConnection()) { | ||||||
|       var statement = |       var statement = | ||||||
|           connection.prepareStatement( |           connection.prepareStatement( | ||||||
|               "select password from sql_challenge_users where userid = ? and password = ?"); |               "select password from sql_challenge_users where userid = ? and password = ?"); | ||||||
|       statement.setString(1, username_login); |       statement.setString(1, username); | ||||||
|       statement.setString(2, password_login); |       statement.setString(2, password); | ||||||
|       var resultSet = statement.executeQuery(); |       var resultSet = statement.executeQuery(); | ||||||
|  |  | ||||||
|       if (resultSet.next()) { |       if (resultSet.next()) { | ||||||
|         return ("tom".equals(username_login)) |         return ("tom".equals(username)) | ||||||
|             ? success(this).build() |             ? success(this).build() | ||||||
|             : failed(this).feedback("ResultsButNotTom").build(); |             : failed(this).feedback("ResultsButNotTom").build(); | ||||||
|       } else { |       } else { | ||||||
|  | |||||||
| @ -17,10 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 6/13/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("SqlInjectionMitigations/servers") | @RequestMapping("SqlInjectionMitigations/servers") | ||||||
| @Slf4j | @Slf4j | ||||||
|  | |||||||
| @ -18,10 +18,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | |||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| import org.springframework.web.servlet.ModelAndView; | import org.springframework.web.servlet.ModelAndView; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class LandingAssignment implements AssignmentEndpoint { | public class LandingAssignment implements AssignmentEndpoint { | ||||||
|   private final String landingPageUrl; |   private final String landingPageUrl; | ||||||
|  | |||||||
| @ -20,10 +20,6 @@ import org.springframework.web.bind.annotation.RestController; | |||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| public class MailAssignment implements AssignmentEndpoint { | public class MailAssignment implements AssignmentEndpoint { | ||||||
|  |  | ||||||
|  | |||||||
| @ -10,10 +10,6 @@ import lombok.Getter; | |||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/8/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Setter | @Setter | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
|  | |||||||
| @ -12,10 +12,6 @@ import lombok.NoArgsConstructor; | |||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 4/8/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Setter | @Setter | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
|  | |||||||
| @ -14,10 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping; | |||||||
| import org.springframework.web.bind.annotation.ResponseBody; | import org.springframework.web.bind.annotation.ResponseBody; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 5/4/17. |  | ||||||
|  */ |  | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("xxe/comments") | @RequestMapping("xxe/comments") | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
|  | |||||||
| @ -14,10 +14,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry | |||||||
| import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; | ||||||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/13/17. |  | ||||||
|  */ |  | ||||||
| @Configuration | @Configuration | ||||||
| public class MvcConfiguration implements WebMvcConfigurer { | public class MvcConfiguration implements WebMvcConfigurer { | ||||||
|  |  | ||||||
|  | |||||||
| @ -18,10 +18,6 @@ import lombok.Builder; | |||||||
| import lombok.Data; | import lombok.Data; | ||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/20/17. |  | ||||||
|  */ |  | ||||||
| @Data | @Data | ||||||
| @Builder | @Builder | ||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
|  | |||||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.mailbox; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import org.springframework.data.jpa.repository.JpaRepository; | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/17/17. |  | ||||||
|  */ |  | ||||||
| public interface MailboxRepository extends JpaRepository<Email, String> { | public interface MailboxRepository extends JpaRepository<Email, String> { | ||||||
|  |  | ||||||
|   List<Email> findByRecipientOrderByTimeDesc(String recipient); |   List<Email> findByRecipientOrderByTimeDesc(String recipient); | ||||||
|  | |||||||
| @ -21,9 +21,6 @@ import org.springframework.web.servlet.ModelAndView; | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific user. |  * Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific user. | ||||||
|  * |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/13/17. |  | ||||||
|  */ |  */ | ||||||
| @Controller | @Controller | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
|  | |||||||
| @ -16,9 +16,6 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; | |||||||
| /** | /** | ||||||
|  * Keep track of all the incoming requests, we are only keeping track of request originating from |  * Keep track of all the incoming requests, we are only keeping track of request originating from | ||||||
|  * WebGoat. |  * WebGoat. | ||||||
|  * |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 8/13/17. |  | ||||||
|  */ |  */ | ||||||
| public class WebWolfTraceRepository implements HttpExchangeRepository { | public class WebWolfTraceRepository implements HttpExchangeRepository { | ||||||
|   private enum MatchingMode { |   private enum MatchingMode { | ||||||
|  | |||||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.user; | |||||||
| import org.springframework.data.jpa.repository.JpaRepository; | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
| import org.springframework.stereotype.Repository; | import org.springframework.stereotype.Repository; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Repository("webWolfUserRepository") | @Repository("webWolfUserRepository") | ||||||
| public interface UserRepository extends JpaRepository<WebWolfUser, String> { | public interface UserRepository extends JpaRepository<WebWolfUser, String> { | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,10 +8,6 @@ import org.springframework.security.core.userdetails.UserDetailsService; | |||||||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Service | @Service | ||||||
| public class UserService implements UserDetailsService { | public class UserService implements UserDetailsService { | ||||||
|  |  | ||||||
|  | |||||||
| @ -15,10 +15,6 @@ import org.springframework.security.core.GrantedAuthority; | |||||||
| import org.springframework.security.core.userdetails.User; | import org.springframework.security.core.userdetails.User; | ||||||
| import org.springframework.security.core.userdetails.UserDetails; | import org.springframework.security.core.userdetails.UserDetails; | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author nbaars |  | ||||||
|  * @since 3/19/17. |  | ||||||
|  */ |  | ||||||
| @Getter | @Getter | ||||||
| @Entity | @Entity | ||||||
| @Table(name = "WEB_GOAT_USER") | @Table(name = "WEB_GOAT_USER") | ||||||
|  | |||||||
| @ -36,10 +36,6 @@ logging.level.org.hidbernate.SQL=INFO | |||||||
| webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/ | webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/ | ||||||
| webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/ | webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/ | ||||||
| webgoat.build.version=@project.version@ | webgoat.build.version=@project.version@ | ||||||
| webgoat.email=webgoat@owasp.org |  | ||||||
| webgoat.emaillist=owasp-webgoat@lists.owasp.org |  | ||||||
| webgoat.feedback.address=webgoat@owasp.org |  | ||||||
| webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A> |  | ||||||
| webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} | webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} | ||||||
| webgoat.default.language=en | webgoat.default.language=en | ||||||
| webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path} | webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path} | ||||||
| @ -51,9 +47,9 @@ webwolf.url=http://${webwolf.host}:${webwolf.port}${webwolf.context} | |||||||
| webwolf.landingpage.url=${webwolf.url}/landing | webwolf.landingpage.url=${webwolf.url}/landing | ||||||
| webwolf.mail.url=${webwolf.url}/mail | webwolf.mail.url=${webwolf.url}/mail | ||||||
|  |  | ||||||
| spring.jpa.properties.jakarta.persistence.schema-generation.scripts.action=create | #spring.jpa.properties.jakarta.persistence.schema-generation.scripts.action=create | ||||||
| spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-target=create.sql | #spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-target=create.sql | ||||||
| spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-source=metadata | #spring.jpa.properties.jakarta.persistence.schema-generation.scripts.create-source=metadata | ||||||
|  |  | ||||||
| spring.jackson.serialization.indent_output=true | spring.jackson.serialization.indent_output=true | ||||||
| spring.jackson.serialization.write-dates-as-timestamps=false | spring.jackson.serialization.write-dates-as-timestamps=false | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| lesson.completed=Congratulations. You have successfully completed this lesson. |  | ||||||
| assignment.solved=Congratulations. You have successfully completed the assignment. | assignment.solved=Congratulations. You have successfully completed the assignment. | ||||||
| assignment.not.solved=Sorry the solution is not correct, please try again. | assignment.not.solved=Sorry the solution is not correct, please try again. | ||||||
| RestartLesson=Restart this Lesson | RestartLesson=Restart this Lesson | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #General | #General | ||||||
| lesson.completed=Herzlichen Gl\u00fcckwunsch! Sie haben diese Lektion erfolgreich abgeschlossen. |  | ||||||
| assignment.solved=Herzlichen Gl\u00fcckwunsch! Sie haben diesen Auftrag erfolgreich abgeschlossen. | assignment.solved=Herzlichen Gl\u00fcckwunsch! Sie haben diesen Auftrag erfolgreich abgeschlossen. | ||||||
| assignment.not.solved=Die L\u00f6sung ist nicht korrekt, versuchen Sie es erneut. | assignment.not.solved=Die L\u00f6sung ist nicht korrekt, versuchen Sie es erneut. | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #General | #General | ||||||
| lesson.completed=F\u00e9licitations. Vous avez termin\u00e9 cette le\u00e7on avec succ\u00e9s. |  | ||||||
| RestartLesson=Recommencer cette le\u00e7on | RestartLesson=Recommencer cette le\u00e7on | ||||||
| SolutionVideos=Solution vid\u00e9os | SolutionVideos=Solution vid\u00e9os | ||||||
| ErrorGenerating=Error generating | ErrorGenerating=Error generating | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| lesson.completed=Gefeliciteerd, je hebt deze les succesvol afgerond. |  | ||||||
| assignment.solved=Gefeliciteerd, je hebt deze opdracht succesvol afgerond. | assignment.solved=Gefeliciteerd, je hebt deze opdracht succesvol afgerond. | ||||||
| assignment.not.solved=Sorry de oplossing is niet correct, probeer het nog eens. | assignment.not.solved=Sorry de oplossing is niet correct, probeer het nog eens. | ||||||
| RestartLesson=Herstart de les | RestartLesson=Herstart de les | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	