Compare commits

...

164 Commits

Author SHA1 Message Date
72968d9619 Merge branch 'release/v8.0.0.M23' 2019-01-18 08:46:50 +01:00
631fedb752 New release, updating pom.xml 2019-01-18 08:45:44 +01:00
4f59bf545e Updating release doc 2019-01-18 08:44:46 +01:00
5d5ba53473 Merge tag 'v8.0.0.M22' into develop
v8.0.0.M22
2019-01-18 08:39:19 +01:00
7b8e3cdb52 Merge branch 'release/v8.0.0.M22' 2019-01-18 08:38:10 +01:00
9be4361afc New release, updating pom.xml 2019-01-18 08:37:26 +01:00
b0e3a06b50 Password reset lesson 5 not working #512
Added comment to not use OWASP ZAP
2019-01-17 16:35:04 +01:00
9170dcb87f Fix a grammatical error 2019-01-17 14:50:07 +01:00
dc5f9880af Full implementation of "Update Webgoat Dockerfile to use entrypoints and commands #523" based on the pull request of Nicklaus McClendon 2019-01-17 14:49:42 +01:00
ed490a5ecf Fix for #545
Introduced new macro to make a clear distinction between /WebWolf with
context root and without.
2019-01-16 11:07:30 +01:00
81d6e12ae1 Spring devtools no longer work in combination with Spring and Java 11 2019-01-15 16:29:49 +01:00
c3ee0b7662 Travis build should also use Java 11 2019-01-15 16:24:39 +01:00
959a3c6420 Docker images should use new jar version notation 2019-01-15 16:23:21 +01:00
3fa10c4b10 Update to Java 11 2019-01-15 16:23:03 +01:00
ec225558b9 Move to latest Spring Boot version and move to Java 11 2018-12-15 13:59:54 +01:00
dd1009bc54 Add Maven wrapper 2018-12-14 12:56:21 +01:00
bf45a0a8e5 Fix for XXE docs 2018-12-14 12:43:19 +01:00
f81a6852db YAML structure fix, postgres version fix
The structure of the environment was incorrect. The postgres dialect doesn't match the postgres:latest image.
2018-11-19 08:16:49 +01:00
6699456ee1 Bug fix in sample code 2018-11-19 08:15:41 +01:00
ecbbb5258e encapsulated the WEBGOAT_HOME in quotes
Encapsulating the `WEBGOAT_HOME` variable in quotes allows for spaces to exist in the path
2018-11-19 08:14:29 +01:00
1520c7571f HTML Tampering Mitigation Description Typo 2018-11-19 08:13:17 +01:00
5921a06747 Fix SQL injection mitigation answer (fixes #505)
You need to submit the IP of the webgoat-prd server, not just any of the IPs.
2018-11-19 08:12:17 +01:00
b6e4995d11 Fixed Vagrant file
- Added correct wget urls for .jar files
- changed server address to 0.0.0.0(pointing to all interfaces) because by default it listens for connections on VM's localhost only but we want to access webgoat on NAT adapter via port forwarding
2018-11-19 08:10:11 +01:00
a2f28460c0 Update password_reset.html
Without this attribute it is impossible to pass the lesson "password-reset" `Email functionality with WebWolf`.
2018-11-19 08:08:41 +01:00
0797c3e2bf Merge pull request #519 from pingiun/patch-1
Fix typo
2018-09-13 08:16:11 -07:00
f9a4061604 Fix typo 2018-09-12 09:54:44 +02:00
580e50f558 Same form post is used and with autocomplete this does not work because all fields will be posted. The endpoint could no long distinguish between the different actions (sending e-mail and checking password) 2018-08-10 13:15:40 +02:00
3d58049af6 docker-compose-local.yml now extends docker-compose.yml
WebWolf waits for 8 seconds after WebGoat starts so the database connection can be established
2018-08-08 18:26:12 +02:00
bca8b3c650 Fix buildscripts to wait for Docker and build snapshots 2018-08-08 18:23:27 +02:00
1252e3dc21 Update instructions to use docker-compose only 2018-07-17 20:17:35 +02:00
63a50df7a1 Add hint to lesson users no longer have guess the complete ip address 2018-07-06 18:22:29 +02:00
f9e552f1cd Add instructions how to run WebGoat on Java 9 or higher 2018-07-04 19:15:54 +02:00
2233550fe1 Adding more solutions for SQL order by lesson 2018-06-22 14:12:37 +02:00
cb18295f9f Update hint 2018-06-21 07:53:21 +02:00
651698d96c Add different solution for XXE attack 2018-06-21 07:17:27 +02:00
4d7d0058c3 Update how to create a release document 2018-06-20 18:38:16 +02:00
e3fba396de Merge tag 'v8.0.0.M21' into develop 2018-06-20 18:24:06 +02:00
3536fd0b6d Merge branch 'release/v8.0.0.M21' 2018-06-20 18:23:59 +02:00
bc84e8f207 Build release when tag is set 2018-06-20 18:22:35 +02:00
14dbd47675 Merge tag 'v8.0.0.M20' into develop
New release M20
2018-06-20 18:06:26 +02:00
898dd90c6f Merge branch 'release/v8.0.0.M20' 2018-06-20 18:06:17 +02:00
ac12a009e4 New release v8.0.0.M20 2018-06-20 18:05:59 +02:00
699b1bfd89 Only do releases and Docker updates when building master 2018-06-20 18:05:06 +02:00
ad77a7ab24 Merge tag 'v8.0.0.M19' into develop
New release M19
2018-06-20 16:40:44 +02:00
b7278590f5 Merge branch 'release/v8.0.0.M19' 2018-06-20 16:40:33 +02:00
9dd93d88d9 New release v8.0.0.M19 2018-06-20 16:40:28 +02:00
4c767cb977 Merge tag 'v8.0.0.M18' into develop
New release
2018-06-20 16:32:44 +02:00
12123ef13b Merge branch 'release/v8.0.0.M18' 2018-06-20 16:32:31 +02:00
c7da546249 Improve text for lesson about CSRF login 2018-06-16 17:52:18 +02:00
a41ff0083c Merge pull request #479 from misfir3/develop
Recent updates, including Missing Function AC content & patch for Vuln Components Lesson
2018-06-13 18:44:09 -06:00
701a99cf8f Merge pull request #487 from matthias-g/xssFixes
Small lesson improvements
2018-06-13 18:42:14 -06:00
844808bfa7 Merge pull request #485 from matthias-g/fixSQLInjection
Fix sql injection
2018-06-13 18:41:05 -06:00
81aac93dfe Usage base64 encoded password as expected by JJWT 2018-06-13 17:58:52 +02:00
e5ec2c1ee0 Fix html attribute 2018-06-13 17:56:57 +02:00
b0fbeaff2c This improves the text of the lesson about XSS 2018-06-13 17:56:23 +02:00
b47bb96534 Update changed password in tests 2018-06-13 16:11:28 +02:00
3b9b695ef1 Check host header instead of origin which might not be present #475 2018-06-13 11:38:33 +02:00
1d2575a211 Allow - in usernames because CSRF lesson requires username starting with prefix crsf- #476 2018-06-13 11:38:33 +02:00
56fc983414 Update database layout so that proposed solution works 2018-06-12 17:40:28 +02:00
268adbcf7e Move assignments to correct package so that hints are shown 2018-06-12 17:40:28 +02:00
f383454440 Fix spelling in JWT lesson 2018-06-12 11:02:51 +02:00
bae3e75ae2 Fix minor issues in hint view 2018-06-12 11:02:16 +02:00
a7b82985d4 Fix usage of JJWT API which expects base64 encoded strings as key 2018-06-12 11:01:23 +02:00
3d282e163c Show newest comments first
This prevents new comments from not being displayed after a comment containing invalid html has been posted.
2018-06-12 10:54:13 +02:00
7068c84c6a Fix parameter in url and some spelling 2018-06-12 10:54:13 +02:00
0030c7bdfb Merge pull request #480 from matthias-g/fixPageNum
Fix next page button when url doesn't end with page number
2018-06-07 11:27:29 -06:00
89f6a73275 Fix next page button when url doesn't end with page number 2018-06-07 19:07:58 +02:00
cf0e4e40cf clean up 2018-06-05 14:36:40 -06:00
dfd51f8b54 Merge branch 'develop' of github.com:misfir3/WebGoat into develop 2018-06-05 14:10:51 -06:00
5e8c610fbf gke-deploy.sh 2018-06-05 14:10:29 -06:00
71514fc39b GKE deploy script 2018-06-05 09:45:47 -06:00
1734170e9e updates to missing function ac lesson 2018-06-04 16:53:13 -06:00
c89afe6334 Merge remote-tracking branch 'upstream/develop' into develop 2018-06-01 09:54:03 -06:00
9af0054b5b Merge branch 'release/v8.0.0.M17' 2018-05-30 20:54:18 +02:00
26aa72e721 New release 2018-05-30 20:54:13 +02:00
c510bd9bf1 New develop version 2018-05-30 20:37:25 +02:00
6bf853d953 Merge tag 'v8.0.0.M16' into develop
New release
2018-05-30 20:35:56 +02:00
b298440985 Merge branch 'release/v8.0.0.M16' 2018-05-30 20:35:22 +02:00
c7a714a590 Move to next release 2018-05-30 17:05:50 +02:00
93620f148b Remove challenges which are also incorporated in the lessons themselves 2018-05-30 16:46:50 +02:00
ecb7688e08 Update to new version for develop
Move WebWolf to port 9090 easier since most of the time something is running on 8081
Add scripts for easy building Docker files etc
2018-05-30 13:17:05 +02:00
0de784eb32 Update README and simply the java command to one with optional arguments 2018-05-29 22:16:29 +02:00
4691bc5fd5 Extended proxy lesson with Edit and Resend and explained how to exclude WebGoat internal calls from proxying 2018-05-29 21:30:13 +02:00
fc2c99bcb4 Limit the username to letters and digits only 2018-05-29 16:16:52 +02:00
7292a577e3 Only do a release when we build master and have a tagged the release 2018-05-29 15:20:07 +02:00
396c1c1d47 Update order of starting WebGoat 2018-05-29 15:16:29 +02:00
2911788679 Merge tag 'v8.0.0' into develop
Release v8.0.0
2018-05-29 14:59:32 +02:00
985148ede3 Merge branch 'release/v8.0.0' 2018-05-29 14:59:07 +02:00
9587550bc5 Fixed column name on sql injection lesson 7 2018-05-29 14:42:22 +02:00
9a0995dae5 Fixed column name on sql injection lesson 6 2018-05-29 14:42:02 +02:00
4e07e0ebfa Fix links to open new browser tab 2018-05-29 14:04:33 +02:00
6e95fdfe56 Adjusted documentation 2018-05-29 13:33:52 +02:00
e045bc692d Buying page also calculates the prices
Product image added
2018-05-29 12:47:27 +02:00
589872ad47 Fix for JWT assignment 1 log in now works again.
Reset button only triggers reset when admin is set to true in the token
2018-05-29 11:20:40 +02:00
5f4889cefe Clicking link in first password reset link only switched back and forward 2018-05-29 09:29:50 +02:00
55793dd153 New release v8.0.0.M15 2018-05-27 20:54:50 +02:00
1edceb0aa8 Extended and fixed some lessons 2018-05-27 20:37:44 +02:00
d2b6725f3b Moved challenge2 to client-side-filtering as final assignment 2018-05-27 12:41:52 +02:00
6e003bc088 Working last password assignment 2018-05-26 18:48:48 +02:00
f8a7a61e85 New lesson working 2018-05-26 15:09:18 +02:00
eaf68d38c5 Initial commit for password reset lesson 2018-05-25 14:27:45 +02:00
8d7ecb19d7 Added testcases for all JWT endpoints 2018-05-23 14:28:19 +02:00
e0cf5b4a84 Removed under construction from JWT lesson 2018-05-23 14:28:19 +02:00
5b524d3a94 Added more unit tests 2018-05-23 14:28:19 +02:00
dda6f674a3 Last assignment for JWT tokens finished 2018-05-23 14:28:19 +02:00
e06d4642eb Fix error in testcase 2018-05-23 14:28:19 +02:00
4a8fdcf887 Fix content-type for login (gives error in console of browser) 2018-05-23 14:28:19 +02:00
fd96ba18f1 Added test cases for solving the lesson 2018-05-23 14:28:19 +02:00
60ef35e241 Working lesson 2018-05-23 14:28:19 +02:00
9d7886d572 More JWT work 2018-05-23 14:28:19 +02:00
7a0820bf89 WIP 2018-05-23 14:28:19 +02:00
ea9c1a453d Initial version for JWT 2018-05-23 14:28:19 +02:00
63ca11a1bb Change WebWolf to WebGoat
The links for the WebGoat download were mislabeled as WebWolf
2018-05-23 14:07:32 +02:00
5378d72600 Change version in pom.xml 2018-05-23 14:04:21 +02:00
93d6d0e6b7 Added lesson texts 2018-05-23 13:58:37 +02:00
84860e65f6 Insecure Deserialization exercise 2018-05-23 13:58:03 +02:00
a73bf58d36 more hintview patching 2018-05-23 13:35:51 +02:00
0ff6000511 wiring jqueryui to vuln jquery #368 2018-05-23 13:35:51 +02:00
91d9db5f80 work-arounds, fixes for page initialization and some clean-up 2018-05-23 13:35:51 +02:00
ac1b9e8311 cleanup that was missed in prev. commit 2018-05-23 13:35:51 +02:00
9d49373486 fix for periodic fail on StoredXssCommentsTest 2018-05-23 13:35:51 +02:00
ead78d40e6 Chore - fix spelling issues 2018-05-23 13:35:51 +02:00
7b5bb6d6f1 Fixed typos 2018-05-23 13:35:51 +02:00
408a637649 Update HttpBasics_ProxyIntro0.adoc
Fixed typo, Actual : "wihtin" , Expected :  "within"
2018-05-23 13:35:51 +02:00
e96ab488ff Merge branch 'develop' of github.com:misfir2/WebGoat into develop 2018-05-14 12:17:32 -06:00
31f7ea6985 script to automate WebGoat deployment on GKE 2018-05-14 12:15:48 -06:00
6cf96f971d Fix typo 2018-05-11 15:14:11 +02:00
0b9a027c19 Fix some minor grammatical issues. 2018-05-11 15:13:30 +02:00
186f24f1df more hintview patching 2018-05-03 10:49:58 -06:00
089dd56a15 wiring jqueryui to vuln jquery #368 2018-05-03 10:49:31 -06:00
6cfefba0ee work-arounds, fixes for page initialization and some clean-up 2018-05-03 10:25:34 -06:00
20e45da8ae cleanup that was missed in prev. commit 2018-05-02 16:36:34 -06:00
e34faa13d6 fix for periodic fail on StoredXssCommentsTest 2018-05-02 16:35:57 -06:00
927bbad488 merging from release branch ... PR's and Nanne's recent work 2018-05-02 14:27:44 -06:00
6a5ca43e7e Strip out slash-escaped JSON sequence received in client.
The server will slash-escape some JSON related characters before sending. Need to strip them out before using, on the client side.
2018-05-02 22:21:22 +02:00
5d28ef9fbe small fix for CSRF content type lesson descrption 2018-05-02 22:10:06 +02:00
9aa674e326 stringfy object so it's visible in the console 2018-05-02 22:04:25 +02:00
84e3fcde07 Added .sonatype (author: @maurycupitt) 2018-05-02 21:34:17 +02:00
6209b3fe8d Updated lesson for starting WebWolf as a Docker container 2018-05-02 21:25:44 +02:00
a1db8e8bd9 Added documentation how to mount the data directory of WebGoat running in Docker to your host system. 2018-05-02 09:29:52 +02:00
6b4a488c8c Users shared now between WebGoat and WebWolf by starting HSQLDB
as standalone database
2018-05-01 22:00:07 +02:00
0e160c19f5 Docker-compose for postgres and hsqldb 2018-05-01 21:58:43 +02:00
8050a2b56d XXE lesson not showing correct link for WebWolf 2018-05-01 21:54:28 +02:00
11ffa5702c Added "WebWolf" enabled to the lessons which support the usage of WebWolf 2018-04-29 15:02:19 +02:00
32927c8109 Bumped Spring Boot version 2018-04-28 16:02:09 +02:00
8b8a89a8ab Add extra informational message when a failure occurs while sending an email from WebGoat to WebWolf. 2018-04-28 16:01:57 +02:00
e4ca0c4836 Make report working again 2018-04-27 19:26:01 +02:00
e422da4c64 Polling for lesson updates (updates the menu and page navigation) 2018-04-27 18:50:13 +02:00
76daac0db5 Label was missing for HTTP basic lesson 2018-04-27 11:29:52 +02:00
245ba2c3d1 Fix XXE lesson, the exact .webgoat directory including version number will be put in the lesson. 2018-04-24 20:44:05 +02:00
672d78eebc Resource bundle in UTF-8 2018-04-23 16:12:50 +02:00
f4eb96fc6a Add additional remark WebWolf should be running if interaction is necessary 2018-04-23 11:32:07 +02:00
46fedf3764 Fix for Docker command to start WebWolf 2018-04-23 11:20:25 +02:00
f30db3abfc New version number 2018-04-11 20:45:12 +02:00
58d4b81df2 Wrong image name mentioned in lesson for WebWolf 2018-04-11 20:22:19 +02:00
a922c00182 Chore - fix spelling issues 2018-02-15 20:12:53 +00:00
2ae1b4955f By default binds to ALL network interfaces #431
Fix for Docker not binding to any address by default
2018-01-30 07:18:05 +01:00
f21fe7f2c3 Fixed typos 2018-01-30 05:49:51 +00:00
13a4b69cbe All lesson flags are displayed while running webgoat 8.0 standalone java file #430 2018-01-29 15:43:19 +01:00
98efc1235f By default binds to ALL network interfaces #431 2018-01-29 15:32:02 +01:00
b99b554522 Version: docker 8.0.0.M9 Multiple users can't finalize the same lesson #432 2018-01-29 15:29:48 +01:00
3cd349bb4b Update HttpBasics_ProxyIntro0.adoc
Fixed typo, Actual : "wihtin" , Expected :  "within"
2018-01-23 18:01:42 +00:00
04ccf9a422 New release should create a new webgoat directory with version tag inside #423 2018-01-21 17:46:43 +01:00
e3e7ed004f Not making a Docker release is we build develop (putting a tag will create a release which is more a controlled/intuitive way to make a release to Docker) 2018-01-02 22:19:49 +01:00
285 changed files with 4537 additions and 2002 deletions

9
.gitignore vendored
View File

@ -42,3 +42,12 @@ webgoat-lessons/**/target
**/.DS_Store **/.DS_Store
webgoat-server/mongo-data/* webgoat-server/mongo-data/*
webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml
**/.sts4-cache/*
**/.vscode/*
**/.factorypath
/.sonatype
**/bin/*
webgoat.lck
webgoat.log
webgoat.properties
webgoat.script

1
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@ -0,0 +1 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip

View File

@ -2,7 +2,7 @@ services:
- docker - docker
language: java language: java
jdk: jdk:
- oraclejdk8 - openjdk11
install: "/bin/true" install: "/bin/true"
script: script:
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
@ -28,12 +28,6 @@ deploy:
on: on:
repo: WebGoat/WebGoat repo: WebGoat/WebGoat
tags: true tags: true
- provider: script
skip_cleanup: true
script: bash scripts/deploy-webgoat.sh
on:
repo: WebGoat/WebGoat
branch: develop
- provider: releases - provider: releases
skip_cleanup: true skip_cleanup: true
overwrite: true overwrite: true

View File

@ -13,17 +13,15 @@ At the moment we use Gitflow, for a release you create a new release branch and
git checkout develop git checkout develop
git flow release start <version> git flow release start <version>
mvn versions:set <<version> mvn versions:set <<version>
git commit -am "New release, updaing pom.xml" git commit -am "New release, updating pom.xml"
git flow release publish git flow release publish
``` git push origin develop
git push origin master
Now we can make a new release, be sure you committed all your changes. git push --tags
```
git tag v8.0.0.M3
git push origin v8.0.0.M3
``` ```
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

View File

@ -29,61 +29,47 @@ first thing that all hackers claim.*
# Run Instructions: # Run Instructions:
## 1. Run using Docker ## 1. Standalone
From time to time we publish a new development preview of WebGoat 8 on Docker HUB, you can download this version Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
[https://hub.docker.com/r/webgoat/webgoat-8.0/](https://hub.docker.com/r/webgoat/webgoat-8.0/).
First install Docker, then open a command shell/window and type:
```Shell ```Shell
docker pull webgoat/webgoat-8.0 java -jar webgoat-server-8.0.0.VERSION.jar [--server.port=8080] [--server.address=localhost]
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
``` ```
Wait for the Docker container to start, and run `docker ps` to verify it's running. By default WebGoat starts on port 8080 with `--server.port` you can specify a different port. With `server.address` you
can bind it to a different address (default localhost)
- If you are using `docker-machine`, verify the machine IP using `docker-machine env` If you use Java 9 or higher you need to run WebGoat as follows:
- If you are using `boot2docker` on OSX, verify the IP by running `docker network inspect bridge`
- Otherwise, the host will be bound to localhost
Once you have the IP and port, you'll want to navigate to the `/WebGoat` path in the URL. For example:
```
http://192.168.99.100:8080/WebGoat
```
Here you'll be able to register a new user and get started.
_Please note: this version may not be completely in sync with the develop branch._
## 2. Standalone
Download the latest WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```Shell ```Shell
java -jar webgoat-server-<<version>>.jar java --add-modules java.xml.bind -jar webgoat-server-8.0.0.VERSION.jar
``` ```
By default WebGoat starts at port 8080 in order to change this use the following property: ## 2. Run using Docker
```Shell Every release is also published on [DockerHub]((https://hub.docker.com/r/webgoat/webgoat-8.0/)).
java -jar webgoat-server-<<version>>.jar --server.port=9090
### Using docker-compose
The easiest way to start WebGoat as a Docker container is to use the `docker-compose.yml` [file](https://raw.githubusercontent.com/WebGoat/WebGoat/develop/docker-compose.yml)
from our Github repository. This will start both containers and it also takes care of setting up the
connection between WebGoat and WebWolf.
```shell
curl https://raw.githubusercontent.com/WebGoat/WebGoat/develop/docker-compose.yml | docker-compose -f - up
``` ```
You can specify one of the following arguments when starting WebGoat: **Important**: the current directory on your host will be mapped into the container for keeping state.
```Shell Using the `docker-compose` file will simplify getting WebGoat and WebWolf up and running.
java -jar webgoat-server-<<version>>.jar --server.port=9090 --server.address=x.x.x.x
```
This will start WebGoat on a different port and/or different address.
## 3. Run from the sources ## 3. Run from the sources
### Prerequisites: ### Prerequisites:
* Java 8 * Java 11
* Maven > 3.2.1 * Maven > 3.2.1
* Your favorite IDE * Your favorite IDE
* Git, or Git support in your IDE * Git, or Git support in your IDE
@ -118,7 +104,7 @@ server.address=x.x.x.x
# Vagrant # Vagrant
We supply a complete development environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed. We supply a complete environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed.
```shell ```shell
$ cd WebGoat/webgoat-images/vagrant-training $ cd WebGoat/webgoat-images/vagrant-training
@ -126,7 +112,7 @@ We supply a complete development environment using Vagrant, to run WebGoat with
``` ```
Once the provisioning is complete login to the Virtualbox with username vagrant and password vagrant. Once the provisioning is complete login to the Virtualbox with username vagrant and password vagrant.
The source code will be available in the home directory. WebGoat and WebWolf will automatically start when you login to this image.
# Building a new Docker image # Building a new Docker image

13
docker-compose-local.yml Normal file
View File

@ -0,0 +1,13 @@
version: '2.1'
services:
webgoat:
image: webgoat/webgoat-v8.0.0.snapshot
extends:
file: docker-compose.yml
service: webgoat
webwolf:
extends:
file: docker-compose.yml
service: webwolf
image: webgoat/webwolf-v8.0.0.snapshot

View File

@ -0,0 +1,40 @@
version: '2.0'
services:
webgoat:
image: webgoat/webgoat-8.0
user: webgoat
environment:
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
- spring.datasource.username=webgoat
- spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect
- webgoat.server.directory=/home/webgoat/.webgoat/
- webgoat.user.directory=/home/webgoat/.webgoat/
ports:
- "8080:8080"
webwolf:
image: webgoat/webwolf
environment:
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
- spring.datasource.username=webgoat
- spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect
ports:
- "9090:9090"
webgoat_db:
image: postgres:9.4
# Uncomment to store the state of the database on the host.
# volumes:
# - ./database:/var/lib/postgresql
environment:
- POSTGRES_PASSWORD=webgoat
- POSTGRES_USER=webgoat
- POSTGRES_DB=webgoat
ports:
- "5432:5432"

View File

@ -1,15 +1,18 @@
version: '2.0' version: '2.1'
services: services:
webgoat: webgoat:
build: webgoat-server/ image: webgoat/webgoat-8.0
command: "sh /home/webgoat/start.sh" environment:
- WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090
ports: ports:
- "8080:8080" - "8080:8080"
- "9001:9001"
volumes:
- .:/home/webgoat/.webgoat
webwolf: webwolf:
build: webwolf/ image: webgoat/webwolf
command: "sh /home/webwolf/start.sh"
depends_on:
- webgoat
ports: ports:
- "8081:8081" - "9090:9090"
command: --spring.datasource.url=jdbc:hsqldb:hsql://webgoat:9001/webgoat --server.address=0.0.0.0

286
mvnw vendored Executable file
View File

@ -0,0 +1,286 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

161
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,161 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
)
@REM End of extension
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@ -0,0 +1,4 @@
CURTAG=webgoat/webgoat-8.0
DEST_TAG=gcr.io/astech-training/raging-wire-webgoat
CLUSTER_NAME=raging-wire-webgoat
PORT_NUM=8080

View File

@ -0,0 +1,4 @@
CURTAG=webgoat/webgoat-8.0
DEST_TAG=gcr.io/your-gke-project/your-webgoat-tag
CLUSTER_NAME=your-cluster-name
PORT_NUM=8080

160
pom.xml
View File

@ -1,11 +1,12 @@
<?xml version="1.0"?> <?xml version="1.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"> <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> <modelVersion>4.0.0</modelVersion>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId> <artifactId>webgoat-parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
<name>WebGoat Parent Pom</name> <name>WebGoat Parent Pom</name>
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description> <description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
@ -20,7 +21,7 @@
<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>1.5.9.RELEASE</version> <version>1.5.18.RELEASE</version>
</parent> </parent>
<licenses> <licenses>
@ -53,17 +54,17 @@
<developer> <developer>
<id>jwayman</id> <id>jwayman</id>
<name>Jeff Wayman</name> <name>Jeff Wayman</name>
<email /> <email/>
</developer> </developer>
<developer> <developer>
<id>dcowden</id> <id>dcowden</id>
<name>Dave Cowden</name> <name>Dave Cowden</name>
<email /> <email/>
</developer> </developer>
<developer> <developer>
<id>lawson89</id> <id>lawson89</id>
<name>Richard Lawson</name> <name>Richard Lawson</name>
<email /> <email/>
</developer> </developer>
<developer> <developer>
<id>dougmorato</id> <id>dougmorato</id>
@ -92,8 +93,8 @@
<url>https://github.com/WebGoat/WebGoat</url> <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>
</scm> </scm>
<issueManagement> <issueManagement>
<system>Github Issues</system> <system>Github Issues</system>
@ -106,9 +107,6 @@
</ciManagement> </ciManagement>
<properties> <properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Use UTF-8 Encoding --> <!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@ -128,42 +126,37 @@
<commons-digester.version>2.1</commons-digester.version> <commons-digester.version>2.1</commons-digester.version>
<commons-discovery.version>0.5</commons-discovery.version> <commons-discovery.version>0.5</commons-discovery.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version> <commons-fileupload.version>1.3.1</commons-fileupload.version>
<commons-io.version>2.4</commons-io.version> <commons-io.version>2.6</commons-io.version>
<commons-lang3.version>3.4</commons-lang3.version> <commons-lang3.version>3.4</commons-lang3.version>
<coveralls-maven-plugin.version>4.0.0</coveralls-maven-plugin.version> <coveralls-maven-plugin.version>4.0.0</coveralls-maven-plugin.version>
<gatling.version>2.2.5</gatling.version> <gatling.version>2.2.5</gatling.version>
<gatling-plugin.version>2.2.4</gatling-plugin.version> <gatling-plugin.version>2.2.4</gatling-plugin.version>
<guava.version>18.0</guava.version> <guava.version>18.0</guava.version>
<h2.version>1.4.190</h2.version> <h2.version>1.4.190</h2.version>
<hsqldb.version>2.3.2</hsqldb.version> <hsqldb.version>2.3.4</hsqldb.version>
<j2h.version>1.3.1</j2h.version> <j2h.version>1.3.1</j2h.version>
<jackson-core.version>2.6.3</jackson-core.version> <jackson-core.version>2.6.3</jackson-core.version>
<jackson-databind.version>2.6.3</jackson-databind.version> <jackson-databind.version>2.6.3</jackson-databind.version>
<javaee-api.version>6.0</javaee-api.version> <javaee-api.version>6.0</javaee-api.version>
<javax.transaction-api.version>1.2</javax.transaction-api.version> <javax.transaction-api.version>1.3</javax.transaction-api.version>
<jcl-over-slf4j.version>1.7.12</jcl-over-slf4j.version> <jcl-over-slf4j.version>1.7.12</jcl-over-slf4j.version>
<jtds.version>1.3.1</jtds.version> <jtds.version>1.3.1</jtds.version>
<junit.version>4.12</junit.version> <junit.version>4.12</junit.version>
<lombok.version>1.18.4</lombok.version>
<mail-api.version>1.5.4</mail-api.version> <mail-api.version>1.5.4</mail-api.version>
<maven-compiler-plugin.version>3.3</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.19</maven-failsafe-plugin.version> <maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version> <maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
<maven-jar-plugin.version>2.6</maven-jar-plugin.version> <maven-jar-plugin.version>2.6</maven-jar-plugin.version>
<maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version> <maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version>
<maven-release-plugin.version>2.5.2</maven-release-plugin.version> <maven-release-plugin.version>2.5.2</maven-release-plugin.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version> <maven-source-plugin.version>3.0.1</maven-source-plugin.version>
<maven-surefire-plugin.version>2.19</maven-surefire-plugin.version> <maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
<nexus-staging-maven-plugin.version>1.6.6</nexus-staging-maven-plugin.version> <nexus-staging-maven-plugin.version>1.6.6</nexus-staging-maven-plugin.version>
<scala.version>2.11.7</scala.version> <scala.version>2.11.7</scala.version>
<sauce_junit.version>2.1.20</sauce_junit.version> <sauce_junit.version>2.1.20</sauce_junit.version>
<selenium-java.version>2.48.2</selenium-java.version> <selenium-java.version>2.48.2</selenium-java.version>
<spring.security.version>3.2.4.RELEASE</spring.security.version> <spring.security.version>3.2.4.RELEASE</spring.security.version>
<standard.version>1.1.2</standard.version>
<tiles.version>3.0.5</tiles.version>
<tomcat-catalina.version>7.0.65</tomcat-catalina.version>
<tomcat7-maven-plugin.version>2.3-SNAPSHOT</tomcat7-maven-plugin.version>
<versioneye-maven-plugin.version>3.5.1</versioneye-maven-plugin.version>
<wsdl4j.version>1.6.3</wsdl4j.version>
</properties> </properties>
<modules> <modules>
@ -199,103 +192,12 @@
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
<profiles>
<profile>
<id>release</id>
<dependencies>
<dependency>
<groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>dist</artifactId>
<version>1.0</version>
<type>zip</type>
<scope>provided</scope>
<classifier>plugins</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-lesson</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.basedir}/webgoat-container/src/main/webapp/plugin_lessons</outputDirectory>
<includeArtifactIds>dist</includeArtifactIds>
<includes>*.jar</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>${nexus-staging-maven-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>${maven-gpg-plugin.version}</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<keyname>WebGoat</keyname>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<scope>provided</scope> <scope>provided</scope>
<version>${lombok.version}</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
@ -303,10 +205,25 @@
<artifactId>commons-exec</artifactId> <artifactId>commons-exec</artifactId>
<version>1.3</version> <version>1.3</version>
</dependency> </dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-release-plugin</artifactId>
@ -324,7 +241,7 @@
<artifactId>coveralls-maven-plugin</artifactId> <artifactId>coveralls-maven-plugin</artifactId>
<version>${coveralls-maven-plugin.version}</version> <version>${coveralls-maven-plugin.version}</version>
<configuration> <configuration>
<repoToken /> <repoToken/>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -332,22 +249,13 @@
<artifactId>cobertura-maven-plugin</artifactId> <artifactId>cobertura-maven-plugin</artifactId>
<version>${cobertura-maven-plugin.version}</version> <version>${cobertura-maven-plugin.version}</version>
<configuration> <configuration>
<check /> <check/>
<format>xml</format> <format>xml</format>
<maxmem>256m</maxmem> <maxmem>256m</maxmem>
<!-- aggregated reports for multi-module projects --> <!-- aggregated reports for multi-module projects -->
<aggregate>true</aggregate> <aggregate>true</aggregate>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>com.versioneye</groupId>
<artifactId>versioneye-maven-plugin</artifactId>
<version>${versioneye-maven-plugin.version}</version>
<configuration>
<apiKey>a1e4a9da4ed34ee44cab</apiKey>
<projectId>562da95be346d7000e0369ac</projectId>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

34
scripts/build-all.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
cd ..
nc -zv 127.0.0.1 8080 2>/dev/null
SUCCESS=$?
nc -zv 127.0.0.1 9090 2>/dev/null
SUCCESS=${SUCCESS}$?
if [[ "${SUCCESS}" -eq 0 ]] ; then
echo "WebGoat and or WebWolf are still running, please stop them first otherwise unit tests might fail!"
exit 127
fi
sh mvnw clean install
if [[ "$?" -ne 0 ]] ; then
exit y$?
fi
cd -
sh build_docker.sh
if [[ "$?" -ne 0 ]] ; then
exit y$?
fi
while true; do
read -p "Do you want to run docker-compose?" yn
case ${yn} in
[Yy]* ) sh clean-run-docker-compose.sh; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done

10
scripts/build_docker.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
WEBGOAT_HOME=$(pwd)/../
cd "${WEBGOAT_HOME}"/webgoat-server
docker build -t webgoat/webgoat-v8.0.0.snapshot .
cd "${WEBGOAT_HOME}"/webwolf
docker build -t webgoat/webwolf-v8.0.0.snapshot .

View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
cd ..
docker-compose rm -f
docker-compose -f docker-compose-local.yml up

View File

@ -6,17 +6,31 @@ export REPO=webgoat/webgoat-8.0
cd webgoat-server cd webgoat-server
ls target/ ls target/
if [ "${BRANCH}" == "master" ] && [ ! -z "${TRAVIS_TAG}" ]; then if [ ! -z "${TRAVIS_TAG}" ]; then
# If we push a tag to master this will update the LATEST Docker image and tag with the version number # If we push a tag to master this will update the LATEST Docker image and tag with the version number
docker build --build-arg webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} . docker build --build-arg webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} .
docker push $REPO docker push $REPO
elif [ ! -z "${TRAVIS_TAG}" ]; then #elif [ ! -z "${TRAVIS_TAG}" ]; then
# Creating a tag build we push it to Docker with that tag # # Creating a tag build we push it to Docker with that tag
docker build --build-arg webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:${TRAVIS_TAG} -t $REPO:latest . # docker build --build-arg webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:${TRAVIS_TAG} -t $REPO:latest .
docker push $REPO # docker push $REPO
#elif [ "${BRANCH}" == "develop" ]; then #elif [ "${BRANCH}" == "develop" ]; then
# docker build -f Dockerfile -t $REPO:snapshot . # docker build -f Dockerfile -t $REPO:snapshot .
# docker push $REPO # docker push $REPO
else else
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}" echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
fi fi
export REPO=webgoat/webwolf
cd ..
cd webwolf
ls target/
if [ ! -z "${TRAVIS_TAG}" ]; then
# If we push a tag to master this will update the LATEST Docker image and tag with the version number
docker build --build-arg webwolf_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} .
docker push $REPO
else
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
fi

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
cd ..
docker-compose up

18
scripts/start.sh Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
DATABASE_PORT=9001
checkDatabaseAvailable(){
#for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)
local started = $(netstat -lnt | grep ${DATABASE_PORT})
echo $?
}
#java -Djava.security.egd=file:/dev/./urandom -jar home/webgoat/webgoat.jar --server.address=0.0.0.0
$(checkDatabaseAvailable)
#java -Djava.security.egd=file:/dev/./urandom -jar /home/webwolf/webwolf.jar --server.port=9090 --server.address=0.0.0.0

View File

@ -10,7 +10,7 @@
<parent> <parent>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId> <artifactId>webgoat-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
</parent> </parent>
<profiles> <profiles>
@ -64,16 +64,6 @@
<useDefaultDelimiters>false</useDefaultDelimiters> <useDefaultDelimiters>false</useDefaultDelimiters>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>ISO-8859-1</encoding>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
@ -191,7 +181,9 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>${junit.version}</version> <version>${junit.version}</version>
<type>jar</type> <type>jar</type>
<scope>test</scope>
</dependency> </dependency>
<!-- ************* END: Dependencies for Unit and Integration Testing ************** --> <!-- ************* END: Dependencies for Unit and Integration Testing ************** -->
<!-- ************* END: <dependencies> ************** --> <!-- ************* END: <dependencies> ************** -->
</dependencies> </dependencies>

View File

@ -35,7 +35,9 @@ import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.JavaExtensionRegistry; import org.asciidoctor.extension.JavaExtensionRegistry;
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
import org.owasp.webgoat.asciidoc.WebWolfMacro; import org.owasp.webgoat.asciidoc.WebWolfMacro;
import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Language;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.resourceresolver.IResourceResolver;
@ -86,6 +88,8 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry(); JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8)); return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8));

View File

@ -130,6 +130,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Bean @Bean
public PluginMessages pluginMessages(Messages messages, Language language) { public PluginMessages pluginMessages(Messages messages, Language language) {
PluginMessages pluginMessages = new PluginMessages(messages, language); PluginMessages pluginMessages = new PluginMessages(messages, language);
pluginMessages.setDefaultEncoding("UTF-8");
pluginMessages.setBasenames("i18n/WebGoatLabels"); pluginMessages.setBasenames("i18n/WebGoatLabels");
return pluginMessages; return pluginMessages;
} }
@ -142,6 +143,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Bean @Bean
public Messages messageSource(Language language) { public Messages messageSource(Language language) {
Messages messages = new Messages(language); Messages messages = new Messages(language);
messages.setDefaultEncoding("UTF-8");
messages.setBasename("classpath:i18n/messages"); messages.setBasename("classpath:i18n/messages");
return messages; return messages;
} }

View File

@ -0,0 +1,23 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public class WebGoatVersionMacro extends InlineMacroProcessor {
public WebGoatVersionMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
}
}

View File

@ -10,6 +10,12 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Map; 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 WebWolfMacro extends InlineMacroProcessor { public class WebWolfMacro extends InlineMacroProcessor {
public WebWolfMacro(String macroName, Map<String, Object> config) { public WebWolfMacro(String macroName, Map<String, Object> config) {
@ -20,9 +26,17 @@ public class WebWolfMacro extends InlineMacroProcessor {
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) { protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
Environment env = EnvironmentExposure.getEnv(); Environment env = EnvironmentExposure.getEnv();
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port")); String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
if (displayCompleteLinkNoFormatting(attributes)) {
return hostname + (hostname.endsWith("/") ? "" : "/") + target;
}
return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>"; return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>";
} }
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().filter(a -> a.equals("noLink")).findFirst().isPresent();
}
/** /**
* Look at the remote address from received from the browser first. This way it will also work if you run * Look at the remote address from received from the browser first. This way it will also work if you run
* the browser in a Docker container and WebGoat on your local machine. * the browser in a Docker container and WebGoat on your local machine.
@ -31,6 +45,10 @@ public class WebWolfMacro extends InlineMacroProcessor {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String ip = request.getRemoteAddr(); String ip = request.getRemoteAddr();
String hostname = StringUtils.hasText(ip) ? ip : host; String hostname = StringUtils.hasText(ip) ? ip : host;
return "http://" + hostname + ":" + port + "/WebWolf"; return "http://" + hostname + ":" + port + (includeWebWolfContext() ? "/WebWolf" : "");
}
protected boolean includeWebWolfContext() {
return true;
} }
} }

View File

@ -0,0 +1,20 @@
package org.owasp.webgoat.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, Map<String, Object> config) {
super(macroName, config);
}
protected boolean includeWebWolfContext() {
return false;
}
}

View File

@ -55,7 +55,7 @@ public abstract class AssignmentEndpoint extends Endpoint {
//// TODO: 11/13/2016 events better fit? //// TODO: 11/13/2016 events better fit?
protected AttackResult trackProgress(AttackResult attackResult) { protected AttackResult trackProgress(AttackResult attackResult) {
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (userTracker == null) { if (userTracker == null) {
userTracker = new UserTracker(webSession.getUserName()); userTracker = new UserTracker(webSession.getUserName());
} }

View File

@ -1,11 +1,9 @@
package org.owasp.webgoat.lessons; package org.owasp.webgoat.lessons;
import com.google.common.collect.Lists;
import lombok.*; import lombok.*;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.util.List; import java.util.List;
/** /**
@ -37,19 +35,30 @@ import java.util.List;
* @version $Id: $Id * @version $Id: $Id
* @since November 25, 2016 * @since November 25, 2016
*/ */
@AllArgsConstructor
@RequiredArgsConstructor
@NoArgsConstructor
@Getter @Getter
@EqualsAndHashCode @EqualsAndHashCode
@Entity @Entity
public class Assignment { public class Assignment {
@NonNull
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name; private String name;
@NonNull
private String path; private String path;
@Transient @Transient
private List<String> hints; private List<String> hints;
private Assignment() {
//Hibernate
}
public Assignment(String name, String path) {
this(name, path, Lists.newArrayList());
}
public Assignment(String name, String path, List<String> hints) {
this.name = name;
this.path = path;
this.hints = hints;
}
} }

View File

@ -46,6 +46,7 @@ public enum Category {
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)), INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)),
INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)), INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)),
INSECURE_STORAGE("Insecure Storage", new Integer(800)), INSECURE_STORAGE("Insecure Storage", new Integer(800)),
INSECURE_DESERIALIZATION("Insecure Deserialization", new Integer(850)),
REQUEST_FORGERIES("Request Forgeries", new Integer(900)), REQUEST_FORGERIES("Request Forgeries", new Integer(900)),
VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)), VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)),
AJAX_SECURITY("AJAX Security", new Integer(1000)), AJAX_SECURITY("AJAX Security", new Integer(1000)),

