Travis now builds Docker and create a Github release.

Removed ActiveMQ between WebGoat and WebWolf they now act as standalone applications
This commit is contained in:
Nanne Baars 2017-10-13 23:30:22 +02:00
parent 50543a9b55
commit 3ee1a1ca16
43 changed files with 291 additions and 453 deletions

1
.gitignore vendored
View File

@ -38,3 +38,4 @@ webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom
webgoat-lessons/**/target
**/*.jar
**/.DS_Store
webgoat-server/mongo-data/*

View File

@ -3,40 +3,36 @@ jdk:
- oraclejdk8
install: "/bin/true"
script:
- mvn clean install
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
- echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH"
- mvn clean install -q
cache:
directories:
- "$HOME/.m2"
before_deploy:
- export WEBGOAT_SERVER_TARGET_DIR=$HOME/build/$TRAVIS_REPO_SLUG/webgoat-server/target
- export WEBGOAT_ARTIFACTS_FOLDER=$HOME/build/$TRAVIS_REPO_SLUG/Deployable_Artifacts/
- mkdir $WEBGOAT_ARTIFACTS_FOLDER
- cp -fa $WEBGOAT_SERVER_TARGET_DIR/*.jar $WEBGOAT_ARTIFACTS_FOLDER/
- echo "Contents of artifacts folder:"
- ls $WEBGOAT_ARTIFACTS_FOLDER
deploy:
provider: heroku
api_key:
secure: eqSm5syJhyvIwxQ/ZCMtfFVayiZjsr+1m0eIR36FKMU6iSz5V351G+VNjCy/G+7EIsm+KuoLHqbl+NxmmOsDf2YoQk8KAdnbecMLWVwB+VncLM0ZU4mEEBt3lJWUzStoy9UNgzKs6Nc/HQ0zllV61NfgFS17pNHvce5WfjKHzTA=
app: WebGoat
on:
repo: WebGoat/WebGoat
branch: develop
after_success:
- mvn versioneye:update
- mvn cobertura:cobertura coveralls:report
notifications:
slack:
secure: S9VFew5NSE8WDzYD1VDBUULKKT0fzgblQACznwQ85699b2yeX9TX58N3RZvRS1JVagVP1wu2xOrwN2g+AWx4Ro3UBZD5XG86uTJWpCLD4cRWHBoGMH2TfvI7/IzsWmgxH4MBxFRvZr/eEhlVAux+N9H4EoEdS4CKsJXEqV37PlA=
- provider: script
skip_cleanup: true
script: bash scripts/deploy-webgoat.sh
on:
repo: WebGoat/WebGoat
tags: true
- provider: script
skip_cleanup: true
script: bash scripts/deploy-webgoat.sh
on:
repo: WebGoat/WebGoat
branch: develop
- provider: releases
api_key:
#api-key from webgoat-github user
secure: pJOLBnl6427PcVg/tVy/qB18JC7b8cKpffau+IP0pjdSt7KUfBdBY3QuJ7mrM65zRoVILzggLckaew2PlRmYQRdumyWlyRn44XiJ9KO4n6Bsufbz+ictB4ggtozpp9+I9IIUh1TmqypL9lhkX2ONM9dSHmyblYpAAgMuYSK8FYc=
file: "webgoat-server/target/webgoat-server*.jar"
on:
repo: WebGoat/WebGoat
tags: true
env:
global:
- secure: ZLZKz6lGt8YZ+NhkZPBAlI235+lEmu37Tcf+yTwh5yXuHAlnvvF6hPui7rANA/stbYGOIqIdhGOXbdrwyTU4Pvg78VwJOwsa9RtHJfou3pg4Ud9i0/dEeVl8aakmg2HDaWYGcFox8X1ViVc5UWjuBLztfJKQUEx0buJoWdMSf2E=
addons:
coverity_scan:
project:
name: WebGoat/WebGoat
description: Coverity Scan from Travis CI Build Automation
notification_email: webgoat@owasp.org
build_command_prepend: mvn clean
build_command: mvn -DskipTests=true package
branch_pattern: coverity_scan
#Docker login
- secure: XgPc0UKRTUI70I4YWNQpThPPWeQIxkmzh1GNoR/SSDC2GPIBq3EfkkbSQewqil8stTy+S1/xSzc0JXG8NTn7UOxHVHA/2nhI6jX9E+DKtXQ89YwmaDNQjkbMjziAtDCIex+5TRykxNfkxj6VPYbDssrzI7iJXOIZVj/HoyO3O5E=
#Docker password
- secure: aly5TKBUK9sIiqtMbytNNPZHQhC0a7Yond5tEtuJ8fO+j/KZB4Uro3I6BhzYjGWFb5Kndd0j2TXHPFvtOl402J1CmFsY3v0BhilQd0g6zOssp5T0A73m8Jgq4ItV8wQJJy2bQsXqL1B+uFYieYPiMchj7JxWW0vBn7TV5b68l6U=

View File

@ -41,7 +41,7 @@ First install Docker, then open a command shell/window and type:
```Shell
docker pull webgoat/webgoat-8.0
docker run -p 8080:8080 webgoat/webgoat-8.0
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
```
Wait for the Docker container to start, and run `docker ps` to verify it's running.
@ -60,7 +60,16 @@ Here you'll be able to register a new user and get started.
_Please note: this version may not be completely in sync with the develop branch._
## 2. Run from the sources
## 2. Standalone
Download the latest WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
```Shell
java -jar webwolf-<<version>>.jar
```
## 3. Run from the sources
### Prerequisites:
@ -86,7 +95,7 @@ mvn clean install
Now we are ready to run the project. WebGoat 8.x is using Spring-Boot.
```Shell
mvn -pl webgoat-server spring-boot:run
mvn -pl webwolf spring-boot:run
```
... you should be running webgoat on localhost:8080/WebGoat momentarily
@ -118,7 +127,7 @@ On x86 you can build a container with the following commands:
cd WebGoat/
mvn install
cd webgoat-server
mvn docker:build
docker build -t webgoat/webgoat-8.0 .
docker tag webgoat/webgoat-8.0 webgoat/webgoat-8.0:8.0
docker login
docker push webgoat/webgoat-8.0

40
docker-compose.yml Normal file
View File

@ -0,0 +1,40 @@
version: '2.0'
services:
activemq:
image: webcenter/activemq:latest
ports:
- 8161:8161
- 61616:61616
- 61613:61613
mongo:
image: mongo:latest
expose:
- "27017"
volumes:
- './mongo-data:/data/db'
webgoat:
build: webgoat-server/
command: "sh /home/webgoat/start.sh"
ports:
- "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:
build: webwolf/
command: "sh /home/webwolf/start.sh"
depends_on:
- webgoat
ports:
- "8081:8081"
environment:
WG_MONGO_PORT: 27017
WG_MONGO_HOST: mongo
WG_MQ_HOST: activemq
WG_MQ_PORT: 61616

View File

@ -168,7 +168,6 @@
</properties>
<modules>
<module>webgoat-commons</module>
<module>webgoat-container</module>
<module>webgoat-lessons</module>
<module>webgoat-server</module>

23
scripts/deploy-webgoat.sh Normal file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
#docker login -u $DOCKER_USER -p $DOCKER_PASS
export REPO=webgoat/webgoat-8.0
cd webgoat-server
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 -f Dockerfile -t $REPO:latest .
docker tag $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 -f Dockerfile -t $REPO:${TRAVIS_TAG} .
docker tag $REPO:${TRAVIS_TAG}
docker push $REPO
elif [ "${BRANCH}" == "develop" ]; then
docker build -f Dockerfile -t $REPO:snapshot .
docker push $REPO
else
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
fi

View File

@ -1,37 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>webgoat-commons</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId>
<version>8.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>ISO-8859-1</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,15 +0,0 @@
package org.owasp.webgoat.login;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author nbaars
* @since 8/20/17.
*/
@Data
@AllArgsConstructor
public class LoginEvent {
private String user;
private String cookie;
}

