diff --git a/README.MD b/README.MD index 9c1420801..ccfee85bb 100644 --- a/README.MD +++ b/README.MD @@ -29,7 +29,18 @@ first thing that all hackers claim.* # Run Instructions: -## 1. Run using Docker +## 1. Standalone + +Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) + +```Shell +java -jar webgoat-server-<>.jar [--server.port=8080] [--server.address=localhost] +``` + +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) + +## 2. Run using Docker From time to time we publish a new development preview of WebGoat 8 on Docker HUB, you can download this version [https://hub.docker.com/r/webgoat/webgoat-8.0/](https://hub.docker.com/r/webgoat/webgoat-8.0/). @@ -65,27 +76,6 @@ 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 WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases) - -```Shell -java -jar webgoat-server-<>.jar -``` - -By default WebGoat starts at port 8080 in order to change this use the following property: - -```Shell -java -jar webgoat-server-<>.jar --server.port=9090 -``` - -You can specify one of the following arguments when starting WebGoat: - -```Shell -java -jar webgoat-server-<>.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 diff --git a/docker-compose-postgres.yml b/docker-compose-postgres.yml index 7ecc68403..919cbd509 100644 --- a/docker-compose-postgres.yml +++ b/docker-compose-postgres.yml @@ -6,6 +6,7 @@ services: 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 @@ -22,7 +23,7 @@ services: - spring.datasource.driver-class-name=org.postgresql.Driver - spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect ports: - - "8081:8081" + - "9090:9090" db: container_name: webgoat_db image: postgres:latest diff --git a/docker-compose.yml b/docker-compose.yml index 8d2bcdee3..725195504 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,7 @@ services: image: webgoat/webgoat-8.0 environment: - WEBWOLF_HOST=webwolf + - WEBWOLF_PORT=9090 - spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat ports: - "8080:8080" @@ -15,7 +16,7 @@ services: environment: - spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat ports: - - "8081:8081" + - "9090:9090" depends_on: - db db: diff --git a/pom.xml b/pom.xml index ca4c1caf8..6235a3843 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,12 @@ - + 4.0.0 org.owasp.webgoat webgoat-parent pom - v8.0.0.M15 + v8.0.0.M16 WebGoat Parent Pom Parent Pom for the WebGoat Project. A deliberately insecure Web Application @@ -53,17 +54,17 @@ jwayman Jeff Wayman - + dcowden Dave Cowden - + lawson89 Richard Lawson - + dougmorato @@ -92,8 +93,8 @@ https://github.com/WebGoat/WebGoat scm:git:git@github.com:WebGoat/WebGoat.git scm:git:git@github.com:WebGoat/WebGoat.git - HEAD - + HEAD + Github Issues @@ -202,7 +203,7 @@ release - + org.owasp.webgoat.lesson dist @@ -214,7 +215,7 @@ - + org.apache.maven.plugins maven-dependency-plugin @@ -225,7 +226,9 @@ generate-resources - ${project.basedir}/webgoat-container/src/main/webapp/plugin_lessons + + ${project.basedir}/webgoat-container/src/main/webapp/plugin_lessons + dist *.jar @@ -324,7 +327,7 @@ coveralls-maven-plugin ${coveralls-maven-plugin.version} - + @@ -332,7 +335,7 @@ cobertura-maven-plugin ${cobertura-maven-plugin.version} - + xml 256m diff --git a/scripts/build-all.sh b/scripts/build-all.sh new file mode 100644 index 000000000..a4430802e --- /dev/null +++ b/scripts/build-all.sh @@ -0,0 +1,32 @@ +#!/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 00 ]] ; then + echo "WebGoat and or WebWolf are still running, please stop them first otherwise unit tests might fail!" + exit 127 +fi + + +#mvn clean install +#if [[ "$?" -ne 0 ]] ; then +# exit y$? +#fi + +cd - +sh build_docker.sh + +echo "Do you want to run docker-compose?" +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 \ No newline at end of file diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh new file mode 100644 index 000000000..f63329476 --- /dev/null +++ b/scripts/build_docker.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +WEBGOAT_HOME=$(pwd)/../ + +cd ${WEBGOAT_HOME}/webgoat-server +docker build -t webgoat/webgoat-8.0 . + +cd ${WEBGOAT_HOME}/webwolf +docker build -t webgoat/webwolf . + diff --git a/scripts/clean-run-docker-compose.sh b/scripts/clean-run-docker-compose.sh new file mode 100644 index 000000000..c804d8d36 --- /dev/null +++ b/scripts/clean-run-docker-compose.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +cd .. +docker-compose rm -f +docker-compose up diff --git a/scripts/deploy-webgoat.sh b/scripts/deploy-webgoat.sh index b9562d0fa..eb9db07c8 100644 --- a/scripts/deploy-webgoat.sh +++ b/scripts/deploy-webgoat.sh @@ -10,10 +10,10 @@ if [ "${BRANCH}" == "master" ] && [ ! -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 webgoat_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} . docker push $REPO -elif [ ! -z "${TRAVIS_TAG}" ]; then - # 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 push $REPO +#elif [ ! -z "${TRAVIS_TAG}" ]; then +# # 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 push $REPO #elif [ "${BRANCH}" == "develop" ]; then # docker build -f Dockerfile -t $REPO:snapshot . # docker push $REPO diff --git a/scripts/run-docker-compose.sh b/scripts/run-docker-compose.sh new file mode 100644 index 000000000..4ed58bcf0 --- /dev/null +++ b/scripts/run-docker-compose.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd .. +docker-compose up diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index 3894d0869..ab6441be2 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -10,7 +10,7 @@ org.owasp.webgoat webgoat-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java index afcbd0615..c9e3b7d70 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; /** @@ -16,6 +17,7 @@ public class UserForm { @NotNull @Size(min=6, max=20) + @Pattern(regexp = "[a-zA-Z0-9]*", message = "can only contain letters and digits") private String username; @NotNull @Size(min=6, max=10) diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index 6ccb8fa93..ba8b75afc 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -37,7 +37,7 @@ webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.default.language=en 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.landingpage=http://${webwolf.host}:${webwolf.port}/landing webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail diff --git a/webgoat-images/vagrant-training/Vagrantfile b/webgoat-images/vagrant-training/Vagrantfile index ec6bc9b25..4772a8904 100644 --- a/webgoat-images/vagrant-training/Vagrantfile +++ b/webgoat-images/vagrant-training/Vagrantfile @@ -3,7 +3,7 @@ Vagrant.configure(2) do |config| config.vm.box = "ubuntu/trusty64" 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| vb.gui = false vb.memory = "4096" diff --git a/webgoat-lessons/auth-bypass/pom.xml b/webgoat-lessons/auth-bypass/pom.xml index 2e63e366a..a2309e4b7 100644 --- a/webgoat-lessons/auth-bypass/pom.xml +++ b/webgoat-lessons/auth-bypass/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/bypass-restrictions/pom.xml b/webgoat-lessons/bypass-restrictions/pom.xml index 4e8455ae4..ec5a85416 100755 --- a/webgoat-lessons/bypass-restrictions/pom.xml +++ b/webgoat-lessons/bypass-restrictions/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/challenge/pom.xml b/webgoat-lessons/challenge/pom.xml index 69db4dd4d..813bd6528 100644 --- a/webgoat-lessons/challenge/pom.xml +++ b/webgoat-lessons/challenge/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java index 333d29b2c..79881e6e4 100644 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java +++ b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/SolutionConstants.java @@ -11,7 +11,5 @@ public interface SolutionConstants { //TODO should be random generated when starting the server String PASSWORD = "!!webgoat_admin_1234!!"; String PASSWORD_TOM = "thisisasecretfortomonly"; - String PASSWORD_LARRY = "larryknows"; - String JWT_PASSWORD = "victory"; String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2"; } diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Assignment3.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Assignment3.java deleted file mode 100644 index 2fd355bd3..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Assignment3.java +++ /dev/null @@ -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> userComments = Maps.newHashMap(); - private static final EvictingQueue 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 retrieveComments() { - Collection allComments = Lists.newArrayList(); - Collection 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 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(); - } - } - - -} - diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Challenge3.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Challenge3.java deleted file mode 100644 index 91a05d4ea..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Challenge3.java +++ /dev/null @@ -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 getHints() { - return Lists.newArrayList(); - } - - @Override - public Integer getDefaultRanking() { - return 10; - } - - @Override - public String getTitle() { - return "challenge3.title"; - } - - @Override - public String getId() { - return "Challenge3"; - } -} diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Comment.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Comment.java deleted file mode 100644 index 0ea3e0d07..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge3/Comment.java +++ /dev/null @@ -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; -} - diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Assignment4.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Assignment4.java deleted file mode 100644 index 199ac4d62..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Assignment4.java +++ /dev/null @@ -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 - -} diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Challenge4.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Challenge4.java deleted file mode 100644 index 0e878d761..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Challenge4.java +++ /dev/null @@ -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 getHints() { - return Lists.newArrayList(); - } - - @Override - public Integer getDefaultRanking() { - return 10; - } - - @Override - public String getTitle() { - return "challenge4.title"; - } - - @Override - public String getId() { - return "Challenge4"; - } -} diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Views.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Views.java deleted file mode 100644 index e9f47594c..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Views.java +++ /dev/null @@ -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 { - } -} diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Vote.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Vote.java deleted file mode 100644 index ccb51c3b1..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/Vote.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.owasp.webgoat.plugin.challenge4; - -import com.fasterxml.jackson.annotation.JsonView; -import lombok.Getter; -import lombok.Setter; - -/** - * @author nbaars - * @since 5/2/17. - */ -@Getter -public class Vote { - @JsonView(Views.GuestView.class) - private final String title; - @JsonView(Views.GuestView.class) - private final String information; - @JsonView(Views.GuestView.class) - private final String imageSmall; - @JsonView(Views.GuestView.class) - private final String imageBig; - @JsonView(Views.UserView.class) - private int numberOfVotes; - @JsonView(Views.AdminView.class) - @Setter - private String flag; - @JsonView(Views.UserView.class) - private boolean votingAllowed = true; - @JsonView(Views.UserView.class) - private long average = 0; - - - public Vote(String title, String information, String imageSmall, String imageBig, int numberOfVotes, int totalVotes) { - this.title = title; - this.information = information; - this.imageSmall = imageSmall; - this.imageBig = imageBig; - this.numberOfVotes = numberOfVotes; - this.average = calculateStars(totalVotes); - } - - public void incrementNumberOfVotes(int totalVotes) { - this.numberOfVotes = this.numberOfVotes + 1; - this.average = calculateStars(totalVotes); - } - - private long calculateStars(int totalVotes) { - return Math.round(((double) numberOfVotes / (double) totalVotes) * 4); - } -} \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/VotesEndpoint.java b/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/VotesEndpoint.java deleted file mode 100644 index 619e35c13..000000000 --- a/webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/plugin/challenge4/VotesEndpoint.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.owasp.webgoat.plugin.challenge4; - -import com.google.common.collect.Maps; -import io.jsonwebtoken.*; -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.json.MappingJacksonValue; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.PostConstruct; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static java.util.Comparator.comparingLong; -import static java.util.Optional.ofNullable; -import static java.util.stream.Collectors.toList; -import static org.owasp.webgoat.plugin.Flag.FLAGS; -import static org.owasp.webgoat.plugin.SolutionConstants.JWT_PASSWORD; - -/** - * @author nbaars - * @since 4/23/17. - */ -@RestController -@RequestMapping("/votings") -public class VotesEndpoint { - - private static String validUsers = "TomJerrySylvester"; - - private static int totalVotes = 38929; - private Map votes = Maps.newHashMap(); - - @PostConstruct - public void initVotes() { - votes.put("Admin lost password", new Vote("Admin lost password", - "In this challenge you will need to help the admin and find the password in order to login", - "challenge1-small.png", "challenge1.png", 36000, totalVotes)); - votes.put("Vote for your favourite", - new Vote("Vote for your favourite", - "In this challenge ...", - "challenge5-small.png", "challenge5.png", 30000, totalVotes)); - votes.put("Get it for free", - new Vote("Get it for free", - "The objective for this challenge is to buy a Samsung phone for free.", - "challenge2-small.png", "challenge2.png", 20000, totalVotes)); - votes.put("Photo comments", - new Vote("Photo comments", - "n this challenge you can comment on the photo you will need to find the flag somewhere.", - "challenge3-small.png", "challenge3.png", 10000, totalVotes)); - } - - @GetMapping("/login") - public void login(@RequestParam("user") String user, HttpServletResponse response) { - if (validUsers.contains(user)) { - Map claims = Maps.newHashMap(); - claims.put("admin", "false"); - claims.put("user", user); - String token = Jwts.builder() - .setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10))) - .setClaims(claims) - .signWith(SignatureAlgorithm.HS512, JWT_PASSWORD) - .compact(); - Cookie cookie = new Cookie("access_token", token); - response.addCookie(cookie); - response.setStatus(HttpStatus.OK.value()); - } else { - Cookie cookie = new Cookie("access_token", ""); - response.addCookie(cookie); - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - } - } - - @GetMapping - public MappingJacksonValue getVotes(@CookieValue(value = "access_token", required = false) String accessToken) { - MappingJacksonValue value = new MappingJacksonValue(votes.values().stream().sorted(comparingLong(Vote::getAverage).reversed()).collect(toList())); - if (StringUtils.isEmpty(accessToken)) { - value.setSerializationView(Views.GuestView.class); - } else { - try { - Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken); - Claims claims = (Claims) jwt.getBody(); - String user = (String) claims.get("user"); - boolean isAdmin = Boolean.valueOf((String) claims.get("admin")); - if ("Guest".equals(user) || !validUsers.contains(user)) { - value.setSerializationView(Views.GuestView.class); - } else { - ((Collection) value.getValue()).forEach(v -> v.setFlag(FLAGS.get(4))); - value.setSerializationView(isAdmin ? Views.AdminView.class : Views.UserView.class); - } - } catch (JwtException e) { - value.setSerializationView(Views.GuestView.class); - } - } - return value; - } - - @PostMapping(value = "{title}") - @ResponseBody - @ResponseStatus(HttpStatus.ACCEPTED) - public ResponseEntity vote(@PathVariable String title, @CookieValue(value = "access_token", required = false) String accessToken) { - if (StringUtils.isEmpty(accessToken)) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } else { - try { - Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken); - Claims claims = (Claims) jwt.getBody(); - String user = (String) claims.get("user"); - if (validUsers.contains(user)) { - ofNullable(votes.get(title)).ifPresent(v -> v.incrementNumberOfVotes(totalVotes)); - return ResponseEntity.accepted().build(); - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - } catch (JwtException e) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - } - } -} diff --git a/webgoat-lessons/challenge/src/main/resources/css/challenge3.css b/webgoat-lessons/challenge/src/main/resources/css/challenge3.css deleted file mode 100644 index 3bc2ca4eb..000000000 --- a/webgoat-lessons/challenge/src/main/resources/css/challenge3.css +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/css/challenge4.css b/webgoat-lessons/challenge/src/main/resources/css/challenge4.css deleted file mode 100644 index 590e2a4b0..000000000 --- a/webgoat-lessons/challenge/src/main/resources/css/challenge4.css +++ /dev/null @@ -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%; -} \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/html/Challenge3.html b/webgoat-lessons/challenge/src/main/resources/html/Challenge3.html deleted file mode 100644 index 62255ab95..000000000 --- a/webgoat-lessons/challenge/src/main/resources/html/Challenge3.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - -
-
- - -
-
- -
-
-
-
- user profile image -
-
-
- John Doe - uploaded a photo. -
-
24 days ago
-
-
- -
- image post -
- -
- -
- -
-
- -
-
-
-
- -
-
- -
-
- -
- - -
-
-
-
-
- \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/html/Challenge4.html b/webgoat-lessons/challenge/src/main/resources/html/Challenge4.html deleted file mode 100644 index f760beffe..000000000 --- a/webgoat-lessons/challenge/src/main/resources/html/Challenge4.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - -
-
- - - -
-
-
- -
- -
-
- -
-