View File

@ -2,7 +2,6 @@ package org.owasp.webgoat.lessons;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.session.WebSession;
/** /**
* <p>LessonInfoModel class.</p> * <p>LessonInfoModel class.</p>

View File

@ -73,7 +73,7 @@ public class LessonMenuService {
List<LessonMenuItem> showLeftNav() { List<LessonMenuItem> showLeftNav() {
List<LessonMenuItem> menu = new ArrayList<>(); List<LessonMenuItem> menu = new ArrayList<>();
List<Category> categories = course.getCategories(); List<Category> categories = course.getCategories();
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
for (Category category : categories) { for (Category category : categories) {
LessonMenuItem categoryItem = new LessonMenuItem(); LessonMenuItem categoryItem = new LessonMenuItem();

View File

@ -40,17 +40,19 @@ public class LessonProgressService {
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json") @RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public Map getLessonInfo() { public Map getLessonInfo() {
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
Map json = Maps.newHashMap(); Map json = Maps.newHashMap();
String successMessage = ""; UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
boolean lessonCompleted = false; if (webSession.getCurrentLesson() != null) {
if (lessonTracker != null) { LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
lessonCompleted = lessonTracker.isLessonSolved(); String successMessage = "";
successMessage = "LessonCompleted"; //@todo we still use this?? boolean lessonCompleted = false;
if (lessonTracker != null) {
lessonCompleted = lessonTracker.isLessonSolved();
successMessage = "LessonCompleted"; //@todo we still use this??
}
json.put("lessonCompleted", lessonCompleted);
json.put("successMessage", successMessage);
} }
json.put("lessonCompleted", lessonCompleted);
json.put("successMessage", successMessage);
return json; return json;
} }
@ -63,7 +65,7 @@ public class LessonProgressService {
@RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json") @RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public List<LessonOverview> lessonOverview() { public List<LessonOverview> lessonOverview() {
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
AbstractLesson currentLesson = webSession.getCurrentLesson(); AbstractLesson currentLesson = webSession.getCurrentLesson();
List<LessonOverview> result = Lists.newArrayList(); List<LessonOverview> result = Lists.newArrayList();
if ( currentLesson != null ) { if ( currentLesson != null ) {

View File

@ -32,6 +32,7 @@ import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
@ -57,6 +58,7 @@ public class ReportCardService {
private final WebSession webSession; private final WebSession webSession;
private final UserTrackerRepository userTrackerRepository; private final UserTrackerRepository userTrackerRepository;
private final Course course; private final Course course;
private final PluginMessages pluginMessages;
/** /**
* Endpoint which generates the report card for the current use to show the stats on the solved lessons * Endpoint which generates the report card for the current use to show the stats on the solved lessons
@ -64,7 +66,7 @@ public class ReportCardService {
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json") @GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public ReportCard reportCard() { public ReportCard reportCard() {
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
List<AbstractLesson> lessons = course.getLessons(); List<AbstractLesson> lessons = course.getLessons();
ReportCard reportCard = new ReportCard(); ReportCard reportCard = new ReportCard();
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons()); reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
@ -74,7 +76,7 @@ public class ReportCardService {
for (AbstractLesson lesson : lessons) { for (AbstractLesson lesson : lessons) {
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson); LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
LessonStatistics lessonStatistics = new LessonStatistics(); LessonStatistics lessonStatistics = new LessonStatistics();
lessonStatistics.setName(lesson.getTitle()); lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
lessonStatistics.setNumberOfAttempts(lessonTracker.getNumberOfAttempts()); lessonStatistics.setNumberOfAttempts(lessonTracker.getNumberOfAttempts());
lessonStatistics.setSolved(lessonTracker.isLessonSolved()); lessonStatistics.setSolved(lessonTracker.isLessonSolved());
reportCard.lessonStatistics.add(lessonStatistics); reportCard.lessonStatistics.add(lessonStatistics);

View File

@ -59,7 +59,7 @@ public class RestartLessonService {
AbstractLesson al = webSession.getCurrentLesson(); AbstractLesson al = webSession.getCurrentLesson();
log.debug("Restarting lesson: " + al); log.debug("Restarting lesson: " + al);
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
userTracker.reset(al); userTracker.reset(al);
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);
} }

View File

@ -81,6 +81,39 @@ public class CreateDB {
} }
} }
/**
* Description of the Method
*
* @param connection Description of the Parameter
* @throws SQLException Description of the Exception
*/
private void createJWTKeys(Connection connection) throws SQLException {
Statement statement = connection.createStatement();
// Drop servers table
try {
String dropTable = "DROP TABLE jwt_keys";
statement.executeUpdate(dropTable);
} catch (SQLException e) {
System.out.println("Info - Could not drop jwtkeys table");
}
// Create the new table
try {
String createTableStatement = "CREATE TABLE jwt_keys"
+ " (" + "id varchar(20),"
+ "key varchar(20))";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO jwt_keys VALUES ('webgoat_key', 'qwertyqwerty1234')";
String insertData2 = "INSERT INTO jwt_keys VALUES ('webwolf_key', 'doesnotreallymatter')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
} catch (SQLException e) {
System.out.println("Error creating product table " + e.getLocalizedMessage());
}
}
/** /**
* Description of the Method * Description of the Method
@ -199,7 +232,7 @@ public class CreateDB {
// Create the new table // Create the new table
try { try {
String createTableStatement = "CREATE TABLE user_system_data (" + "userid varchar(5) not null primary key," String createTableStatement = "CREATE TABLE user_system_data (" + "userid int not null primary key,"
+ "user_name varchar(12)," + "password varchar(10)," + "cookie varchar(30)" + ")"; + "user_name varchar(12)," + "password varchar(10)," + "cookie varchar(30)" + ")";
statement.executeUpdate(createTableStatement); statement.executeUpdate(createTableStatement);
} catch (SQLException e) { } catch (SQLException e) {
@ -207,11 +240,11 @@ public class CreateDB {
} }
// Populate // Populate
String insertData1 = "INSERT INTO user_system_data VALUES ('101','jsnow','passwd1', '')"; String insertData1 = "INSERT INTO user_system_data VALUES (101,'jsnow','passwd1', '')";
String insertData2 = "INSERT INTO user_system_data VALUES ('102','jdoe','passwd2', '')"; String insertData2 = "INSERT INTO user_system_data VALUES (102,'jdoe','passwd2', '')";
String insertData3 = "INSERT INTO user_system_data VALUES ('103','jplane','passwd3', '')"; String insertData3 = "INSERT INTO user_system_data VALUES (103,'jplane','passwd3', '')";
String insertData4 = "INSERT INTO user_system_data VALUES ('104','jeff','jeff', '')"; String insertData4 = "INSERT INTO user_system_data VALUES (104,'jeff','jeff', '')";
String insertData5 = "INSERT INTO user_system_data VALUES ('105','dave','dave', '')"; String insertData5 = "INSERT INTO user_system_data VALUES (105,'dave','passW0rD', '')";
statement.executeUpdate(insertData1); statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2); statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3); statement.executeUpdate(insertData3);
@ -975,6 +1008,7 @@ public class CreateDB {
createTanTable(connection); createTanTable(connection);
createMFEImagesTable(connection); createMFEImagesTable(connection);
createModifyWithSQLLessonTable(connection); createModifyWithSQLLessonTable(connection);
createJWTKeys(connection);
System.out.println("Success: creating tables."); System.out.println("Success: creating tables.");
} }
} }

View File

@ -47,8 +47,11 @@ import java.util.stream.Collectors;
*/ */
@Entity @Entity
public class LessonTracker { public class LessonTracker {
@Getter
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Getter
private String lessonName; private String lessonName;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private final Set<Assignment> solvedAssignments = Sets.newHashSet(); private final Set<Assignment> solvedAssignments = Sets.newHashSet();

View File

@ -38,7 +38,7 @@ public class Scoreboard {
List<WebGoatUser> allUsers = userRepository.findAll(); List<WebGoatUser> allUsers = userRepository.findAll();
List<Ranking> rankings = Lists.newArrayList(); List<Ranking> rankings = Lists.newArrayList();
for (WebGoatUser user : allUsers) { for (WebGoatUser user : allUsers) {
UserTracker userTracker = userTrackerRepository.findOne(user.getUsername()); UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker))); rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
} }
return rankings; return rankings;