View File

@ -1,14 +0,0 @@
package org.owasp.webgoat.login;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author nbaars
* @since 8/20/17.
*/
@AllArgsConstructor
@Data
public class LogoutEvent {
private String user;
}

View File

@ -13,7 +13,6 @@
<version>8.0-SNAPSHOT</version>
</parent>
<profiles>
<profile>
<id>performance</id>
@ -34,23 +33,6 @@
</plugins>
</build>
</profile>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>ctf</id>
<!-- Connect to real mongodb -->
</profile>
</profiles>
@ -149,11 +131,6 @@
</build>
<dependencies>
<dependency>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
@ -178,16 +155,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>1.5.4</version>

View File

@ -1,23 +1,15 @@
package org.owasp.webgoat;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.login.LoginEvent;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
import static java.util.Optional.empty;
import static java.util.Optional.of;
/**
* *************************************************************************************************
@ -58,34 +50,12 @@ import static java.util.Optional.of;
public class HammerHead {
private final Course course;
private JmsTemplate jmsTemplate;
/**
* Entry point for WebGoat, redirects to the first lesson found within the course.
*/
@RequestMapping(path = "/attack", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView attack(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
sendUserLoggedInMessage(request, response, authentication);
return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink());
}
private void sendUserLoggedInMessage(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
WebGoatUser user = (WebGoatUser) authentication.getPrincipal();
getWebGoatCookie(request).ifPresent(c -> {
jmsTemplate.convertAndSend("webgoat", new LoginEvent(user.getUsername(), c.getValue()), m -> {
m.setStringProperty("type", LoginEvent.class.getSimpleName());
return m;
}
);
});
}
private Optional<Cookie> getWebGoatCookie(HttpServletRequest request) {
for (Cookie c : request.getCookies()) {
if (c.getName().equals("JSESSIONID")) {
return of(c);
}
}
return empty();
}
}