Welcome back,

-
-
- -
-

Vote for your favorite

-
-
- -
-
-
-
- -
-
-
-
-
- -
-
- -
-
- -
- -
-
-
-
-
- - \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/challenge/src/main/resources/i18n/WebGoatLabels.properties index e79acbac5..267502639 100644 --- a/webgoat-lessons/challenge/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/challenge/src/main/resources/i18n/WebGoatLabels.properties @@ -2,7 +2,6 @@ challenge0.title=WebGoat Challenge challenge1.title=Admin lost password challenge2.title=Get it for free challenge3.title=Photo comments -challenge4.title=Voting challenge5.title=Without password challenge6.title=Creating a new account challenge7.title=Admin password reset diff --git a/webgoat-lessons/challenge/src/main/resources/images/cat.jpg b/webgoat-lessons/challenge/src/main/resources/images/cat.jpg deleted file mode 100644 index e0e1fb983..000000000 Binary files a/webgoat-lessons/challenge/src/main/resources/images/cat.jpg and /dev/null differ diff --git a/webgoat-lessons/challenge/src/main/resources/js/challenge3.js b/webgoat-lessons/challenge/src/main/resources/js/challenge3.js deleted file mode 100644 index fb902e050..000000000 --- a/webgoat-lessons/challenge/src/main/resources/js/challenge3.js +++ /dev/null @@ -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 = '
  • ' + - '
    ' + - 'avatar' + - '
    ' + - '
    ' + - '
    ' + - '

    USER

    ' + - '
    DATETIME
    ' + - '
    ' + - '

    COMMENT

    ' + - '
    ' + - '
  • '; - - 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); - } - - }); - } -}) \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/js/challenge4.js b/webgoat-lessons/challenge/src/main/resources/js/challenge4.js deleted file mode 100644 index 5c9d6a38d..000000000 --- a/webgoat-lessons/challenge/src/main/resources/js/challenge4.js +++ /dev/null @@ -1,84 +0,0 @@ -$(document).ready(function () { - login('Guest'); -}) - -function login(user) { - $("#name").text(user); - $.ajax({ - url: "votings/login?user=" + user, - complete: function (result, status) { - getVotings(); - } - }); -} - -var html = '' + - '
    ' + - '
    ' + - 'placehold.it/350x250' + - '
    ' + - '
    ' + - '
    ' + - '

    TITLE

    ' + - '

    INFORMATION

    ' + - '
    ' + - '
    ' + - '

    NO_VOTES' + - ' votes' + - '

    ' + - '' + - '
    ' + - '' + - '' + - '' + - '' + - '
    ' + - '

    Average AVERAGE /4

    ' + - '
    ' + - '
    ' + - '
    '; - -function getVotings() { - $("#votesList").empty(); - $.get("votings/", function (result, status) { - for (var i = 0; i < result.length; i++) { - var voteTemplate = html.replace('IMAGE_SMALL', result[i].imageSmall); - if (i === 0) { - voteTemplate = voteTemplate.replace('ACTIVE', 'active'); - voteTemplate = voteTemplate.replace('BUTTON', 'btn-default'); - } else { - voteTemplate = voteTemplate.replace('ACTIVE', ''); - voteTemplate = voteTemplate.replace('BUTTON', 'btn-primary'); - } - voteTemplate = voteTemplate.replace(/TITLE/g, result[i].title); - voteTemplate = voteTemplate.replace('INFORMATION', result[i].information || ''); - voteTemplate = voteTemplate.replace('NO_VOTES', result[i].numberOfVotes || ''); - voteTemplate = voteTemplate.replace('AVERAGE', result[i].average || ''); - - var hidden = (result[i].numberOfVotes === undefined ? 'hidden' : ''); - voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_VOTES/g, hidden); - hidden = (result[i].average === undefined ? 'hidden' : ''); - voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_RATING/g, hidden); - - $("#votesList").append(voteTemplate); - } - }) -} - -function vote(title) { - var user = $("#name").text(); - if (user === 'Guest') { - alert("As a guest you are not allowed to vote, please login first.") - } else { - $.ajax({ - type: 'POST', - url: 'votings/' + title - }).then( - function () { - getVotings(); - } - ) - } -} - - diff --git a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_3.adoc b/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_3.adoc deleted file mode 100644 index 396cbfa0f..000000000 --- a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_3.adoc +++ /dev/null @@ -1 +0,0 @@ -Changing language can help you find the 'secret' file \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_4.adoc b/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_4.adoc deleted file mode 100644 index 883d4be45..000000000 --- a/webgoat-lessons/challenge/src/main/resources/lessonPlans/en/Challenge_4.adoc +++ /dev/null @@ -1 +0,0 @@ -Try to change to a different user, maybe you can find the flag? \ No newline at end of file diff --git a/webgoat-lessons/challenge/src/test/java/org/owasp/webgoat/plugin/challenge4/VotesEndpointTest.java b/webgoat-lessons/challenge/src/test/java/org/owasp/webgoat/plugin/challenge4/VotesEndpointTest.java deleted file mode 100644 index 322cf8873..000000000 --- a/webgoat-lessons/challenge/src/test/java/org/owasp/webgoat/plugin/challenge4/VotesEndpointTest.java +++ /dev/null @@ -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()); - } -} \ No newline at end of file diff --git a/webgoat-lessons/client-side-filtering/pom.xml b/webgoat-lessons/client-side-filtering/pom.xml index b60276ec5..0f41b8032 100644 --- a/webgoat-lessons/client-side-filtering/pom.xml +++ b/webgoat-lessons/client-side-filtering/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/cross-site-scripting/pom.xml b/webgoat-lessons/cross-site-scripting/pom.xml index 86709473c..44d6e15e4 100644 --- a/webgoat-lessons/cross-site-scripting/pom.xml +++ b/webgoat-lessons/cross-site-scripting/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/csrf/pom.xml b/webgoat-lessons/csrf/pom.xml index e11a77edd..ba8e523b2 100644 --- a/webgoat-lessons/csrf/pom.xml +++ b/webgoat-lessons/csrf/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 \ No newline at end of file diff --git a/webgoat-lessons/html-tampering/pom.xml b/webgoat-lessons/html-tampering/pom.xml index ec3f51ffe..ede6f4522 100755 --- a/webgoat-lessons/html-tampering/pom.xml +++ b/webgoat-lessons/html-tampering/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/http-basics/pom.xml b/webgoat-lessons/http-basics/pom.xml index d70f14823..4607f4def 100644 --- a/webgoat-lessons/http-basics/pom.xml +++ b/webgoat-lessons/http-basics/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/http-proxies/pom.xml b/webgoat-lessons/http-proxies/pom.xml index 42810af9b..591d71a68 100644 --- a/webgoat-lessons/http-proxies/pom.xml +++ b/webgoat-lessons/http-proxies/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/http-proxies/src/main/resources/html/HttpProxies.html b/webgoat-lessons/http-proxies/src/main/resources/html/HttpProxies.html index 595c7f960..fa4928b6e 100644 --- a/webgoat-lessons/http-proxies/src/main/resources/html/HttpProxies.html +++ b/webgoat-lessons/http-proxies/src/main/resources/html/HttpProxies.html @@ -3,36 +3,27 @@
    - -
    - -
    - -
    -
    - - +
    -
    +
    + +
    +
    + +
    +
    +
    diff --git a/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_resend.png b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_resend.png new file mode 100644 index 000000000..e604cbd2a Binary files /dev/null and b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_resend.png differ diff --git a/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_response.png b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_response.png new file mode 100644 index 000000000..88699edca Binary files /dev/null and b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_response.png differ diff --git a/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_send.png b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_send.png new file mode 100644 index 000000000..968db6dda Binary files /dev/null and b/webgoat-lessons/http-proxies/src/main/resources/images/zap_edit_and_send.png differ diff --git a/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude.png b/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude.png new file mode 100644 index 000000000..63ac4bc61 Binary files /dev/null and b/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude.png differ diff --git a/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude_url.png b/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude_url.png new file mode 100644 index 000000000..592afc090 Binary files /dev/null and b/webgoat-lessons/http-proxies/src/main/resources/images/zap_exclude_url.png differ diff --git a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro4.adoc b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro4.adoc index db925accf..afb51ed06 100644 --- a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro4.adoc +++ b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro4.adoc @@ -1,26 +1,25 @@ -=== Use the intercept +=== Exclude WebGoat internal requests -To intercept a request, you start by clicking the green button. This will set a break point for the next request. +Before we start diving into intercepting requests with ZAP we need to exclude the internal requests from the WebGoat +framework otherwise ZAP will also stop at all the requests which are only necessary for the internal working of WebGoat. -image::images/proxy-intercept-button.png[Set break/intercept button,style="lesson-image"] +Right click on one of the links in history tab and select: `Exclude from -> Proxy`, see image below: + +image::images/zap_exclude.png[Select URL from history,style="lesson-image"] + +{nbsp} + +A new window will open and add the following entries: + +``` +http://localhost:8080/WebGoat/service/.* +http://localhost:8080/WebGoat/.*.lesson.lesson +``` + +Click Ok to close the window, ZAP will now no longer proxy internal WebGoat requests. -*NOTE*: It is also possible set breakpoints that are triggered on conditions. That won't be covered in this lesson though. You are encouraged to explore. -That's part of what hackers do ... explore! +image::images/zap_exclude_url.png[Exclude internal APIs from WebGoat,style="lesson-image"] -Once you are intercepting requests and a request is made, it should look something like this: -image::images/proxy-intercept-details.png[ZAP history tab,style="lesson-image"] -=== Intercept and modify a request - -Set up the intercept as noted above and then submit the form/request below by clicking the submit button. When you request is intercepted (hits the breakpoint), -modify it as follows. - -* Change the Method to GET -* Add a header 'x-request-intercepted:true' -* Change the input value 'changeMe' to 'Requests are tampered easily' (without the single quotes) - -Then let the request continue through (by hitting the play button). - -NOTE: The two play buttons behave a little differently, but we'll let you tinker and figure that out for yourself. \ No newline at end of file diff --git a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc new file mode 100644 index 000000000..db925accf --- /dev/null +++ b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc @@ -0,0 +1,26 @@ +=== Use the intercept + +To intercept a request, you start by clicking the green button. This will set a break point for the next request. + +image::images/proxy-intercept-button.png[Set break/intercept button,style="lesson-image"] + + +*NOTE*: It is also possible set breakpoints that are triggered on conditions. That won't be covered in this lesson though. You are encouraged to explore. +That's part of what hackers do ... explore! + +Once you are intercepting requests and a request is made, it should look something like this: + +image::images/proxy-intercept-details.png[ZAP history tab,style="lesson-image"] + +=== Intercept and modify a request + +Set up the intercept as noted above and then submit the form/request below by clicking the submit button. When you request is intercepted (hits the breakpoint), +modify it as follows. + +* Change the Method to GET +* Add a header 'x-request-intercepted:true' +* Change the input value 'changeMe' to 'Requests are tampered easily' (without the single quotes) + +Then let the request continue through (by hitting the play button). + +NOTE: The two play buttons behave a little differently, but we'll let you tinker and figure that out for yourself. \ No newline at end of file diff --git a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro6.adoc b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro6.adoc new file mode 100644 index 000000000..7a90ef913 --- /dev/null +++ b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro6.adoc @@ -0,0 +1,29 @@ +=== Use the "Edit and resend" functionality in ZAP + +Another way to send a request again instead of clicking in WebGoat on a button and intercept the request there is also +an option to resend the same request again from within ZAP. +This may significantly help you to solve an assignment because you do not have to switch to ZAP enable the intercept button +and go back to WebGoat and perform the request again from within the browser. + +Let's look at an example, we are going to use the e-mail example from the WebWolf introduction lesson. This lesson +will generate a request for `/WebGoat/WebWolf/mail`, in the "History" window select the URL you want to resend right click +on the URL and select `Open/Resend with Request Editor`. You can also find the request in the left pane of ZAP as indicated +with the red arrow in the image below: + +image::images/zap_edit_and_resend.png[Open/Resend with Request Editor,style="lesson-image"] + +{nbsp} + +A new window will open and here you can modify the request for example change the e-mail address to someone else and send it again. +In the response tab you can inspect the response of the request. In some assignments the response will show a solved message +but sometimes you get a code/flag which you need to submit in WebGoat in order to complete the assignment. Always be on the +lookout for the response. If you solved the assignment by make a request in this way WebGoat will automatically mark +the lesson as solved. + +image::images/zap_edit_and_send.png[Open/Resend with Request Editor,style="lesson-image"] + +{nbsp} + +image::images/zap_edit_and_response.png[Open/Resend response,style="lesson-image"] + + diff --git a/webgoat-lessons/idor/pom.xml b/webgoat-lessons/idor/pom.xml index 1ff614abb..c9f28f005 100644 --- a/webgoat-lessons/idor/pom.xml +++ b/webgoat-lessons/idor/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 \ No newline at end of file diff --git a/webgoat-lessons/insecure-deserialization/pom.xml b/webgoat-lessons/insecure-deserialization/pom.xml index 70dc18780..2328677de 100755 --- a/webgoat-lessons/insecure-deserialization/pom.xml +++ b/webgoat-lessons/insecure-deserialization/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/insecure-login/pom.xml b/webgoat-lessons/insecure-login/pom.xml index 4e2efea24..67029e4c2 100755 --- a/webgoat-lessons/insecure-login/pom.xml +++ b/webgoat-lessons/insecure-login/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/jwt/pom.xml b/webgoat-lessons/jwt/pom.xml index cc52fc036..6755f8e11 100644 --- a/webgoat-lessons/jwt/pom.xml +++ b/webgoat-lessons/jwt/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/missing-function-ac/pom.xml b/webgoat-lessons/missing-function-ac/pom.xml index 903bf96b8..4d16a7e58 100644 --- a/webgoat-lessons/missing-function-ac/pom.xml +++ b/webgoat-lessons/missing-function-ac/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/password-reset/pom.xml b/webgoat-lessons/password-reset/pom.xml index 2835a7523..f881f259f 100644 --- a/webgoat-lessons/password-reset/pom.xml +++ b/webgoat-lessons/password-reset/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignment.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignment.java index 99eb8c41e..39254d783 100644 --- a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignment.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignment.java @@ -62,7 +62,7 @@ public class ResetLinkAssignment extends AssignmentEndpoint { resetLinks.add(resetLink); String host = request.getHeader("host"); if (org.springframework.util.StringUtils.hasText(email)) { - if (email.equals(TOM_EMAIL) && host.contains("8081")) { //User indeed changed the host header. + if (email.equals(TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header. userToTomResetLink.put(getWebSession().getUserName(), resetLink); fakeClickingLinkEmail(host, resetLink); } else { diff --git a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties index 3b3f6bb69..709165e15 100644 --- a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties @@ -15,7 +15,7 @@ password-reset-not-solved=Sorry but you did not redirect the reset link to WebWo password-reset-hint1=Try to send a password reset link to your own account at {user}@webgoat.org, you can read this e-mail in WebWolf. password-reset-hint2=Look at the link, can you think how the server creates this link? password-reset-hint3=Tom clicks all the links he receives in his mailbox, you can use the landing page in WebWolf to get the reset link... -password-reset-hint4=The link points to localhost:8080/PasswordReset/.... can you change the host to localhost:8081 +password-reset-hint4=The link points to localhost:8080/PasswordReset/.... can you change the host to localhost:9090 password-reset-hint5=Intercept the request and change the host header login_failed=Login failed login_failed.tom=Sorry only Tom can login at the moment \ No newline at end of file diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 94903db5d..7a491d024 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -5,12 +5,12 @@ org.owasp.webgoat.lesson webgoat-lessons-parent pom - v8.0.0.M15 + v8.0.0.M16 org.owasp.webgoat webgoat-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/sql-injection/pom.xml b/webgoat-lessons/sql-injection/pom.xml index 8e02035d3..b4d86eb12 100644 --- a/webgoat-lessons/sql-injection/pom.xml +++ b/webgoat-lessons/sql-injection/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 \ No newline at end of file diff --git a/webgoat-lessons/vulnerable-components/pom.xml b/webgoat-lessons/vulnerable-components/pom.xml index 343969ac3..d47d0aa4c 100644 --- a/webgoat-lessons/vulnerable-components/pom.xml +++ b/webgoat-lessons/vulnerable-components/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/webgoat-introduction/pom.xml b/webgoat-lessons/webgoat-introduction/pom.xml index 4d7b403f8..b40f205fd 100644 --- a/webgoat-lessons/webgoat-introduction/pom.xml +++ b/webgoat-lessons/webgoat-introduction/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 \ No newline at end of file diff --git a/webgoat-lessons/webwolf-introduction/pom.xml b/webgoat-lessons/webwolf-introduction/pom.xml index 7f0903586..00e76a4f1 100644 --- a/webgoat-lessons/webwolf-introduction/pom.xml +++ b/webgoat-lessons/webwolf-introduction/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 \ No newline at end of file diff --git a/webgoat-lessons/webwolf-introduction/src/main/resources/lessonPlans/en/IntroductionWebWolf.adoc b/webgoat-lessons/webwolf-introduction/src/main/resources/lessonPlans/en/IntroductionWebWolf.adoc index 0bbd39bc1..bf15f54c3 100644 --- a/webgoat-lessons/webwolf-introduction/src/main/resources/lessonPlans/en/IntroductionWebWolf.adoc +++ b/webgoat-lessons/webwolf-introduction/src/main/resources/lessonPlans/en/IntroductionWebWolf.adoc @@ -27,21 +27,24 @@ WebWolf runs as a separate web application and is started automatically when usi are not using the Docker image you will need to download the jar file and start it: ``` -java -jar webwolf-<>.jar +java -jar webwolf-<>.jar [--server.port=9090] [--server.address=localhost] ``` +By default WebWolf starts on port 9090 with `--server.port` you can specify a different port. With `server.address` you +can bind it to a different address (default localhost) + WebWolf is also available as a Docker container, because it shares the database with WebGoat we first need to find out the ip address of the Docker container. ``` WEBGOAT_SERVER_ADDRESS=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" `docker ps | grep webgoat | awk '{print $1}'`) docker pull webgoat/webwolf -docker run -e webgoat.server.address=${WEBGOAT_SERVER_ADDRESS} -it -p 8081:8081 webgoat/webwolf /home/webwolf/run.sh +docker run -e webgoat.server.address=${WEBGOAT_SERVER_ADDRESS} -it -p 9090:9090 webgoat/webwolf /home/webwolf/run.sh ``` Note: if you start WebGoat as standalone application you need to start WebWolf as standalone application as well. If you start WebGoat as Docker container you need to start WebWolf as Docker container as well. -This will start the application on port 8081, click webWolfLink:here[] to open WebWolf. +This will start the application on port 9090, click webWolfLink:here[] to open WebWolf. First thing you need to do is register a new user within WebWolf. \ No newline at end of file diff --git a/webgoat-lessons/xxe/pom.xml b/webgoat-lessons/xxe/pom.xml index 6d6eae1e6..2c6fe3043 100644 --- a/webgoat-lessons/xxe/pom.xml +++ b/webgoat-lessons/xxe/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M15 + v8.0.0.M16 diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 9f48290cf..dd823e1ca 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -89,7 +89,7 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { /** + %remote; ]> test&send; @@ -102,14 +102,14 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { *
          *     
          *     
    -     *     ">
    +     *     ">
          *      %all;
          * 
    * * This will be reduced to: * *
    -     *     
    +     *     
          * 
    * * Wire it all up in the xml send to the server: @@ -117,7 +117,7 @@ public class BlindSendFileAssignment extends AssignmentEndpoint { *
          *  
          *  
    +     *  
          *  %remote;
          *   ]>
          *  
    diff --git a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties
    index 9af5a6300..766440f01 100644
    --- a/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties
    +++ b/webgoat-lessons/xxe/src/main/resources/i18n/WebGoatLabels.properties
    @@ -43,4 +43,4 @@ xxe.blind.hints.1=This assignment is more complicated you need to upload the con
     xxe.blind.hints.2=In this case you cannot combine external entities in combination with internal entities.
     xxe.blind.hints.3=Use parameter entities to perform the attack, see for example: https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/
     xxe.blind.hints.4=An example DTD can be found here WebGoat/images/example.dtd, include this DTD in the xml comment
    -xxe.blind.hints.5=Use for the comment, be aware to replace the url accordingly: <?xml version="1.0"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "http://localhost:8081/files/test1234/test.dtd">%remote;]><comment><text>test&send;</text></comment>
    +xxe.blind.hints.5=Use for the comment, be aware to replace the url accordingly: <?xml version="1.0"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM "http://localhost:9090/files/test1234/test.dtd">%remote;]><comment><text>test&send;</text></comment>
    diff --git a/webgoat-lessons/xxe/src/main/resources/images/example.dtd b/webgoat-lessons/xxe/src/main/resources/images/example.dtd
    index 9753b5c2f..76be6d7c6 100644
    --- a/webgoat-lessons/xxe/src/main/resources/images/example.dtd
    +++ b/webgoat-lessons/xxe/src/main/resources/images/example.dtd
    @@ -1,5 +1,4 @@
     
     
    -">
    -%all;
    -        ~
    \ No newline at end of file
    +">
    +%all;
    \ No newline at end of file
    diff --git a/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java b/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java
    index 4efbca7c4..621fdd1b3 100644
    --- a/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java
    +++ b/webgoat-lessons/xxe/src/test/java/org/owasp/webgoat/plugin/BlindSendFileAssignmentTest.java
    @@ -37,7 +37,7 @@ public class BlindSendFileAssignmentTest extends LessonTest {
         private String webGoatHomeDirectory;
     
         @Rule
    -    public WireMockRule webwolfServer = new WireMockRule(8081);
    +    public WireMockRule webwolfServer = new WireMockRule(9090);
     
         @Before
         public void setup() throws Exception {
    @@ -74,7 +74,7 @@ public class BlindSendFileAssignmentTest extends LessonTest {
             //Host DTD on WebWolf site
             String dtd = "\n" +
                     "\n" +
    -                "\">\n" +
    +                "\">\n" +
                     "%all;";
             webwolfServer.stubFor(get(WireMock.urlMatching("/files/test.dtd"))
                     .willReturn(aResponse()
    @@ -85,7 +85,7 @@ public class BlindSendFileAssignmentTest extends LessonTest {
             //Make the request from WebGoat
             String xml = "" +
                     "" +
    +                "" +
                     "%remote;" +
                     "]>" +
                     "test&send;";
    diff --git a/webgoat-server/Dockerfile b/webgoat-server/Dockerfile
    index 860bb1b3f..85562dba0 100644
    --- a/webgoat-server/Dockerfile
    +++ b/webgoat-server/Dockerfile
    @@ -1,6 +1,6 @@
     FROM openjdk:8-jre-slim
     
    -ARG webgoat_version=8.0-SNAPSHOT
    +ARG webgoat_version=v8.0.0.SNAPSHOT
     
     RUN \
       apt-get update && apt-get install && \
    diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml
    index 452985378..529661426 100644
    --- a/webgoat-server/pom.xml
    +++ b/webgoat-server/pom.xml
    @@ -6,7 +6,7 @@
         
             org.owasp.webgoat
             webgoat-parent
    -        v8.0.0.M15
    +        v8.0.0.M16
         
     
         
    diff --git a/webwolf/Dockerfile b/webwolf/Dockerfile
    index a591b2ae5..060f6ee9a 100644
    --- a/webwolf/Dockerfile
    +++ b/webwolf/Dockerfile
    @@ -1,6 +1,6 @@
     FROM openjdk:8-jre-slim
     
    -ARG webwolf_version=8.0-SNAPSHOT
    +ARG webwolf_version=v8.0.0.SNAPSHOT
     
     RUN \
       apt-get update && apt-get install && \
    @@ -9,6 +9,6 @@ RUN \
     USER webwolf
     COPY target/webwolf-${webwolf_version}.jar /home/webwolf/webwolf.jar
     
    -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/home/webwolf/webwolf.jar", "--server.address=0.0.0.0"]
    +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/home/webwolf/webwolf.jar", "--server.port=9090", "--server.address=0.0.0.0"]
     
    -EXPOSE 8081
    +EXPOSE 9090
    diff --git a/webwolf/README.md b/webwolf/README.md
    index 4086c268c..52d5341c8 100644
    --- a/webwolf/README.md
    +++ b/webwolf/README.md
    @@ -21,7 +21,7 @@ At the moment WebWolf offers support for:
     ## 1. Run using Docker
     
     If you use the Docker image of WebGoat this application will automatically be available. Use the following 
    -URL: http://localhost:8081/WebWolf
    +URL: http://localhost:9090/WebWolf
     
     ## 2. Standalone
     
    @@ -36,7 +36,7 @@ Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
     ```Shell
     mvn -pl webwolf spring-boot:run
     ```
    -... you should be running WebWolf on localhost:8081/WebWolf momentarily
    +... you should be running WebWolf on localhost:9090/WebWolf momentarily
     
     
     
    diff --git a/webwolf/pom.xml b/webwolf/pom.xml
    index e68d7163c..f72653dfa 100644
    --- a/webwolf/pom.xml
    +++ b/webwolf/pom.xml
    @@ -6,7 +6,7 @@
         
             org.owasp.webgoat
             webgoat-parent
    -        v8.0.0.M15
    +        v8.0.0.M16
         
     
         
    diff --git a/webwolf/src/main/java/org/owasp/webwolf/FileServer.java b/webwolf/src/main/java/org/owasp/webwolf/FileServer.java
    index d386235a0..8adaa1f3d 100644
    --- a/webwolf/src/main/java/org/owasp/webwolf/FileServer.java
    +++ b/webwolf/src/main/java/org/owasp/webwolf/FileServer.java
    @@ -32,6 +32,11 @@ public class FileServer {
     
         @Value("${webwolf.fileserver.location}")
         private String fileLocatation;
    +    @Value("${server.address}")
    +    private String server;
    +    @Value("${server.port}")
    +    private int port;
    +
     
         @PostMapping(value = "/WebWolf/fileupload")
         @SneakyThrows
    @@ -84,6 +89,7 @@ public class FileServer {
             }
     
             modelAndView.addObject("files", uploadedFiles);
    +        modelAndView.addObject("webwolf_url", "http://" + server +":" + port);
             return modelAndView;
         }
     }
    diff --git a/webwolf/src/main/resources/application.properties b/webwolf/src/main/resources/application.properties
    index 421665f81..25869712a 100644
    --- a/webwolf/src/main/resources/application.properties
    +++ b/webwolf/src/main/resources/application.properties
    @@ -2,8 +2,8 @@ server.error.include-stacktrace=always
     server.error.path=/error.html
     server.session.timeout=6000
     #server.contextPath=/WebWolf
    -server.port=8081
    -server.address=127.0.0.1
    +server.port=9090
    +server.address=localhost
     server.session.cookie.name = WEBWOLFSESSION
     
     spring.datasource.url=jdbc:hsqldb:hsql://${webgoat.server.address:localhost}:9001/webgoat
    diff --git a/webwolf/src/main/resources/templates/files.html b/webwolf/src/main/resources/templates/files.html
    index 0cd43e95e..b3bcde29c 100644
    --- a/webwolf/src/main/resources/templates/files.html
    +++ b/webwolf/src/main/resources/templates/files.html
    @@ -20,7 +20,7 @@
             

    Each file will be available under the following url: - http://localhost:8081/files/{username}/{filename}. + http://localhost:9090//files/{username}/{filename}.

    You can copy and paste the location from the table below. @@ -33,7 +33,7 @@

    - +