View File

@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
/** /**
@ -16,6 +17,7 @@ public class UserForm {
@NotNull @NotNull
@Size(min=6, max=20) @Size(min=6, max=20)
@Pattern(regexp = "[a-zA-Z0-9-]*", message = "can only contain letters, digits, and -")
private String username; private String username;
@NotNull @NotNull
@Size(min=6, max=10) @Size(min=6, max=10)

View File

@ -50,6 +50,9 @@ import java.util.stream.Collectors;
public class UserTracker { public class UserTracker {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "username")
private String user; private String user;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<LessonTracker> lessonTrackers = Sets.newHashSet(); private Set<LessonTracker> lessonTrackers = Sets.newHashSet();

View File

@ -8,5 +8,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
*/ */
public interface UserTrackerRepository extends JpaRepository<UserTracker, String> { public interface UserTrackerRepository extends JpaRepository<UserTracker, String> {
UserTracker findByUser(String user);
} }

View File

@ -3,13 +3,16 @@ server.error.path=/error.html
server.session.timeout=600 server.session.timeout=600
server.contextPath=/WebGoat server.contextPath=/WebGoat
server.port=8080 server.port=8080
server.address=127.0.0.1
spring.datasource.url=jdbc:hsqldb:file:${webgoat.server.directory}/data/webgoat spring.datasource.url=jdbc:hsqldb:hsql://localhost:9001/webgoat
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
logging.level.org.springframework=WARN logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=WARN logging.level.org.springframework.boot.devtools=INFO
logging.level.org.owasp=DEBUG logging.level.org.owasp=DEBUG
logging.level.org.owasp.webgoat=TRACE logging.level.org.owasp.webgoat=TRACE
@ -19,9 +22,10 @@ security.enable-csrf=false
spring.resources.cache-period=0 spring.resources.cache-period=0
spring.thymeleaf.cache=false spring.thymeleaf.cache=false
webgoat.start.hsqldb=true
webgoat.clean=false webgoat.clean=false
webgoat.server.directory=${user.home}/.webgoat/ webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
webgoat.user.directory=${user.home}/.webgoat/ webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
webgoat.build.version=@project.version@ webgoat.build.version=@project.version@
webgoat.build.number=@build.number@ webgoat.build.number=@build.number@
webgoat.email=webgoat@owasp.org webgoat.email=webgoat@owasp.org
@ -33,9 +37,9 @@ webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en webgoat.default.language=en
webwolf.host=${WEBWOLF_HOST:localhost} webwolf.host=${WEBWOLF_HOST:localhost}
webwolf.port=${WEBWOLF_PORT:8081} webwolf.port=${WEBWOLF_PORT:9090}
webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf
webworf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing
webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail
spring.jackson.serialization.indent_output=true spring.jackson.serialization.indent_output=true