View File

@ -1,35 +0,0 @@
package org.owasp.webgoat;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.activemq.broker.BrokerService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
/**
* @author nbaars
* @since 8/20/17.
*/
@Configuration
public class JmsConfig {
@Bean(initMethod = "start", destroyMethod = "stop")
public BrokerService broker() throws Exception {
final BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61616");
broker.addConnector("vm://localhost");
broker.setPersistent(false);
return broker;
}
@Bean
public MessageConverter jacksonJmsMessageConverter(ObjectMapper objectMapper) {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setObjectMapper(objectMapper);
converter.setTypeIdPropertyName("_type");
return converter;
}
}

View File

@ -50,6 +50,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.util.Arrays;
@ -94,6 +95,11 @@ public class WebGoat extends SpringBootServletInitializer {
return new PluginsLoader(pluginEndpointPublisher).loadPlugins();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

View File

@ -31,7 +31,6 @@
package org.owasp.webgoat;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.login.LogoutHandler;
import org.owasp.webgoat.users.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@ -53,7 +52,6 @@ import org.springframework.security.core.userdetails.UserDetailsService;
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
private final LogoutHandler logoutHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
@ -71,8 +69,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.passwordParameter("password")
.permitAll();
security.and()
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true)
.permitAll().logoutSuccessHandler(logoutHandler);
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
security.and().csrf().disable();
http.headers().cacheControl().disable();

View File

