Compare commits

...

5 Commits

35 changed files with 441 additions and 183 deletions

View File

@ -88,20 +88,21 @@ Now let's start by compiling the project.
```Shell ```Shell
cd WebGoat cd WebGoat
git checkout develop git checkout <<branch_name>>
mvn clean install mvn clean install
``` ```
Now we are ready to run the project. WebGoat 8.x is using Spring-Boot. Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
```Shell ```Shell
mvn -pl webwolf spring-boot:run mvn -pl webgoat-server spring-boot:run
``` ```
... you should be running webgoat on localhost:8080/WebGoat momentarily ... you should be running webgoat on localhost:8080/WebGoat momentarily
To change IP addresss add the following variable to WebGoat/webgoat-container/src/main/resources/application.properties file To change IP addresss add the following variable to WebGoat/webgoat-container/src/main/resources/application.properties file
```server.address=x.x.x.x ```
server.address=x.x.x.x
``` ```
# Vagrant # Vagrant

View File

@ -1,25 +1,11 @@
version: '2.0' version: '2.0'
services: services:
mongo:
image: mongo:latest
expose:
- "27017"
volumes:
- './mongo-data:/data/db'
webgoat: webgoat:
build: webgoat-server/ build: webgoat-server/
command: "sh /home/webgoat/start.sh" command: "sh /home/webgoat/start.sh"
ports: ports:
- "8080:8080" - "8080:8080"
depends_on:
[mongo, activemq]
environment:
WG_MONGO_PORT: 27017
WG_MONGO_HOST: mongo
WG_MQ_HOST: activemq
WG_MQ_PORT: 61616
WG_INTERNAL_MONGO: "false"
webwolf: webwolf:
build: webwolf/ build: webwolf/
command: "sh /home/webwolf/start.sh" command: "sh /home/webwolf/start.sh"
@ -27,8 +13,3 @@ services:
- webgoat - webgoat
ports: ports:
- "8081:8081" - "8081:8081"
environment:
WG_MONGO_PORT: 27017
WG_MONGO_HOST: mongo
WG_MQ_HOST: activemq
WG_MQ_PORT: 61616

View File

@ -36,16 +36,6 @@
</profiles> </profiles>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<build> <build>
<resources> <resources>
<resource> <resource>
@ -127,7 +117,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@ -202,12 +192,6 @@
<version>${junit.version}</version> <version>${junit.version}</version>
<type>jar</type> <type>jar</type>
</dependency> </dependency>
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
<!-- ************* END: Dependencies for Unit and Integration Testing ************** --> <!-- ************* END: Dependencies for Unit and Integration Testing ************** -->
<!-- ************* END: <dependencies> ************** --> <!-- ************* END: <dependencies> ************** -->
</dependencies> </dependencies>

View File