View File

@ -1066,6 +1066,7 @@ span.show-next-page, span.show-prev-page {
/* ATTACK DISPLAY */ /* ATTACK DISPLAY */
.attack-container { .attack-container {
position: relative;
background-color: #f1f1f1; background-color: #f1f1f1;
border: 2px solid #a66; border: 2px solid #a66;
border-radius: 12px; border-radius: 12px;
@ -1151,3 +1152,15 @@ div.captured-flag {
width: 1268px; width: 1268px;
margin-bottom: 20px; margin-bottom: 20px;
} }
#content {
position:relative;
}
.webwolf-enabled {
position:absolute;
top: 10px;
right: 25px;
width: 42px;
height: 47px;
}

View File

@ -73,25 +73,27 @@ define(['jquery',
} }
this.loadLesson = function(name,pageNum) { this.loadLesson = function(name,pageNum) {
if (this.name === name) { if (this.name === name) {
this.listenToOnce(this.lessonHintView, 'hints:showButton', this.onShowHintsButton); this.listenToOnce(this.lessonHintView, 'hints:showButton', this.onShowHintsButton);
this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton); this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton);
this.lessonContentView.navToPage(pageNum); this.lessonContentView.navToPage(pageNum);
this.lessonHintView.hideHints(); this.lessonHintView.hideHints();
this.lessonHintView.showFirstHint();
//this.lessonHintView.selectHints(); //this.lessonHintView.selectHints();
this.titleView.render(this.lessonInfoModel.get('lessonTitle')); this.titleView.render(this.lessonInfoModel.get('lessonTitle'));
return; return;
} }
if (pageNum && !this.name) {
//placeholder
}
this.helpsLoaded = {}; this.helpsLoaded = {};
if (typeof(name) === 'undefined' || name === null) { if (typeof(name) === 'undefined' || name === null) {
//TODO: implement lesson not found or return to welcome page? //TODO: implement lesson not found or return to welcome page?
} }
this.lessonContent.loadData({'name':name}); this.lessonContent.loadData({'name':name});
// this.planView = {};
// this.solutionView = {};
// this.sourceView = {};
// this.lessonHintView = {};
this.name = name; this.name = name;
}; };
@ -124,15 +126,8 @@ define(['jquery',
this.helpControlsView = null; this.helpControlsView = null;
this.lessonContentView.model = this.lessonContent; this.lessonContentView.model = this.lessonContent;
this.lessonContentView.render(); this.lessonContentView.render();
//TODO: consider moving hintView as child of lessonContentView ...
//this.planView = new PlanView(); this.createLessonHintView();
//this.solutionView = new SolutionView();
//this.sourceView = new SourceView();
if (this.lessonHintView) {
this.lessonHintView.stopListening();
this.lessonHintView = null;
}
this.lessonHintView = new HintView();
//TODO: instantiate model with values (not sure why was not working before) //TODO: instantiate model with values (not sure why was not working before)
var paramModel = new ParamModel({}); var paramModel = new ParamModel({});
@ -148,42 +143,25 @@ define(['jquery',
this.lessonProgressModel.completed(); this.lessonProgressModel.completed();
}; };
this.createLessonHintView = function () {
if (this.lessonHintView) {
this.lessonHintView.stopListening();
this.lessonHintView = null;
}
this.lessonHintView = new HintView();
}
this.addCurHelpState = function (curHelp) { this.addCurHelpState = function (curHelp) {
this.helpsLoaded[curHelp.helpElement] = curHelp.value; this.helpsLoaded[curHelp.helpElement] = curHelp.value;
}; };
// this.hideShowHelps = function(showHelp) {
// var showId = '#lesson-' + showHelp + '-row';
// var contentId = '#lesson-' + showHelp + '-content';
// $('.lesson-help').not(showId).hide();
// if (!showId) {
// return;
// }
//
// if ($(showId).is(':visible')) {
// $(showId).hide();
// return;
// } else {
// //TODO: move individual .html operations into individual help views
// switch(showHelp) {
// case 'plan':
// $(contentId).html(this.planView.model.get('content'));
// break;
// case 'solution':
// $(showId).html(this.solutionView.model.get('content'));
// break;
// case 'source':
// $(contentId).html('<pre>' + this.sourceView.model.get('content') + '</pre>');
// break;
// }
// $(showId).show();
// GoatUtils.scrollToHelp()
// }
// };
this.showHintsView = function() { this.showHintsView = function() {
if (!this.lessonHintView) {
this.createLessonHintView();
}
//
this.lessonHintView.render(); this.lessonHintView.render();
if (this.lessonHintView.getHintsCount > 0) { if (this.lessonHintView.getHintsCount() > 0) {
this.helpControlsView.showHintsButton(); this.helpControlsView.showHintsButton();
} else { } else {
this.helpControlsView.hideHintsButton(); this.helpControlsView.hideHintsButton();

View File

@ -32,7 +32,11 @@ define(['jquery',
} }
this.set('content',content); this.set('content',content);
this.set('lessonUrl',document.URL.replace(/\.lesson.*/,'.lesson')); this.set('lessonUrl',document.URL.replace(/\.lesson.*/,'.lesson'));
this.set('pageNum',document.URL.replace(/.*\.lesson\/(\d{1,4})$/,'$1')); if (/.*\.lesson\/(\d{1,4})$/.test(document.URL)) {
this.set('pageNum',document.URL.replace(/.*\.lesson\/(\d{1,4})$/,'$1'));
} else {
this.set('pageNum',0);
}
this.trigger('content:loaded',this,loadHelps); this.trigger('content:loaded',this,loadHelps);
}, },

View File

@ -1,29 +1,33 @@
define(['jquery', define(['jquery',
'underscore', 'underscore',
'backbone', 'backbone',
'goatApp/model/MenuModel'], 'goatApp/model/MenuModel'],
function($,_,Backbone,MenuModel) { function ($, _, Backbone, MenuModel) {
return Backbone.Collection.extend({ return Backbone.Collection.extend({
model: MenuModel, model: MenuModel,
url:'service/lessonmenu.mvc', url: 'service/lessonmenu.mvc',
initialize: function () {
var self = this;
this.fetch();
},
onDataLoaded: function() { initialize: function () {
this.trigger('menuData:loaded'); var self = this;
}, this.fetch();
setInterval(function () {
this.fetch()
}.bind(this), 5000);
},
fetch: function() { onDataLoaded: function () {
var self=this; this.trigger('menuData:loaded');
Backbone.Collection.prototype.fetch.apply(this,arguments).then( },
function(data) {
this.models = data; fetch: function () {
self.onDataLoaded(); var self = this;
} Backbone.Collection.prototype.fetch.apply(this, arguments).then(
); function (data) {
} this.models = data;
}); self.onDataLoaded();
}); }
);
}
});
});

View File

@ -67,7 +67,7 @@ define(['jquery',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8', contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function (data) { success: function (data) {
//devs leave stuff like this in all the time //devs leave stuff like this in all the time
console.log('phone home said ' + data); console.log('phone home said ' + JSON.stringify(data));
} }
}); });
} }