@ -1,47 +0,0 @@
package org.owasp.webgoat.login;
import lombok.AllArgsConstructor;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
/**
* @author nbaars
* @since 8/20/17.
*/
@AllArgsConstructor
@Component
public class LogoutHandler extends SimpleUrlLogoutSuccessHandler {
private JmsTemplate jmsTemplate;
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
if (authentication != null) {
WebGoatUser user = (WebGoatUser) authentication.getPrincipal();
jmsTemplate.convertAndSend("webgoat", new LogoutEvent(user.getUsername()), m -> {
m.setStringProperty("type", LogoutEvent.class.getSimpleName());
return m;
});
}
super.onLogoutSuccess(httpServletRequest, httpServletResponse, authentication);
}
private Optional<Cookie> findSessionCookie(Cookie[] cookies) {
for (Cookie cookie : cookies) {
if ("JSESSIONID".equals(cookie.getName())) {
return Optional.of(cookie);
}
}
return Optional.empty();
}
}

View File

@ -28,17 +28,20 @@ webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org
webgoat.database.driver=org.hsqldb.jdbcDriver
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en
webgoat.embedded.mongo=${WG_INTERNAL_MONGO:true}
webwolf.port=8081
webwolf.url=http://localhost:${webwolf.port}/WebWolf
webworf.url.landingpage=http://localhost:${webwolf.port}/landing
webworf.url.mail=http://localhost:${webwolf.port}/mail
spring.jackson.serialization.indent_output=true
spring.jackson.serialization.write-dates-as-timestamps=false
spring.activemq.brokerUrl=tcp://localhost:61616
spring.activemq.brokerUrl=tcp://${WG_MQ_HOST:localhost}:${WG_MQ_PORT:61616}
spring.data.mongodb.port=27017
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/

View File

@ -1,19 +0,0 @@
package org.owasp.webgoat.plugins;
import org.apache.activemq.broker.BrokerService;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author nbaars
* @since 8/30/17.
*/
@Configuration
public class JmsTestConfig {
@Bean
public BrokerService broker() throws Exception {
return Mockito.mock(BrokerService.class);
}
}

View File

