Compare commits
	
		
			67 Commits
		
	
	
		
			v2025.1
			...
			af45e392d6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| af45e392d6 | |||
| 7c019cf2ab | |||
| c325068f51 | |||
| 788927a5a7 | |||
| 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 | 
							
								
								
									
										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 $SLEEP_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 }} | ||||
|  | ||||
|       - name: "Set up QEMU" | ||||
|         uses: docker/setup-qemu-action@v3.4.0 | ||||
|         uses: docker/setup-qemu-action@v3.6.0 | ||||
|         with: | ||||
|           platforms: all | ||||
|  | ||||
| @ -76,13 +76,13 @@ jobs: | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|  | ||||
|       - name: "Login to dockerhub" | ||||
|         uses: docker/login-action@v3.3.0 | ||||
|         uses: docker/login-action@v3.4.0 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|  | ||||
|       - name: "Build and push WebGoat" | ||||
|         uses: docker/build-push-action@v6.14.0 | ||||
|         uses: docker/build-push-action@v6.16.0 | ||||
|         with: | ||||
|           context: ./ | ||||
|           file: ./Dockerfile | ||||
| @ -95,7 +95,7 @@ jobs: | ||||
|             webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} | ||||
|  | ||||
|       - name: "Build and push WebGoat desktop" | ||||
|         uses: docker/build-push-action@v6.14.0 | ||||
|         uses: docker/build-push-action@v6.16.0 | ||||
|         with: | ||||
|           context: ./ | ||||
|           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/plugin_lessons/dist-*.pom | ||||
| webgoat-lessons/**/target | ||||
| **/*.jar | ||||
| **/.DS_Store | ||||
| webgoat-server/mongo-data/* | ||||
| 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 | ||||
|  | ||||
| @ -8,7 +8,8 @@ and 2023.01 in the `pom.xml`. | ||||
| ### Release notes: | ||||
|  | ||||
| Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of | ||||
| committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main` | ||||
| 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 | ||||
| @ -17,5 +18,9 @@ mvn verify | ||||
| git commit .... | ||||
| git tag v2023.01 | ||||
| git push --tags | ||||
| git push | ||||
| ``` | ||||
|  | ||||
| After the release has been tagged and the build process is done. The release notes should be updated in the GitHub | ||||
| release page. | ||||
|  | ||||
|  | ||||
| @ -99,7 +99,7 @@ For a full overview of all the parameters you can use, please check the [WebGoat | ||||
|  | ||||
| ### Prerequisites: | ||||
|  | ||||
| * Java 17 or 21 | ||||
| * Java 23 | ||||
| * Your favorite IDE | ||||
| * Git, or Git support in your IDE | ||||
|  | ||||
|  | ||||
| @ -1,5 +1,23 @@ | ||||
| # WebGoat release notes | ||||
|  | ||||
| ## Version 2025.3 | ||||
|  | ||||
| ### 🐞 Bug fixes | ||||
|  | ||||
| - Changed URLs imply other exclusion filters for ZAP (#2052) | ||||
| - XSS lesson stage 12 (2 issues) (#1178) | ||||
|  | ||||
| ### 🔄 Technical tasks | ||||
|  | ||||
| - bump docker/setup-qemu-action from 3.4.0 to 3.6.0 (#2049) | ||||
| - bump docker/build-push-action from 6.14.0 to 6.15.0 (#2050) | ||||
|  | ||||
| ## Version 2025.2 | ||||
|  | ||||
| ### 🐞 Bug fixes | ||||
|  | ||||
| - Fix SQL advanced lesson assignment 5 (#2047) | ||||
|  | ||||
| ## Version 2025.1 | ||||
|  | ||||
| ### 🚀 New functionality | ||||
|  | ||||
| @ -3,12 +3,12 @@ | ||||
|  | ||||
| <head> | ||||
|   <meta charset="utf-8"> | ||||
|   <meta http-equiv="refresh" content="0;url=https://owasp.org/www-project-webgoat/" /> | ||||
|   <link rel="canonical" href="https://owasp.org/www-project-webgoat/" /> | ||||
|   <meta http-equiv="refresh" content="0;url=https://webgoat.org" /> | ||||
|   <link rel="canonical" href="https://webgoat.org" /> | ||||
| </head> | ||||
| <body> | ||||
| <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> | ||||
| </body> | ||||
| </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> | ||||
|     <groupId>org.springframework.boot</groupId> | ||||
|     <artifactId>spring-boot-starter-parent</artifactId> | ||||
|     <version>3.4.3</version> | ||||
|     <version>3.4.4</version> | ||||
|   </parent> | ||||
|  | ||||
|   <groupId>org.owasp.webgoat</groupId> | ||||
|   <artifactId>webgoat</artifactId> | ||||
|   <version>2025.1</version> | ||||
|   <version>2025.4-SNAPSHOT</version> | ||||
|   <packaging>jar</packaging> | ||||
|  | ||||
|   <name>WebGoat</name> | ||||
| @ -63,29 +63,29 @@ | ||||
|   <properties> | ||||
|     <!-- Shared properties with plugins and version numbers across submodules--> | ||||
|     <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> | ||||
|     <!-- do not update necessary for lesson --> | ||||
|     <checkstyle.version>3.6.0</checkstyle.version> | ||||
|     <commons-collections.version>3.2.1</commons-collections.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-text.version>1.13.0</commons-text.version> | ||||
|     <guava.version>33.4.0-jre</guava.version> | ||||
|     <commons-text.version>1.13.1</commons-text.version> | ||||
|     <guava.version>33.4.8-jre</guava.version> | ||||
|     <jacoco.version>0.8.11</jacoco.version> | ||||
|     <java.version>23</java.version> | ||||
|     <jaxb.version>2.3.1</jaxb.version> | ||||
|     <jjwt.version>0.9.1</jjwt.version> | ||||
|     <jose4j.version>0.9.3</jose4j.version> | ||||
|     <jquery.version>3.7.1</jquery.version> | ||||
|     <jsoup.version>1.18.3</jsoup.version> | ||||
|     <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> | ||||
|     <jsoup.version>1.19.1</jsoup.version> | ||||
|     <maven-compiler-plugin.version>3.14.0</maven-compiler-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-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> | ||||
|     <maven-source-plugin.version>3.1.0</maven-source-plugin.version> | ||||
|     <maven-surefire-plugin.version>3.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.source>23</maven.compiler.source> | ||||
|     <maven.compiler.target>23</maven.compiler.target> | ||||
| @ -96,14 +96,14 @@ | ||||
|     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||
|     <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version> | ||||
|     <waittimeForServerStart>60</waittimeForServerStart> | ||||
|     <webdriver.version>5.9.3</webdriver.version> | ||||
|     <webdriver.version>6.0.1</webdriver.version> | ||||
|     <webgoat.context>/WebGoat</webgoat.context> | ||||
|     <webgoat.port>8080</webgoat.port> | ||||
|     <webgoat.sslenabled>false</webgoat.sslenabled> | ||||
|     <webjars-locator-core.version>0.59</webjars-locator-core.version> | ||||
|     <webwolf.context>/WebWolf</webwolf.context> | ||||
|     <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> | ||||
|     <xstream.version>1.4.5</xstream.version> | ||||
|     <!-- do not update necessary for lesson --> | ||||
| @ -217,12 +217,12 @@ | ||||
|       <dependency> | ||||
|         <groupId>org.jruby</groupId> | ||||
|         <artifactId>jruby</artifactId> | ||||
|         <version>9.4.12.0</version> | ||||
|         <version>10.0.0.1</version> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|         <groupId>com.microsoft.playwright</groupId> | ||||
|         <artifactId>playwright</artifactId> | ||||
|         <version>1.50.0</version> | ||||
|         <version>1.51.0</version> | ||||
|       </dependency> | ||||
|     </dependencies> | ||||
|   </dependencyManagement> | ||||
| @ -238,7 +238,7 @@ | ||||
|     <dependency> | ||||
|       <groupId>org.projectlombok</groupId> | ||||
|       <artifactId>lombok</artifactId> | ||||
|       <version>1.18.36</version> | ||||
|       <version>1.18.38</version> | ||||
|       <scope>provided</scope> | ||||
|       <optional>true</optional> | ||||
|     </dependency> | ||||
| @ -510,7 +510,7 @@ | ||||
|         <configuration> | ||||
|           <forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds> | ||||
|           <!-- 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/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 | ||||
| @ -536,7 +536,7 @@ | ||||
|       <plugin> | ||||
|         <groupId>com.diffplug.spotless</groupId> | ||||
|         <artifactId>spotless-maven-plugin</artifactId> | ||||
|         <version>2.44.3</version> | ||||
|         <version>2.44.4</version> | ||||
|         <configuration> | ||||
|           <formats> | ||||
|             <format> | ||||
| @ -694,6 +694,7 @@ | ||||
|                     <argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> | ||||
|                     <argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> | ||||
|                     <argument>-Dspring.main.banner-mode=off</argument> | ||||
|                     <argument>--enable-native-access=ALL-UNNAMED</argument> | ||||
|                     <argument>--add-opens</argument> | ||||
|                     <argument>java.base/java.lang=ALL-UNNAMED</argument> | ||||
|                     <argument>--add-opens</argument> | ||||
|  | ||||
| @ -4,12 +4,9 @@ | ||||
|  */ | ||||
| package org.owasp.webgoat.integration; | ||||
|  | ||||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||||
|  | ||||
| import io.restassured.RestAssured; | ||||
| import java.util.Arrays; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import org.assertj.core.api.Assertions; | ||||
| import org.junit.jupiter.api.Test; | ||||
| @ -57,19 +54,6 @@ public class ChallengeIntegrationTest extends IntegrationTest { | ||||
|     checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true); | ||||
|  | ||||
|     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 | ||||
| @ -99,19 +83,6 @@ public class ChallengeIntegrationTest extends IntegrationTest { | ||||
|     checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true); | ||||
|  | ||||
|     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 | ||||
| @ -162,7 +133,9 @@ public class ChallengeIntegrationTest extends IntegrationTest { | ||||
|             .when() | ||||
|             .relaxedHTTPSValidation() | ||||
|             .cookie("JSESSIONID", getWebGoatCookie()) | ||||
|             .get(webGoatUrlConfig.url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2") | ||||
|             .get( | ||||
|                 webGoatUrlConfig.url("challenge/7/reset-password/{link}"), | ||||
|                 "375afe1104f4a487a73823c50a9292a2") | ||||
|             .then() | ||||
|             .statusCode(HttpStatus.ACCEPTED.value()) | ||||
|             .extract() | ||||
|  | ||||
| @ -7,9 +7,6 @@ package org.owasp.webgoat.integration; | ||||
| import java.util.Map; | ||||
| import org.junit.jupiter.api.Test; | ||||
|  | ||||
| /** | ||||
|  * @author Angel Olle Blazquez | ||||
|  */ | ||||
| class SessionManagementIT extends IntegrationTest { | ||||
|  | ||||
|   private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login"; | ||||
|  | ||||
| @ -15,17 +15,16 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest { | ||||
|     startLesson("SqlInjectionAdvanced"); | ||||
|  | ||||
|     Map<String, Object> params = new HashMap<>(); | ||||
|     params.clear(); | ||||
|     params.put("username_reg", "tom' AND substring(password,1,1)='t"); | ||||
|     params.put("password_reg", "password"); | ||||
|     params.put("email_reg", "someone@microsoft.com"); | ||||
|     params.put("confirm_password", "password"); | ||||
|       checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge"), params, true); | ||||
|       checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/register"), params, false); | ||||
|  | ||||
|     params.clear(); | ||||
|     params.put("username_login", "tom"); | ||||
|     params.put("password_login", "thisisasecretfortomonly"); | ||||
|       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge_Login"), params, true); | ||||
|       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/login"), params, true); | ||||
|  | ||||
|     params.clear(); | ||||
|     params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); | ||||
| @ -59,7 +58,5 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest { | ||||
|         "question_4_solution", | ||||
|         "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); | ||||
|       checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true); | ||||
|  | ||||
|     checkResults("SqlInjectionAdvanced"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -19,12 +19,17 @@ public class PlaywrightTest { | ||||
|   public static class WebGoatOptions implements OptionsFactory { | ||||
|     @Override | ||||
|     public Options getOptions() { | ||||
|       return new Options().setHeadless(true).setContextOptions(getContextOptions()); | ||||
|       return new Options() | ||||
|               .setHeadless(true) | ||||
|               .setContextOptions(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) { | ||||
|  | ||||
| @ -35,7 +35,7 @@ public class RegistrationUITest extends PlaywrightTest { | ||||
|   @Test | ||||
|   @DisplayName("Should register a new user") | ||||
|   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); | ||||
|     registrationPage.open(); | ||||
|  | ||||
|  | ||||
| @ -33,19 +33,19 @@ public class Authentication { | ||||
|  | ||||
|   public static Page sylvester(Browser browser) { | ||||
|     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) { | ||||
|     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) { | ||||
|     if (user.loggedIn()) { | ||||
|       return user; | ||||
|     } | ||||
|     var page = browser.newContext().newPage(); | ||||
|     var page = browser.newContext(new Browser.NewContextOptions().setLocale("en-US")).newPage(); | ||||
|     RegistrationPage registrationPage = new RegistrationPage(page); | ||||
|     registrationPage.open(); | ||||
|     registrationPage.register(user.name, user.password); | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
|  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||
|  * 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; | ||||
| 
 | ||||
| @ -15,8 +15,9 @@ import org.junit.jupiter.api.Order; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.TestMethodOrder; | ||||
| 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.HttpBasicsLessonPage; | ||||
| import org.owasp.webgoat.playwright.webgoat.pages.lessons.HttpBasicsLessonPage; | ||||
| 
 | ||||
| @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||
| 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-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.Page; | ||||
| @ -2,7 +2,7 @@ | ||||
|  * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors | ||||
|  * 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; | ||||
| 
 | ||||
| @ -14,7 +14,7 @@ import org.assertj.core.api.Assertions; | ||||
| import org.owasp.webgoat.container.lessons.LessonName; | ||||
| 
 | ||||
| @Getter | ||||
| class LessonPage { | ||||
| public class LessonPage { | ||||
| 
 | ||||
|   private final Page page; | ||||
| 
 | ||||
| @ -65,4 +65,8 @@ class LessonPage { | ||||
|   public Locator getAssignmentOutput() { | ||||
|     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. | ||||
|    * | ||||
|    * @author stupid develop | ||||
|    */ | ||||
|   private void readObject(ObjectInputStream stream) throws Exception { | ||||
|     // 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.web.authentication.LoginUrlAuthenticationEntryPoint; | ||||
|  | ||||
| /** | ||||
|  * AjaxAuthenticationEntryPoint class. | ||||
|  * | ||||
|  * @author zupzup | ||||
|  */ | ||||
| public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { | ||||
|   public AjaxAuthenticationEntryPoint(String loginFormUrl) { | ||||
|     super(loginFormUrl); | ||||
|  | ||||
| @ -47,17 +47,26 @@ public class LessonTemplateResolver extends FileTemplateResolver { | ||||
|     var templateName = resourceName.substring(PREFIX.length()); | ||||
|     byte[] resource = resources.get(templateName); | ||||
|     if (resource == null) { | ||||
|       try { | ||||
|         resource = | ||||
|             resourceLoader | ||||
|                 .getResource("classpath:/" + templateName) | ||||
|                 .getInputStream() | ||||
|                 .readAllBytes(); | ||||
|       } catch (IOException e) { | ||||
|         log.error("Unable to find lesson HTML: {}", template); | ||||
|       resource = loadAndCache(templateName); | ||||
|     } | ||||
|       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)); | ||||
|   } | ||||
|  | ||||
|   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("/lesson_content").setViewName("lesson_content"); | ||||
|     registry.addViewController("/start.mvc").setViewName("main_new"); | ||||
|     registry.addViewController("/scoreboard").setViewName("scoreboard"); | ||||
|   } | ||||
|  | ||||
|   @Bean | ||||
|  | ||||
| @ -4,11 +4,9 @@ | ||||
|  */ | ||||
| package org.owasp.webgoat.container.assignments; | ||||
|  | ||||
| import org.owasp.webgoat.container.i18n.PluginMessages; | ||||
|  | ||||
| public class AttackResultBuilder { | ||||
|  | ||||
|   private boolean lessonCompleted; | ||||
|   private boolean assignmentCompleted; | ||||
|   private Object[] feedbackArgs; | ||||
|   private String feedbackResourceBundleKey; | ||||
|   private String output; | ||||
| @ -16,15 +14,8 @@ public class AttackResultBuilder { | ||||
|   private AssignmentEndpoint assignment; | ||||
|   private boolean attemptWasMade = false; | ||||
|  | ||||
|   public AttackResultBuilder lessonCompleted(boolean lessonCompleted) { | ||||
|     this.lessonCompleted = lessonCompleted; | ||||
|     this.feedbackResourceBundleKey = "lesson.completed"; | ||||
|     return this; | ||||
|   } | ||||
|  | ||||
|   public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) { | ||||
|     this.lessonCompleted = lessonCompleted; | ||||
|     this.feedbackResourceBundleKey = resourceBundleKey; | ||||
|   public AttackResultBuilder assignmentCompleted(boolean lessonCompleted) { | ||||
|     this.assignmentCompleted = lessonCompleted; | ||||
|     return this; | ||||
|   } | ||||
|  | ||||
| @ -55,7 +46,7 @@ public class AttackResultBuilder { | ||||
|  | ||||
|   public AttackResult build() { | ||||
|     return new AttackResult( | ||||
|         lessonCompleted, | ||||
|             assignmentCompleted, | ||||
|         feedbackResourceBundleKey, | ||||
|         feedbackArgs, | ||||
|         output, | ||||
| @ -81,7 +72,7 @@ public class AttackResultBuilder { | ||||
|    */ | ||||
|   public static AttackResultBuilder success(AssignmentEndpoint assignment) { | ||||
|     return new AttackResultBuilder() | ||||
|         .lessonCompleted(true) | ||||
|         .assignmentCompleted(true) | ||||
|         .attemptWasMade() | ||||
|         .feedback("assignment.solved") | ||||
|         .assignment(assignment); | ||||
| @ -99,13 +90,13 @@ public class AttackResultBuilder { | ||||
|    */ | ||||
|   public static AttackResultBuilder failed(AssignmentEndpoint assignment) { | ||||
|     return new AttackResultBuilder() | ||||
|         .lessonCompleted(false) | ||||
|         .assignmentCompleted(false) | ||||
|         .attemptWasMade() | ||||
|         .feedback("assignment.not.solved") | ||||
|         .assignment(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.servlet.ModelAndView; | ||||
|  | ||||
| /** | ||||
|  * Welcome class. | ||||
|  * | ||||
|  * @author rlawson | ||||
|  * @version $Id: $Id | ||||
|  */ | ||||
| @Controller | ||||
| public class Welcome { | ||||
|  | ||||
|  | ||||
| @ -11,8 +11,6 @@ import org.springframework.context.support.ReloadableResourceBundleMessageSource | ||||
| /** | ||||
|  * ExposedReloadableResourceMessageBundleSource class. Extends the reloadable message source with a | ||||
|  * way to get all messages | ||||
|  * | ||||
|  * @author zupzup | ||||
|  */ | ||||
| @AllArgsConstructor | ||||
| public class Messages extends ReloadableResourceBundleMessageSource { | ||||
|  | ||||
| @ -84,7 +84,7 @@ public class CourseConfiguration { | ||||
|  | ||||
|   @Bean | ||||
|   public Course course() { | ||||
|     assignments.stream().forEach(this::attachToLesson); | ||||
|     assignments.forEach(this::attachToLesson); | ||||
|  | ||||
|     // Check if all assignments are attached to a lesson | ||||
|     var assignmentsAttachedToLessons = | ||||
| @ -99,7 +99,7 @@ public class CourseConfiguration { | ||||
|  | ||||
|   private List<String> findDiff() { | ||||
|     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 diff = new ArrayList<>(allAssignments); | ||||
|  | ||||
| @ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Getter; | ||||
|  | ||||
| /** | ||||
|  * LessonInfoModel class. | ||||
|  * | ||||
|  * @author dm | ||||
|  * @version $Id: $Id | ||||
|  */ | ||||
| @Getter | ||||
| @AllArgsConstructor | ||||
| public class LessonInfoModel { | ||||
|  | ||||
| @ -7,12 +7,6 @@ package org.owasp.webgoat.container.lessons; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * LessonMenuItem class. | ||||
|  * | ||||
|  * @author rlawson | ||||
|  * @version $Id: $Id | ||||
|  */ | ||||
| public class LessonMenuItem { | ||||
|  | ||||
|   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.ResponseBody; | ||||
|  | ||||
| /** | ||||
|  * LessonProgressService class. | ||||
|  * | ||||
|  * @author webgoat | ||||
|  */ | ||||
| @Controller | ||||
| @RequiredArgsConstructor | ||||
| public class LessonProgressService { | ||||
|  | ||||
| @ -6,12 +6,6 @@ package org.owasp.webgoat.container.session; | ||||
|  | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * LabelDebugger class. | ||||
|  * | ||||
|  * @author dm | ||||
|  * @version $Id: $Id | ||||
|  */ | ||||
| public class LabelDebugger implements Serializable { | ||||
|  | ||||
|   private boolean enabled = false; | ||||
|  | ||||
| @ -84,6 +84,6 @@ public class LessonProgress { | ||||
|   } | ||||
|  | ||||
|   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.PostMapping; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Controller | ||||
| @RequiredArgsConstructor | ||||
| @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.Setter; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Setter | ||||
| 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 | ||||
|    * @return a lesson tracker created if not already present | ||||
| @ -49,7 +49,7 @@ public class UserProgress { | ||||
|   public LessonProgress getLessonProgress(Lesson lesson) { | ||||
|     Optional<LessonProgress> progress = | ||||
|         lessonProgress.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); | ||||
|     if (!progress.isPresent()) { | ||||
|     if (progress.isEmpty()) { | ||||
|       LessonProgress newLessonTracker = new LessonProgress(lesson); | ||||
|       lessonProgress.add(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) { | ||||
|     LessonProgress progress = getLessonProgress(lesson); | ||||
|     progress.incrementAttempts(); | ||||
|  | ||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.container.users; | ||||
| import java.util.List; | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| public interface UserRepository extends JpaRepository<WebGoatUser, String> { | ||||
|  | ||||
|   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.stereotype.Service; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Service | ||||
| @AllArgsConstructor | ||||
| public class UserService implements UserDetailsService { | ||||
|  | ||||
| @ -10,10 +10,6 @@ import lombok.Getter; | ||||
| import lombok.NoArgsConstructor; | ||||
| import org.springframework.data.annotation.Id; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/15/17. | ||||
|  */ | ||||
| @Getter | ||||
| @AllArgsConstructor | ||||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||||
|  | ||||
| @ -9,10 +9,6 @@ import org.springframework.stereotype.Component; | ||||
| import org.springframework.validation.Errors; | ||||
| import org.springframework.validation.Validator; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Component | ||||
| @AllArgsConstructor | ||||
| 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.UserDetails; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Entity | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/21/17. | ||||
|  */ | ||||
| @Component | ||||
| public class ChallengeIntro extends Lesson { | ||||
|  | ||||
|  | ||||
| @ -9,10 +9,6 @@ import java.time.LocalDateTime; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @Builder | ||||
| @Data | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/21/17. | ||||
|  */ | ||||
| @Component | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/21/17. | ||||
|  */ | ||||
| @Component | ||||
| 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.client.RestTemplate; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/8/17. | ||||
|  */ | ||||
| @RestController | ||||
| @Slf4j | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/21/17. | ||||
|  */ | ||||
| @Component | ||||
| public class Challenge7 extends Lesson { | ||||
|  | ||||
|  | ||||
| @ -8,9 +8,6 @@ import java.util.Random; | ||||
|  | ||||
| /** | ||||
|  * WARNING: DO NOT CHANGE FILE WITHOUT CHANGING .git contents | ||||
|  * | ||||
|  * @author nbaars | ||||
|  * @since 8/17/17. | ||||
|  */ | ||||
| public class PasswordResetLink { | ||||
|  | ||||
|  | ||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | ||||
| import org.owasp.webgoat.container.lessons.Lesson; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/21/17. | ||||
|  */ | ||||
| @Component | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author TMelzer | ||||
|  * @since 30.11.18 | ||||
|  */ | ||||
| @Component | ||||
| 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.RestController; | ||||
|  | ||||
| /** | ||||
|  * This is just a class used to make the HTTP request. | ||||
|  * | ||||
|  * @author TMelzer | ||||
|  * @since 30.11.18 | ||||
|  */ | ||||
| @RestController | ||||
| 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 | ||||
|  * a specific number. | ||||
|  * | ||||
|  * @author TMelzer | ||||
|  * @since 30.11.18 | ||||
|  */ | ||||
| @RestController | ||||
| @AssignmentHints({"networkHint1", "networkHint2"}) | ||||
|  | ||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | ||||
| import org.owasp.webgoat.container.lessons.Lesson; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author BenediktStuhrmann | ||||
|  * @since 11/2/18. | ||||
|  */ | ||||
| @Component | ||||
| 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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/6/17. | ||||
|  */ | ||||
| @RestController | ||||
| @AssignmentHints({ | ||||
|   "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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/6/17. | ||||
|  */ | ||||
| @RestController | ||||
| @RequestMapping("/clientSideFiltering/challenge-store") | ||||
| public class ShopEndpoint { | ||||
|  | ||||
| @ -10,10 +10,6 @@ import lombok.Getter; | ||||
| import lombok.NoArgsConstructor; | ||||
| import lombok.Setter; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/8/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Setter | ||||
| @AllArgsConstructor | ||||
|  | ||||
| @ -8,12 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | ||||
| import org.owasp.webgoat.container.lessons.Lesson; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /*** | ||||
|  * | ||||
|  * @author Angel Olle Blazquez | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| @Component | ||||
| 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.RestController; | ||||
|  | ||||
| /*** | ||||
|  * | ||||
|  * @author Angel Olle Blazquez | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| @RestController | ||||
| @AssignmentHints({ | ||||
|   "hijacksession.hints.1", | ||||
|  | ||||
| @ -9,9 +9,6 @@ import lombok.Builder; | ||||
| import lombok.Getter; | ||||
| import lombok.ToString; | ||||
|  | ||||
| /** | ||||
|  * @author Angel Olle Blazquez | ||||
|  */ | ||||
| @Getter | ||||
| @ToString | ||||
| public class Authentication implements Principal { | ||||
|  | ||||
| @ -6,9 +6,6 @@ package org.owasp.webgoat.lessons.hijacksession.cas; | ||||
|  | ||||
| import java.security.Principal; | ||||
|  | ||||
| /** | ||||
|  * @author Angel Olle Blazquez | ||||
|  */ | ||||
| @FunctionalInterface | ||||
| public interface AuthenticationProvider<T extends Principal> { | ||||
|  | ||||
|  | ||||
| @ -15,10 +15,6 @@ import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.web.context.annotation.ApplicationScope; | ||||
|  | ||||
| /** | ||||
|  * @author Angel Olle Blazquez | ||||
|  */ | ||||
|  | ||||
| // weak id value and mechanism | ||||
|  | ||||
| @ApplicationScope | ||||
|  | ||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | ||||
| import org.owasp.webgoat.container.lessons.Lesson; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/22/17. | ||||
|  */ | ||||
| @Component | ||||
| public class JWT extends Lesson { | ||||
|  | ||||
|  | ||||
| @ -4,10 +4,6 @@ | ||||
|  */ | ||||
| package org.owasp.webgoat.lessons.jwt.votes; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/30/17. | ||||
|  */ | ||||
| public class Views { | ||||
|   public interface GuestView {} | ||||
|  | ||||
|  | ||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.lessons.jwt.votes; | ||||
| import com.fasterxml.jackson.annotation.JsonView; | ||||
| import lombok.Getter; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 5/2/17. | ||||
|  */ | ||||
| @Getter | ||||
| public class Vote { | ||||
|   @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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| 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.servlet.ModelAndView; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| @AssignmentHints({ | ||||
|   "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.client.RestTemplate; | ||||
|  | ||||
| /** | ||||
|  * Part of the password reset assignment. Used to send the e-mail. | ||||
|  * | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| 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.RestController; | ||||
|  | ||||
| /** | ||||
|  * Assignment for picking a good security question. | ||||
|  * | ||||
|  * @author Tobias Melzer | ||||
|  * @since 11.12.18 | ||||
|  */ | ||||
| @RestController | ||||
| 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.RestTemplate; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| public class SimpleMailAssignment implements AssignmentEndpoint { | ||||
|   private final String webWolfURL; | ||||
|  | ||||
| @ -9,10 +9,6 @@ import jakarta.validation.constraints.Size; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/18/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Setter | ||||
| public class PasswordChangeForm { | ||||
|  | ||||
| @ -8,10 +8,6 @@ import org.owasp.webgoat.container.lessons.Category; | ||||
| import org.owasp.webgoat.container.lessons.Lesson; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| /** | ||||
|  * @author BenediktStuhrmann | ||||
|  * @since 12/2/18. | ||||
|  */ | ||||
| @Component | ||||
| 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.springframework.stereotype.Component; | ||||
|  | ||||
| /*** | ||||
|  * | ||||
|  * @author Angel Olle Blazquez | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| @Component | ||||
| 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.RestController; | ||||
|  | ||||
| /*** | ||||
|  * | ||||
|  * @author Angel Olle Blazquez | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| @AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"}) | ||||
| @RestController | ||||
| public class SpoofCookieAssignment implements AssignmentEndpoint { | ||||
|  | ||||
| @ -9,12 +9,6 @@ import java.util.Base64; | ||||
| import org.apache.commons.lang3.RandomStringUtils; | ||||
| import org.springframework.security.crypto.codec.Hex; | ||||
|  | ||||
| /*** | ||||
|  * | ||||
|  * @author Angel Olle Blazquez | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| public class EncDec { | ||||
|  | ||||
|   // PoC: weak encoding method | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| package org.owasp.webgoat.lessons.sqlinjection.advanced; | ||||
|  | ||||
| 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 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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/8/17. | ||||
|  */ | ||||
| @RestController | ||||
| @AssignmentHints( | ||||
|     value = {"SqlInjectionChallenge1", "SqlInjectionChallenge2", "SqlInjectionChallenge3"}) | ||||
|     value = { | ||||
|       "SqlInjectionChallenge1", | ||||
|       "SqlInjectionChallenge2", | ||||
|       "SqlInjectionChallenge3", | ||||
|       "SqlInjectionChallenge4", | ||||
|       "SqlInjectionChallenge5", | ||||
|       "SqlInjectionChallenge6", | ||||
|       "SqlInjectionChallenge7" | ||||
|     }) | ||||
| @Slf4j | ||||
| public class SqlInjectionChallenge implements AssignmentEndpoint { | ||||
|  | ||||
| @ -35,38 +39,34 @@ public class SqlInjectionChallenge implements AssignmentEndpoint { | ||||
|     this.dataSource = dataSource; | ||||
|   } | ||||
|  | ||||
|   @PutMapping("/SqlInjectionAdvanced/challenge") | ||||
|   @PutMapping("/SqlInjectionAdvanced/register") | ||||
|   // assignment path is bounded to class so we use different http method :-) | ||||
|   @ResponseBody | ||||
|   public AttackResult registerNewUser( | ||||
|       @RequestParam String username_reg, | ||||
|       @RequestParam String email_reg, | ||||
|       @RequestParam String password_reg) | ||||
|       throws Exception { | ||||
|     AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg); | ||||
|       @RequestParam("username_reg") String username, | ||||
|       @RequestParam("email_reg") String email, | ||||
|       @RequestParam("password_reg") String password) { | ||||
|     AttackResult attackResult = checkArguments(username, email, password); | ||||
|  | ||||
|     if (attackResult == null) { | ||||
|  | ||||
|       try (Connection connection = dataSource.getConnection()) { | ||||
|         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(); | ||||
|         ResultSet resultSet = statement.executeQuery(checkUserQuery); | ||||
|  | ||||
|         if (resultSet.next()) { | ||||
|           if (username_reg.contains("tom'")) { | ||||
|             attackResult = success(this).feedback("user.exists").build(); | ||||
|           } else { | ||||
|             attackResult = failed(this).feedback("user.exists").feedbackArgs(username_reg).build(); | ||||
|           } | ||||
|           attackResult = failed(this).feedback("user.exists").feedbackArgs(username).build(); | ||||
|         } else { | ||||
|           PreparedStatement preparedStatement = | ||||
|               connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)"); | ||||
|           preparedStatement.setString(1, username_reg); | ||||
|           preparedStatement.setString(2, email_reg); | ||||
|           preparedStatement.setString(3, password_reg); | ||||
|           preparedStatement.setString(1, username); | ||||
|           preparedStatement.setString(2, email); | ||||
|           preparedStatement.setString(3, password); | ||||
|           preparedStatement.execute(); | ||||
|           attackResult = success(this).feedback("user.created").feedbackArgs(username_reg).build(); | ||||
|           attackResult = | ||||
|               informationMessage(this).feedback("user.created").feedbackArgs(username).build(); | ||||
|         } | ||||
|       } catch (SQLException e) { | ||||
|         attackResult = failed(this).output("Something went wrong").build(); | ||||
| @ -75,13 +75,13 @@ public class SqlInjectionChallenge implements AssignmentEndpoint { | ||||
|     return attackResult; | ||||
|   } | ||||
|  | ||||
|   private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) { | ||||
|     if (StringUtils.isEmpty(username_reg) | ||||
|         || StringUtils.isEmpty(email_reg) | ||||
|         || StringUtils.isEmpty(password_reg)) { | ||||
|   private AttackResult checkArguments(String username, String email, String password) { | ||||
|     if (StringUtils.isEmpty(username) | ||||
|         || StringUtils.isEmpty(email) | ||||
|         || StringUtils.isEmpty(password)) { | ||||
|       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 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.assignments.AssignmentEndpoint; | ||||
| import org.owasp.webgoat.container.assignments.AssignmentHints; | ||||
| import org.owasp.webgoat.container.assignments.AttackResult; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| 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; | ||||
|  | ||||
| @RestController | ||||
| @AssignmentHints( | ||||
|     value = { | ||||
|       "SqlInjectionChallengeHint1", | ||||
|       "SqlInjectionChallengeHint2", | ||||
|       "SqlInjectionChallengeHint3", | ||||
|       "SqlInjectionChallengeHint4" | ||||
|     }) | ||||
| public class SqlInjectionChallengeLogin implements AssignmentEndpoint { | ||||
|   private final LessonDataSource dataSource; | ||||
|  | ||||
| @ -31,20 +23,22 @@ public class SqlInjectionChallengeLogin implements AssignmentEndpoint { | ||||
|     this.dataSource = dataSource; | ||||
|   } | ||||
|  | ||||
|   @PostMapping("/SqlInjectionAdvanced/challenge_Login") | ||||
|   @PostMapping("/SqlInjectionAdvanced/login") | ||||
|   @ResponseBody | ||||
|   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()) { | ||||
|       var statement = | ||||
|           connection.prepareStatement( | ||||
|               "select password from sql_challenge_users where userid = ? and password = ?"); | ||||
|       statement.setString(1, username_login); | ||||
|       statement.setString(2, password_login); | ||||
|       statement.setString(1, username); | ||||
|       statement.setString(2, password); | ||||
|       var resultSet = statement.executeQuery(); | ||||
|  | ||||
|       if (resultSet.next()) { | ||||
|         return ("tom".equals(username_login)) | ||||
|         return ("tom".equals(username)) | ||||
|             ? success(this).build() | ||||
|             : failed(this).feedback("ResultsButNotTom").build(); | ||||
|       } 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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 6/13/17. | ||||
|  */ | ||||
| @RestController | ||||
| @RequestMapping("SqlInjectionMitigations/servers") | ||||
| @Slf4j | ||||
|  | ||||
| @ -18,10 +18,6 @@ import org.springframework.web.bind.annotation.ResponseBody; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.servlet.ModelAndView; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| public class LandingAssignment implements AssignmentEndpoint { | ||||
|   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.RestTemplate; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @RestController | ||||
| public class MailAssignment implements AssignmentEndpoint { | ||||
|  | ||||
|  | ||||
| @ -10,10 +10,6 @@ import lombok.Getter; | ||||
| import lombok.NoArgsConstructor; | ||||
| import lombok.Setter; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/8/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Setter | ||||
| @AllArgsConstructor | ||||
|  | ||||
| @ -12,10 +12,6 @@ import lombok.NoArgsConstructor; | ||||
| import lombok.Setter; | ||||
| import lombok.ToString; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 4/8/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Setter | ||||
| @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.RestController; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 5/4/17. | ||||
|  */ | ||||
| @RestController | ||||
| @RequestMapping("xxe/comments") | ||||
| @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.WebMvcConfigurer; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/13/17. | ||||
|  */ | ||||
| @Configuration | ||||
| public class MvcConfiguration implements WebMvcConfigurer { | ||||
|  | ||||
|  | ||||
| @ -18,10 +18,6 @@ import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/20/17. | ||||
|  */ | ||||
| @Data | ||||
| @Builder | ||||
| @AllArgsConstructor | ||||
|  | ||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.mailbox; | ||||
| import java.util.List; | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 8/17/17. | ||||
|  */ | ||||
| public interface MailboxRepository extends JpaRepository<Email, String> { | ||||
|  | ||||
|   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. | ||||
|  * | ||||
|  * @author nbaars | ||||
|  * @since 8/13/17. | ||||
|  */ | ||||
| @Controller | ||||
| @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 | ||||
|  * WebGoat. | ||||
|  * | ||||
|  * @author nbaars | ||||
|  * @since 8/13/17. | ||||
|  */ | ||||
| public class WebWolfTraceRepository implements HttpExchangeRepository { | ||||
|   private enum MatchingMode { | ||||
|  | ||||
| @ -7,10 +7,6 @@ package org.owasp.webgoat.webwolf.user; | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Repository("webWolfUserRepository") | ||||
| 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.stereotype.Service; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Service | ||||
| 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.UserDetails; | ||||
|  | ||||
| /** | ||||
|  * @author nbaars | ||||
|  * @since 3/19/17. | ||||
|  */ | ||||
| @Getter | ||||
| @Entity | ||||
| @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.user.directory=${user.home}/.webgoat-${webgoat.build.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.default.language=en | ||||
| 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.mail.url=${webwolf.url}/mail | ||||
|  | ||||
| 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-source=metadata | ||||
| #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-source=metadata | ||||
|  | ||||
| spring.jackson.serialization.indent_output=true | ||||
| 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.not.solved=Sorry the solution is not correct, please try again. | ||||
| RestartLesson=Restart this Lesson | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| #General | ||||
| lesson.completed=Herzlichen Gl\u00fcckwunsch! Sie haben diese Lektion 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. | ||||
|  | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| #General | ||||
| lesson.completed=F\u00e9licitations. Vous avez termin\u00e9 cette le\u00e7on avec succ\u00e9s. | ||||
| RestartLesson=Recommencer cette le\u00e7on | ||||
| SolutionVideos=Solution vid\u00e9os | ||||
| 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.not.solved=Sorry de oplossing is niet correct, probeer het nog eens. | ||||
| 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
	