View File

@ -32,21 +32,19 @@ function($,
toggleLabel: function() { toggleLabel: function() {
if (this.isVisible()) { if (this.isVisible()) {
$('show-hints-button').text('Hide hints'); $('#show-hints-button').text('Hide hints');
} else { } else {
$('show-hints-button').text('Show hints'); $('#show-hints-button').text('Show hints');
} }
}, },
render:function() { render:function() {
if (this.isVisible()) { if (this.isVisible()) {
this.$el.hide(350); this.$el.hide(350, this.toggleLabel.bind(this));
} else if (this.hintsToShow.length > 0) { } else if (this.hintsToShow.length > 0) {
this.$el.show(350); this.$el.show(350, this.toggleLabel.bind(this));
} }
this.toggleLabel()
if (this.hintsToShow.length > 0) { if (this.hintsToShow.length > 0) {
this.hideShowPrevNextButtons(); this.hideShowPrevNextButtons();
} }
@ -90,9 +88,9 @@ function($,
hideHints: function() { hideHints: function() {
if (this.$el.is(':visible')) { if (this.$el.is(':visible')) {
this.$el.hide(350); this.$el.hide(350, this.toggleLabel.bind(this));
} }
}, },
showNextHint: function() { showNextHint: function() {
this.curHint = (this.curHint < this.hintsToShow.length -1) ? this.curHint+1 : this.curHint; this.curHint = (this.curHint < this.hintsToShow.length -1) ? this.curHint+1 : this.curHint;
@ -106,6 +104,12 @@ function($,
this.displayHint(this.curHint); this.displayHint(this.curHint);
}, },
showFirstHint: function() {
this.curHint = 0;
this.hideShowPrevNextButtons();
this.displayHint(this.curHint);
},
displayHint: function(curHint) { displayHint: function(curHint) {
if(this.hintsToShow.length == 0) { if(this.hintsToShow.length == 0) {
// this.hideHints(); // this.hideHints();

View File

@ -25,6 +25,9 @@ define(['jquery',
self.navToPage(page); self.navToPage(page);
} }
}); });
setInterval(function () {
this.updatePagination();
}.bind(this), 5000);
}, },
findPage: function(assignment) { findPage: function(assignment) {
@ -56,11 +59,13 @@ define(['jquery',
var currentPage = (!isNaN(startPageNum) && startPageNum && startPageNum < this.$contentPages) ? startPageNum : 0; var currentPage = (!isNaN(startPageNum) && startPageNum && startPageNum < this.$contentPages) ? startPageNum : 0;
//init views & pagination //init views & pagination
this.showCurContentPage(currentPage); this.showCurContentPage(currentPage);
this.paginationControlView = new PaginationControlView(this.$contentPages,this.model.get('lessonUrl')); this.paginationControlView = new PaginationControlView(this.$contentPages,this.model.get('lessonUrl'),startPageNum);
}, },
updatePagination: function() { updatePagination: function() {
this.paginationControlView.updateCollection(); if ( this.paginationControlView != undefined ) {
this.paginationControlView.updateCollection();
}
}, },
getCurrentPage: function () { getCurrentPage: function () {
@ -85,6 +90,8 @@ define(['jquery',
var prepareDataFunctionName = $(curForm).attr('prepareData'); var prepareDataFunctionName = $(curForm).attr('prepareData');
var callbackFunctionName = $(curForm).attr('callback'); var callbackFunctionName = $(curForm).attr('callback');
var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize(); var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize();
var additionalHeadersFunctionName = $(curForm).attr('additionalHeaders');
var additionalHeaders = (typeof webgoat.customjs[additionalHeadersFunctionName] === 'function') ? webgoat.customjs[additionalHeadersFunctionName]() : function() {};
var successCallBackFunctionName = $(curForm).attr('successCallback'); var successCallBackFunctionName = $(curForm).attr('successCallback');
var failureCallbackFunctionName = $(curForm).attr('failureCallback'); var failureCallbackFunctionName = $(curForm).attr('failureCallback');
var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {}; var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {};
@ -99,6 +106,7 @@ define(['jquery',
$.ajax({ $.ajax({
//data:submitData, //data:submitData,
url:formUrl, url:formUrl,
headers: additionalHeaders,
method:formMethod, method:formMethod,
contentType:contentType, contentType:contentType,
data: submitData, data: submitData,
@ -146,14 +154,23 @@ define(['jquery',
return false; return false;
}, },
removeSlashesFromJSON: function(str) {
// slashes are leftover escapes from JSON serialization by server
// for every two char sequence starting with backslash,
// replace them in the text with second char only
return str.replace(/\\(.)/g, "$1");
},
renderFeedback: function(feedback) { renderFeedback: function(feedback) {
this.$curFeedback.html(polyglot.t(feedback) || ""); var s = this.removeSlashesFromJSON(feedback);
this.$curFeedback.html(polyglot.t(s) || "");
this.$curFeedback.show(400) this.$curFeedback.show(400)
}, },
renderOutput: function(output) { renderOutput: function(output) {
this.$curOutput.html(polyglot.t(output) || ""); var s = this.removeSlashesFromJSON(output);
this.$curOutput.html(polyglot.t(s) || "");
this.$curOutput.show(400) this.$curOutput.show(400)
}, },
@ -173,13 +190,19 @@ define(['jquery',
return endpoints; return endpoints;
}, },
onNavToPage: function(pageNum) {
var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
this.trigger('endpoints:filtered',assignmentPaths);
},
navToPage: function (pageNum) { navToPage: function (pageNum) {
this.paginationControlView.setCurrentPage(pageNum);//provides validation this.paginationControlView.setCurrentPage(pageNum);//provides validation
this.showCurContentPage(this.paginationControlView.currentPage); this.showCurContentPage(this.paginationControlView.currentPage);
this.paginationControlView.render(); this.paginationControlView.render();
this.paginationControlView.hideShowNavButtons(); this.paginationControlView.hideShowNavButtons();
var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum); this.onNavToPage(pageNum);
this.trigger('endpoints:filtered',assignmentPaths); //var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
//this.trigger('endpoints:filtered',assignmentPaths);
}, },
/* for testing */ /* for testing */

View File

@ -12,14 +12,14 @@ define(['jquery',
template: PaginationTemplate, template: PaginationTemplate,
el: '#lesson-page-controls', el: '#lesson-page-controls',
initialize: function ($contentPages,baseLessonUrl) { initialize: function ($contentPages,baseLessonUrl,initPageNum) {
this.$contentPages = $contentPages; this.$contentPages = $contentPages;
this.collection = new LessonOverviewCollection(); this.collection = new LessonOverviewCollection();
this.listenTo(this.collection, 'reset', this.render); this.listenTo(this.collection, 'reset', this.render);
this.numPages = this.$contentPages.length; this.numPages = this.$contentPages.length;
this.baseUrl = baseLessonUrl; this.baseUrl = baseLessonUrl;
this.collection.fetch({reset:true}); this.collection.fetch({reset:true});
this.initPagination(); this.initPagination(initPageNum);
//this.render(); //this.render();
}, },
@ -117,9 +117,9 @@ define(['jquery',
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide(); $('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
}, },
initPagination: function() { initPagination: function(initPageNum) {
//track pagination state in this view ... start at 0 //track pagination state in this view ... start at 0 .. unless a pageNum was provided
this.currentPage = 0; this.currentPage = !initPageNum ? 0 : initPageNum;
}, },
setCurrentPage: function (pageNum) { setCurrentPage: function (pageNum) {

View File

@ -30,7 +30,7 @@ require.config({
shim: { shim: {
"jqueryui": { "jqueryui": {
exports:"$", exports:"$",
deps: ['jquery'] deps: ['libs/jquery-2.1.4.min']
}, },
underscore: { underscore: {
exports: "_" exports: "_"

View File

@ -123,8 +123,9 @@
<section class="main-content-wrapper"> <section class="main-content-wrapper">
<section id="main-content"> <!--ng-controller="goatLesson"--> <section id="main-content"> <!--ng-controller="goatLesson"-->
<div id="lesson-page" class="pages"> <div id="lesson-page" class="pages">
<span th:text="${numUsers}"> Users in WebGoat</span> <span th:text="${numUsers}"></span>
<!-- iterate over users below -->su <span> Users in WebGoat</span>
<div sec:authorize="hasAuthority('WEBGOAT_ADMIN')"> <div sec:authorize="hasAuthority('WEBGOAT_ADMIN')">
<h3>WebGoat Users</h3> <h3>WebGoat Users</h3>
<div th:each="user : ${allUsers}"> <div th:each="user : ${allUsers}">

View File

@ -76,24 +76,25 @@
</a> </a>
</li> </li>
<li role="presentation" class="divider"></li> <li role="presentation" class="divider"></li>
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#" <li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">
th:text="#{version}">Version: <span <span th:text="#{version}">Version:</span><span>: </span>
th:text="${@environment.getProperty('webgoat.build.version')}"></span></a> <span th:text="${@environment.getProperty('webgoat.build.version')}"></span></a>
</li> </li>
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#" <li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">
th:text="#{build}">Build: <span th:text="#{build}">Build:</span><span>: </span>
<span th:text="${@environment.getProperty('webgoat.build.number')}"></span></a></li> <span th:text="${@environment.getProperty('webgoat.build.number')}"></span></a></li>
</ul> </ul>
</div> </div>
<div style="display:inline" id="settings"> <div style="display:inline" id="settings">
<!--<button type="button" id="admin-button" class="btn btn-default right_nav_button" title="Administrator">--> <!--<button type="button" id="admin-button" class="btn btn-default right_nav_button" title="Administrator">-->
<!--<i class="fa fa-cog"></i>--> <!--<i class="fa fa-cog"></i>-->
<!--</button>--> <!--</button>-->
<button type="button" id="report-card-button" class="btn btn-default right_nav_button button-up" <a href="#reportCard">
th:title="#{report.card}"> <button type="button" id="report-card-button" class="btn btn-default right_nav_button button-up"
<a href="#reportCard"><i class="fa fa-bar-chart-o"></i></a> th:title="#{report.card}">
</button> <i class="fa fa-bar-chart-o"></i>
</button>
</a>
<!--<button type="button" id="user-management" class="btn btn-default right_nav_button"--> <!--<button type="button" id="user-management" class="btn btn-default right_nav_button"-->
<!--title="User management">--> <!--title="User management">-->
<!--<i class="fa fa-users"></i>--> <!--<i class="fa fa-users"></i>-->

View File

@ -62,7 +62,7 @@ public class AssignmentEndpointTest {
public void init(AssignmentEndpoint a) { public void init(AssignmentEndpoint a) {
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels"); messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository); ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository);
ReflectionTestUtils.setField(a, "userSessionData", userSessionData); ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
ReflectionTestUtils.setField(a, "webSession", webSession); ReflectionTestUtils.setField(a, "webSession", webSession);

View File

@ -63,7 +63,7 @@ public class LessonMenuServiceTest {
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2)); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC)) mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -81,7 +81,7 @@ public class LessonMenuServiceTest {
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1)); when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL)); when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC)) mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))

View File

@ -72,7 +72,7 @@ public class LessonProgressServiceTest {
@Before @Before
public void setup() { public void setup() {
Assignment assignment = new Assignment("test", "test"); Assignment assignment = new Assignment("test", "test");
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
when(websession.getCurrentLesson()).thenReturn(lesson); when(websession.getCurrentLesson()).thenReturn(lesson);
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true)); when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));

View File

@ -6,6 +6,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
@ -40,10 +41,13 @@ public class ReportCardServiceTest {
private UserTrackerRepository userTrackerRepository; private UserTrackerRepository userTrackerRepository;
@Mock @Mock
private WebSession websession; private WebSession websession;
@Mock
private PluginMessages pluginMessages;
@Before @Before
public void setup() { public void setup() {
this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course)).build(); this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course, pluginMessages)).build();
when(pluginMessages.getMessage(anyString())).thenReturn("Test");
} }
@Test @Test
@ -53,7 +57,7 @@ public class ReportCardServiceTest {
when(course.getTotalOfLessons()).thenReturn(1); when(course.getTotalOfLessons()).thenReturn(1);
when(course.getTotalOfAssignments()).thenReturn(10); when(course.getTotalOfAssignments()).thenReturn(10);
when(course.getLessons()).thenReturn(Lists.newArrayList(lesson)); when(course.getLessons()).thenReturn(Lists.newArrayList(lesson));
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc")) mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
.andExpect(status().isOk()) .andExpect(status().isOk())

View File

@ -62,7 +62,7 @@ public class UserTrackerRepositoryTest {
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);
userTracker = userTrackerRepository.findOne("test"); userTracker = userTrackerRepository.findByUser("test");
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull(); Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull();
} }
@ -77,7 +77,7 @@ public class UserTrackerRepositoryTest {
userTrackerRepository.saveAndFlush(userTracker); userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findOne("test"); userTracker = userTrackerRepository.findByUser("test");
Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1); Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1);
} }
@ -90,7 +90,7 @@ public class UserTrackerRepositoryTest {
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker); userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findOne("test"); userTracker = userTrackerRepository.findByUser("test");
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson); userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker); userTrackerRepository.saveAndFlush(userTracker);

View File

@ -1 +1,15 @@
<configuration /> <configuration />
<!--
Enable below if you want to debug a unit test and see why the controller fails the configuration above is there
to keep the Travis build going otherwise it fails with too much logging.
//TODO we should use a different Spring profile for Travis
-->
<!--
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
-->

View File

@ -3,7 +3,7 @@
Vagrant.configure(2) do |config| Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64" config.vm.box = "ubuntu/trusty64"
config.vm.network :forwarded_port, guest: 8080, host: 8080 config.vm.network :forwarded_port, guest: 8080, host: 8080
config.vm.network :forwarded_port, guest: 8081, host: 8081 config.vm.network :forwarded_port, guest: 9090, host: 9090
config.vm.provider "virtualbox" do |vb| config.vm.provider "virtualbox" do |vb|
vb.gui = false vb.gui = false
vb.memory = "4096" vb.memory = "4096"
@ -19,17 +19,17 @@ Vagrant.configure(2) do |config|
end end
config.vm.provision "shell", inline: <<-SHELL config.vm.provision "shell", inline: <<-SHELL
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.RELEASE/webgoat-server-8.0.0.RELEASE.jar wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M21/webgoat-server-8.0.0.M21.jar
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.RELEASE/webwolf-8.0.0.RELEASE.jar wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M21/webwolf-8.0.0.M21.jar
sudo add-apt-repository ppa:openjdk-r/ppa sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update sudo apt-get update
sudo apt-get install openjdk-8-jre -y sudo apt-get install openjdk-8-jre -y
SHELL SHELL
config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL
java -jar webgoat-server-8.0.0.RELEASE.jar & java -jar webgoat-server-8.0.0.M21.jar --server.address=0.0.0.0 &
sleep 40s sleep 40s
java -jar webwolf-8.0.0.RELEASE.jar java -jar webwolf-8.0.0.M21.jar --server.address=0.0.0.0 &
SHELL SHELL
end end

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.owasp.webgoat.lesson</groupId> <groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId> <artifactId>webgoat-lessons-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
</parent> </parent>
</project> </project>

View File

@ -58,7 +58,7 @@ public class AccountVerificationHelper {
return false; return false;
} }
if (submittedQuestions.containsKey("secQuestion1") && !submittedQuestions.get("seQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) { if (submittedQuestions.containsKey("secQuestion1") && !submittedQuestions.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) {
return false; return false;
} }

View File

@ -1,4 +1,4 @@
== Authentication Bpasses == Authentication Bypasses
Authentication Bypasses happen in many ways, but usually take advantage of some flaw in the configuration or logic. Tampering to achieve the right conditions. Authentication Bypasses happen in many ways, but usually take advantage of some flaw in the configuration or logic. Tampering to achieve the right conditions.
@ -12,4 +12,4 @@ Sometimes, if an attacker doesn't know the correct value of a parameter, they ma
=== Forced Browsing === Forced Browsing
If an area of a site is not protected properly by configuation, that area of the site may be accessed by guessing/brute-forcing. If an area of a site is not protected properly by configuration, that area of the site may be accessed by guessing/brute-forcing.

View File

@ -6,6 +6,6 @@
<parent> <parent>
<groupId>org.owasp.webgoat.lesson</groupId> <groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId> <artifactId>webgoat-lessons-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
</parent> </parent>
</project> </project>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.owasp.webgoat.lesson</groupId> <groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId> <artifactId>webgoat-lessons-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
</parent> </parent>

View File

@ -46,7 +46,6 @@ public class Flag extends Endpoint {
@PostConstruct @PostConstruct
public void initFlags() { public void initFlags() {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString())); IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
FLAGS.entrySet().stream().forEach(e -> log.debug("Flag {} {}", e.getKey(), e.getValue()));
} }
@Override @Override

View File

@ -10,11 +10,6 @@ public interface SolutionConstants {
//TODO should be random generated when starting the server //TODO should be random generated when starting the server
String PASSWORD = "!!webgoat_admin_1234!!"; String PASSWORD = "!!webgoat_admin_1234!!";
String SUPER_COUPON_CODE = "get_it_for_free";
String PASSWORD_TOM = "thisisasecretfortomonly"; String PASSWORD_TOM = "thisisasecretfortomonly";
String PASSWORD_LARRY = "larryknows";
String JWT_PASSWORD = "victory";
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2"; String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
String TOM_EMAIL = "tom@webgoat-cloud.org";
} }

View File

@ -1,39 +0,0 @@
package org.owasp.webgoat.plugin.challenge2;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.NewLesson;
import java.util.List;
/**
* @author nbaars
* @since 3/21/17.
*/
public class Challenge2 extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public List<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 10;
}
@Override
public String getTitle() {
return "challenge2.title";
}
@Override
public String getId() {
return "Challenge2";
}
}

View File

@ -1,150 +0,0 @@
package org.owasp.webgoat.plugin.challenge3;
import com.beust.jcommander.internal.Lists;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.plugin.Flag;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.PostConstruct;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Map;
import static org.springframework.http.MediaType.ALL_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
/**
* @author nbaars
* @since 4/8/17.
*/
@AssignmentPath("/challenge/3")
@Slf4j
public class Assignment3 extends AssignmentEndpoint {
@Value("${webgoat.server.directory}")
private String webGoatHomeDirectory;
@Autowired
private WebSession webSession;
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
private static final String secretContents = "Congratulations you may now collect your flag";
static {
comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "Silly cat...."));
comments.add(new Comment("guest", DateTime.now().toString(fmt), "I think I will use this picture in one of my projects."));
comments.add(new Comment("guest", DateTime.now().toString(fmt), "Lol!! :-)."));
}
@PostConstruct
@SneakyThrows
public void copyFile() {
File targetDirectory = new File(webGoatHomeDirectory);
if (!targetDirectory.exists()) {
targetDirectory.mkdir();
}
log.info("Copied secret.txt to: {}", targetDirectory);
Files.write(secretContents, new File(targetDirectory, "secret.txt"), Charset.defaultCharset());
}
@RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Collection<Comment> retrieveComments() {
Collection<Comment> allComments = Lists.newArrayList();
Collection<Comment> xmlComments = userComments.get(webSession.getUserName());
if (xmlComments != null) {
allComments.addAll(xmlComments);
}
allComments.addAll(comments);
return allComments;
}
@RequestMapping(method = POST, consumes = ALL_VALUE, produces = APPLICATION_JSON_VALUE)
@ResponseBody
public AttackResult createNewComment(@RequestBody String commentStr, @RequestHeader("Content-Type") String contentType) throws Exception {
Comment comment = null;
AttackResult attackResult = failed().build();
if (APPLICATION_JSON_VALUE.equals(contentType)) {
comment = parseJson(commentStr);
comment.setDateTime(DateTime.now().toString(fmt));
comment.setUser(webSession.getUserName());
comments.add(comment);
}
if (MediaType.APPLICATION_XML_VALUE.equals(contentType)) {
//Do not show these comments to all users
comment = parseXml(commentStr);
comment.setDateTime(DateTime.now().toString(fmt));
comment.setUser(webSession.getUserName());
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
comments.add(comment);
userComments.put(webSession.getUserName(), comments);
}
if (checkSolution(comment)) {
attackResult = success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(3)).build();
}
return attackResult;
}
private boolean checkSolution(Comment comment) {
if (comment.getText().contains(secretContents)) {
comment.setText("Congratulations to " + webSession.getUserName() + " for finding the flag!! Check your original response where you posted the XXE attack ");
comments.add(comment);
return true;
}
return false;
}
public static Comment parseXml(String xml) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Comment.class);
XMLInputFactory xif = XMLInputFactory.newFactory();
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
xif.setProperty(XMLInputFactory.IS_VALIDATING, false);
xif.setProperty(XMLInputFactory.SUPPORT_DTD, true);
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml));
Unmarshaller unmarshaller = jc.createUnmarshaller();
return (Comment) unmarshaller.unmarshal(xsr);
}
private Comment parseJson(String comment) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(comment, Comment.class);
} catch (IOException e) {
return new Comment();
}
}
}