@ -42,6 +42,7 @@ import org.thymeleaf.templateresolver.TemplateResolver;
import java.io.*; import java.io.*;
import java.util.Map; import java.util.Map;
import static org.apache.commons.lang3.CharEncoding.UTF_8;
import static org.asciidoctor.Asciidoctor.Factory.create; import static org.asciidoctor.Asciidoctor.Factory.create;
/** /**
@ -82,7 +83,7 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
} else { } else {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes()); return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8));
} }
} catch (IOException e) { } catch (IOException e) {
//no html yet //no html yet

View File

@ -23,11 +23,5 @@ public class CleanupLocalProgressFiles {
@PostConstruct @PostConstruct
public void clean() { public void clean() {
File dir = new File(webgoatHome);
//do it safe, check whether the subdir mongodb is available as subdirectory
File[] mongoDir = dir.listFiles(f -> f.isDirectory() && f.getName().contains("mongodb"));
if (mongoDir != null && mongoDir.length == 1) {
FileSystemUtils.deleteRecursively(dir);
}
} }
} }

View File

@ -2,6 +2,10 @@ package org.owasp.webgoat.lessons;
import lombok.*; import lombok.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.util.List; import java.util.List;
/** /**
@ -38,11 +42,14 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@Getter @Getter
@EqualsAndHashCode @EqualsAndHashCode
@Entity
public class Assignment { public class Assignment {
@NonNull @NonNull
@Id
private String name; private String name;
@NonNull @NonNull
private String path; private String path;
@Transient
private List<String> hints; private List<String> hints;
} }

View File

@ -7,6 +7,7 @@ import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import javax.persistence.*;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -44,16 +45,20 @@ import java.util.stream.Collectors;
* @version $Id: $Id * @version $Id: $Id
* @since October 29, 2003 * @since October 29, 2003
*/ */
@Entity
public class LessonTracker { public class LessonTracker {
@Getter @Getter
@Id
private String lessonName; private String lessonName;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private final Set<Assignment> solvedAssignments = Sets.newHashSet(); private final Set<Assignment> solvedAssignments = Sets.newHashSet();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private final List<Assignment> allAssignments = Lists.newArrayList(); private final List<Assignment> allAssignments = Lists.newArrayList();
@Getter @Getter
private int numberOfAttempts = 0; private int numberOfAttempts = 0;
protected LessonTracker() { private LessonTracker() {
//Mongo //JPA
} }
public LessonTracker(AbstractLesson lesson) { public LessonTracker(AbstractLesson lesson) {

View File

@ -1,6 +1,6 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List; import java.util.List;
@ -8,7 +8,7 @@ import java.util.List;
* @author nbaars * @author nbaars
* @since 3/19/17. * @since 3/19/17.
*/ */
public interface UserRepository extends MongoRepository<WebGoatUser, String> { public interface UserRepository extends JpaRepository<WebGoatUser, String> {
WebGoatUser findByUsername(String username); WebGoatUser findByUsername(String username);

View File

@ -5,8 +5,8 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import org.springframework.data.annotation.Id;
import javax.persistence.*;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -44,12 +44,16 @@ import java.util.stream.Collectors;
* @since October 29, 2003 * @since October 29, 2003
*/ */
@Slf4j @Slf4j
@Entity
public class UserTracker { public class UserTracker {
@Id @Id
private final String user; private String user;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<LessonTracker> lessonTrackers = Lists.newArrayList(); private List<LessonTracker> lessonTrackers = Lists.newArrayList();
private UserTracker() {}
public UserTracker(final String user) { public UserTracker(final String user) {
this.user = user; this.user = user;
} }

View File

@ -1,12 +1,12 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.jpa.repository.JpaRepository;
/** /**
* @author nbaars * @author nbaars
* @since 4/30/17. * @since 4/30/17.
*/ */
public interface UserTrackerRepository extends MongoRepository<UserTracker, String> { public interface UserTrackerRepository extends JpaRepository<UserTracker, String> {
} }

View File

@ -1,13 +1,14 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import lombok.Getter; import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -16,6 +17,7 @@ import java.util.Collections;
* @since 3/19/17. * @since 3/19/17.
*/ */
@Getter @Getter
@Entity
public class WebGoatUser implements UserDetails { public class WebGoatUser implements UserDetails {
public static final String ROLE_USER = "WEBGOAT_USER"; public static final String ROLE_USER = "WEBGOAT_USER";

View File

@ -4,6 +4,9 @@ server.session.timeout=600
server.contextPath=/WebGoat server.contextPath=/WebGoat
server.port=8080 server.port=8080
spring.datasource.url=jdbc:hsqldb:file:${webgoat.server.directory}/data/webgoat
spring.jpa.hibernate.ddl-auto=update
logging.level.org.springframework=WARN logging.level.org.springframework=WARN
logging.level.org.springframework.boot.devtools=WARN logging.level.org.springframework.boot.devtools=WARN
@ -28,7 +31,6 @@ webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org
webgoat.database.driver=org.hsqldb.jdbcDriver webgoat.database.driver=org.hsqldb.jdbcDriver
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en webgoat.default.language=en
webgoat.embedded.mongo=${WG_INTERNAL_MONGO:true}
webwolf.host=${WEBWOLF_HOST:localhost} webwolf.host=${WEBWOLF_HOST:localhost}
webwolf.port=${WEBWOLF_PORT:8081} webwolf.port=${WEBWOLF_PORT:8081}
@ -39,10 +41,5 @@ webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail
spring.jackson.serialization.indent_output=true spring.jackson.serialization.indent_output=true
spring.jackson.serialization.write-dates-as-timestamps=false spring.jackson.serialization.write-dates-as-timestamps=false
spring.data.mongodb.host=${WG_MONGO_HOST:localhost}
spring.data.mongodb.port=${WG_MONGO_PORT:27017}
spring.data.mongodb.database=webgoat
spring.mongodb.embedded.storage.databaseDir=${webgoat.user.directory}/mongodb/
#For static file refresh ... and faster dev :D #For static file refresh ... and faster dev :D
spring.devtools.restart.additional-paths=webgoat-container/src/main/resources/static/js,webgoat-container/src/main/resources/static/css spring.devtools.restart.additional-paths=webgoat-container/src/main/resources/static/js,webgoat-container/src/main/resources/static/css

View File

@ -1,23 +0,0 @@
package org.owasp.webgoat.plugins;
import com.github.fakemongo.Fongo;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
/**
* Using Fongo for embedded in memory MongoDB testing
*/
@Configuration
public class TestConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongo() throws Exception {
return new Fongo(getDatabaseName()).getMongo();
}
}

View File

@ -0,0 +1,29 @@
package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
@DataJpaTest
@RunWith(SpringRunner.class)
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void userShouldBeSaved() {
WebGoatUser user = new WebGoatUser("test", "password");
userRepository.saveAndFlush(user);
user = userRepository.findByUsername("test");
Assertions.assertThat(user.getUsername()).isEqualTo("test");
Assertions.assertThat(user.getPassword()).isEqualTo("password");
}
}

View File

@ -0,0 +1,101 @@
package org.owasp.webgoat.users;
import org.assertj.core.api.Assertions;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.NewLesson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@DataJpaTest
@RunWith(SpringRunner.class)
public class UserTrackerRepositoryTest {
private class TestLesson extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.AJAX_SECURITY;
}
@Override
public List<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 12;
}
@Override
public String getTitle() {
return "test";
}
@Override
public String getId() {
return "test";
}
@Override
public List<Assignment> getAssignments() {
Assignment assignment = new Assignment("test", "test", Lists.newArrayList());
return Lists.newArrayList(assignment);
}
}
@Autowired
private UserTrackerRepository userTrackerRepository;
@Test
public void saveUserTracker() {
UserTracker userTracker = new UserTracker("test");
LessonTracker lessonTracker = userTracker.getLessonTracker(new TestLesson());
userTrackerRepository.save(userTracker);
userTracker = userTrackerRepository.findOne("test");
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull();
}
@Test
public void solvedAssignmentsShouldBeSaved() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentSolved(lesson, "test");
userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findOne("test");
Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1);
}
@Test
public void saveAndLoadShouldHaveCorrectNumberOfAttemtps() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findOne("test");
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker);
Assertions.assertThat(userTracker.getLessonTracker(lesson).getNumberOfAttempts()).isEqualTo(4);
}
}

View File

@ -1 +1,4 @@
webgoat.user.directory=${java.io.tmpdir} webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
spring.jpa.hibernate.ddl-auto=create-drop

View File

@ -43,34 +43,13 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>provided</scope> <scope>provided</scope>
<type>jar</type> <type>jar</type>
<!-- Exclude Mongo embedded so testcases do not start it automatically, seems to be
the easiest way to stop the autoconfiguration of Spring Boot -->
<exclusions>
<exclusion>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!--<dependency>-->
<!--<groupId>org.apache.commons</groupId>-->
<!--<artifactId>commons-exec</artifactId>-->
<!--<version>1.3</version>-->
<!--</dependency>-->
<dependency> <dependency>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-container</artifactId> <artifactId>webgoat-container</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<classifier>tests</classifier> <classifier>tests</classifier>
<scope>test</scope> <scope>test</scope>
<!-- Exclude Mongo embedded so testcases do not start it automatically, seems to be
the easiest way to stop the autoconfiguration of Spring Boot -->
<exclusions>
<exclusion>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
@ -96,12 +75,6 @@
<version>4.1.3.RELEASE</version> <version>4.1.3.RELEASE</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.owasp.encoder</groupId> <groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId> <artifactId>encoder</artifactId>

View File

@ -10,7 +10,5 @@ COPY start.sh /home/webgoat/start.sh
RUN chmod +x /home/webgoat/start.sh RUN chmod +x /home/webgoat/start.sh
USER webgoat USER webgoat
RUN mkdir -p /home/webgoat/.embedmongo/linux
RUN curl -o /home/webgoat/.embedmongo/linux/mongodb-linux-x86_64-3.2.2.tgz https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.2.tgz
RUN cd /home/webgoat/; mkdir -p .webgoat RUN cd /home/webgoat/; mkdir -p .webgoat
COPY target/webgoat-server-${webgoat_version}.jar /home/webgoat/webgoat.jar COPY target/webgoat-server-${webgoat_version}.jar /home/webgoat/webgoat.jar

View File

@ -90,11 +90,6 @@
<scope>test</scope> <scope>test</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>2.0.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-container</artifactId> <artifactId>webgoat-container</artifactId>

View File

@ -1,40 +0,0 @@
package org.owasp.webgoat;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import de.flapdoodle.embed.mongo.MongodExecutable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import java.io.IOException;
/**
* If we run
*/
@Configuration
@ConditionalOnProperty(value = "webgoat.embedded.mongo", havingValue = "false")
public class ExternalMongoConfiguration {
@Autowired
private MongoProperties properties;
@Autowired(required = false)
private MongoClientOptions options;
@Bean
public MongodExecutable mongodExecutable() throws IOException {
return null;
}
@Bean
public MongoDbFactory mongoDbFactory(Environment env) throws Exception {
MongoClient client = properties.createMongoClient(this.options, env);
return new SimpleMongoDbFactory(client, properties.getDatabase());
}
}

View File

@ -1,4 +0,0 @@
WG_MONGO_PORT=27017
WG_MONGO_HOST=mongo
WG_MQ_HOST=activemq
WG_MQ_PORT=61616

View File

@ -139,7 +139,7 @@ developer_bootstrap() {
sleep 5 sleep 5
# Starting WebGoat # Starting WebGoat
mvn -q -pl webgoat-container spring-boot:run mvn -q -pl webgoat-server spring-boot:run
} }
# Start main script # Start main script

