Compare commits

..

67 Commits

Author SHA1 Message Date
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
f7a9995fe0 chore: create release v2023.5 2023-11-23 16:05:13 +01:00
d6c4e8e454 chore: bump docker/build-push-action from 4.1.1 to 5.1.0 (#1670)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.1 to 5.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4.1.1...v5.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>
2023-11-20 15:11:59 +01:00
26628a39e1 chore: bump org.apache.commons:commons-compress from 1.23.0 to 1.25.0 (#1672)
Bumps org.apache.commons:commons-compress from 1.23.0 to 1.25.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-compress
  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>
2023-11-20 15:05:36 +01:00
2d26a318d1 chore: bump org.owasp:dependency-check-maven from 6.5.1 to 8.4.3 (#1671)
Bumps [org.owasp:dependency-check-maven](https://github.com/jeremylong/DependencyCheck) from 6.5.1 to 8.4.3.
- [Release notes](https://github.com/jeremylong/DependencyCheck/releases)
- [Changelog](https://github.com/jeremylong/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jeremylong/DependencyCheck/compare/v6.5.1...v8.4.3)

---
updated-dependencies:
- dependency-name: org.owasp:dependency-check-maven
  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-11-20 14:55:37 +01:00
dc16e9a0fb fix: typo in WebGoad.txt (#1667)
Signed-off-by: Agustín Díaz <agustin.ramiro.diaz@gmail.com>
2023-11-17 18:59:02 +01:00
88a321c268 search box moved and jwt encode/decode with little delay (#1664) 2023-11-16 14:42:10 +01:00
8450c5a5be skip validation for JWT (#1663)
* skip validation for JWT

* skip validation for JWT

* skip validation for JWT
2023-11-15 18:30:14 +01:00
ba75e10efd fixed issue in JWT test tool and added robot test (#1658) 2023-11-14 18:14:48 +01:00
d1e44bbc98 Password reset link test condition more strict and move all WebWolf links to /WebWolf (#1645)
* better check on host and port for password reset and make context roots more flexible

* spotless applied

* removed hardcoded /WebGoat from js

* removed hardcoded /WebGoat from js

* fix spotless

* fix scoreboard

* upgrade WebWolf bootstrap version and icons and templates - part 1

* fixed more bootstrap 5 style issues and context path issues

* organized WebSecurityConfig based on latest conventions and added basic support for oauth (more work needed)

* spotless applied

* added mock bean

* requires updates to properties - commented for now

* requires updates to properties - commented for now

* oauth secrets through env values

* user creation after oauth login

* integration test against non default context paths

* adjusted StartupMessage

* add global model element username

* conditionally show login oauth links

* fixed WebWolf login

---------

Co-authored-by: René Zubcevic <rene@Mac-mini-van-Rene.local>
2023-11-14 10:01:59 +01:00
5a4974f3c2 chore: bump org.apache.maven.plugins:maven-checkstyle-plugin (#1640)
Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-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>
2023-11-02 08:13:39 +01:00
4fc1d1fb22 chore: bump org.apache.maven.plugins:maven-surefire-plugin (#1641)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.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>
2023-11-02 07:26:26 +01:00
084a105c69 Java 21 initial support (#1622)
* check java 17 and 21 in build

* build on regular branch push

* build on regular branch push

* build on regular branch push

* update spring boot for Java21 support
2023-10-23 20:21:00 +02:00
7485cb8b9a chore: bump org.webjars:bootstrap from 3.3.7 to 5.3.2 (#1624)
* chore: bump org.webjars:bootstrap from 3.3.7 to 5.3.2

Bumps [org.webjars:bootstrap](https://github.com/webjars/bootstrap) from 3.3.7 to 5.3.2.
- [Commits](https://github.com/webjars/bootstrap/compare/bootstrap-3.3.7...bootstrap-5.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>

* small update and ignore major updates

* small update and ignore major updates

---------

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>
2023-10-23 20:09:48 +02:00
c312ae989f chore: bump docker/setup-buildx-action from 2 to 3 (#1628)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-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>
2023-10-23 17:12:25 +02:00
5fde7fbf29 chore: bump docker/login-action from 2.2.0 to 3.0.0 (#1630)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2.2.0...v3.0.0)

---
updated-dependencies:
- dependency-name: docker/login-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>
2023-10-23 17:03:54 +02:00
a32c56bfc7 chore: bump actions/first-interaction from 1.1.1 to 1.2.0 (#1629)
Bumps [actions/first-interaction](https://github.com/actions/first-interaction) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/actions/first-interaction/releases)
- [Commits](https://github.com/actions/first-interaction/compare/v1.1.1...v1.2.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>
Co-authored-by: René Zubcevic <rene@zubcevic.com>
2023-10-23 16:57:16 +02:00
6fd3eb57eb chore: bump com.google.guava:guava from 32.1.1-jre to 32.1.3-jre (#1627)
Bumps [com.google.guava:guava](https://github.com/google/guava) from 32.1.1-jre to 32.1.3-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-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>
2023-10-23 16:49:02 +02:00
1743d017ff chore: bump commons-io:commons-io from 2.13.0 to 2.14.0 (#1626)
Bumps commons-io:commons-io from 2.13.0 to 2.14.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>
2023-10-23 16:25:45 +02:00
2b2638943b chore: bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11 (#1625)
Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.10 to 0.8.11.
- [Release notes](https://github.com/jacoco/jacoco/releases)
- [Commits](https://github.com/jacoco/jacoco/compare/v0.8.10...v0.8.11)

---
updated-dependencies:
- dependency-name: org.jacoco:jacoco-maven-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>
2023-10-23 16:18:27 +02:00
45c26d8aaf Fix servers id (#1619) 2023-10-22 15:25:52 +02:00
be30551850 fix: potential NPE in the stored XSS assignment 2023-08-27 14:31:35 +02:00
49862f6b90 fix: fixes the default change in trailing slash matching and address the affected assignments 2023-08-27 14:14:27 +02:00
4009785bb8 fix: crypto basics broken links 2023-08-27 13:16:08 +02:00
d8341c86a1 bug: fix hint that was breaking the template, causing hints from different assignments to mix (#1424) 2023-08-27 02:08:52 +02:00
055578893d feat: improve MFAC lesson hint texts for a better user experience (#1424) 2023-08-27 02:08:52 +02:00
b89ebd70ad chore: bump webdrivermanager from 5.3.2 to 5.3.3
Bumps [webdrivermanager](https://github.com/bonigarcia/webdrivermanager) from 5.3.2 to 5.3.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.2...webdrivermanager-5.3.3)

---
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>
2023-08-27 00:34:41 +02:00
7b81247dd1 fix: HijackSession lesson template deprecated Tymeleaf attribute 2023-08-26 02:57:50 +02:00
3bc2e57c9c Fix NPE in IDOR lesson 2023-08-26 02:22:33 +02:00
c3ec168d59 Add new assignment IT tests 2023-08-26 01:30:17 +02:00
a67fbf5a5a fix: XSS mitigation 2023-08-26 01:30:17 +02:00
3365c8d447 Remove wrong files 2023-08-25 22:50:40 +02:00
368c046779 fix: Stored Cross-Site Scripting Lesson 2023-08-25 20:55:26 +02:00
8749137d1e chore: bump org.webjars:jquery from 3.6.4 to 3.7.0
Bumps [org.webjars:jquery](https://github.com/webjars/jquery) from 3.6.4 to 3.7.0.
- [Commits](https://github.com/webjars/jquery/compare/jquery-3.6.4...jquery-3.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 00:31:04 +02:00
786cabd251 Make webjar dependencies version agnostic 2023-08-24 16:43:28 +02:00
dda8b10f55 chore: bump org.jruby:jruby from 9.4.2.0 to 9.4.3.0
Bumps org.jruby:jruby from 9.4.2.0 to 9.4.3.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>
2023-08-19 00:20:59 +02:00
d6ca083529 chore: bump commons-io:commons-io from 2.11.0 to 2.13.0
Bumps commons-io:commons-io from 2.11.0 to 2.13.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>
2023-08-18 16:15:17 +02:00
7c92d625dd doc: fix version strings
Replace `2023.3` with `2023.4`
2023-08-16 15:59:23 +02:00
4ba818533c fix: WebWolf JWT jquery webjar 2023-08-09 01:32:03 +02:00
a9b1fd66b8 feat: implement JWT jku example (#1552)
Closes #1539
2023-08-08 17:18:22 +02:00
8f6e47e6d4 chore: bump com.nulab-inc:zxcvbn from 1.7.0 to 1.8.0 (#1542)
Bumps [com.nulab-inc:zxcvbn](https://github.com/nulab/zxcvbn4j) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/nulab/zxcvbn4j/releases)
- [Changelog](https://github.com/nulab/zxcvbn4j/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nulab/zxcvbn4j/compare/1.7.0...1.8.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>
2023-08-04 16:34:49 +02:00
61de52840f chore: bump com.diffplug.spotless:spotless-maven-plugin from 2.33.0 to 2.38.0 (#1535)
* chore: bump com.diffplug.spotless:spotless-maven-plugin

Bumps [com.diffplug.spotless:spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.33.0 to 2.38.0.
- [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md)
- [Commits](https://github.com/diffplug/spotless/compare/lib/2.33.0...lib/2.38.0)

---
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>

* chore: format code

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nanne Baars <nanne.baars@owasp.org>
2023-07-30 15:10:31 +02:00
fd3eb2451c chore: bump guava from 31.1-jre to 32.1.1-jre (#1530)
Bumps [guava](https://github.com/google/guava) from 31.1-jre to 32.1.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
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-29 12:35:06 +02:00
32fa1ec0a6 chore: bump jquery from 3.5.1 to 3.6.4 (#1529)
Bumps [jquery](https://github.com/webjars/jquery) from 3.5.1 to 3.6.4.
- [Commits](https://github.com/webjars/jquery/compare/jquery-3.5.1...jquery-3.6.4)

---
updated-dependencies:
- dependency-name: org.webjars:jquery
  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>
2023-07-27 13:04:46 +02:00
ad00119b0d Add Assignment7 Tests 2023-07-18 00:38:23 +02:00
25f49537e7 bug: Fix IDOR lesson 2023-07-16 17:14:27 +02:00
8cb735e623 chore: bump joonvena/robotframework-reporter-action from 2.1 to 2.2
Bumps [joonvena/robotframework-reporter-action](https://github.com/joonvena/robotframework-reporter-action) from 2.1 to 2.2.
- [Release notes](https://github.com/joonvena/robotframework-reporter-action/releases)
- [Commits](https://github.com/joonvena/robotframework-reporter-action/compare/v2.1...v2.2)

---
updated-dependencies:
- dependency-name: joonvena/robotframework-reporter-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-16 16:01:06 +02:00
155a40aab4 chore: bump docker/build-push-action from 4.1.0 to 4.1.1
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4.1.0...v4.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-16 15:55:22 +02:00
6c4ddbbaad chore: bump maven-surefire-plugin from 3.1.0 to 3.1.2
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.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>
2023-07-16 15:41:25 +02:00
d704f69879 chore: bump commons-compress from 1.22 to 1.23.0 (#1514)
Bumps commons-compress from 1.22 to 1.23.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-compress
  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-07-15 09:28:40 +02:00
3b2b613aa5 chore: bump asciidoctorj from 2.5.3 to 2.5.10 (#1498)
Bumps [asciidoctorj](https://github.com/asciidoctor/asciidoctorj) from 2.5.3 to 2.5.10.
- [Release notes](https://github.com/asciidoctor/asciidoctorj/releases)
- [Changelog](https://github.com/asciidoctor/asciidoctorj/blob/v2.5.10/CHANGELOG.adoc)
- [Commits](https://github.com/asciidoctor/asciidoctorj/compare/v2.5.3...v2.5.10)

---
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>
2023-06-18 20:21:53 +02:00
934ba3e496 fix: remove steps from release script (#1509)
Closes gh-1383
2023-06-18 20:13:38 +02:00
8ec718c1ef format 2023-06-15 19:26:33 +02:00
1df7ca61a3 Text content improvement 2023-06-15 19:26:33 +02:00
75398feca0 Add hints 2023-06-15 19:26:33 +02:00
76a2365abf chore: bump docker/setup-qemu-action from 2.1.0 to 2.2.0 (#1503)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.1.0...v2.2.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>
2023-06-14 10:31:00 +02:00
180 changed files with 4037 additions and 1064 deletions

View File

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

54
.github/workflows/branchbuild.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: "Branch build"
on:
push:
branches:
- "*"
- "!main"
jobs:
branch-build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java-version: [ 17, 21 ]
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ matrix.java-version }}
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.3.1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2-
- name: Build with Maven
run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.2.0
- name: "Set up Docker Buildx"
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v2
- name: "Verify Docker WebGoat build"
if: runner.os == 'Linux'
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Verify Docker WebGoat desktop build"
uses: docker/build-push-action@v5.1.0
if: runner.os == 'Linux'
with:
context: ./
file: ./Dockerfile_desktop
push: false
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}

View File

@ -21,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
@ -36,13 +36,13 @@ jobs:
run: mvn --no-transfer-progress verify
- name: "Set up QEMU"
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2.1.0
uses: docker/setup-qemu-action@v2.2.0
- name: "Set up Docker Buildx"
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: "Verify Docker WebGoat build"
if: runner.os == 'Linux'
uses: docker/build-push-action@v4.1.0
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile
@ -50,7 +50,7 @@ jobs:
build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Verify Docker WebGoat desktop build"
uses: docker/build-push-action@v4.1.0
uses: docker/build-push-action@v5.1.0
if: runner.os == 'Linux'
with:
context: ./

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
@ -44,7 +44,7 @@ jobs:
files: |
target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: |
## Version ${{ steps.tag.outputs.tag }}
## Version ${{ github.ref_name }}
### New functionality
@ -54,7 +54,7 @@ jobs:
- [#743 - Character encoding errors](https://github.com/WebGoat/WebGoat/issues/743)
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ steps.tag.outputs.tag }}...${{ steps.tag.outputs.tag }}
Full change log: https://github.com/WebGoat/WebGoat/compare/${{ github.ref_name }}...${{ github.ref_name }}
## Contributors
@ -72,21 +72,21 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU"
uses: docker/setup-qemu-action@v2.1.0
uses: docker/setup-qemu-action@v2.2.0
with:
platforms: all
- name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: "Login to dockerhub"
uses: docker/login-action@v2.2.0
uses: docker/login-action@v3.0.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push WebGoat"
uses: docker/build-push-action@v4.1.0
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile
@ -99,7 +99,7 @@ jobs:
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Build and push WebGoat desktop"
uses: docker/build-push-action@v4.1.0
uses: docker/build-push-action@v5.1.0
with:
context: ./
file: ./Dockerfile_desktop
@ -121,7 +121,7 @@ jobs:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17

View File

@ -30,7 +30,7 @@ jobs:
architecture: x64
# Uses an action to add JDK 17 to the VM (and mvn?)
- name: set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
@ -61,7 +61,7 @@ jobs:
# 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.1
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'
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.1.1
- uses: actions/first-interaction@v1.3.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'

View File

@ -8,7 +8,7 @@ and 2023.01 in the `pom.xml`.
### Release notes:
Update the release notes with the correct version. Use `git shortlog -s -n --since "JAN 06 2023"` for the list of
committers.
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

View File

@ -1,4 +1,4 @@
FROM docker.io/eclipse-temurin:19-jre-focal
FROM docker.io/eclipse-temurin:21-jdk-ubi9-minimal
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
MAINTAINER "WebGoat team"
@ -14,6 +14,8 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
EXPOSE 8080
EXPOSE 9090
ENV TZ=Europe/Amsterdam
WORKDIR /home/webgoat
ENTRYPOINT [ "java", \
"-Duser.home=/home/webgoat", \
@ -30,8 +32,4 @@ ENTRYPOINT [ "java", \
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
"-Drunning.in.docker=true", \
"-Dwebgoat.host=0.0.0.0", \
"-Dwebwolf.host=0.0.0.0", \
"-Dwebgoat.port=8080", \
"-Dwebwolf.port=9090", \
"-jar", "webgoat.jar" ]
"-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]

View File

@ -1,4 +1,4 @@
# WebGoat 8: 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)
[![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/)
@ -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
```
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
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
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
@ -71,7 +79,8 @@ 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)
```shell
java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.3.jar
export TZ=Europe/Amsterdam # or your timezone
java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar
```
Click the link in the log to start WebGoat.
@ -80,7 +89,7 @@ Click the link in the log to start WebGoat.
### Prerequisites:
* Java 17
* Java 17 or 21
* Your favorite IDE
* Git, or Git support in your IDE
@ -132,9 +141,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:
```Shell
export TZ=Europe/Amsterdam # or your timezone
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar target/webgoat-2023.3-SNAPSHOT.jar
java -jar target/webgoat-2023.6-SNAPSHOT.jar
```
Or in a docker run it would (once this version is pushed into docker hub) look like this:

View File

@ -1,5 +1,60 @@
# WebGoat release notes
## Version 2023.6
### 🚀 New functionality
- Consistent environment values and url references (#1677)
- Show directly requested file in requests overview
- Show creating time in file upload overview
### 🐞 Bug fixes
- Fix startup message (#1687)
- Fix/state of software supply chain links (#1683)
- Fix WebWolf UI (#1686)
### 🔄 Technical tasks
- bump actions/setup-java from 3 to 4 (#1690)
- bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
- bump com.diffplug.spotless:spotless-maven-plugin (#1688)
## Version 2023.5
### New functionality
- Implement JWT jku example (#1552)
- Java 21 initial support (#1622)
- improve MFAC lesson hint texts for a better user experience (#1424)
- upgrade to Spring Boot version 3 (#1477)
### Bug fixes
- typo in WebGoad.txt (#1667)
- search box moved and jwt encode/decode with little delay (#1664)
- skip validation for JWT (#1663)
- fixed issue in JWT test tool and added robot test (#1658)
- Password reset link test condition more strict and move all WebWolf links to /WebWolf (#1645)
- fix servers id (#1619)
- potential NPE in the stored XSS assignment
- crypto basics broken links
- fixes the default change in trailing slash matching and address the affected assignments
- hint that was breaking the template, causing hints from different assignments to mix (#1424)
- HijackSession lesson template deprecated Tymeleaf attribute
- Fix NPE in IDOR lesson
- Add new assignment IT tests
- XSS mitigation
- Stored Cross-Site Scripting Lesson
- Add Assignment7 Tests
- Fix IDOR lesson
- remove steps from release script (#1509)
- robotframework fails due to updated dependencies (#1508)
- fix Java image inside Docker file The image now downloads the correct Java version based on the architecture.
- Fix typo of HijackSession_content0.adoc
- Restrict SSRF Regexes
- update challenge code - Flags are now wired through a Spring config - Introduced Flag class - Removed Flags from the FlagController
## Version 2023.4
### New functionality

View File

@ -3,7 +3,7 @@
With this image you have WebGoat and ZAP and a browser available to you in a browser running on Ubuntu.
You can start WebGoat and ZAP by opening a terminal and type:
./start-webgoat.sh
./start_webgoat.sh
./start_zap.sh
Happy hacking,

103
pom.xml
View File

@ -5,12 +5,12 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<version>3.1.5</version>
</parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId>
<version>2023.5-SNAPSHOT</version>
<version>2023.6</version>
<packaging>jar</packaging>
<name>WebGoat</name>
@ -109,30 +109,29 @@
<properties>
<!-- Shared properties with plugins and version numbers across submodules-->
<asciidoctorj.version>2.5.3</asciidoctorj.version>
<!-- Upgrading needs UI work in WebWolf -->
<bootstrap.version>3.3.7</bootstrap.version>
<asciidoctorj.version>2.5.10</asciidoctorj.version>
<bootstrap.version>5.3.1</bootstrap.version>
<cglib.version>3.3.0</cglib.version>
<!-- do not update necessary for lesson -->
<checkstyle.version>3.3.0</checkstyle.version>
<checkstyle.version>3.3.1</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version>
<commons-io.version>2.11.0</commons-io.version>
<commons-io.version>2.15.1</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-text.version>1.10.0</commons-text.version>
<guava.version>31.1-jre</guava.version>
<jacoco.version>0.8.10</jacoco.version>
<guava.version>32.1.3-jre</guava.version>
<jacoco.version>0.8.11</jacoco.version>
<java.version>17</java.version>
<jaxb.version>2.3.1</jaxb.version>
<jjwt.version>0.9.1</jjwt.version>
<jose4j.version>0.9.3</jose4j.version>
<jquery.version>3.5.1</jquery.version>
<jquery.version>3.7.0</jquery.version>
<jsoup.version>1.16.1</jsoup.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-surefire-plugin.version>3.1.0</maven-surefire-plugin.version>
<maven-surefire-plugin.version>3.2.1</maven-surefire-plugin.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<pmd.version>3.15.0</pmd.version>
@ -140,14 +139,16 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
<webdriver.version>5.3.2</webdriver.version>
<webgoat.port>8080</webgoat.port>
<webwolf.port>9090</webwolf.port>
<webdriver.version>5.3.3</webdriver.version>
<webgoat.context>/</webgoat.context>
<webgoat.sslenabled>false</webgoat.sslenabled>
<webjars-locator-core.version>0.53</webjars-locator-core.version>
<webwolf.context>/</webwolf.context>
<wiremock.version>2.27.2</wiremock.version>
<xml-resolver.version>1.2</xml-resolver.version>
<xstream.version>1.4.5</xstream.version>
<!-- do not update necessary for lesson -->
<zxcvbn.version>1.7.0</zxcvbn.version>
<zxcvbn.version>1.8.0</zxcvbn.version>
</properties>
<dependencyManagement>
@ -200,6 +201,17 @@
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.22.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@ -230,6 +242,11 @@
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
<version>${webjars-locator-core.version}</version>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
@ -243,12 +260,12 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.22</version>
<version>1.25.0</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>9.4.2.0</version>
<version>9.4.3.0</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -310,6 +327,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
@ -346,6 +367,15 @@
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@ -374,6 +404,10 @@
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
@ -478,10 +512,19 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<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>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables>
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
<argLine>-Xmx512m</argLine>
<includes>org/owasp/webgoat/*Test</includes>
</configuration>
<executions>
@ -504,6 +547,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
<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/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
@ -521,7 +565,6 @@
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
@ -532,7 +575,7 @@
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.33.0</version>
<version>2.41.1</version>
<configuration>
<formats>
<format>
@ -650,16 +693,15 @@
<portNames>
<portName>webgoat.port</portName>
<portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<groupId>org.honton.chas</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>0.9</version>
<version>0.9.2</version>
<executions>
<execution>
<id>start-jar</id>
@ -667,8 +709,18 @@
<goal>start</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<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>
<argument>java</argument>
<argument>-jar</argument>
@ -676,8 +728,6 @@
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
<argument>-Dspring.main.banner-mode=off</argument>
<argument>-Dwebgoat.port=${webgoat.port}</argument>
<argument>-Dwebwolf.port=${webwolf.port}</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
@ -703,7 +753,6 @@
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
</arguments>
<waitForInterrupt>false</waitForInterrupt>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
</configuration>
</execution>
<execution>
@ -728,7 +777,6 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.5.1</version>
<configuration>
<failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>false</skipProvidedScope>
@ -777,7 +825,6 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>before-unit-test</id>

View File

@ -12,8 +12,10 @@ Then see security settings and allow the file to run
pip3 install virtualenv --user
python3 -m virtualenv .venv
source .venv/bin/activate
pip install robotframework
pip install robotframework-SeleniumLibrary
pip install webdriver-manager
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

@ -2,6 +2,7 @@
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
@ -11,7 +12,7 @@ ${BROWSER} chrome
${SLEEP} 100
${DELAY} 0.25
${ENDPOINT} http://127.0.0.1:8080/WebGoat
${ENDPOINT_WOLF} http://127.0.0.1:9090
${ENDPOINT_WOLF} http://127.0.0.1:9090/WebWolf
${USERNAME} robotuser
${PASSWORD} password
${HEADLESS} ${FALSE}
@ -22,22 +23,25 @@ Initial_Page
[Arguments] ${ENDPOINT} ${BROWSER}
Log To Console Start WebGoat UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT} ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webgoat
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
IF ${HEADLESS}
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
ELSE
Open Browser ${ENDPOINT_WOLF}/WebWolf ${BROWSER} options=add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) alias=webwolf
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 ${400} ${200}
Set Window Position ${500} ${0}
Set Selenium Speed ${DELAY}
Close_Page
@ -53,6 +57,7 @@ Close_Page
*** Test Cases ***
Check_Initial_Page
[Tags] WebGoatTests
Switch Browser webgoat
Page Should Contain Username
Click Button Sign in
@ -60,6 +65,7 @@ Check_Initial_Page
Click Link /WebGoat/registration
Check_Registration_Page
[Tags] WebGoatTests
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
@ -68,6 +74,7 @@ Check_Registration_Page
Click Button Sign up
Check_Welcome_Page
[Tags] WebGoatTests
Page Should Contain WebGoat
Go To ${ENDPOINT}/login
Page Should Contain Username
@ -77,6 +84,7 @@ Check_Welcome_Page
Page Should Contain WebGoat
Check_Menu_Page
[Tags] WebGoatTests
Click Element css=a[category='Introduction']
Click Element Introduction-WebGoat
CLick Element Introduction-WebWolf
@ -93,9 +101,29 @@ Check_Menu_Page
Check_WebWolf
Switch Browser webwolf
location should be ${ENDPOINT_WOLF}/WebWolf
Go To ${ENDPOINT_WOLF}/mail
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

@ -25,7 +25,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("/WebGoat/access-control/users-admin-fix"))
.get(url("access-control/users-admin-fix"))
.then()
.statusCode(HttpStatus.SC_FORBIDDEN);
@ -40,7 +40,7 @@ class AccessControlIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.body(String.format(userTemplate, this.getUser(), this.getUser()))
.post(url("/WebGoat/access-control/users"))
.post(url("access-control/users"))
.then()
.statusCode(HttpStatus.SC_OK);
@ -51,15 +51,14 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("/WebGoat/access-control/users-admin-fix"))
.get(url("access-control/users-admin-fix"))
.then()
.statusCode(200)
.extract()
.jsonPath()
.get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(
url("/WebGoat/access-control/user-hash-fix"), Map.of("userHash", userHash), true);
checkAssignment(url("access-control/user-hash-fix"), Map.of("userHash", userHash), true);
}
private void assignment2() {
@ -69,18 +68,18 @@ class AccessControlIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("/WebGoat/access-control/users"))
.get(url("access-control/users"))
.then()
.statusCode(200)
.extract()
.jsonPath()
.get("find { it.username == \"Jerry\" }.userHash");
checkAssignment(url("/WebGoat/access-control/user-hash"), Map.of("userHash", userHash), true);
checkAssignment(url("access-control/user-hash"), Map.of("userHash", userHash), true);
}
private void assignment1() {
var params = Map.of("hiddenMenu1", "Users", "hiddenMenu2", "Config");
checkAssignment(url("/WebGoat/access-control/hidden-menu"), params, true);
checkAssignment(url("access-control/hidden-menu"), params, true);
}
}

View File

@ -64,12 +64,12 @@ public class CSRFIntegrationTest extends IntegrationTest {
public void init() {
startLesson("CSRF");
webwolfFileDir = getWebWolfFileServerLocation();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("csrf/feedback/message")));
uploadTrickHtml(
"csrf8.html",
trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
trickHTML8.replace("WEBGOATURL", url("login")).replace("USERNAME", this.getUser()));
}
@TestFactory
@ -103,7 +103,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", htmlName, htmlContent.getBytes())
.post(webWolfUrl("/WebWolf/fileupload"))
.post(webWolfUrl("fileupload"))
.then()
.extract()
.response()
@ -118,7 +118,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
.get(webWolfUrl("files/" + this.getUser() + "/" + htmlName))
.then()
.extract()
.response()
@ -136,7 +136,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html"))
.header("Referer", webWolfUrl("files/fake.html"))
.post(goatURL)
.then()
.extract()
@ -146,7 +146,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("confirmFlagVal", flag);
checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true);
checkAssignment(url("csrf/confirm-flag-1"), params, true);
}
private void checkAssignment4(String goatURL) {
@ -163,7 +163,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html"))
.header("Referer", webWolfUrl("files/fake.html"))
.formParams(params)
.post(goatURL)
.then()
@ -184,7 +184,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html"))
.header("Referer", webWolfUrl("files/fake.html"))
.contentType(ContentType.TEXT)
.body(
"{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is"
@ -198,7 +198,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
params.clear();
params.put("confirmFlagVal", flag);
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
checkAssignment(url("csrf/feedback"), params, true);
}
private void checkAssignment8(String goatURL) {
@ -217,7 +217,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Referer", webWolfUrl("/files/fake.html"))
.header("Referer", webWolfUrl("files/fake.html"))
.params(params)
.post(goatURL)
.then()
@ -239,7 +239,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", newCookie)
.post(url("/csrf/login"))
.post(url("csrf/login"))
.then()
.statusCode(200)
.extract()
@ -253,7 +253,8 @@ public class CSRFIntegrationTest extends IntegrationTest {
Overview[] assignments =
RestAssured.given()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/service/lessonoverview.mvc"))
.relaxedHTTPSValidation()
.get(url("service/lessonoverview.mvc"))
.then()
.extract()
.jsonPath()

View File

@ -22,7 +22,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/challenge/logo"))
.get(url("challenge/logo"))
.then()
.statusCode(200)
.extract()
@ -34,14 +34,14 @@ public class ChallengeIntegrationTest extends IntegrationTest {
params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("/WebGoat/challenge/1"), params, true);
checkAssignment(url("challenge/1"), params, true);
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/1"))
.post(url("challenge/1"))
.then()
.statusCode(200)
.extract()
@ -50,7 +50,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkAssignment(url("challenge/flag"), params, true);
checkResults("/challenge/1");
@ -59,7 +59,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.get(url("scoreboard-data"))
.then()
.statusCode(200)
.extract()
@ -83,7 +83,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/5"))
.post(url("challenge/5"))
.then()
.statusCode(200)
.extract()
@ -92,7 +92,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkAssignment(url("challenge/flag"), params, true);
checkResults("/challenge/5");
@ -101,7 +101,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.get(url("scoreboard-data"))
.then()
.statusCode(200)
.extract()
@ -120,7 +120,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/challenge/7/.git"))
.get(url("challenge/7/.git"))
.then()
.statusCode(200)
.extract()
@ -132,7 +132,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", getUser() + "@webgoat.org")
.post(url("/WebGoat/challenge/7"))
.post(url("challenge/7"))
.then()
.statusCode(200)
.extract()
@ -144,7 +144,7 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/mail"))
.get(webWolfUrl("mail"))
.then()
.extract()
.response()
@ -158,13 +158,13 @@ public class ChallengeIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
.get(url("challenge/7/reset-password/{link}"), "375afe1104f4a487a73823c50a9292a2")
.then()
.statusCode(HttpStatus.ACCEPTED.value())
.extract()
.asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
checkAssignment(url("/WebGoat/challenge/flag"), Map.of("flag", flag), true);
checkAssignment(url("challenge/flag"), Map.of("flag", flag), true);
}
}

View File

@ -52,7 +52,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/crypto/encoding/basic"))
.get(url("crypto/encoding/basic"))
.then()
.extract()
.asString();
@ -64,7 +64,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("answer_user", answer_user);
params.put("answer_pwd", answer_pwd);
checkAssignment(url("/crypto/encoding/basic-auth"), params, true);
checkAssignment(url("crypto/encoding/basic-auth"), params, true);
}
private void checkAssignment3() {
@ -72,7 +72,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("answer_pwd1", answer_1);
checkAssignment(url("/crypto/encoding/xor"), params, true);
checkAssignment(url("crypto/encoding/xor"), params, true);
}
private void checkAssignment4() throws NoSuchAlgorithmException {
@ -82,7 +82,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/crypto/hashing/md5"))
.get(url("crypto/hashing/md5"))
.then()
.extract()
.asString();
@ -92,7 +92,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/crypto/hashing/sha256"))
.get(url("crypto/hashing/sha256"))
.then()
.extract()
.asString();
@ -112,7 +112,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("answer_pwd1", answer_1);
params.put("answer_pwd2", answer_2);
checkAssignment(url("/WebGoat/crypto/hashing"), params, true);
checkAssignment(url("crypto/hashing"), params, true);
}
private void checkAssignmentSigning() throws NoSuchAlgorithmException, InvalidKeySpecException {
@ -122,7 +122,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/crypto/signing/getprivate"))
.get(url("crypto/signing/getprivate"))
.then()
.extract()
.asString();
@ -135,7 +135,7 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("modulus", modulus);
params.put("signature", signature);
checkAssignment(url("/crypto/signing/verify"), params, true);
checkAssignment(url("crypto/signing/verify"), params, true);
}
private void checkAssignmentDefaults() {
@ -151,6 +151,6 @@ public class CryptoIntegrationTest extends IntegrationTest {
params.clear();
params.put("secretText", text);
params.put("secretFileName", "default_secret");
checkAssignment(url("/crypto/secure/defaults"), params, true);
checkAssignment(url("crypto/secure/defaults"), params, true);
}
}

View File

@ -26,7 +26,7 @@ public class DeserializationIntegrationTest extends IntegrationTest {
params.put(
"token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
}
checkAssignment(url("/WebGoat/InsecureDeserialization/task"), params, true);
checkAssignment(url("InsecureDeserialization/task"), params, true);
checkResults("/InsecureDeserialization/");
}

View File

@ -72,7 +72,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put(
"question_3_solution",
"Solution 2: The systems security is compromised even if only one goal is harmed.");
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
checkAssignment(url("cia/quiz"), params, true);
checkResults("/cia/");
}
@ -95,7 +95,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("payload", solution);
checkAssignment(url("/WebGoat/VulnerableComponents/attack1"), params, true);
checkAssignment(url("VulnerableComponents/attack1"), params, true);
checkResults("/VulnerableComponents/");
}
}
@ -107,7 +107,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("username", "CaptainJack");
params.put("password", "BlackPearl");
checkAssignment(url("/WebGoat/InsecureLogin/task"), params, true);
checkAssignment(url("InsecureLogin/task"), params, true);
checkResults("/InsecureLogin/");
}
@ -117,7 +117,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("password", "ajnaeliclm^&&@kjn.");
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
checkAssignment(url("SecurePasswords/assignment"), params, true);
checkResults("SecurePasswords/");
startLesson("AuthBypass");
@ -127,7 +127,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
checkAssignment(url("auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
startLesson("HttpProxies");
@ -138,8 +138,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true")
.contentType(ContentType.JSON)
.get(
url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then()
.statusCode(200)
.extract()
@ -165,7 +164,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest")
.formParams(params)
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
.post(url("CrossSiteScripting/phone-home-xss"))
.then()
.statusCode(200)
.extract()
@ -174,12 +173,12 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("successMessage", secretNumber);
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
checkAssignment(url("ChromeDevTools/dummy"), params, true);
params.clear();
params.put("number", "24");
params.put("network_num", "24");
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
checkAssignment(url("ChromeDevTools/network"), params, true);
checkResults("/ChromeDevTools/");
}
@ -194,7 +193,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("/auth-bypass/verify-account"), params, true);
checkAssignment(url("auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
}
@ -205,7 +204,7 @@ public class GeneralLessonIntegrationTest extends IntegrationTest {
params.clear();
params.put("param1", "secr37Value");
params.put("param2", "Main");
checkAssignment(url("/lesson-template/sample-attack"), params, true);
checkAssignment(url("lesson-template/sample-attack"), params, true);
checkResults("/lesson-template/");
}
}

View File

@ -4,11 +4,9 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach;
@ -19,7 +17,6 @@ import org.junit.jupiter.api.TestFactory;
public class IDORIntegrationTest extends IntegrationTest {
@BeforeEach
@SneakyThrows
public void init() {
startLesson("IDOR");
}
@ -27,56 +24,63 @@ public class IDORIntegrationTest extends IntegrationTest {
@TestFactory
Iterable<DynamicTest> testIDORLesson() {
return Arrays.asList(
dynamicTest("login", () -> loginIDOR()), dynamicTest("profile", () -> profile()));
dynamicTest("assignment 2 - login", this::loginIDOR),
dynamicTest("profile", this::profile));
}
@AfterEach
public void shutdown() throws IOException {
public void shutdown() {
checkResults("/IDOR");
}
private void loginIDOR() throws IOException {
private void loginIDOR() {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "tom");
params.put("password", "cat");
checkAssignment(url("/WebGoat/IDOR/login"), params, true);
checkAssignment(url("IDOR/login"), params, true);
}
private void profile() {
// View profile - assignment 3a
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/IDOR/profile"))
.get(url("IDOR/profile"))
.then()
.statusCode(200)
.extract()
.path("userId"),
CoreMatchers.is("2342384"));
// Show difference - assignment 3b
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("attributes", "userId,role");
checkAssignment(url("/WebGoat/IDOR/diff-attributes"), params, true);
checkAssignment(url("IDOR/diff-attributes"), params, true);
// View profile another way - assignment 4
params.clear();
params.put("url", "WebGoat/IDOR/profile/2342384");
checkAssignment(url("/WebGoat/IDOR/profile/alt-path"), params, true);
checkAssignment(url("IDOR/profile/alt-path"), params, true);
// assignment 5a
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/IDOR/profile/2342388"))
.get(url("IDOR/profile/2342388"))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
// assignment 5b
MatcherAssert.assertThat(
RestAssured.given()
.when()
@ -86,7 +90,7 @@ public class IDORIntegrationTest extends IntegrationTest {
.body(
"{\"role\":\"1\", \"color\":\"red\", \"size\":\"large\", \"name\":\"Buffalo Bill\","
+ " \"userId\":\"2342388\"}")
.put(url("/WebGoat/IDOR/profile/2342388"))
.put(url("IDOR/profile/2342388"))
.then()
.statusCode(200)
.extract()

View File

@ -5,7 +5,6 @@ import static io.restassured.RestAssured.given;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.Map;
import java.util.Objects;
import lombok.Getter;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
@ -15,34 +14,42 @@ import org.springframework.http.HttpStatus;
public abstract class IntegrationTest {
private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080");
private static String webGoatContext =
System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/");
@Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090");
@Getter
private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
private static String webWolfHost = System.getenv().getOrDefault("WEBWOLF_HOST", "127.0.0.1");
private static boolean useSSL = false;
@Getter
private static String webGoatHost = System.getenv().getOrDefault("WEBGOAT_HOST", "127.0.0.1");
private static String webWolfContext =
System.getenv().getOrDefault("WEBWOLF_CONTEXT", "/WebWolf/");
private static boolean useSSL =
Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "false"));
private static String webgoatUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
private static String webWolfUrl =
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
(useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext;
private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext;
@Getter private String webGoatCookie;
@Getter private String webWolfCookie;
@Getter private final String user = "webgoat";
protected String url(String url) {
url = url.replaceFirst("/WebGoat/", "");
url = url.replaceFirst("/WebGoat", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webgoatUrl + url;
}
protected String webWolfUrl(String url) {
url = url.replaceFirst("/WebWolf/", "");
url = url.replaceFirst("/WebWolf", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return webWolfUrl + url;
}
protected String webWolfFileUrl(String fileName) {
return webWolfUrl("files") + "/" + getUser() + "/" + fileName;
}
@BeforeEach
public void login() {
String location =
@ -231,7 +238,7 @@ public abstract class IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/file-server-location"))
.get(webWolfUrl("file-server-location"))
.then()
.extract()
.response()
@ -246,7 +253,7 @@ public abstract class IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/server-directory"))
.get(url("server-directory"))
.then()
.extract()
.response()
@ -259,7 +266,7 @@ public abstract class IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.delete(webWolfUrl("/mail"))
.delete(webWolfUrl("mail"))
.then()
.statusCode(HttpStatus.ACCEPTED.value());
}

View File

@ -14,7 +14,10 @@ import io.restassured.RestAssured;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.util.Base64;
import java.util.Calendar;
@ -23,6 +26,8 @@ import java.util.HashMap;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwk.RsaJsonWebKey;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
@ -40,7 +45,9 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
buyAsTom();
deleteTom();
deleteTomThroughKidClaim();
deleteTomThroughJkuClaim();
quiz();
@ -81,7 +88,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParam("jwt-encode-user", "user")
.post(url("/WebGoat/JWT/decode"))
.post(url("JWT/decode"))
.then()
.statusCode(200)
.extract()
@ -96,7 +103,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/JWT/secret/gettoken"))
.get(url("JWT/secret/gettoken"))
.then()
.extract()
.response()
@ -110,7 +117,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParam("token", generateToken(secret))
.post(url("/WebGoat/JWT/secret"))
.post(url("JWT/secret"))
.then()
.statusCode(200)
.extract()
@ -124,7 +131,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
.get(url("JWT/votings/login?user=Tom"))
.then()
.extract()
.cookie("access_token");
@ -157,7 +164,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.cookie("access_token", replacedToken)
.post(url("/WebGoat/JWT/votings"))
.post(url("JWT/votings"))
.then()
.statusCode(200)
.extract()
@ -198,7 +205,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("Authorization", "Bearer " + replacedToken)
.post(url("/WebGoat/JWT/refresh/checkout"))
.post(url("JWT/refresh/checkout"))
.then()
.statusCode(200)
.extract()
@ -206,8 +213,7 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
CoreMatchers.is(true));
}
private void deleteTom() {
private void deleteTomThroughKidClaim() {
Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE);
header.put(
@ -232,7 +238,54 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.post(url("/WebGoat/JWT/final/delete?token=" + token))
.post(url("JWT/kid/delete?token=" + token))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
}
private void deleteTomThroughJkuClaim() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
var jwks = new JsonWebKeySet(new RsaJsonWebKey((RSAPublicKey) keyPair.getPublic()));
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "jwks.json", jwks.toJson().getBytes())
.post(webWolfUrl("fileupload"))
.then()
.extract()
.response()
.getBody()
.asString();
Map<String, Object> header = new HashMap();
header.put(Header.TYPE, Header.JWT_TYPE);
header.put(JwsHeader.JWK_SET_URL, webWolfFileUrl("jwks.json"));
String token =
Jwts.builder()
.setHeader(header)
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[] {"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.RS256, keyPair.getPrivate())
.compact();
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.post(url("JWT/jku/delete?token=" + token))
.then()
.statusCode(200)
.extract()
@ -245,6 +298,6 @@ public class JWTLessonIntegrationTest extends IntegrationTest {
params.put("question_0_solution", "Solution 1");
params.put("question_1_solution", "Solution 2");
checkAssignment(url("/WebGoat/JWT/quiz"), params, true);
checkAssignment(url("JWT/quiz"), params, true);
}
}

View File

@ -11,12 +11,13 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.springframework.http.HttpHeaders;
public class PasswordResetLessonIntegrationTest extends IntegrationTest {
@BeforeEach
public void init() {
startLesson("/PasswordReset");
startLesson("PasswordReset");
}
@TestFactory
@ -68,7 +69,6 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
// WebWolf
var link = getPasswordResetLinkFromLandingPage();
// WebGoat
changePassword(link);
checkAssignment(
@ -85,7 +85,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/mail"))
.get(webWolfUrl("mail"))
.then()
.extract()
.response()
@ -119,7 +119,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests"))
.get(webWolfUrl("requests"))
.then()
.extract()
.response()
@ -136,7 +136,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
private void clickForgotEmailLink(String user) {
RestAssured.given()
.when()
.header("host", String.format("%s:%s", "localhost", getWebWolfPort()))
.header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort()))
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user)

View File

@ -55,7 +55,7 @@ class PathTraversalIT extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullName", "../John Doe")
.post(url("/WebGoat/PathTraversal/profile-upload"))
.post(url("PathTraversal/profile-upload"))
.then()
.statusCode(200)
.extract()
@ -71,7 +71,7 @@ class PathTraversalIT extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullNameFix", "..././John Doe")
.post(url("/WebGoat/PathTraversal/profile-upload-fix"))
.post(url("PathTraversal/profile-upload-fix"))
.then()
.statusCode(200)
.extract()
@ -89,7 +89,7 @@ class PathTraversalIT extends IntegrationTest {
"uploadedFileRemoveUserInput",
"../test.jpg",
Files.readAllBytes(fileToUpload.toPath()))
.post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
.post(url("PathTraversal/profile-upload-remove-user-input"))
.then()
.statusCode(200)
.extract()
@ -98,7 +98,7 @@ class PathTraversalIT extends IntegrationTest {
}
private void assignment4() throws IOException {
var uri = "/WebGoat/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()
.urlEncodingEnabled(false)
.when()
@ -110,7 +110,7 @@ class PathTraversalIT extends IntegrationTest {
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
checkAssignment(
url("/WebGoat/PathTraversal/random"),
url("PathTraversal/random"),
Map.of("secret", Sha512DigestUtils.shaHex(this.getUser())),
true);
}
@ -133,8 +133,10 @@ class PathTraversalIT extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
.post(url("/WebGoat/PathTraversal/zip-slip"))
.post(url("PathTraversal/zip-slip"))
.then()
.log()
.all()
.statusCode(200)
.extract()
.path("lessonCompleted"),

View File

@ -29,7 +29,7 @@ public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(Map.of("flag", "test"))
.post(url("/challenge/flag"));
.post(url("challenge/flag"));
};
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_PARALLEL_THREADS);
List<? extends Callable<Response>> flagCalls =

View File

@ -15,11 +15,11 @@ public class SSRFIntegrationTest extends IntegrationTest {
params.clear();
params.put("url", "images/jerry.png");
checkAssignment(url("/WebGoat/SSRF/task1"), params, true);
checkAssignment(url("SSRF/task1"), params, true);
params.clear();
params.put("url", "http://ifconfig.pro");
checkAssignment(url("/WebGoat/SSRF/task2"), params, true);
checkAssignment(url("SSRF/task2"), params, true);
checkResults("/SSRF/");
}

View File

@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
*/
class SessionManagementIT extends IntegrationTest {
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
private static final String HIJACK_LOGIN_CONTEXT_PATH = "HijackSession/login";
@Test
void hijackSessionTest() {

View File

@ -16,27 +16,27 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put("password_reg", "password");
params.put("email_reg", "someone@microsoft.com");
params.put("confirm_password", "password");
checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
checkAssignmentWithPUT(url("SqlInjectionAdvanced/challenge"), params, true);
params.clear();
params.put("username_login", "tom");
params.put("password_login", "thisisasecretfortomonly");
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
checkAssignment(url("SqlInjectionAdvanced/challenge_Login"), params, true);
params.clear();
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
params.clear();
params.put(
"userid_6a",
"Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from"
+ " user_system_data --");
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
checkAssignment(url("SqlInjectionAdvanced/attack6a"), params, true);
params.clear();
params.put("userid_6b", "passW0rD");
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
checkAssignment(url("SqlInjectionAdvanced/attack6b"), params, true);
params.clear();
params.put(
@ -54,7 +54,7 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
params.put(
"question_4_solution",
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
checkAssignment(url("SqlInjectionAdvanced/quiz"), params, true);
checkResults("/SqlInjectionAdvanced/");
}

View File

@ -34,44 +34,44 @@ public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("query", sql_2);
checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true);
checkAssignment(url("SqlInjection/attack2"), params, true);
params.clear();
params.put("query", sql_3);
checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true);
checkAssignment(url("SqlInjection/attack3"), params, true);
params.clear();
params.put("query", sql_4_add);
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
checkAssignment(url("SqlInjection/attack4"), params, true);
params.clear();
params.put("query", sql_5);
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);
checkAssignment(url("SqlInjection/attack5"), params, true);
params.clear();
params.put("operator", sql_9_operator);
params.put("account", sql_9_account);
params.put("injection", sql_9_injection);
checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true);
checkAssignment(url("SqlInjection/assignment5a"), params, true);
params.clear();
params.put("login_count", sql_10_login_count);
params.put("userid", sql_10_userid);
checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true);
checkAssignment(url("SqlInjection/assignment5b"), params, true);
params.clear();
params.put("name", sql_11_a);
params.put("auth_tan", sql_11_b);
checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true);
checkAssignment(url("SqlInjection/attack8"), params, true);
params.clear();
params.put("name", sql_12_a);
params.put("auth_tan", sql_12_b);
checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true);
checkAssignment(url("SqlInjection/attack9"), params, true);
params.clear();
params.put("action_string", sql_13);
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
checkAssignment(url("SqlInjection/attack10"), params, true);
checkResults("/SqlInjection/");
}

View File

@ -23,7 +23,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.put("field5", "?");
params.put("field6", "prep.setString(1,\"\")");
params.put("field7", "prep.setString(2,\\\"\\\")");
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
checkAssignment(url("SqlInjectionMitigations/attack10a"), params, true);
params.put(
"editor",
@ -37,18 +37,18 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
+ "} catch (Exception e) {\r\n"
+ " System.out.println(\"Oops. Something went wrong!\");\r\n"
+ "}");
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
checkAssignment(url("SqlInjectionMitigations/attack10b"), params, true);
params.clear();
params.put(
"userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--");
checkAssignment(url("/WebGoat/SqlOnlyInputValidation/attack"), params, true);
checkAssignment(url("SqlOnlyInputValidation/attack"), params, true);
params.clear();
params.put(
"userid_sql_only_input_validation_on_keywords",
"Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--");
checkAssignment(url("/WebGoat/SqlOnlyInputValidationOnKeywords/attack"), params, true);
checkAssignment(url("SqlOnlyInputValidationOnKeywords/attack"), params, true);
RestAssured.given()
.when()
@ -57,7 +57,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
.contentType(ContentType.JSON)
.get(
url(
"/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname"
"SqlInjectionMitigations/servers?column=(case when (true) then hostname"
+ " else id end)"))
.then()
.statusCode(200);
@ -67,7 +67,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON)
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
.get(url("SqlInjectionMitigations/servers?column=unknown"))
.then()
.statusCode(500)
.body(
@ -78,7 +78,7 @@ public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
params.clear();
params.put("ip", "104.130.219.202");
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true);
checkAssignment(url("SqlInjectionMitigations/attack12a"), params, true);
checkResults();
}

View File

@ -3,7 +3,6 @@ package org.owasp.webgoat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import io.restassured.RestAssured;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
@ -11,21 +10,20 @@ import org.junit.jupiter.api.Test;
public class WebWolfIntegrationTest extends IntegrationTest {
@Test
public void runTests() throws IOException {
public void runTests() {
startLesson("WebWolfIntroduction");
// Assignment 3
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("email", this.getUser() + "@webgoat.org");
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
checkAssignment(url("WebWolf/mail/send"), params, false);
String responseBody =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/mail"))
.get(webWolfUrl("mail"))
.then()
.extract()
.response()
@ -39,7 +37,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
uniqueCode.lastIndexOf("your unique code is: ") + (21 + this.getUser().length()));
params.clear();
params.put("uniqueCode", uniqueCode);
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);
checkAssignment(url("WebWolf/mail"), params, true);
// Assignment 4
RestAssured.given()
@ -47,7 +45,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.queryParams(params)
.get(url("/WebGoat/WebWolf/landing/password-reset"))
.get(url("WebWolf/landing/password-reset"))
.then()
.statusCode(200);
RestAssured.given()
@ -55,7 +53,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.queryParams(params)
.get(webWolfUrl("/landing"))
.get(webWolfUrl("landing"))
.then()
.statusCode(200);
responseBody =
@ -63,7 +61,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests"))
.get(webWolfUrl("requests"))
.then()
.extract()
.response()
@ -72,7 +70,7 @@ public class WebWolfIntegrationTest extends IntegrationTest {
assertTrue(responseBody.contains(uniqueCode));
params.clear();
params.put("uniqueCode", uniqueCode);
checkAssignment(url("/WebGoat/WebWolf/landing"), params, true);
checkAssignment(url("WebWolf/landing"), params, true);
checkResults("/WebWolf");
}

View File

@ -14,7 +14,7 @@ public class XSSIntegrationTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("checkboxAttack1", "value");
checkAssignment(url("/CrossSiteScripting/attack1"), params, true);
checkAssignment(url("CrossSiteScripting/attack1"), params, true);
params.clear();
params.put("QTY1", "1");
@ -23,11 +23,11 @@ public class XSSIntegrationTest extends IntegrationTest {
params.put("QTY4", "1");
params.put("field1", "<script>alert('XSS+Test')</script>");
params.put("field2", "111");
checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true);
checkAssignmentWithGet(url("CrossSiteScripting/attack5a"), params, true);
params.clear();
params.put("DOMTestRoute", "start.mvc#test");
checkAssignment(url("/CrossSiteScripting/attack6a"), params, true);
checkAssignment(url("CrossSiteScripting/attack6a"), params, true);
params.clear();
params.put("param1", "42");
@ -41,7 +41,7 @@ public class XSSIntegrationTest extends IntegrationTest {
.header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest")
.formParams(params)
.post(url("/CrossSiteScripting/phone-home-xss"))
.post(url("CrossSiteScripting/phone-home-xss"))
.then()
.statusCode(200)
.extract()
@ -50,7 +50,7 @@ public class XSSIntegrationTest extends IntegrationTest {
params.clear();
params.put("successMessage", secretNumber);
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
checkAssignment(url("CrossSiteScripting/dom-follow-up"), params, true);
params.clear();
params.put(
@ -73,8 +73,44 @@ public class XSSIntegrationTest extends IntegrationTest {
"question_4_solution",
"Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that"
+ " the browser executes.");
checkAssignment(url("/CrossSiteScripting/quiz"), params, true);
checkAssignment(url("CrossSiteScripting/quiz"), params, true);
checkResults("/CrossSiteScripting/");
params.clear();
params.put(
"editor",
"<%@ taglib uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\" %>"
+ "<html>"
+ "<head>"
+ "<title>Using GET and POST Method to Read Form Data</title>"
+ "</head>"
+ "<body>"
+ "<h1>Using POST Method to Read Form Data</h1>"
+ "<table>"
+ "<tbody>"
+ "<tr>"
+ "<td><b>First Name:</b></td>"
+ "<td>${e:forHtml(param.first_name)}</td>"
+ "</tr>"
+ "<tr>"
+ "<td><b>Last Name:</b></td>"
+ "<td>${e:forHtml(param.last_name)}</td>"
+ "</tr>"
+ "</tbody>"
+ "</table>"
+ "</body>"
+ "</html>");
checkAssignment(url("CrossSiteScripting/attack3"), params, true);
params.clear();
params.put(
"editor2",
"Policy.getInstance(\"antisamy-slashdot.xml\");"
+ "Sammy s = new AntiSamy();"
+ "s.scan(newComment,\"\");"
+ "CleanResults();"
+ "MyCommentDAO.addComment(threadID, userID).getCleanHTML());");
checkAssignment(url("CrossSiteScripting/attack4"), params, true);
checkResults("/CrossSiteScripting");
}
}

View File

@ -45,10 +45,10 @@ public class XXEIntegrationTest extends IntegrationTest {
.get(url("service/enable-security.mvc"))
.then()
.statusCode(200);
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(
url("/WebGoat/xxe/blind"),
url("xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
false);
@ -68,7 +68,7 @@ public class XXEIntegrationTest extends IntegrationTest {
}
String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
String dtd7String =
dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
dtd7.replace("WEBWOLFURL", webWolfUrl("landing")).replace("SECRET", secretFile);
// upload DTD
RestAssured.given()
@ -76,7 +76,7 @@ public class XXEIntegrationTest extends IntegrationTest {
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("/fileupload"))
.post(webWolfUrl("fileupload"))
.then()
.extract()
.response()
@ -84,8 +84,8 @@ public class XXEIntegrationTest extends IntegrationTest {
.asString();
// upload attack
String xxe7String =
xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
xxe7.replace("WEBWOLFURL", webWolfUrl("files")).replace("USERNAME", this.getUser());
checkAssignment(url("xxe/blind"), ContentType.XML, xxe7String, false);
// read results from WebWolf
String result =
@ -93,7 +93,7 @@ public class XXEIntegrationTest extends IntegrationTest {
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests"))
.get(webWolfUrl("requests"))
.then()
.extract()
.response()
@ -114,10 +114,10 @@ public class XXEIntegrationTest extends IntegrationTest {
startLesson("XXE", true);
webGoatHomeDirectory = webGoatServerDirectory();
webWolfFileServerLocation = getWebWolfFileServerLocation();
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(url("xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(
url("/WebGoat/xxe/blind"),
url("xxe/blind"),
ContentType.XML,
"<comment><text>" + getSecret() + "</text></comment>",
true);

View File

@ -6,7 +6,6 @@ import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.service.RestartLessonService;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
@ -20,7 +19,6 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class DatabaseConfiguration {
private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean
@Primary

View File

@ -242,6 +242,7 @@ public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(new UserInterceptor());
}
@Bean

View File

@ -0,0 +1,53 @@
package org.owasp.webgoat.container;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.owasp.webgoat.container.asciidoc.EnvironmentExposure;
import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class UserInterceptor implements HandlerInterceptor {
private Environment env = EnvironmentExposure.getEnv();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// Do nothing
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
if (null != modelAndView) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (null != authentication) {
modelAndView.getModel().put("username", authentication.getName());
}
if (null != env) {
String githubClientId =
env.getProperty("spring.security.oauth2.client.registration.github.client-id");
if (null != githubClientId && !githubClientId.equals("dummy")) {
modelAndView.getModel().put("oauth", Boolean.TRUE);
}
} else {
modelAndView.getModel().put("oauth", Boolean.FALSE);
}
}
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// Do nothing
}
}

View File

@ -34,6 +34,9 @@ package org.owasp.webgoat.container;
import java.io.File;
import org.owasp.webgoat.container.session.UserSessionData;
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.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
@ -42,6 +45,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.web.client.RestTemplate;
@Configuration
@ -50,6 +55,8 @@ import org.springframework.web.client.RestTemplate;
@EnableAutoConfiguration
public class WebGoat {
@Autowired private UserRepository userRepository;
@Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome);
@ -58,7 +65,14 @@ public class WebGoat {
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession() {
return new WebSession();
WebGoatUser webGoatUser = null;
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

View File

@ -54,32 +54,41 @@ public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
return http.authorizeHttpRequests(
auth ->
auth.requestMatchers(
"/",
"/favicon.ico",
"/css/**",
"/images/**",
"/js/**",
"fonts/**",
"/plugins/**",
"/registration",
"/register.mvc",
"/actuator/**")
"/register.mvc")
.permitAll()
.anyRequest()
.authenticated());
http.formLogin()
.authenticated())
.formLogin(
login ->
login
.loginPage("/login")
.defaultSuccessUrl("/welcome.mvc", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll();
http.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
http.csrf().disable();
http.headers().cacheControl().disable();
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
return http.build();
.permitAll())
.oauth2Login(
oidc -> {
oidc.defaultSuccessUrl("/login-oauth.mvc");
oidc.loginPage("/login");
})
.logout(logout -> logout.deleteCookies("JSESSIONID").invalidateHttpSession(true))
.csrf(csrf -> csrf.disable())
.headers(headers -> headers.disable())
.exceptionHandling(
handling ->
handling.authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")))
.build();
}
@Autowired
@ -98,7 +107,6 @@ public class WebSecurityConfig {
return authenticationConfiguration.getAuthenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();

View File

@ -16,7 +16,7 @@ public class EnvironmentExposure implements ApplicationContextAware {
private static ApplicationContext context;
public static Environment getEnv() {
return context.getEnvironment();
return (null != context) ? context.getEnvironment() : null;
}
@Override

View File

@ -1,12 +1,9 @@
package org.owasp.webgoat.container.asciidoc;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* Usage in asciidoc:
@ -26,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
@Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
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 href = hostname + "/" + target;
@ -45,29 +42,4 @@ public class WebWolfMacro extends InlineMacroProcessor {
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
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

@ -17,9 +17,4 @@ public class WebWolfRootMacro extends WebWolfMacro {
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected boolean includeWebWolfContext() {
return false;
}
}

View File

@ -3,7 +3,6 @@ package org.owasp.webgoat.container.session;
import java.io.Serializable;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* *************************************************************************************************
@ -40,13 +39,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
public class WebSession implements Serializable {
private static final long serialVersionUID = -4270066103101711560L;
private final WebGoatUser currentUser;
private WebGoatUser currentUser;
private transient Lesson currentLesson;
private boolean securityEnabled;
public WebSession() {
this.currentUser =
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
public WebSession(WebGoatUser webGoatUser) {
this.currentUser = webGoatUser;
}
/**

View File

@ -3,8 +3,10 @@ package org.owasp.webgoat.container.users;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
@ -44,4 +46,12 @@ public class RegistrationController {
return "redirect:/attack";
}
@GetMapping("/login-oauth.mvc")
public String registrationOAUTH(Authentication authentication, HttpServletRequest request)
throws ServletException {
log.info("register oauth user in database");
userService.addUser(authentication.getName(), UUID.randomUUID().toString());
return "redirect:/welcome.mvc";
}
}

View File

@ -42,6 +42,7 @@ public class AccountVerificationHelper {
static {
secQuestionStore.put(verifyUserId, userSecQuestions);
}
// end 'data store set up'
// this is to aid feedback in the attack process and is not intended to be part of the
@ -68,6 +69,7 @@ public class AccountVerificationHelper {
return likely;
}
// end of cheating check ... the method below is the one of real interest. Can you find the flaw?
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
"idor.hints.otherProfile8",
"idor.hints.otherProfile9"
})
public class IDOREditOtherProfiile extends AssignmentEndpoint {
public class IDOREditOtherProfile extends AssignmentEndpoint {
@Autowired private UserSessionData userSessionData;
@ -69,7 +70,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
// we will persist in the session object for now in case we want to refer back or use it later
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
if (currentUserProfile.getRole() <= 1
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
return success(this)
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
@ -77,16 +78,16 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
}
if (currentUserProfile.getRole() > 1
&& currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
&& currentUserProfile.getColor().equalsIgnoreCase("red")) {
return failed(this)
.feedback("idor.edit.profile.failure1")
.output(currentUserProfile.profileToMap().toString())
.build();
}
if (currentUserProfile.getRole() <= 1
&& !currentUserProfile.getColor().toLowerCase().equals("red")) {
return success(this)
&& !currentUserProfile.getColor().equalsIgnoreCase("red")) {
return failed(this)
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build();

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -23,8 +24,6 @@
package org.owasp.webgoat.lessons.idor;
import jakarta.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
@ -56,9 +55,9 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
produces = {"application/json"})
@ResponseBody
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
Map<String, Object> details = new HashMap<>();
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
Object obj = userSessionData.getValue("idor-authenticated-as");
if (obj != null && obj.equals("tom")) {
// going to use session auth to view this one
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
if (userId != null && !userId.equals(authUserId)) {
@ -66,7 +65,8 @@ public class IDORViewOtherProfile extends AssignmentEndpoint {
UserProfile requestedProfile = new UserProfile(userId);
// secure code would ensure there was a horizontal access control check prior to dishing up
// the requested profile
if (requestedProfile.getUserId().equals("2342388")) {
if (requestedProfile.getUserId() != null
&& requestedProfile.getUserId().equals("2342388")) {
return success(this)
.feedback("idor.view.profile.success")
.output(requestedProfile.profileToMap().toString())

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -68,7 +69,7 @@ public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint {
return failed(this).feedback("idor.view.own.profile.failure2").build();
}
} catch (Exception ex) {
return failed(this).feedback("an error occurred with your request").build();
return failed(this).output("an error occurred with your request").build();
}
}
}

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -0,0 +1,70 @@
package org.owasp.webgoat.lessons.jwt.claimmisuse;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.JwkProviderBuilder;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPublicKey;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/JWT/jku")
@RestController
@AssignmentHints({
"jwt-jku-hint1",
"jwt-jku-hint2",
"jwt-jku-hint3",
"jwt-jku-hint4",
"jwt-jku-hint5"
})
public class JWTHeaderJKUEndpoint extends AssignmentEndpoint {
@PostMapping("/follow/{user}")
public @ResponseBody String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) {
return "Following yourself seems redundant";
} else {
return "You are now following Tom";
}
}
@PostMapping("/delete")
public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build();
} else {
try {
var decodedJWT = JWT.decode(token);
var jku = decodedJWT.getHeaderClaim("jku");
JwkProvider jwkProvider = new JwkProviderBuilder(new URL(jku.asString())).build();
var jwk = jwkProvider.get(decodedJWT.getKeyId());
var algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey());
JWT.require(algorithm).build().verify(decodedJWT);
String username = decodedJWT.getClaims().get("username").asString();
if ("Jerry".equals(username)) {
return failed(this).feedback("jwt-final-jerry-account").build();
}
if ("Tom".equals(username)) {
return success(this).build();
} else {
return failed(this).feedback("jwt-final-not-tom").build();
}
} catch (MalformedURLException | JWTVerificationException | JwkException e) {
return failed(this).feedback("jwt-invalid-token").output(e.toString()).build();
}
}
}
}

View File

@ -20,7 +20,7 @@
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
package org.owasp.webgoat.lessons.jwt.claimmisuse;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
@ -38,28 +38,30 @@ import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AssignmentHints({
"jwt-final-hint1",
"jwt-final-hint2",
"jwt-final-hint3",
"jwt-final-hint4",
"jwt-final-hint5",
"jwt-final-hint6"
"jwt-kid-hint1",
"jwt-kid-hint2",
"jwt-kid-hint3",
"jwt-kid-hint4",
"jwt-kid-hint5",
"jwt-kid-hint6"
})
public class JWTFinalEndpoint extends AssignmentEndpoint {
@RequestMapping("/JWT/kid")
public class JWTHeaderKIDEndpoint extends AssignmentEndpoint {
private final LessonDataSource dataSource;
private JWTFinalEndpoint(LessonDataSource dataSource) {
private JWTHeaderKIDEndpoint(LessonDataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/JWT/final/follow/{user}")
@PostMapping("/follow/{user}")
public @ResponseBody String follow(@PathVariable("user") String user) {
if ("Jerry".equals(user)) {
return "Following yourself seems redundant";
@ -68,7 +70,7 @@ public class JWTFinalEndpoint extends AssignmentEndpoint {
}
}
@PostMapping("/JWT/final/delete")
@PostMapping("/delete")
public @ResponseBody AttackResult resetVotes(@RequestParam("token") String token) {
if (StringUtils.isEmpty(token)) {
return failed(this).feedback("jwt-invalid-token").build();

View File

@ -39,7 +39,8 @@ import org.springframework.web.bind.annotation.RestController;
"access-control.hash.hint9",
"access-control.hash.hint10",
"access-control.hash.hint11",
"access-control.hash.hint12"
"access-control.hash.hint12",
"access-control.hash.hint13"
})
public class MissingFunctionACYourHashAdmin extends AssignmentEndpoint {

View File

@ -48,16 +48,19 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
private final RestTemplate restTemplate;
private String webWolfHost;
private String webWolfPort;
private String webWolfURL;
private final String webWolfMailURL;
public ResetLinkAssignmentForgotPassword(
RestTemplate restTemplate,
@Value("${webwolf.host}") String webWolfHost,
@Value("${webwolf.port}") String webWolfPort,
@Value("${webwolf.url}") String webWolfURL,
@Value("${webwolf.mail.url}") String webWolfMailURL) {
this.restTemplate = restTemplate;
this.webWolfHost = webWolfHost;
this.webWolfPort = webWolfPort;
this.webWolfURL = webWolfURL;
this.webWolfMailURL = webWolfMailURL;
}
@ -67,12 +70,12 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
@RequestParam String email, HttpServletRequest request) {
String resetLink = UUID.randomUUID().toString();
ResetLinkAssignment.resetLinks.add(resetLink);
String host = request.getHeader("host");
String host = request.getHeader(HttpHeaders.HOST);
if (ResetLinkAssignment.TOM_EMAIL.equals(email)
&& (host.contains(webWolfPort)
|| host.contains(webWolfHost))) { // User indeed changed the host header.
&& host.contains(webWolfHost))) { // User indeed changed the host header.
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
fakeClickingLinkEmail(host, resetLink);
fakeClickingLinkEmail(webWolfURL, resetLink);
} else {
try {
sendMailToUser(email, host, resetLink);
@ -97,13 +100,13 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
}
private void fakeClickingLinkEmail(String host, String resetLink) {
private void fakeClickingLinkEmail(String webWolfURL, String resetLink) {
try {
HttpHeaders httpHeaders = new HttpHeaders();
HttpEntity httpEntity = new HttpEntity(httpHeaders);
new RestTemplate()
.exchange(
String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink),
String.format("%s/PasswordReset/reset/reset-password/%s", webWolfURL, resetLink),
HttpMethod.GET,
httpEntity,
Void.class);

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -27,6 +28,7 @@ import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
@ -44,6 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
*
*/
@AssignmentHints({"spoofcookie.hint1", "spoofcookie.hint2", "spoofcookie.hint3"})
@RestController
public class SpoofCookieAssignment extends AssignmentEndpoint {

View File

@ -58,7 +58,8 @@ public class LandingAssignment extends AssignmentEndpoint {
public ModelAndView openPasswordReset(HttpServletRequest request) throws URISyntaxException {
URI uri = new URI(request.getRequestURL().toString());
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("webwolfUrl", landingPageUrl);
modelAndView.addObject(
"webwolfLandingPageUrl", landingPageUrl.replace("//landing", "/landing"));
modelAndView.addObject("uniqueCode", StringUtils.reverse(getWebSession().getUserName()));
modelAndView.setViewName("lessons/webwolfintroduction/templates/webwolfPasswordReset.html");

View File

@ -35,6 +35,6 @@ public class CrossSiteScripting extends Lesson {
@Override
public String getTitle() {
return "xss.title";
return "4.xss.title";
}
}

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -30,12 +31,9 @@ import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
// @RestController
@Deprecated
// TODO This assignment seems not to be in use in the UI
// it is there to make sure the lesson can be marked complete
// in order to restore it, make it accessible through the UI and uncomment RestController
@RestController
@AssignmentHints(
value = {
"xss-mitigation-3-hint1",
@ -60,9 +58,9 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
String lastNameElement =
doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
Boolean includeCorrect = false;
Boolean firstNameCorrect = false;
Boolean lastNameCorrect = false;
boolean includeCorrect = false;
boolean firstNameCorrect = false;
boolean lastNameCorrect = false;
if (include.contains("<%@")
&& include.contains("taglib")

View File

@ -22,20 +22,15 @@
package org.owasp.webgoat.lessons.xss;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
// @RestController
@Deprecated
// TODO This assignment seems not to be in use in the UI
// it is there to make sure the lesson can be marked complete
// in order to restore it, make it accessible through the UI and uncomment RestController@Slf4j
@Slf4j
@RestController
@AssignmentHints(value = {"xss-mitigation-4-hint1"})
public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
@ -44,7 +39,6 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
public AttackResult completed(@RequestParam String editor2) {
String editor = editor2.replaceAll("\\<.*?>", "");
log.debug(editor);
if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"")
|| editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"")
@ -54,10 +48,8 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
&& editor.contains("CleanResults")
&& editor.contains("MyCommentDAO.addComment(threadID, userID")
&& editor.contains(".getCleanHTML());")) {
log.debug("true");
return success(this).feedback("xss-mitigation-4-success").build();
} else {
log.debug("false");
return failed(this).feedback("xss-mitigation-4-failed").build();
}
}

View File

@ -15,7 +15,8 @@
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
@ -24,7 +25,9 @@ package org.owasp.webgoat.lessons.xss;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class CrossSiteScriptingMitigation extends Lesson {
@Override
public Category getDefaultCategory() {
@ -33,6 +36,6 @@ public class CrossSiteScriptingMitigation extends Lesson {
@Override
public String getTitle() {
return "xss-mitigation.title";
return "6.xss-mitigation.title";
}
}

View File

@ -24,7 +24,9 @@ package org.owasp.webgoat.lessons.xss.stored;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.stereotype.Component;
@Component
public class CrossSiteScriptingStored extends Lesson {
@Override
public Category getDefaultCategory() {
@ -33,6 +35,6 @@ public class CrossSiteScriptingStored extends Lesson {
@Override
public String getTitle() {
return "xss-stored.title";
return "5.xss-stored.title";
}
}

View File

@ -34,21 +34,15 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
// TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
@ResponseBody
public AttackResult completed(@RequestParam String successMessage) {
UserSessionData userSessionData = getUserSessionData();
if (successMessage.equals(userSessionData.getValue("randValue").toString())) {
if (successMessage.equals(userSessionData.getValue("randValue"))) {
return success(this).feedback("xss-stored-callback-success").build();
} else {
return failed(this).feedback("xss-stored-callback-failure").build();
}
}
}
// something like ...
// http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere%3Cscript%3Ewebgoat.customjs.phoneHome();%3C%2Fscript%3E
// or
// http://localhost:8080/WebGoat/start.mvc#test/testParam=foobar&_someVar=234902384lotslsfjdOf9889080GarbageHere<script>webgoat.customjs.phoneHome();<%2Fscript>

View File

@ -72,7 +72,6 @@ public class StoredXssComments extends AssignmentEndpoint {
"Can you post a comment, calling webgoat.customjs.phoneHome() ?"));
}
// TODO This assignment seems not to be in use in the UI
@GetMapping(
path = "/CrossSiteScriptingStored/stored-xss",
produces = MediaType.APPLICATION_JSON_VALUE,
@ -89,7 +88,6 @@ public class StoredXssComments extends AssignmentEndpoint {
return allComments;
}
// TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss")
@ResponseBody
public AttackResult createNewComment(@RequestBody String commentStr) {

View File

@ -31,20 +31,30 @@ import org.owasp.webgoat.webwolf.WebWolf;
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
@Slf4j
public class StartWebGoat {
public static void main(String[] args) {
var parentBuilder =
new SpringApplicationBuilder()
.parent(ParentConfig.class)
.web(WebApplicationType.NONE)
.bannerMode(Banner.Mode.OFF)
.child(WebGoat.class)
.web(WebApplicationType.SERVLET)
.sibling(WebWolf.class)
.bannerMode(Banner.Mode.OFF)
.web(WebApplicationType.SERVLET)
.run(args);
.bannerMode(Banner.Mode.OFF);
parentBuilder.child(WebWolf.class).web(WebApplicationType.SERVLET).run(args);
ApplicationContext webGoatContext =
parentBuilder.child(WebGoat.class).web(WebApplicationType.SERVLET).run(args);
printStartUpMessage(webGoatContext);
}
private static void printStartUpMessage(ApplicationContext webGoatContext) {
var url = webGoatContext.getEnvironment().getProperty("webgoat.url");
var sslEnabled =
webGoatContext.getEnvironment().getProperty("server.ssl.enabled", Boolean.class);
log.warn(
"Please browse to " + "{} to start using WebGoat...",
sslEnabled ? url.replace("http", "https") : url);
}
}

View File

@ -1,33 +0,0 @@
package org.owasp.webgoat.server;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
@Slf4j
@NoArgsConstructor
public class StartupMessage {
private String port;
private String address;
@EventListener
void onStartup(ApplicationReadyEvent event) {
if (StringUtils.hasText(port)
&& !StringUtils.hasText(System.getProperty("running.in.docker"))) {
log.info("Please browse to http://{}:{}/WebGoat to get started...", address, port);
}
if (event.getApplicationContext().getApplicationName().contains("WebGoat")) {
port = event.getApplicationContext().getEnvironment().getProperty("server.port");
address = event.getApplicationContext().getEnvironment().getProperty("server.address");
}
}
@EventListener
void onShutdown(ContextStoppedEvent event) {}
}

View File

@ -22,20 +22,23 @@
package org.owasp.webgoat.webwolf;
import static java.util.Comparator.comparing;
import static org.springframework.http.MediaType.ALL_VALUE;
import jakarta.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.TimeZone;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.owasp.webgoat.webwolf.user.WebGoatUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
@ -52,12 +55,18 @@ import org.springframework.web.servlet.view.RedirectView;
@Slf4j
public class FileServer {
private static final DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Value("${webwolf.fileserver.location}")
private String fileLocation;
@Value("${server.address}")
private String server;
@Value("${server.servlet.context-path}")
private String contextPath;
@Value("${server.port}")
private int port;
@ -71,9 +80,11 @@ public class FileServer {
}
@PostMapping(value = "/fileupload")
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var destinationDir = new File(fileLocation, user.getUsername());
public ModelAndView importFile(
@RequestParam("file") MultipartFile myFile, Authentication authentication)
throws IOException {
String username = authentication.getName();
var destinationDir = new File(fileLocation, username);
destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
@ -83,41 +94,47 @@ public class FileServer {
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful"));
}
@AllArgsConstructor
@Getter
private class UploadedFile {
private final String name;
private final String size;
private final String link;
}
@GetMapping(value = "/files")
public ModelAndView getFiles(HttpServletRequest request) {
WebGoatUser user =
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
public ModelAndView getFiles(
HttpServletRequest request, Authentication authentication, TimeZone timezone) {
String username = (null != authentication) ? authentication.getName() : "anonymous";
File destinationDir = new File(fileLocation, username);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("files");
File changeIndicatorFile = new File(destinationDir, user.getUsername() + "_changed");
File changeIndicatorFile = new File(destinationDir, username + "_changed");
if (changeIndicatorFile.exists()) {
modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess"));
}
changeIndicatorFile.delete();
var uploadedFiles = new ArrayList<>();
record UploadedFile(String name, String size, String link, String creationTime) {}
var uploadedFiles = new ArrayList<UploadedFile>();
File[] files = destinationDir.listFiles(File::isFile);
if (files != null) {
for (File file : files) {
String size = FileUtils.byteCountToDisplaySize(file.length());
String link = String.format("files/%s/%s", username, file.getName());
uploadedFiles.add(new UploadedFile(file.getName(), size, link));
uploadedFiles.add(
new UploadedFile(file.getName(), size, link, getCreationTime(timezone, file)));
}
}
modelAndView.addObject("files", uploadedFiles);
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
modelAndView.addObject(
"files",
uploadedFiles.stream().sorted(comparing(UploadedFile::creationTime).reversed()).toList());
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port + contextPath);
return modelAndView;
}
private String getCreationTime(TimeZone timezone, File file) {
try {
FileTime creationTime = (FileTime) Files.getAttribute(file.toPath(), "creationTime");
ZonedDateTime zonedDateTime = creationTime.toInstant().atZone(timezone.toZoneId());
return dateTimeFormatter.format(zonedDateTime);
} catch (IOException e) {
return "unknown";
}
}
}

View File

@ -24,8 +24,10 @@ package org.owasp.webgoat.webwolf;
import jakarta.annotation.PostConstruct;
import java.io.File;
import org.owasp.webgoat.container.UserInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -55,6 +57,12 @@ public class MvcConfiguration implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("webwolf-login");
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor());
}
@PostConstruct

View File

@ -22,6 +22,7 @@
package org.owasp.webgoat.webwolf;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.AjaxAuthenticationEntryPoint;
import org.owasp.webgoat.webwolf.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@ -46,16 +47,39 @@ public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
auth -> auth.requestMatchers(HttpMethod.POST, "/fileupload").authenticated());
http.authorizeHttpRequests(
auth ->
auth.requestMatchers(HttpMethod.GET, "/files", "/mail", "/requests").authenticated());
http.authorizeHttpRequests().anyRequest().permitAll();
http.csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=true");
http.formLogin().loginPage("/login").defaultSuccessUrl("/home", true).permitAll();
http.logout().permitAll();
return http.build();
return http.authorizeHttpRequests(
auth -> {
auth.requestMatchers("/css/**", "/webjars/**", "/favicon.ico", "/js/**", "/images/**")
.permitAll();
auth.requestMatchers(
HttpMethod.GET,
"/fileupload/**",
"/files/**",
"/landing/**",
"/PasswordReset/**")
.permitAll();
auth.requestMatchers(HttpMethod.POST, "/files", "/mail", "/requests").permitAll();
auth.anyRequest().authenticated();
})
.csrf(csrf -> csrf.disable())
.formLogin(
login ->
login
.loginPage("/login")
.failureUrl("/login?error=true")
.defaultSuccessUrl("/home", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll())
.oauth2Login(
oidc -> {
oidc.defaultSuccessUrl("/home");
})
.logout(logout -> logout.deleteCookies("WEBWOLFSESSION").invalidateHttpSession(true))
.exceptionHandling(
handling ->
handling.authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")))
.build();
}
@Autowired

View File

@ -1,11 +1,11 @@
package org.owasp.webgoat.webwolf.jwt;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.Base64Utils.decodeFromUrlSafeString;
import static org.springframework.util.StringUtils.hasText;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
import lombok.AllArgsConstructor;
@ -103,8 +103,8 @@ public class JWTToken {
var builder = JWTToken.builder().encoded(jwt);
if (token.length >= 2) {
var header = new String(decodeFromUrlSafeString(token[0]), UTF_8);
var payloadAsString = new String(decodeFromUrlSafeString(token[1]), UTF_8);
var header = new String(Base64.getUrlDecoder().decode(token[0]), UTF_8);
var payloadAsString = new String(Base64.getUrlDecoder().decode(token[1]), UTF_8);
var headers = parse(header);
var payload = parse(payloadAsString);
builder.header(write(header, headers));

View File

@ -25,8 +25,8 @@ package org.owasp.webgoat.webwolf.mailbox;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.Authentication;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -42,16 +42,16 @@ public class MailboxController {
private final MailboxRepository mailboxRepository;
@GetMapping("/mail")
public ModelAndView mail() {
UserDetails user =
(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
public ModelAndView mail(Authentication authentication, Model model) {
String username = (null != authentication) ? authentication.getName() : "anonymous";
ModelAndView modelAndView = new ModelAndView();
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(username);
if (emails != null && !emails.isEmpty()) {
modelAndView.addObject("total", emails.size());
modelAndView.addObject("emails", emails);
}
modelAndView.setViewName("mailbox");
model.addAttribute("username", username);
return modelAndView;
}

View File

@ -22,8 +22,6 @@
package org.owasp.webgoat.webwolf.requests;
import static java.util.stream.Collectors.toList;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;
@ -33,8 +31,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -64,30 +61,29 @@ public class Requests {
}
@GetMapping
public ModelAndView get() {
public ModelAndView get(Authentication authentication) {
var model = new ModelAndView("requests");
var user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = (null != authentication) ? authentication.getName() : "anonymous";
var traces =
traceRepository.findAllTraces().stream()
.filter(t -> allowedTrace(t, user))
traceRepository.findAll().stream()
.filter(t -> allowedTrace(t, username))
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
.collect(toList());
.toList();
model.addObject("traces", traces);
return model;
}
private boolean allowedTrace(HttpExchange t, UserDetails user) {
private boolean allowedTrace(HttpExchange t, String username) {
HttpExchange.Request req = t.getRequest();
boolean allowed = true;
/* do not show certain traces to other users in a classroom setup */
if (req.getUri().getPath().contains("/files")
&& !req.getUri().getPath().contains(user.getUsername())) {
if (req.getUri().getPath().contains("/files") && !req.getUri().getPath().contains(username)) {
allowed = false;
} else if (req.getUri().getPath().contains("/landing")
&& req.getUri().getQuery() != null
&& req.getUri().getQuery().contains("uniqueCode")
&& !req.getUri().getQuery().contains(StringUtils.reverse(user.getUsername()))) {
&& !req.getUri().getQuery().contains(StringUtils.reverse(username))) {
allowed = false;
}
@ -95,7 +91,7 @@ public class Requests {
}
private String path(HttpExchange t) {
return (String) t.getRequest().getUri().getPath();
return t.getRequest().getUri().getPath();
}
private String toJsonString(HttpExchange t) {

View File

@ -22,10 +22,12 @@
package org.owasp.webgoat.webwolf.requests;
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.contains;
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.endsWith;
import com.google.common.collect.EvictingQueue;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
@ -36,34 +38,51 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
* @author nbaars
* @since 8/13/17.
*/
@Slf4j
public class WebWolfTraceRepository implements HttpExchangeRepository {
private enum MatchingMode {
CONTAINS,
ENDS_WITH,
EQUALS;
}
record Exclusion(String path, MatchingMode mode) {
public boolean matches(String path) {
return switch (mode) {
case CONTAINS -> path.contains(this.path);
case ENDS_WITH -> path.endsWith(this.path);
case EQUALS -> path.equals(this.path);
};
}
public static Exclusion contains(String exclusionPattern) {
return new Exclusion(exclusionPattern, MatchingMode.CONTAINS);
}
public static Exclusion endsWith(String exclusionPattern) {
return new Exclusion(exclusionPattern, MatchingMode.ENDS_WITH);
}
}
private final EvictingQueue<HttpExchange> traces = EvictingQueue.create(10000);
private final List<String> exclusionList =
private final List<Exclusion> exclusionList =
List.of(
"/tmpdir",
"/home",
"/files",
"/images/",
"/favicon.ico",
"/js/",
"/webjars/",
"/requests",
"/css/",
"/mail");
contains("/tmpdir"),
contains("/home"),
endsWith("/files"),
contains("/images/"),
contains("/js/"),
contains("/webjars/"),
contains("/requests"),
contains("/css/"),
contains("/mail"));
@Override
public List<HttpExchange> findAll() {
return List.of();
}
public List<HttpExchange> findAllTraces() {
return new ArrayList<>(traces);
}
private boolean isInExclusionList(String path) {
return exclusionList.stream().anyMatch(e -> path.contains(e));
return exclusionList.stream().anyMatch(e -> e.matches(path));
}
@Override

View File

@ -1,10 +1,12 @@
server.error.include-stacktrace=always
server.error.path=/error.html
server.servlet.context-path=/WebGoat
server.servlet.context-path=${WEBGOAT_CONTEXT:/WebGoat}
server.servlet.session.persistent=false
server.port=${webgoat.port:8080}
server.address=${webgoat.host}
server.port=${WEBGOAT_PORT:8080}
server.address=${WEBGOAT_HOST:127.0.0.1}
webgoat.host=${WEBGOAT_HOST:127.0.0.1}
webgoat.port=${WEBGOAT_PORT:8080}
webgoat.context=${WEBGOAT_CONTEXT:/WebGoat}
spring.application.name=WebGoat
server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12}
@ -27,9 +29,10 @@ logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=INFO
logging.level.org.springframework.web=INFO
logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=INFO
logging.level.org.owasp=DEBUG
logging.level.org.owasp.webgoat=DEBUG
logging.level.org.hidbernate.SQL=DEBUG
logging.level.org.owasp=INFO
logging.level.org.owasp.webgoat=INFO
logging.level.org.hidbernate.SQL=INFO
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
@ -40,10 +43,12 @@ webgoat.feedback.address=webgoat@owasp.org
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en
webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path}
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
webwolf.port=${WEBWOLF_PORT:9090}
webwolf.url=http://${webwolf.host}:${webwolf.port}
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
webwolf.url=http://${WEBWOLF_HOST:127.0.0.1}:${WEBWOLF_PORT:9090}${WEBWOLF_CONTEXT:/WebWolf}
webwolf.landingpage.url=${webwolf.url}/landing
webwolf.mail.url=${webwolf.url}/mail
@ -62,3 +67,7 @@ exclude.lessons=${EXCLUDE_LESSONS:none,none}
management.health.db.enabled=true
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=env, health,configprops
spring.security.oauth2.client.registration.github.client-id=${WEBGOAT_OAUTH_CLIENTID:dummy}
spring.security.oauth2.client.registration.github.client-secret=${WEBGOAT_OAUTH_CLIENTSECRET:dummy}

View File

@ -1,10 +1,13 @@
server.error.include-stacktrace=always
server.error.path=/error.html
server.port=${webwolf.port:9090}
server.servlet.context-path=${webwolf.context}
server.port=${webwolf.port}
server.address=${webwolf.host}
spring.application.name=WebWolf
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
webwolf.port=${WEBWOLF_PORT:9090}
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
management.server.port=-1
server.servlet.session.cookie.name=WEBWOLFSESSION
@ -47,3 +50,6 @@ spring.jackson.serialization.write-dates-as-timestamps=false
#For static file refresh ... and faster dev :D
spring.devtools.restart.additional-paths=webwolf/src/main/resources/static/
spring.security.oauth2.client.registration.github.client-id=${WEBWOLF_OAUTH_CLIENTID:dummy}
spring.security.oauth2.client.registration.github.client-secret=${WEBWOLF_OAUTH_CLIENTSECRET:dummy}

View File

@ -23,7 +23,7 @@
<form class="attack-form" accept-charset="UNKNOWN" id="verify-account-form"
method="POST" name="form"
successCallback="onBypassResponse"
action="/WebGoat/auth-bypass/verify-account">
action="auth-bypass/verify-account">
<p>Verify Your Account by answering the questions below:</p>
<p>What is the name of your favorite teacher?</p>
@ -43,7 +43,7 @@
<form class="attack-form" accept-charset="UNKNOWN" id="change-password-form"
method="POST" name="form"
successCallback="onBypassResponse"
action="/WebGoat/auth-bypass/verify-account"
action="auth-bypass/verify-account"
style="display:none"><!-- start off hidden -->
<p>Please provide a new password for your account</p>

View File

@ -9,7 +9,7 @@ var onViewProfile = function () {
console.warn("on view profile activated")
webgoat.customjs.jquery.ajax({
method: "GET",
url: "/WebGoat/IDOR/profile",
url: "IDOR/profile",
contentType: 'application/json; charset=UTF-8'
}).then(webgoat.customjs.idorViewProfile);
}

View File

@ -18,7 +18,7 @@
<div class="container-fluid">
<form class="attack-form" accept-charset="UNKNOWN" name="fieldRestrictions"
method="POST"
action="/WebGoat/BypassRestrictions/FieldRestrictions">
action="BypassRestrictions/FieldRestrictions">
<div class="bypass-input-container"><b>Select field with two possible value</b>
<div class="input-group">
@ -66,7 +66,7 @@
<form class="attack-form" accept-charset="UNKNOWN" name="frontendValidation"
id="frontendValidation"
method="POST"
action="/WebGoat/BypassRestrictions/frontendValidation/"
action="BypassRestrictions/frontendValidation"
onsubmit="return validate()">
<div>
<strong>Field 1:</strong> exactly three lowercase characters(^[a-z]{3}$)

View File

@ -4,7 +4,7 @@
The challenges contain more a CTF like lessons where we do not provide any explanations what you need to do, no hints
will be provided. You can use these challenges in a CTF style where you can run WebGoat on one server and all
participants can join and hack the challenges. A scoreboard is available at link:/WebGoat/scoreboard["/WebGoat/scoreboard",window=_blank]
participants can join and hack the challenges. A scoreboard is available at link:scoreboard["scoreboard",window=_blank]
:hardbreaks:
In this CTF you will need to solve a couple of challenges, each challenge will give you a flag which you will

View File

@ -17,7 +17,7 @@
<div class="panel-body">
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/1"
action="challenge/1"
style="width: 200px;">
<div class="form-group">
@ -37,7 +37,7 @@
</div>
</div>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<form class="attack-form" method="POST" name="form" action="challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"

View File

@ -25,7 +25,7 @@
<div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/5" role="form">
action="challenge/5" role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
class="form-control" placeholder="Username" value=""/>
@ -66,7 +66,7 @@
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<form class="attack-form" method="POST" name="form" action="challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"

View File

@ -29,7 +29,7 @@
<div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/6" role="form">
action="challenge/6" role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
class="form-control" placeholder="Username" value=""/>
@ -64,7 +64,7 @@
</form>
<form id="register-form" class="attack-form" accept-charset="UNKNOWN"
method="PUT" name="form"
action="/WebGoat/challenge/6" style="display: none;" role="form">
action="challenge/6" style="display: none;" role="form">
<div class="form-group">
<input type="text" name="username_reg" id="username" tabindex="1"
class="form-control" placeholder="Username" value=""/>
@ -99,7 +99,7 @@
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<form class="attack-form" method="POST" name="form" action="challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"

View File

@ -28,7 +28,7 @@ f94008f801fceb8833a30fe56a8b26976347edcf First version of WebGoat Cloud website
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/7" role="form">
action="challenge/7" role="form">
<div class="form-group">
<div class="input-group">
@ -43,7 +43,7 @@ f94008f801fceb8833a30fe56a8b26976347edcf First version of WebGoat Cloud website
value="Reset Password" type="submit"/>
</div>
<div class="form-group">
<p>(c) 2017 WebGoat Cloud Platform</p>
<p>(c) 2023 WebGoat Cloud Platform</p>
</div>
<input type="hidden" class="hide" name="token" id="token" value=""/>
@ -57,7 +57,7 @@ f94008f801fceb8833a30fe56a8b26976347edcf First version of WebGoat Cloud website
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<form class="attack-form" method="POST" name="form" action="challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"

View File

@ -231,7 +231,7 @@
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<form class="attack-form" method="POST" name="form" action="challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"

View File

@ -24,7 +24,7 @@
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="DOMFollowUp"
action="/WebGoat/ChromeDevTools/dummy">
action="ChromeDevTools/dummy">
<input name="successMessage" value="" type="TEXT" />
<input name="submitMessage" value="Submit" type="SUBMIT"/>
</form>
@ -45,7 +45,7 @@
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/ChromeDevTools/network">
action="ChromeDevTools/network">
<script>
// sample custom javascript in the recommended way ...
// a namespace has been assigned for it, but you can roll your own if you prefer
@ -66,7 +66,7 @@
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/ChromeDevTools/network">
action="ChromeDevTools/network">
<table>
<tr>
<td>What is the number you found: </td>

View File

@ -14,7 +14,7 @@
<input type="hidden" id="user_id" value="102"/>
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
<form class="attack-form" accept-charset="UNKNOWN" method="POST" name="form"
action="/WebGoat/clientSideFiltering/attack1">
action="clientSideFiltering/attack1">
<link rel="stylesheet" type="text/css"
th:href="@{/lesson_css/clientSideFiltering-stage1.css}"/>
<script th:src="@{/lesson_js/clientSideFiltering.js}"
@ -83,7 +83,7 @@
<div class="container-fluid">
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/clientSideFiltering/getItForFree">
action="clientSideFiltering/getItForFree">
<input id="discount" type="hidden" value="0"/>
<div class="row">

View File

@ -14,19 +14,19 @@ endif::[]
The goal is to get familiar with the following forms of techniques:
* link:start.mvc#lesson/Crypto.lesson/1[Encoding]
* link:start.mvc#lesson/Cryptography.lesson/1[Encoding]
* link:start.mvc#lesson/Crypto.lesson/3[Hashing]
* link:start.mvc#lesson/Cryptography.lesson/3[Hashing]
* link:start.mvc#lesson/Crypto.lesson/4[Encryption]
* link:start.mvc#lesson/Cryptography.lesson/4[Encryption]
* link:start.mvc#lesson/Crypto.lesson/5[Signing]
* link:start.mvc#lesson/Cryptography.lesson/5[Signing]
* link:start.mvc#lesson/Crypto.lesson/6[Keystores]
* link:start.mvc#lesson/Cryptography.lesson/6[Keystores]
* link:start.mvc#lesson/Crypto.lesson/7[Security defaults]
* link:start.mvc#lesson/Cryptography.lesson/7[Security defaults]
* link:start.mvc#lesson/Crypto.lesson/8[Post quantum crypto]
* link:start.mvc#lesson/Cryptography.lesson/8[Post quantum crypto]
=== Assignments

View File

@ -7,10 +7,10 @@
* JavaScript to load initial assignment tokens
*/
function initialise() {
$("#sha256token").load('/WebGoat/crypto/hashing/sha256');
$("#md5token").load('/WebGoat/crypto/hashing/md5');
$("#basicauthtoken").load('/WebGoat/crypto/encoding/basic');
$("#privatekey").load('/WebGoat/crypto/signing/getprivate');
$("#sha256token").load('crypto/hashing/sha256');
$("#md5token").load('crypto/hashing/md5');
$("#basicauthtoken").load('crypto/encoding/basic');
$("#privatekey").load('crypto/signing/getprivate');
}
$(document).ready(initialise);
</script>
@ -28,7 +28,7 @@ $(document).ready(initialise);
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
Now suppose you have intercepted the following header:<br/>
<div id="basicauthtoken" ></div><br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/crypto/encoding/basic-auth">
<form class="attack-form" method="POST" name="form" action="crypto/encoding/basic-auth">
Then what was the username
<input name="answer_user" value="" type="TEXT"/>
and what was the password:
@ -45,7 +45,7 @@ $(document).ready(initialise);
<!-- 3. assignment xor -->
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" method="POST" name="form" action="/WebGoat/crypto/encoding/xor">
<form class="attack-form" method="POST" name="form" action="crypto/encoding/xor">
Suppose you found the database password encoded as {xor}Oz4rPj0+LDovPiwsKDAtOw==<br/>
What would be the actual password
<input name="answer_pwd1" value="" type="TEXT"/><br/>
@ -62,7 +62,7 @@ $(document).ready(initialise);
<!-- 4. weak hashing exercise -->
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" method="POST" name="form" action="/WebGoat/crypto/hashing">
<form class="attack-form" method="POST" name="form" action="crypto/hashing">
Which password belongs to this hash: <div id="md5token" ></div>
<input name="answer_pwd1" value="" type="TEXT"/><br/>
Which password belongs to this hash: <div id="sha256token" ></div>
@ -87,7 +87,7 @@ $(document).ready(initialise);
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
Now suppose you have the following private key:<br/>
<pre><div id="privatekey" ></div></pre><br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/crypto/signing/verify">
<form class="attack-form" method="POST" name="form" action="crypto/signing/verify">
Then what was the modulus of the public key
<input name="modulus" value="" type="TEXT"/>
and now provide a signature for us based on that modulus
@ -110,7 +110,7 @@ $(document).ready(initialise);
<!-- 8. assignment -->
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" method="POST" name="form" action="/WebGoat/crypto/secure/defaults">
<form class="attack-form" method="POST" name="form" action="crypto/secure/defaults">
What is the unencrypted message<br/>
<input name="secretText" value="" type="TEXT"/><br/>
and what is the name of the file that stored the password <br/>

View File

@ -17,7 +17,7 @@
method="POST" name="form1"
target="_blank"
successCallback=""
action="/WebGoat/csrf/basic-get-flag">
action="csrf/basic-get-flag">
<input name="csrf" type="hidden" value="false"/>
<input type="submit" name="submit"/>
@ -35,7 +35,7 @@
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-1"
method="POST" name="form2"
successCallback=""
action="/WebGoat/csrf/confirm-flag-1">
action="csrf/confirm-flag-1">
Confirm Flag Value:
<input type="text" length="6" name="confirmFlagVal" value=""/>
@ -93,7 +93,7 @@
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-review"
method="POST" name="review-form"
successCallback=""
action="/WebGoat/csrf/review">
action="csrf/review">
<input class="form-control" id="reviewText" name="reviewText" placeholder="Add a Review"
type="text"/>
<input class="form-control" id="reviewStars" name="stars" type="text"/>
@ -146,7 +146,7 @@
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-feedback"
method="POST"
prepareData="feedback"
action="/WebGoat/csrf/feedback/message"
action="csrf/feedback/message"
contentType="application/json">
<div class="row">
<div class="col-md-6">
@ -212,7 +212,7 @@
</div>
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-feedback"
method="POST" name="form2"
action="/WebGoat/csrf/feedback">
action="csrf/feedback">
Confirm Flag Value:
<input type="text" length="6" name="confirmFlagVal" value=""/>
@ -236,7 +236,7 @@
</div>
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-login"
method="POST" name="form2"
action="/WebGoat/csrf/login">
action="csrf/login">
Press the button below when your are logged in as the other user<br/>

View File

@ -25,7 +25,7 @@
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" accept-charset="UNKNOWN" name="task"
method="POST"
action="/WebGoat/InsecureDeserialization/task">
action="InsecureDeserialization/task">
<input type="textarea" rows="4" cols="40" value="" name="token" placeholder="token"/>
<input type="submit" value="Submit" />

View File

@ -19,7 +19,7 @@
</div>
<div class="container-fluid">
<div th:include="/lessons/hijacksession/templates/hijackform.html" id="content"></div>
<div th:insert="~{/lessons/hijacksession/templates/hijackform.html}" id="content"></div>
</div>
<div class="attack-feedback"></div>

View File

@ -1,7 +1,7 @@
<div class="row">
<div class="col-md-4">
<form class="attack-form" accept-charset="UNKNOWN" method="POST"
action="/WebGoat/HijackSession/login">
action="HijackSession/login">
<div style="padding: 20px;" id="password-login">
<h4 style="border-bottom: 1px solid #c5c5c5;">Account Access</h4>
<fieldset>

View File

@ -13,7 +13,7 @@
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" accept-charset="UNKNOWN" id="task" name="task"
method="POST"
action="/WebGoat/HtmlTampering/task">
action="HtmlTampering/task">
<script>
var regex = /^2999.99$/;
var price = 2999.99;

View File

@ -21,7 +21,7 @@
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/HttpBasics/attack1">
action="HttpBasics/attack1">
<div id="lessonContent">
<form accept-charset="UNKNOWN" method="POST" name="form"
action="#attack/307/100">
@ -51,7 +51,7 @@
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/HttpBasics/attack2">
action="HttpBasics/attack2">
<script>
// sample custom javascript in the recommended way ...
// a namespace has been assigned for it, but you can roll your own if you prefer

View File

@ -24,7 +24,7 @@
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<form class="attack-form" accept-charset="UNKNOWN" name="intercept-request"
method="POST"
action="/WebGoat/HttpProxies/intercept-request">
action="HttpProxies/intercept-request">
<input type="text" value="doesn't matter really" name="changeMe" />
<input type="submit" value="Submit" />

View File

@ -22,7 +22,7 @@
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/IDOR/login">
action="IDOR/login">
<table>
<tr>
<td>user/pass</td>
@ -57,7 +57,7 @@
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="GET" name="form"
action="/WebGoat/IDOR/profile">
action="IDOR/profile">
<script th:src="@{/lesson_js/idor.js}" />
<input name="View Profile" value="View Profile" type="button" onclick="onViewProfile();" />
@ -107,7 +107,7 @@
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/IDOR/profile/alt-path">
action="IDOR/profile/alt-path">
<div class="adoc-content" th:replace="~{doc:lessons/idor/documentation/IDOR_inputAltPath.adoc}"></div>
<input name="url" value="WebGoat/" type="text"/>
<input name="submit" value="Submit" type="SUBMIT"/>
@ -134,7 +134,7 @@
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN" id="view-other"
method="GET" name="view-other-profile"
action="/WebGoat/IDOR/profile/{userId}">
action="IDOR/profile/{userId}">
<script th:src="@{/lesson_js/idor.js}" />
<input name="View Profile" value="View Profile" type="submit" />
@ -158,7 +158,7 @@
<!-- modify the action to point to the intended endpoint -->
<form class="attack-form" accept-charset="UNKNOWN" id="edit-other"
method="GET" name="edit-other-profile"
action="/WebGoat/IDOR/profile/{userId}">
action="IDOR/profile/{userId}">
<script th:src="@{/lesson_js/idor.js}" />
<input name="View Profile" value="View Profile" type="submit" />

View File

@ -27,7 +27,7 @@ idor.diff.failure=Try again. Look in your browser dev tools or Proxy and compare
idor.edit.profile.success1=Well done, you have modified someone else's profile (as displayed below)
idor.edit.profile.success2=Good work! View the updated profile below
idor.edit.profile.failure1=Close ... you've got the technique. Now try for a lower role number
idor.edit.profile.failure2=Close ... you've got the technique. Now change the color in their profile to red.)
idor.edit.profile.failure2=Close ... you've got the technique. Now change the color in their profile to red.
idor.edit.profile.failure3=Try again. Use the hints if you need to.
idor.edit.profile.failure4=Modifying your own profile is good, but we want to do this to Buffalo Bill's profile.

View File

@ -12,7 +12,7 @@ var onViewProfile = function () {
console.warn("on view profile activated")
webgoat.customjs.jquery.ajax({
method: "GET",
url: "/WebGoat/IDOR/profile",
url: "IDOR/profile",
contentType: 'application/json; charset=UTF-8'
}).then(webgoat.customjs.idorViewProfile);
}

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