@ -9,7 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
@ -24,7 +23,6 @@ import static org.mockito.Mockito.when;
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:/application-test.properties")
@Import(JmsTestConfig.class)
public abstract class LessonTest {
@LocalServerPort

View File

@ -1,8 +1,9 @@
package org.owasp.webgoat.mail;
package org.owasp.webgoat.plugin;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
@ -11,7 +12,7 @@ import java.time.LocalDateTime;
*/
@Builder
@Data
public class IncomingMailEvent {
public class Email implements Serializable {
private LocalDateTime time;
private String contents;

View File

@ -5,16 +5,17 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.mail.IncomingMailEvent;
import org.owasp.webgoat.plugin.Email;
import org.owasp.webgoat.plugin.SolutionConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
@ -43,7 +44,9 @@ public class Assignment7 extends AssignmentEndpoint {
"Kind regards, \nTeam WebGoat";
@Autowired
private JmsTemplate jmsTemplate;
private RestTemplate restTemplate;
@Value("${webworf.url.mail}")
private String webWolfMailURL;
@GetMapping("/reset-password/{link}")
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
@ -62,13 +65,13 @@ public class Assignment7 extends AssignmentEndpoint {
String username = email.substring(0, email.indexOf("@"));
if (StringUtils.hasText(username)) {
URI uri = new URI(request.getRequestURL().toString());
IncomingMailEvent mail = IncomingMailEvent.builder()
Email mail = Email.builder()
.title("Your password reset link for challenge 7")
.contents(String.format(TEMPLATE, uri.getScheme() + "://" + uri.getHost(), new PasswordResetLink().createPasswordReset(username, "webgoat")))
.sender("password-reset@webgoat-cloud.net")
.recipient(username)
.time(LocalDateTime.now()).build();
jmsTemplate.convertAndSend("mailbox", mail);
restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
}
}
return success().feedback("email.send").feedbackArgs(email).build();

View File

@ -7,14 +7,14 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.mail.IncomingMailEvent;
import org.owasp.webgoat.plugin.Email;
import org.owasp.webgoat.users.UserRepository;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
@ -53,9 +53,11 @@ public class Assignment9 extends AssignmentEndpoint {
"Kind regards, \nTeam WebGoat";
@Autowired
private JmsTemplate jmsTemplate;
private RestTemplate restTemplate;
@Autowired
private UserRepository userRepository;
@Value("${webwolf.url}")
private String webWolfURL;
@RequestMapping(method = POST, value = "/create-password-reset-link")
@ResponseBody
@ -79,13 +81,13 @@ public class Assignment9 extends AssignmentEndpoint {
WebGoatUser webGoatUser = userRepository.findByUsername(email.substring(0, email.indexOf("@")));
if (webGoatUser != null) {
username = webGoatUser.getUsername();
IncomingMailEvent mail = IncomingMailEvent.builder()
Email mail = Email.builder()
.title("Your password reset link for challenge 9")
.contents(String.format(TEMPLATE, host, resetLink))
.sender("password-reset@webgoat-cloud.net")
.recipient(username)
.time(LocalDateTime.now()).build();
jmsTemplate.convertAndSend("mailbox", mail);
restTemplate.postForEntity(webWolfURL + "/WebWolf/mail", mail, Object.class);
}
}

View File

@ -1,13 +1,13 @@
package org.owasp.webgoat.plugin;
import com.sun.corba.se.spi.activation.EndPointInfo;
import org.owasp.webgoat.assignments.*;
import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.users.UserService;
import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@ -26,7 +26,7 @@ public class MissingFunctionACUsers {
@Autowired
private UserService userService;
@RequestMapping(path = {"users", "/"}, method = RequestMethod.GET)
@RequestMapping(path = {"users"}, method = RequestMethod.GET)
public ModelAndView listUsers(HttpServletRequest request) {
ModelAndView model = new ModelAndView();

View File

@ -0,0 +1,18 @@
package org.owasp.webgoat.plugin;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Builder
@Data
public class Email implements Serializable {
private LocalDateTime time;
private String contents;
private String sender;
private String title;
private String recipient;
}

View File

@ -1,15 +1,14 @@
package org.owasp.webgoat.plugin;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.mail.IncomingMailEvent;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
@ -18,29 +17,33 @@ import java.time.LocalDateTime;
* @since 8/20/17.
*/
@AssignmentPath("/WebWolf/mail")
@AllArgsConstructor
public class MailAssignment extends AssignmentEndpoint {
private JmsTemplate jmsTemplate;
private final String webWolfURL;
private RestTemplate restTemplate;
public MailAssignment(RestTemplate restTemplate, @Value("${webwolf.url}") String webWolfURL) {
this.restTemplate = restTemplate;
this.webWolfURL = webWolfURL;
}
@PostMapping("send")
@ResponseBody
public AttackResult sendEmail(@RequestParam String email) {
String username = email.substring(0, email.indexOf("@"));
if (username.equals(getWebSession().getUserName())) {
IncomingMailEvent mailEvent = IncomingMailEvent.builder()
Email mailEvent = Email.builder()
.recipient(username)
.title("Test messages from WebWolf")
.time(LocalDateTime.now())
.contents("This is a test message from WebWolf, your unique code is" + StringUtils.reverse(username))
.sender("webgoat@owasp.org")
.build();
jmsTemplate.convertAndSend("mailbox", mailEvent);
restTemplate.postForEntity(webWolfURL + "/WebWolf/mail", mailEvent, Object.class);
return informationMessage().feedback("webwolf.email_send").feedbackArgs(email).build();
} else {
return informationMessage().feedback("webwolf.email_mismatch").feedbackArgs(username).build();
}
}
@PostMapping

View File

@ -17,5 +17,12 @@ are not using the Docker image you will need to download the jar file and start
java -jar webwolf-<<version>>.jar
```
WebWolf is also available as a Docker container:
```
docker pull webwolf/webwolf-8.0
docker run -it 8081:8081 /home/webwolf/run.sh
```
This will start the application on port 8081, in your browser type: `http://localhost:8081/WebWolf`
You will be redirected to the login page where you need to login with your WebGoat username and password

15
webgoat-server/Dockerfile Normal file
View File

@ -0,0 +1,15 @@
FROM openjdk:8-jre-slim
RUN useradd --home-dir /home/webgoat --create-home -U webgoat
RUN apt-get install curl -y
COPY start.sh /home/webgoat/start.sh
RUN chmod +x /home/webgoat/start.sh
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
COPY target/webgoat-server-8.0-SNAPSHOT.jar /home/webgoat/webgoat.jar

View File

@ -62,35 +62,24 @@
<version>0.4.10</version>
<configuration>
<imageName>webgoat/webgoat-8.0</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<dockerDirectory>${project.basedir}</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
<resource>
<targetPath>/</targetPath>
<directory>${project.basedir}/../webwolf/target</directory>
<include>webwolf-${project.version}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>ctf</id>
<dependencies>
<dependency>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-container</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
@ -100,6 +89,11 @@
<version>0.4.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-container</artifactId>

View File

@ -1,12 +0,0 @@
FROM openjdk:8-jre
RUN useradd --home-dir /home/webgoat --create-home -U webgoat
USER webgoat
RUN cd /home/webgoat/; mkdir -p .webgoat
COPY webgoat-server-8.0-SNAPSHOT.jar /home/webgoat/webgoat.jar
COPY webwolf-8.0-SNAPSHOT.jar /home/webgoat/webwolf.jar
COPY startup.sh /home/webgoat/startup.sh
RUN sudo chmod +x /home/webgoat/startup.sh
CMD ["/home/webgoat/startup.sh"]

View File

@ -1,6 +0,0 @@
#!/bin/sh
java -Djava.security.egd=file:/dev/./urandom -jar /home/webgoat/webgoat.jar &
echo "Waiting for WebGoat to start..."
sleep 20
java -Djava.security.egd=file:/dev/./urandom -jar /home/webgoat/webwolf.jar

View File

@ -0,0 +1,40 @@
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

@ -39,4 +39,5 @@ public class StartWebGoat {
}
}

3
webgoat-server/start.sh Normal file
View File

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

4
webgoat.env Normal file
View File

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

8
webwolf/Dockerfile Normal file
View File

@ -0,0 +1,8 @@
FROM openjdk:8-jre-slim
RUN useradd --home-dir /home/webwolf --create-home -U webwolf
USER webwolf
RUN cd /home/webwolf/
COPY target/webwolf-8.0-SNAPSHOT.jar /home/webwolf/webwolf.jar
COPY start.sh /home/webwolf/start.sh

View File

@ -16,14 +16,14 @@ At the moment WebWolf offers support for:
- Serving files
- Logging of incoming requests (cookies etc)
## Running
# Run instructions
### Docker
## 1. Run using Docker
If you use the Docker image of WebGoat this application will automatically be available. Use the following
URL: http://localhost:8081/WebWolf
### Standalone
## 2. Standalone
```Shell
cd WebGoat

View File

@ -10,11 +10,6 @@
</parent>
<dependencies>
<dependency>
<groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
@ -62,14 +57,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>

View File

@ -1,6 +1,5 @@
package org.owasp.webwolf;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webwolf.requests.WebWolfTraceRepository;
import org.owasp.webwolf.user.UserRepository;
@ -8,18 +7,9 @@ import org.owasp.webwolf.user.WebGoatUserToCookieRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import javax.jms.ConnectionFactory;
@SpringBootApplication
@Slf4j
@ -35,25 +25,6 @@ public class WebWolf extends SpringBootServletInitializer {
return application.sources(WebWolf.class);
}
@Bean
public JmsListenerContainerFactory<?> jmsFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
@Bean
public MessageConverter jacksonJmsMessageConverter(ObjectMapper objectMapper) {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
converter.setObjectMapper(objectMapper);
return converter;
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebWolf.class, args);
}

View File

@ -1,7 +1,9 @@
package org.owasp.webwolf.mailbox;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
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;
@ -17,6 +19,8 @@ import java.time.format.DateTimeFormatter;
@Builder
@Data
@Document
@NoArgsConstructor
@AllArgsConstructor
public class Email implements Serializable {
@Id
@ -32,6 +36,10 @@ public class Email implements Serializable {
return "-" + this.contents.substring(0, 50);
}
public LocalDateTime getTimestamp() {
return time;
}
public String getTime() {
return DateTimeFormatter.ofPattern("h:mm a").format(time);
}

View File

@ -1,10 +1,12 @@
package org.owasp.webwolf.mailbox;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webwolf.user.UserRepository;
import org.owasp.webwolf.user.WebGoatUser;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@ -15,8 +17,10 @@ import java.util.List;
*/
@RestController
@AllArgsConstructor
@Slf4j
public class MailboxController {
private final UserRepository userRepository;
private final MailboxRepository mailboxRepository;
@GetMapping(value = "/WebWolf/mail")
@ -32,4 +36,14 @@ public class MailboxController {
return modelAndView;
}
@PostMapping(value = "/mail")
@ResponseStatus(HttpStatus.CREATED)
public void sendEmail(@RequestBody Email email) {
if (userRepository.findByUsername(email.getRecipient()) != null) {
mailboxRepository.save(email);
} else {
log.trace("Mail received for unknown user: {}", email.getRecipient());
}
}
}

View File

@ -1,37 +0,0 @@
package org.owasp.webwolf.mailbox;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.mail.IncomingMailEvent;
import org.owasp.webwolf.user.UserRepository;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 8/20/17.
*/
@Component
@AllArgsConstructor
@Slf4j
public class MailboxListener {
private final MailboxRepository repository;
private final UserRepository userRepository;
@JmsListener(destination = "mailbox", containerFactory = "jmsFactory")
public void incomingMail(IncomingMailEvent event) {
if (userRepository.findByUsername(event.getRecipient()) != null) {
Email email = Email.builder()
.contents(event.getContents())
.sender(event.getSender())
.time(event.getTime())
.recipient(event.getRecipient())
.title(event.getTitle()).build();
repository.save(email);
} else {
log.trace("Mail received for unknown user: {}", event.getRecipient());
}
}
}

View File

@ -1,33 +0,0 @@
package org.owasp.webwolf.user;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.login.LoginEvent;
import org.owasp.webgoat.login.LogoutEvent;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 8/20/17.
*/
@Component
@Slf4j
@AllArgsConstructor
public class LoginListener {
private final WebGoatUserToCookieRepository repository;
@JmsListener(destination = "webgoat", containerFactory = "jmsFactory", selector = "type = 'LoginEvent'")
public void loginEvent(LoginEvent loginEvent) {
log.trace("Login event occurred for user: '{}'", loginEvent.getUser());
repository.save(new WebGoatUserCookie(loginEvent.getUser(), loginEvent.getCookie()));
}
@JmsListener(destination = "webgoat", containerFactory = "jmsFactory", selector = "type = 'LogoutEvent'")
public void logoutEvent(LogoutEvent logoutEvent) {
repository.delete(logoutEvent.getUser());
}
}

View File

@ -28,13 +28,14 @@ multipart.max-request-size=1Mb
webwolf.fileserver.location=${java.io.tmpdir}/webwolf-fileserver
spring.data.mongodb.port=27017
spring.data.mongodb.host=${WG_MONGO_HOST:localhost}
spring.data.mongodb.port=${WG_MONGO_PORT:27017}
spring.data.mongodb.database=webgoat
spring.jackson.serialization.indent_output=true
spring.jackson.serialization.write-dates-as-timestamps=false
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.broker-url=tcp://${WG_MQ_HOST:localhost}:${WG_MQ_PORT:61616}
spring.activemq.in-memory=true
#For static file refresh ... and faster dev :D

3
webwolf/start.sh Normal file
View File

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