View File

@ -1,39 +0,0 @@
package org.owasp.webgoat.plugin.challenge3;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.NewLesson;
import java.util.List;
/**
* @author nbaars
* @since 3/21/17.
*/
public class Challenge3 extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public List<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 10;
}
@Override
public String getTitle() {
return "challenge3.title";
}
@Override
public String getId() {
return "Challenge3";
}
}

View File

@ -1,24 +0,0 @@
package org.owasp.webgoat.plugin.challenge3;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author nbaars
* @since 4/8/17.
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement
public class Comment {
private String user;
private String dateTime;
private String text;
}

View File

@ -1,17 +0,0 @@
package org.owasp.webgoat.plugin.challenge4;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
/**
* @author nbaars
* @since 5/3/17.
*/
@AssignmentPath("/challenge/4")
@Slf4j
public class Assignment4 extends AssignmentEndpoint {
//just empty, posting the flag will mark the challenge as done as well no need to specify an endpoint here
}

View File

@ -1,39 +0,0 @@
package org.owasp.webgoat.plugin.challenge4;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.NewLesson;
import java.util.List;
/**
* @author nbaars
* @since 3/21/17.
*/
public class Challenge4 extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public List<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 10;
}
@Override
public String getTitle() {
return "challenge4.title";
}
@Override
public String getId() {
return "Challenge4";
}
}