View File

@ -55,7 +55,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -73,6 +73,11 @@
<artifactId>jquery</artifactId> <artifactId>jquery</artifactId>
<version>3.2.1</version> <version>3.2.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -4,10 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -18,7 +17,7 @@ import java.time.format.DateTimeFormatter;
*/ */
@Builder @Builder
@Data @Data
@Document @Entity
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class Email implements Serializable { public class Email implements Serializable {
@ -29,7 +28,6 @@ public class Email implements Serializable {
private String contents; private String contents;
private String sender; private String sender;
private String title; private String title;
@Indexed
private String recipient; private String recipient;
public String getSummary() { public String getSummary() {

View File

@ -1,7 +1,6 @@
package org.owasp.webwolf.mailbox; package org.owasp.webwolf.mailbox;
import org.bson.types.ObjectId; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List; import java.util.List;
@ -9,7 +8,7 @@ import java.util.List;
* @author nbaars * @author nbaars
* @since 8/17/17. * @since 8/17/17.
*/ */
public interface MailboxRepository extends MongoRepository<Email, ObjectId> { public interface MailboxRepository extends JpaRepository<Email, String> {
List<Email> findByRecipientOrderByTimeDesc(String recipient); List<Email> findByRecipientOrderByTimeDesc(String recipient);

View File

@ -0,0 +1,47 @@
package org.owasp.webwolf.user;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
/**
* @author nbaars
* @since 3/19/17.
*/
@Controller
@AllArgsConstructor
@Slf4j
public class RegistrationController {
private UserValidator userValidator;
private UserService userService;
private AuthenticationManager authenticationManager;
@GetMapping("/registration")
public String showForm(UserForm userForm) {
return "registration";
}
@PostMapping("/register.mvc")
@SneakyThrows
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.addUser(userForm.getUsername(), userForm.getPassword());
request.login(userForm.getUsername(), userForm.getPassword());
return "redirect:/WebWolf/home";
}
}

View File

@ -0,0 +1,28 @@
package org.owasp.webwolf.user;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* @author nbaars
* @since 3/19/17.
*/
@Getter
@Setter
public class UserForm {
@NotNull
@Size(min=6, max=20)
private String username;
@NotNull
@Size(min=6, max=10)
private String password;
@NotNull
@Size(min=6, max=10)
private String matchingPassword;
@NotNull
private String agree;
}

View File

@ -1,12 +1,12 @@
package org.owasp.webwolf.user; package org.owasp.webwolf.user;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.jpa.repository.JpaRepository;
/** /**
* @author nbaars * @author nbaars
* @since 3/19/17. * @since 3/19/17.
*/ */
public interface UserRepository extends MongoRepository<WebGoatUser, String> { public interface UserRepository extends JpaRepository<WebGoatUser, String> {
WebGoatUser findByUsername(String username); WebGoatUser findByUsername(String username);
} }

View File

@ -27,4 +27,9 @@ public class UserService implements UserDetailsService {
} }
public void addUser(String username, String password) {
userRepository.save(new WebGoatUser(username, password));
}
} }

View File

@ -0,0 +1,35 @@
package org.owasp.webwolf.user;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* @author nbaars
* @since 3/19/17.
*/
@Component
@AllArgsConstructor
public class UserValidator implements Validator {
private final UserRepository userRepository;
@Override
public boolean supports(Class<?> aClass) {
return UserForm.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
UserForm userForm = (UserForm) o;
if (userRepository.findByUsername(userForm.getUsername()) != null) {
errors.rejectValue("username", "username.duplicate");
}
if (!userForm.getMatchingPassword().equals(userForm.getPassword())) {
errors.rejectValue("matchingPassword", "password.diff");
}
}
}

View File

@ -1,13 +1,14 @@
package org.owasp.webwolf.user; package org.owasp.webwolf.user;
import lombok.Getter; import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -16,6 +17,7 @@ import java.util.Collections;
* @since 3/19/17. * @since 3/19/17.
*/ */
@Getter @Getter
@Entity
public class WebGoatUser implements UserDetails { public class WebGoatUser implements UserDetails {
public static final String ROLE_USER = "WEBGOAT_USER"; public static final String ROLE_USER = "WEBGOAT_USER";

View File

@ -5,6 +5,10 @@ server.session.timeout=6000
server.port=8081 server.port=8081
server.session.cookie.name = WEBWOLFSESSION server.session.cookie.name = WEBWOLFSESSION
spring.datasource.url=jdbc:hsqldb:file:${webgoat.server.directory}/data/webwolf
spring.jpa.hibernate.ddl-auto=update
spring.messages.basename=i18n/messages
logging.level.org.springframework=INFO logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=WARN logging.level.org.springframework.boot.devtools=WARN
logging.level.org.owasp=DEBUG logging.level.org.owasp=DEBUG
@ -25,12 +29,9 @@ 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/
webwolf.fileserver.location=${java.io.tmpdir}/webwolf-fileserver webwolf.fileserver.location=${java.io.tmpdir}/webwolf-fileserver
spring.data.mongodb.host=${WG_MONGO_HOST:}
spring.data.mongodb.port=${WG_MONGO_PORT:27017}
spring.data.mongodb.database=webgoat
spring.jackson.serialization.indent_output=true spring.jackson.serialization.indent_output=true
spring.jackson.serialization.write-dates-as-timestamps=false spring.jackson.serialization.write-dates-as-timestamps=false

View File

@ -0,0 +1,40 @@
#
# This file is part of WebGoat, an Open Web Application Security Project utility. For details,
# please see http://www.owasp.org/
# <p>
# Copyright (c) 2002 - 2017 Bruce Mayhew
# <p>
# This program is free software; you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
# <p>
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# <p>
# You should have received a copy of the GNU General Public License along with this program; if
# not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# <p>
# Getting Source ==============
# <p>
# Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
# projects.
# <p>
#
register.new=Register new user
sign.up=Sign up
register.title=Register
password=Password
password.confirm=Confirm password
username=Username
not.empty=This field is required.
username.size=Please use between 6 and 10 characters.
username.duplicate=User already exists.
password.size=Password should at least contain 6 characters
password.diff=The passwords do not match.

View File

@ -45,6 +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>
</fieldset> </fieldset>
</form> </form>
</div> </div>

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<br/><br/>
<fieldset>
<legend th:text="#{register.title}">Please Sign Up</legend>
<form class="form-horizontal" action="#" th:action="@{/register.mvc}" th:object="${userForm}"
method='POST'>
<div class="form-group" th:classappend="${#fields.hasErrors('username')}? 'has-error'">
<label for="username" class="col-sm-2 control-label" th:text="#{username}">Username</label>
<div class="col-sm-4">
<input autofocus="dummy_for_thymeleaf_parser" type="text" class="form-control"
th:field="*{username}"
id="username" placeholder="Username" name='username'/>
</div>
<span th:if="${#fields.hasErrors('username')}" th:errors="*{username}">Username error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<label for="password" class="col-sm-2 control-label" th:text="#{password}">Password</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" placeholder="Password"
name='password' th:value="*{password}"/>
</div>
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('matchingPassword')}? 'has-error'">
<label for="matchingPassword" class="col-sm-2 control-label" th:text="#{password.confirm}">Confirm
password</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="matchingPassword" placeholder="Password"
name='matchingPassword' th:value="*{matchingPassword}"/>
</div>
<span th:if="${#fields.hasErrors('matchingPassword')}"
th:errors="*{matchingPassword}">Password error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('agree')}? 'has-error'">
<label class="col-sm-2 control-label">Terms of use</label>
<div class="col-sm-6">
<div style="border: 1px solid #e5e5e5; height: 200px; overflow: auto; padding: 10px;">
<p>
While running this program your machine will be extremely
vulnerable to attack. You should disconnect from the Internet while using
this program. WebGoat's default configuration binds to localhost to minimize
the exposure.
</p>
<p>
This program is for educational purposes only. If you attempt
these techniques without authorization, you are very likely to get caught. If
you are caught engaging in unauthorized hacking, most companies will fire you.
Claiming that you were doing security research will not work as that is the
first thing that all hackers claim.
</p>
</div>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('agree')}? 'has-error'">
<div class="col-sm-6 col-sm-offset-2">
<div class="checkbox">
<label>
<input type="checkbox" name="agree" value="agree"/>Agree with the terms and
conditions
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<button type="submit" class="btn btn-primary" th:text="#{sign.up}">Sign up</button>
</div>
</div>
</form>
</fieldset>
</div>
</body>
</html>