View File

@ -1,16 +0,0 @@
package org.owasp.webgoat.plugin.challenge4;
/**
* @author nbaars
* @since 4/30/17.
*/
public class Views {
interface GuestView {
}
interface UserView extends GuestView {
}
interface AdminView extends UserView {
}
}

View File

@ -1,75 +0,0 @@
/* Component: Posts */
.post .post-heading {
height: 95px;
padding: 20px 15px;
}
.post .post-heading .avatar {
width: 60px;
height: 60px;
display: block;
margin-right: 15px;
}
.post .post-heading .meta .title {
margin-bottom: 0;
}
.post .post-heading .meta .title a {
color: black;
}
.post .post-heading .meta .title a:hover {
color: #aaaaaa;
}
.post .post-heading .meta .time {
margin-top: 8px;
color: #999;
}
.post .post-image .image {
width:20%;
height: 40%;
}
.post .post-description {
padding: 5px;
}
.post .post-footer {
border-top: 1px solid #ddd;
padding: 15px;
}
.post .post-footer .input-group-addon a {
color: #454545;
}
.post .post-footer .comments-list {
padding: 0;
margin-top: 20px;
list-style-type: none;
}
.post .post-footer .comments-list .comment {
display: block;
width: 100%;
margin: 20px 0;
}
.post .post-footer .comments-list .comment .avatar {
width: 35px;
height: 35px;
}
.post .post-footer .comments-list .comment .comment-heading {
display: block;
width: 100%;
}
.post .post-footer .comments-list .comment .comment-heading .user {
font-size: 14px;
font-weight: bold;
display: inline;
margin-top: 0;
margin-right: 10px;
}
.post .post-footer .comments-list .comment .comment-heading .time {
font-size: 12px;
color: #aaa;
margin-top: 0;
display: inline;
}
.post .post-footer .comments-list .comment .comment-body {
margin-left: 50px;
}
.post .post-footer .comments-list .comment > .comments-list {
margin-left: 50px;
}

View File

@ -1,12 +0,0 @@
a.list-group-item {
height:auto;
}
a.list-group-item.active small {
color:#fff;
}
.stars {
margin:20px auto 1px;
}
.img-responsive {
min-width: 100%;
}

View File

@ -1,112 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_2.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge2.css}"/>
<script th:src="@{/lesson_js/challenge2.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/2"
enctype="application/json;charset=UTF-8">
<input id="discount" type="hidden" value="0"/>
<div class="row">
<div class="col-xs-3 item-photo">
<img style="max-width:100%;" th:src="@{/images/samsung-black.jpg}"/>
</div>
<div class="col-xs-5" style="border:0px solid gray">
<h3>Samsung Galaxy S8</h3>
<h5 style="color:#337ab7"><a href="http://www.samsung.com">Samsung</a> ·
<small style="color:#337ab7">(124421 reviews)</small>
</h5>
<h6 class="title-price">
<small>PRICE</small>
</h6>
<h3 style="margin-top:0px;"><span>US $</span><span id="price">899</span></h3>
<div class="section">
<h6 class="title-attr" style="margin-top:15px;">
<small>COLOR</small>
</h6>
<div>
<div class="attr" style="width:25px;background:lightgrey;"></div>
<div class="attr" style="width:25px;background:black;"></div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>CAPACITY</small>
</h6>
<div>
<div class="attr2">64 GB</div>
<div class="attr2">128 GB</div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>QUANTITY</small>
</h6>
<div>
<div class="btn-minus"><span class="glyphicon glyphicon-minus"></span></div>
<input class="quantity" value="1"/>
<div class="btn-plus"><span class="glyphicon glyphicon-plus"></span></div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>CHECKOUT CODE</small>
</h6>
<!--
Checkout code: webgoat, owasp, owasp-webgoat
-->
<input name="checkoutCode" class="checkoutCode" value=""/>
</div>
<div class="section" style="padding-bottom:20px;">
<button type="submit" class="btn btn-success"><span style="margin-right:20px"
class="glyphicon glyphicon-shopping-cart"
aria-hidden="true"></span>Buy
</button>
<h6><a href="#"><span class="glyphicon glyphicon-heart-empty"
style="cursor:pointer;"></span>
Like</a></h6>
</div>
</div>
</div>
</form>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_3.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge3.css}"/>
<script th:src="@{/lesson_js/challenge3.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="panel post">
<div class="post-heading">
<div class="pull-left image">
<img th:src="@{/images/avatar1.png}"
class="img-circle avatar" alt="user profile image"/>
</div>
<div class="pull-left meta">
<div class="title h5">
<a href="#"><b>John Doe</b></a>
uploaded a photo.
</div>
<h6 class="text-muted time">24 days ago</h6>
</div>
</div>
<div class="post-image">
<img th:src="@{images/cat.jpg}" class="image" alt="image post"/>
</div>
<div class="post-description">
</div>
<div class="post-footer">
<div class="input-group">
<input class="form-control" id="commentInput" placeholder="Add a comment" type="text"/>
<span class="input-group-addon">
<i id="postComment" class="fa fa-edit" style="font-size: 20px"></i>
</span>
</div>
<ul class="comments-list">
<div id="list">
</div>
</ul>
</div>
</div>
</div>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

@ -1,75 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_4.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge4.css}"/>
<script th:src="@{/lesson_js/bootstrap.min.js}" language="JavaScript"></script>
<script th:src="@{/lesson_js/challenge4.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="well">
<div class="pull-right">
<div class="dropdown">
<button type="button" data-toggle="dropdown" class="btn btn-default dropdown-toggle">
<i class="fa fa-user"></i> <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-left">
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Guest')"
th:text="Guest">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Tom')"
th:text="Tom">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Jerry')"
th:text="Jerry">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Sylvester')"
th:text="Sylvester">current</a></li>
</ul>
</div>
<div>
<p class="text-right">Welcome back, <b><span id="name"></span></b></p>
</div>
</div>
<div>
<h3>Vote for your favorite</h3>
</div>
<div id ="votesList" class="list-group">
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

@ -1,109 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_9.adoc"></div>
<script th:src="@{/lesson_js/challenge9.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<h4 style="border-bottom: 1px solid #c5c5c5;">
<i class="glyphicon glyphicon-user"></i>
Account Access
</h4>
<div style="padding: 20px;" id="form-login">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/9/login"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<div class="form-group input-group">
<span class="input-group-addon"> @ </span>
<input class="form-control" placeholder="Email" name="email" type="email"
required="" autofocus=""/>
</div>
<div class="form-group input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-lock">
</i>
</span>
<input class="form-control" placeholder="Password" name="password" type="password"
value="" required=""/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">
Access
</button>
<p class="help-block">
<a class="pull-right text-muted" href="#" id="login">
<small>Forgot your password?</small>
</a>
</p>
</div>
</fieldset>
</form>
</div>
<div style="display: none;" id="form-login">
<h4 class="">
Forgot your password?
</h4>
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/9/create-password-reset-link"
enctype="application/json;charset=UTF-8" role="form">
<fieldset>
<span class="help-block">
Email address you use to log in to your account
<br/>
We'll send you an email with instructions to choose a new password.
</span>
<div class="form-group input-group">
<span class="input-group-addon">
@
</span>
<input class="form-control" placeholder="Email" name="email" type="email"
required=""/>
</div>
<button type="submit" class="btn btn-primary btn-block" id="btn-login">
Continue
</button>
<p class="help-block">
<a class="text-muted" href="#" id="forgot">
<small>Account Access</small>
</a>
</p>
</fieldset>
</form>
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

@ -2,7 +2,6 @@ challenge0.title=WebGoat Challenge
challenge1.title=Admin lost password challenge1.title=Admin lost password
challenge2.title=Get it for free challenge2.title=Get it for free
challenge3.title=Photo comments challenge3.title=Photo comments
challenge4.title=Voting
challenge5.title=Without password challenge5.title=Without password
challenge6.title=Creating a new account challenge6.title=Creating a new account
challenge7.title=Admin password reset challenge7.title=Admin password reset
@ -22,8 +21,7 @@ challenge.flag.incorrect=Sorry this is not the correct flag, please try again.
ip.address.unknown=IP address unknown, e-mail has been sent. ip.address.unknown=IP address unknown, e-mail has been sent.
login_failed=Login failed
login_failed.tom=Sorry only Tom can login at the moment
required4=Missing username or password, please specify both. required4=Missing username or password, please specify both.
user.not.larry=Please try to log in as Larry not {0}. user.not.larry=Please try to log in as Larry not {0}.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -1,45 +0,0 @@
$(document).ready(function () {
$("#postComment").on("click", function () {
var commentInput = $("#commentInput").val();
$.ajax({
type: 'POST',
url: 'challenge/3',
data: JSON.stringify({text: commentInput}),
contentType: "application/json",
dataType: 'json'
}).then(
function () {
getChallenges();
$("#commentInput").val('');
}
)
})
var html = '<li class="comment">' +
'<div class="pull-left">' +
'<img class="avatar" src="images/avatar1.png" alt="avatar"/>' +
'</div>' +
'<div class="comment-body">' +
'<div class="comment-heading">' +
'<h4 class="user">USER</h4>' +
'<h5 class="time">DATETIME</h5>' +
'</div>' +
'<p>COMMENT</p>' +
'</div>' +
'</li>';
getChallenges();
function getChallenges() {
$("#list").empty();
$.get("challenge/3", function (result, status) {
for (var i = 0; i < result.length; i++) {
var comment = html.replace('USER', result[i].user);
comment = comment.replace('DATETIME', result[i].dateTime);
comment = comment.replace('COMMENT', result[i].text);
$("#list").append(comment);
}
});
}
})

View File

@ -1,10 +0,0 @@
$(document).ready(function() {
$('#login').click(function(e) {
e.preventDefault();
$('div#form-login').toggle('500');
});
$('#forgot').click(function(e) {
e.preventDefault();
$('div#form-login').toggle('500');
});
});

View File

@ -1 +0,0 @@
Changing language can help you find the 'secret' file

View File

@ -1 +0,0 @@
Try to change to a different user, maybe you can find the flag?

View File

@ -1,3 +0,0 @@
Tom always resets his password immediately after receiving the email with the link.
Try to reset the password of Tom (tom@webgoat-cloud.org) to your own choice and login as Tom with
that password.

View File

@ -1,49 +0,0 @@
package org.owasp.webgoat.plugin.challenge2;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.plugin.Flag;
import org.owasp.webgoat.plugin.SolutionConstants;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
* @author nbaars
* @since 5/2/17.
*/
@RunWith(MockitoJUnitRunner.class)
public class Assignment2Test extends AssignmentEndpointTest {
private MockMvc mockMvc;
@Before
public void setup() {
Assignment2 assignment2 = new Assignment2();
init(assignment2);
new Flag().initFlags();
this.mockMvc = standaloneSetup(assignment2).build();
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/2")
.param("checkoutCode", SolutionConstants.SUPER_COUPON_CODE))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("flag: " + Flag.FLAGS.get(2))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void wrongCouponCode() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/2")
.param("checkoutCode", "test"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -1,161 +0,0 @@
package org.owasp.webgoat.plugin.challenge4;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.plugin.Flag;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import javax.servlet.http.Cookie;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
* @author nbaars
* @since 5/2/17.
*/
@RunWith(MockitoJUnitRunner.class)
public class VotesEndpointTest {
private MockMvc mockMvc;
@Before
public void setup() {
VotesEndpoint votesEndpoint = new VotesEndpoint();
votesEndpoint.initVotes();
new Flag().initFlags();
this.mockMvc = standaloneSetup(votesEndpoint).build();
}
@Test
public void loginWithUnknownUser() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "uknown"))
.andExpect(unauthenticated());
}
@Test
public void loginWithTomShouldGiveJwtToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Tom"))
.andExpect(status().isOk()).andExpect(cookie().exists("access_token"));
}
@Test
public void loginWithGuestShouldNotGiveJwtToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Guest"))
.andExpect(unauthenticated()).andExpect(cookie().value("access_token", ""));
}
@Test
public void userShouldSeeMore() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Tom"))
.andExpect(status().isOk()).andExpect(cookie().exists("access_token")).andReturn();
mockMvc.perform(MockMvcRequestBuilders.get("/votings")
.cookie(mvcResult.getResponse().getCookie("access_token")))
.andExpect(jsonPath("$.[*].numberOfVotes").exists());
}
@Test
public void guestShouldNotSeeNumberOfVotes() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Guest"))
.andExpect(unauthenticated()).andExpect(cookie().exists("access_token")).andReturn();
mockMvc.perform(MockMvcRequestBuilders.get("/votings")
.cookie(mvcResult.getResponse().getCookie("access_token")))
.andExpect(jsonPath("$.[*].numberOfVotes").doesNotExist());
}
@Test
public void adminShouldSeeFlags() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings")
.cookie(new Cookie("access_token", "eyJhbGciOiJub25lIn0.eyJhZG1pbiI6InRydWUiLCJ1c2VyIjoiSmVycnkifQ.")))
.andExpect(jsonPath("$.[*].flag").isNotEmpty());
}
@Test
public void votingIsNotAllowedAsGuest() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/votings/Get it for free"))
.andExpect(unauthenticated());
}
@Test
public void normalUserShouldBeAbleToVote() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Tom"))
.andExpect(status().isOk()).andExpect(cookie().exists("access_token")).andReturn();
mockMvc.perform(MockMvcRequestBuilders.post("/votings/Get it for free")
.cookie(mvcResult.getResponse().getCookie("access_token")));
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(mvcResult.getResponse().getCookie("access_token")))
.andExpect(jsonPath("$..[?(@.title == 'Get it for free')].numberOfVotes", CoreMatchers.hasItem(20001)));
}
@Test
public void votingForUnknownLessonShouldNotCrash() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/votings/login")
.param("user", "Tom"))
.andExpect(status().isOk()).andExpect(cookie().exists("access_token")).andReturn();
mockMvc.perform(MockMvcRequestBuilders.post("/votings/UKNOWN_VOTE")
.cookie(mvcResult.getResponse().getCookie("access_token"))).andExpect(status().isAccepted());
}
@Test
public void votingWithInvalidToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/votings/UKNOWN_VOTE")
.cookie(new Cookie("access_token", "abc"))).andExpect(unauthenticated());
}
@Test
public void gettingVotesWithInvalidToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(new Cookie("access_token", "abc"))).andExpect(unauthenticated());
}
@Test
public void gettingVotesWithUnknownUserInToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(new Cookie("access_token", "eyJhbGciOiJub25lIn0.eyJhZG1pbiI6InRydWUiLCJ1c2VyIjoiVW5rbm93biJ9.")))
.andExpect(unauthenticated())
.andExpect(jsonPath("$.[*].numberOfVotes").doesNotExist());
}
@Test
public void gettingVotesForUnknownShouldWork() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(new Cookie("access_token", "eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiVW5rbm93biJ9.")))
.andExpect(unauthenticated())
.andExpect(jsonPath("$.[*].numberOfVotes").doesNotExist());
}
@Test
public void gettingVotesForKnownWithoutAdminFieldShouldWork() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(new Cookie("access_token", "eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiVG9tIn0.")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.[*].numberOfVotes").exists());
}
@Test
public void gettingVotesWithEmptyToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/votings/")
.cookie(new Cookie("access_token", "")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.[*].numberOfVotes").doesNotExist());
}
@Test
public void votingAsUnknownUserShouldNotBeAllowed() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/votings/Get it for free")
.cookie(new Cookie("access_token", "eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiVW5rbm93biJ9.")))
.andExpect(unauthenticated());
}
}

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.owasp.webgoat.lesson</groupId> <groupId>org.owasp.webgoat.lesson</groupId>
<artifactId>webgoat-lessons-parent</artifactId> <artifactId>webgoat-lessons-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M23</version>
</parent> </parent>
</project> </project>

View File

@ -56,7 +56,7 @@ public class ClientSideFiltering extends NewLesson {
@Override @Override
public String getTitle() { public String getTitle() {
return "Client side filtering"; return "client.side.filtering.title";
} }
@Override @Override

View File

@ -1,9 +1,9 @@
package org.owasp.webgoat.plugin.challenge2; package org.owasp.webgoat.plugin;
import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.plugin.Flag;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -11,22 +11,23 @@ import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException; import java.io.IOException;
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE;
/** /**
* @author nbaars * @author nbaars
* @since 4/6/17. * @since 4/6/17.
*/ */
@AssignmentPath("/challenge/2") @AssignmentPath("/clientSideFiltering/getItForFree")
public class Assignment2 extends AssignmentEndpoint { @AssignmentHints({"client.side.filtering.free.hint1", "client.side.filtering.free.hint2", "client.side.filtering.free.hint3"})
public class ClientSideFilteringFreeAssignment extends AssignmentEndpoint {
public static final String SUPER_COUPON_CODE = "get_it_for_free";
@RequestMapping(method = RequestMethod.POST) @RequestMapping(method = RequestMethod.POST)
public public
@ResponseBody @ResponseBody
AttackResult completed(@RequestParam String checkoutCode) throws IOException { AttackResult completed(@RequestParam String checkoutCode) {
if (SUPER_COUPON_CODE.equals(checkoutCode)) { if (SUPER_COUPON_CODE.equals(checkoutCode)) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(2)).build(); return trackProgress(success().build());
} }
return failed().build(); return trackProgress(failed().build());
} }
} }

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge2; package org.owasp.webgoat.plugin;
import com.beust.jcommander.internal.Lists; import com.beust.jcommander.internal.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -12,21 +12,21 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE; import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
/** /**
* @author nbaars * @author nbaars
* @since 4/6/17. * @since 4/6/17.
*/ */
@RestController @RestController
@RequestMapping("challenge-store") @RequestMapping("/clientSideFiltering/challenge-store")
public class ShopEndpoint { public class ShopEndpoint {
@AllArgsConstructor @AllArgsConstructor
private class CheckoutCodes { private class CheckoutCodes {
@Getter @Getter
private List<CheckoutCode> codes = Lists.newArrayList(); private List<CheckoutCode> codes;
public Optional<CheckoutCode> get(String code) { public Optional<CheckoutCode> get(String code) {
return codes.stream().filter(c -> c.getCode().equals(code)).findFirst(); return codes.stream().filter(c -> c.getCode().equals(code)).findFirst();

View File

@ -73,7 +73,96 @@
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons --> <!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
</div> </div>
</div> </div>
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:ClientSideFiltering_final.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/clientSideFilteringFree.css}"/>
<script th:src="@{/lesson_js/clientSideFilteringFree.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<form class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/clientSideFiltering/getItForFree"
enctype="application/json;charset=UTF-8">
<input id="discount" type="hidden" value="0"/>
<div class="row">
<div class="col-xs-3 item-photo">
<img style="max-width:100%;" th:src="@{/images/samsung-black.jpg}"/>
</div>
<div class="col-xs-5" style="border:0px solid gray">
<h3>Samsung Galaxy S8</h3>
<h5 style="color:#337ab7"><a href="http://www.samsung.com">Samsung</a> ·
<small style="color:#337ab7">(124421 reviews)</small>
</h5>
<h6 class="title-price">
<small>PRICE</small>
</h6>
<h3 style="margin-top:0px;"><span>US $</span><span id="price">899</span></h3>
<div class="section">
<h6 class="title-attr" style="margin-top:15px;">
<small>COLOR</small>
</h6>
<div>
<div class="attr" style="width:25px;background:lightgrey;"></div>
<div class="attr" style="width:25px;background:black;"></div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>CAPACITY</small>
</h6>
<div>
<div class="attr2">64 GB</div>
<div class="attr2">128 GB</div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>QUANTITY</small>
</h6>
<div>
<div class="btn-minus"><span class="glyphicon glyphicon-minus"></span></div>
<input class="quantity" value="1"/>
<div class="btn-plus"><span class="glyphicon glyphicon-plus"></span></div>
</div>
</div>
<div class="section" style="padding-bottom:5px;">
<h6 class="title-attr">
<small>CHECKOUT CODE</small>
</h6>
<!--
Checkout code: webgoat, owasp, owasp-webgoat
-->
<input name="checkoutCode" class="checkoutCode" value=""/>
</div>
<div class="section" style="padding-bottom:20px;">
<button type="submit" class="btn btn-success"><span style="margin-right:20px"
class="glyphicon glyphicon-shopping-cart"
aria-hidden="true"></span>Buy
</button>
<h6><a href="#"><span class="glyphicon glyphicon-heart-empty"
style="cursor:pointer;"></span>
Like</a></h6>
</div>
</div>
</div>
</form>
</div>
<br/>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html> </html>

View File

@ -1,3 +1,4 @@
client.side.filtering.title=Client side filtering
ClientSideFilteringSelectUser=Select user: ClientSideFilteringSelectUser=Select user:
ClientSideFilteringUserID=User ID ClientSideFilteringUserID=User ID
ClientSideFilteringFirstName=First Name ClientSideFilteringFirstName=First Name
@ -25,3 +26,7 @@ ClientSideFilteringHint10=Stage 2: Your filter operator should look something li
ClientSideFilteringInstructions1=STAGE 1: You are logged in as Moe Stooge, CSO of Goat Hills Financial. You have access to everyone in the company's information, except the CEO, . Or at least you shouldn't have access to the CEO's information. For this exercise, examine the contents of the page to see what extra information you can find. ClientSideFilteringInstructions1=STAGE 1: You are logged in as Moe Stooge, CSO of Goat Hills Financial. You have access to everyone in the company's information, except the CEO, . Or at least you shouldn't have access to the CEO's information. For this exercise, examine the contents of the page to see what extra information you can find.
ClientSideFilteringInstructions2=STAGE 2: Now, fix the problem. Modify the server to only return results that Moe Stooge is allowed to see. ClientSideFilteringInstructions2=STAGE 2: Now, fix the problem. Modify the server to only return results that Moe Stooge is allowed to see.
ClientSideFiltering.incorrect=This is not the salary from Neville Bartholomew... ClientSideFiltering.incorrect=This is not the salary from Neville Bartholomew...
client.side.filtering.free.hint1=Look through the webpage inspect the sources etc
client.side.filtering.free.hint2=Try to see the flow of request from the page to the backend
client.side.fiterling.free.hint3=One of the responses contains the answer

View File

@ -38,7 +38,7 @@ $(document).ready(function () {
}) })
$(".checkoutCode").on("blur", function () { $(".checkoutCode").on("blur", function () {
var checkoutCode = $(".checkoutCode").val(); var checkoutCode = $(".checkoutCode").val();
$.get("challenge-store/coupons/" + checkoutCode, function (result, status) { $.get("clientSideFiltering/challenge-store/coupons/" + checkoutCode, function (result, status) {
var discount = result.discount; var discount = result.discount;
if (discount > 0) { if (discount > 0) {
$('#discount').text(discount); $('#discount').text(discount);

View File

@ -0,0 +1,49 @@
package org.owasp.webgoat.plugin;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
/**
* @author nbaars
* @since 5/2/17.
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class ClientSideFilteringFreeAssignmentTest extends LessonTest {
private MockMvc mockMvc;
@Before
public void setup() {
ClientSideFiltering clientSideFiltering = new ClientSideFiltering();
when(webSession.getCurrentLesson()).thenReturn(clientSideFiltering);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
.param("checkoutCode", SUPER_COUPON_CODE))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void wrongCouponCode() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
.param("checkoutCode", "test"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge2; package org.owasp.webgoat.plugin;
import org.hamcrest.CoreMatchers; import org.hamcrest.CoreMatchers;
import org.junit.Before; import org.junit.Before;
@ -9,7 +9,7 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE; import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ -30,28 +30,28 @@ public class ShopEndpointTest {
@Test @Test
public void getSuperCoupon() throws Exception { public void getSuperCoupon() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/" + SUPER_COUPON_CODE)) mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/" + SUPER_COUPON_CODE))
.andExpect(jsonPath("$.code", CoreMatchers.is(SUPER_COUPON_CODE))) .andExpect(jsonPath("$.code", CoreMatchers.is(SUPER_COUPON_CODE)))
.andExpect(jsonPath("$.discount", CoreMatchers.is(100))); .andExpect(jsonPath("$.discount", CoreMatchers.is(100)));
} }
@Test @Test
public void getCoupon() throws Exception { public void getCoupon() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/webgoat")) mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/webgoat"))
.andExpect(jsonPath("$.code", CoreMatchers.is("webgoat"))) .andExpect(jsonPath("$.code", CoreMatchers.is("webgoat")))
.andExpect(jsonPath("$.discount", CoreMatchers.is(25))); .andExpect(jsonPath("$.discount", CoreMatchers.is(25)));
} }
@Test @Test
public void askForUnknownCouponCode() throws Exception { public void askForUnknownCouponCode() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/does-not-exists")) mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/does-not-exists"))
.andExpect(jsonPath("$.code", CoreMatchers.is("no"))) .andExpect(jsonPath("$.code", CoreMatchers.is("no")))
.andExpect(jsonPath("$.discount", CoreMatchers.is(0))); .andExpect(jsonPath("$.discount", CoreMatchers.is(0)));
} }
@Test @Test
public void fetchAllTheCouponsShouldContainGetItForFree() throws Exception { public void fetchAllTheCouponsShouldContainGetItForFree() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/")) mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/"))
.andExpect(jsonPath("$.codes[3].code", is("get_it_for_free"))); .andExpect(jsonPath("$.codes[3].code", is("get_it_for_free")));
} }

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