Use separate project for integration tests so we can start WebGoat and WebWolf
This commit is contained in:
parent
139651615e
commit
ff530e926e
1
pom.xml
1
pom.xml
@ -143,6 +143,7 @@
|
|||||||
<module>webgoat-lessons</module>
|
<module>webgoat-lessons</module>
|
||||||
<module>webgoat-server</module>
|
<module>webgoat-server</module>
|
||||||
<module>webwolf</module>
|
<module>webwolf</module>
|
||||||
|
<module>webgoat-integration-tests</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
|
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
|
||||||
import org.owasp.webgoat.plugins.PluginsLoader;
|
import org.owasp.webgoat.plugins.PluginsLoader;
|
||||||
import org.owasp.webgoat.session.Course;
|
import org.owasp.webgoat.session.Course;
|
||||||
@ -38,30 +37,17 @@ import org.owasp.webgoat.session.UserSessionData;
|
|||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
import org.owasp.webgoat.session.WebgoatContext;
|
import org.owasp.webgoat.session.WebgoatContext;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
|
||||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.context.annotation.ScopedProxyMode;
|
import org.springframework.context.annotation.ScopedProxyMode;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@SpringBootApplication
|
@Configuration
|
||||||
@Slf4j
|
public class WebGoat {
|
||||||
public class WebGoat extends SpringBootServletInitializer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
|
||||||
return application.sources(WebGoat.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
SpringApplication.run(WebGoat.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "pluginTargetDirectory")
|
@Bean(name = "pluginTargetDirectory")
|
||||||
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
|
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
|
||||||
|
@ -58,7 +58,7 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
|||||||
* Constructor for the Lesson object
|
* Constructor for the Lesson object
|
||||||
*/
|
*/
|
||||||
public AbstractLesson() {
|
public AbstractLesson() {
|
||||||
id = new Integer(++count);
|
id = ++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,40 +36,40 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
public enum Category {
|
public enum Category {
|
||||||
|
|
||||||
INTRODUCTION("Introduction", new Integer(5)),
|
INTRODUCTION("Introduction", 5),
|
||||||
GENERAL("General", new Integer(100)),
|
GENERAL("General", 100),
|
||||||
|
|
||||||
INJECTION("(A1) Injection", new Integer(300)),
|
INJECTION("(A1) Injection", 300),
|
||||||
AUTHENTICATION("(A2) Broken Authentication", new Integer(302)),
|
AUTHENTICATION("(A2) Broken Authentication", 302),
|
||||||
INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", new Integer(303)),
|
INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", 303),
|
||||||
XXE("(A4) XML External Entities (XXE)", Integer.valueOf(304)),
|
XXE("(A4) XML External Entities (XXE)", 304),
|
||||||
ACCESS_CONTROL("(A5) Broken Access Control", new Integer(305)),
|
ACCESS_CONTROL("(A5) Broken Access Control", 305),
|
||||||
|
|
||||||
XSS("(A7) Cross-Site Scripting (XSS)", new Integer(307)),
|
XSS("(A7) Cross-Site Scripting (XSS)", 307),
|
||||||
INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", new Integer(308)),
|
INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", 308),
|
||||||
VULNERABLE_COMPONENTS("(A9) Vulnerable Components", new Integer(309)),
|
VULNERABLE_COMPONENTS("(A9) Vulnerable Components", 309),
|
||||||
|
|
||||||
REQUEST_FORGERIES("(A8:2013) Request Forgeries", new Integer(318)),
|
REQUEST_FORGERIES("(A8:2013) Request Forgeries", 318),
|
||||||
|
|
||||||
|
|
||||||
REQ_FORGERIES("Request Forgeries", new Integer(450)),
|
REQ_FORGERIES("Request Forgeries", 450),
|
||||||
|
|
||||||
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)),
|
INSECURE_CONFIGURATION("Insecure Configuration", 600),
|
||||||
INSECURE_STORAGE("Insecure Storage", new Integer(800)),
|
INSECURE_STORAGE("Insecure Storage", 800),
|
||||||
|
|
||||||
|
|
||||||
AJAX_SECURITY("AJAX Security", new Integer(1000)),
|
AJAX_SECURITY("AJAX Security", 1000),
|
||||||
BUFFER_OVERFLOW("Buffer Overflows", new Integer(1100)),
|
BUFFER_OVERFLOW("Buffer Overflows", 1100),
|
||||||
CODE_QUALITY("Code Quality", new Integer(1200)),
|
CODE_QUALITY("Code Quality", 1200),
|
||||||
CONCURRENCY("Concurrency", new Integer(1300)),
|
CONCURRENCY("Concurrency", 1300),
|
||||||
ERROR_HANDLING("Improper Error Handling", new Integer(1400)),
|
ERROR_HANDLING("Improper Error Handling", 1400),
|
||||||
DOS("Denial of Service", new Integer(1500)),
|
DOS("Denial of Service", 1500),
|
||||||
MALICIOUS_EXECUTION("Malicious Execution", new Integer(1600)),
|
MALICIOUS_EXECUTION("Malicious Execution", 1600),
|
||||||
CLIENT_SIDE("Client side", new Integer(1700)),
|
CLIENT_SIDE("Client side", 1700),
|
||||||
SESSION_MANAGEMENT("Session Management Flaws", new Integer(1800)),
|
SESSION_MANAGEMENT("Session Management Flaws", 1800),
|
||||||
WEB_SERVICES("Web Services", new Integer(1900)),
|
WEB_SERVICES("Web Services", 1900),
|
||||||
ADMIN_FUNCTIONS("Admin Functions", new Integer(2000)),
|
ADMIN_FUNCTIONS("Admin Functions", 2000),
|
||||||
CHALLENGE("Challenges", new Integer(3000));
|
CHALLENGE("Challenges", 3000);
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -51,7 +51,7 @@ public abstract class LessonAdapter extends AbstractLesson {
|
|||||||
// Do Nothing - called when restart lesson is pressed. Each lesson can do something
|
// Do Nothing - called when restart lesson is pressed. Each lesson can do something
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Integer DEFAULT_RANKING = new Integer(1000);
|
private final static Integer DEFAULT_RANKING = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>getDefaultRanking.</p>
|
* <p>getDefaultRanking.</p>
|
||||||
|
@ -16,7 +16,7 @@ import javax.validation.constraints.Size;
|
|||||||
public class UserForm {
|
public class UserForm {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=20)
|
@Size(min=6, max=40)
|
||||||
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
||||||
private String username;
|
private String username;
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -22,7 +22,7 @@ import static org.mockito.Mockito.when;
|
|||||||
* @since 5/20/17.
|
* @since 5/20/17.
|
||||||
*/
|
*/
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
@TestPropertySource(locations = "classpath:/application-test.properties")
|
@TestPropertySource(locations = {"classpath:/application-webgoat.properties", "classpath:/application-test.properties"})
|
||||||
public abstract class LessonTest {
|
public abstract class LessonTest {
|
||||||
|
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
|
66
webgoat-integration-tests/pom.xml
Normal file
66
webgoat-integration-tests/pom.xml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<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-integration-tests</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
|
<artifactId>webgoat-parent</artifactId>
|
||||||
|
<version>v8.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
|
<artifactId>webgoat-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
|
<artifactId>webgoat-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>internal</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
|
<artifactId>webwolf</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>internal</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
|
<artifactId>webwolf</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.rest-assured</groupId>
|
||||||
|
<artifactId>rest-assured</artifactId>
|
||||||
|
<version>4.0.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<forkCount>0</forkCount>
|
||||||
|
<reuseForks>true</reuseForks>
|
||||||
|
<argLine>
|
||||||
|
--illegal-access=permit
|
||||||
|
</argLine>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,127 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public class GeneralLessonTest extends IntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void httpBasics() {
|
||||||
|
startLesson("HttpBasics");
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("person", "goatuser");
|
||||||
|
checkAssignment(url("HttpBasics/attack1"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("answer", "POST");
|
||||||
|
params.put("magic_answer", "33");
|
||||||
|
params.put("magic_num", "4");
|
||||||
|
checkAssignment(url("HttpBasics/attack2"), params, false);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("answer", "POST");
|
||||||
|
params.put("magic_answer", "33");
|
||||||
|
params.put("magic_num", "33");
|
||||||
|
checkAssignment(url("HttpBasics/attack2"), params, true);
|
||||||
|
|
||||||
|
checkResults("/HttpBasics/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void httpProxies() {
|
||||||
|
startLesson("HttpProxies");
|
||||||
|
Assert.assertThat(RestAssured.given()
|
||||||
|
.when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||||
|
|
||||||
|
checkResults("/HttpProxies/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cia() {
|
||||||
|
startLesson("CIA");
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
|
||||||
|
params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database.");
|
||||||
|
params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers.");
|
||||||
|
params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed.");
|
||||||
|
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
|
||||||
|
checkResults("/cia/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securePasswords() {
|
||||||
|
startLesson("SecurePasswords");
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("password", "ajnaeliclm^&&@kjn.");
|
||||||
|
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
|
||||||
|
checkResults("SecurePasswords/");
|
||||||
|
|
||||||
|
startLesson("AuthBypass");
|
||||||
|
params.clear();
|
||||||
|
params.put("secQuestion2", "John");
|
||||||
|
params.put("secQuestion3", "Main");
|
||||||
|
params.put("jsEnabled", "1");
|
||||||
|
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||||
|
params.put("userId", "12309746");
|
||||||
|
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
|
||||||
|
checkResults("/auth-bypass/");
|
||||||
|
|
||||||
|
startLesson("HttpProxies");
|
||||||
|
Assert.assertThat(RestAssured.given().when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then()
|
||||||
|
.statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||||
|
checkResults("/HttpProxies/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chrome() {
|
||||||
|
startLesson("ChromeDevTools");
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("param1", "42");
|
||||||
|
params.put("param2", "24");
|
||||||
|
|
||||||
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||||
|
.header("X-Requested-With", "XMLHttpRequest")
|
||||||
|
.formParams(params)
|
||||||
|
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract().path("output");
|
||||||
|
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("successMessage", secretNumber);
|
||||||
|
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("number", "24");
|
||||||
|
params.put("network_num", "24");
|
||||||
|
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
|
||||||
|
|
||||||
|
checkResults("/ChromeDevTools/");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,200 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.config.RestAssuredConfig;
|
||||||
|
import io.restassured.config.SSLConfig;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.owasp.webwolf.WebWolf;
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public abstract class IntegrationTest {
|
||||||
|
|
||||||
|
private static String WEBGOAT_URL = "http://localhost:8080/WebGoat/";
|
||||||
|
private static String WEBWOLF_URL = "http://localhost:9090/";
|
||||||
|
|
||||||
|
//This also allows to test the application with HTTPS when outside testing option is used
|
||||||
|
protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private String webGoatCookie;
|
||||||
|
@Getter
|
||||||
|
private String webWolfCookie;
|
||||||
|
@Getter
|
||||||
|
private String webgoatUser = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
private static boolean started = false;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeAll() {
|
||||||
|
if (!started) {
|
||||||
|
started = true;
|
||||||
|
if (!areAlreadyRunning()) {
|
||||||
|
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
|
||||||
|
.properties(Map.of("spring.config.name", "application-webgoat"));
|
||||||
|
wgs.run();
|
||||||
|
SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
|
||||||
|
.properties(Map.of("spring.config.name", "application-webwolf"));
|
||||||
|
wws.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean areAlreadyRunning() {
|
||||||
|
return checkIfServerIsRunnningOn(9090) && checkIfServerIsRunnningOn(8080);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkIfServerIsRunnningOn(int port) {
|
||||||
|
try (var ignored = new ServerSocket(port)) {
|
||||||
|
return false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String url(String url) {
|
||||||
|
url = url.replaceFirst("/WebGoat/", "");
|
||||||
|
url = url.replaceFirst("/WebGoat", "");
|
||||||
|
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||||
|
return WEBGOAT_URL + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String webWolfUrl(String url) {
|
||||||
|
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||||
|
return WEBWOLF_URL + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void login() {
|
||||||
|
webGoatCookie = RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.formParam("username", webgoatUser)
|
||||||
|
.formParam("password", "password")
|
||||||
|
.formParam("matchingPassword", "password")
|
||||||
|
.formParam("agree", "agree")
|
||||||
|
.post(url("register.mvc"))
|
||||||
|
.then()
|
||||||
|
.cookie("JSESSIONID")
|
||||||
|
.statusCode(302)
|
||||||
|
.extract()
|
||||||
|
.cookie("JSESSIONID");
|
||||||
|
|
||||||
|
webWolfCookie = RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.formParam("username", webgoatUser)
|
||||||
|
.formParam("password", "password")
|
||||||
|
.post(WEBWOLF_URL + "login")
|
||||||
|
.then()
|
||||||
|
.cookie("WEBWOLFSESSION")
|
||||||
|
.statusCode(302)
|
||||||
|
.extract()
|
||||||
|
.cookie("WEBWOLFSESSION");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void logout() {
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.get(WEBGOAT_URL + "logout")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
|
||||||
|
*
|
||||||
|
* @param lessonName
|
||||||
|
*/
|
||||||
|
public void startLesson(String lessonName) {
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url(lessonName + ".lesson.lesson"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("service/restartlesson.mvc"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for most common type of test.
|
||||||
|
* POST with parameters.
|
||||||
|
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param params
|
||||||
|
* @param expectedResult
|
||||||
|
*/
|
||||||
|
public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) {
|
||||||
|
Assert.assertThat(
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.formParams(params)
|
||||||
|
.post(url)
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for most common type of test.
|
||||||
|
* PUT with parameters.
|
||||||
|
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param params
|
||||||
|
* @param expectedResult
|
||||||
|
*/
|
||||||
|
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
|
||||||
|
Assert.assertThat(
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.formParams(params)
|
||||||
|
.put(url)
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkResults(String prefix) {
|
||||||
|
Assert.assertThat(RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("service/lessonoverview.mvc"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
|
||||||
|
|
||||||
|
Assert.assertThat(RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.get(url("service/lessonoverview.mvc"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PasswordResetLessonTest extends IntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void solveAssignment() {
|
||||||
|
//WebGoat
|
||||||
|
startLesson("PasswordReset");
|
||||||
|
clickForgotEmailLink("tom@webgoat-cloud.org");
|
||||||
|
|
||||||
|
//WebWolf
|
||||||
|
var link = getPasswordResetLinkFromLandingPage();
|
||||||
|
|
||||||
|
//WebGoat
|
||||||
|
changePassword(link);
|
||||||
|
checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendEmailShouldBeAvailabeInWebWolf() {
|
||||||
|
startLesson("PasswordReset");
|
||||||
|
clickForgotEmailLink(getWebgoatUser() + "@webgoat.org");
|
||||||
|
|
||||||
|
var responseBody = RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
|
.get(webWolfUrl("/WebWolf/mail"))
|
||||||
|
.then()
|
||||||
|
.extract().response().getBody().asString();
|
||||||
|
|
||||||
|
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changePassword(String link) {
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.formParams("resetLink", link, "password", "123456")
|
||||||
|
.post(url("PasswordReset/reset/change-password"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPasswordResetLinkFromLandingPage() {
|
||||||
|
var responseBody = RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||||
|
.get(webWolfUrl("WebWolf/requests"))
|
||||||
|
.then()
|
||||||
|
.extract().response().getBody().asString();
|
||||||
|
int startIndex = responseBody.lastIndexOf("\"path\" : \"/PasswordReset/reset/reset-password/");
|
||||||
|
var link = responseBody.substring(startIndex + "\"path\" : \"/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickForgotEmailLink(String user) {
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.header("host", "localhost:9090")
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.formParams("email", user)
|
||||||
|
.post(url("PasswordReset/ForgotPassword/create-password-reset-link"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SqlInjectionAdvancedTest extends IntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runTests() {
|
||||||
|
startLesson("SqlInjectionAdvanced");
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("username_reg", "tom' AND substring(password,1,1)='t");
|
||||||
|
params.put("password_reg", "password");
|
||||||
|
params.put("email_reg", "someone@microsoft.com");
|
||||||
|
params.put("confirm_password", "password");
|
||||||
|
checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("username_login", "tom");
|
||||||
|
params.put("password_login", "thisisasecretfortomonly");
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("userid_6b", "passW0rD");
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
|
||||||
|
params.put("question_1_solution", "Solution 3: ?");
|
||||||
|
params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
|
||||||
|
params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
|
||||||
|
params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
|
||||||
|
|
||||||
|
checkResults("/SqlInjectionAdvanced/");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SqlInjectionLessonTest extends IntegrationTest {
|
||||||
|
|
||||||
|
private static final String sql_2 = "select department from employees where last_name='Franco'";
|
||||||
|
private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";
|
||||||
|
private static final String sql_4_drop = "alter table employees drop column phone";
|
||||||
|
private static final String sql_4_add = "alter table employees add column phone varchar(20)";
|
||||||
|
private static final String sql_5 = "grant alter table to UnauthorizedUser";
|
||||||
|
private static final String sql_9_account = " ' ";
|
||||||
|
private static final String sql_9_operator = "or";
|
||||||
|
private static final String sql_9_injection = "'1'='1";
|
||||||
|
private static final String sql_10_login_count = "2";
|
||||||
|
private static final String sql_10_userid = "1 or 1=1";
|
||||||
|
|
||||||
|
private static final String sql_11_a = "Smith' or '1' = '1";
|
||||||
|
private static final String sql_11_b = "3SL99A' or '1'='1";
|
||||||
|
|
||||||
|
private static final String sql_12_a = "Smith";
|
||||||
|
private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith";
|
||||||
|
|
||||||
|
private static final String sql_13 = "%update% '; drop table access_log ; --'";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runTests() {
|
||||||
|
startLesson("SqlInjection");
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("query", sql_2);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("query", sql_3);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("query", sql_4_drop);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, false);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("query", sql_4_add);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("query", sql_5);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("operator", sql_9_operator);
|
||||||
|
params.put("account", sql_9_account);
|
||||||
|
params.put("injection", sql_9_injection);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("login_count", sql_10_login_count);
|
||||||
|
params.put("userid", sql_10_userid);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("name", sql_11_a);
|
||||||
|
params.put("auth_tan", sql_11_b);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("name", sql_12_a);
|
||||||
|
params.put("auth_tan", sql_12_b);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("action_string", sql_13);
|
||||||
|
checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true);
|
||||||
|
|
||||||
|
checkResults("/SqlInjection/");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SqlInjectionMitigation_TestHelper extends TestHelper {
|
public class SqlInjectionMitigationTest extends IntegrationTest {
|
||||||
|
|
||||||
public void runTests(String webgoatURL, String cookie) {
|
@Test
|
||||||
|
public void runTests() {
|
||||||
startLesson(cookie, webgoatURL, "SqlInjectionMitigations");
|
startLesson("SqlInjectionMitigations");
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -18,7 +20,7 @@ public class SqlInjectionMitigation_TestHelper extends TestHelper {
|
|||||||
params.put("field5", "?");
|
params.put("field5", "?");
|
||||||
params.put("field6", "prep.setString(1,\"\")");
|
params.put("field6", "prep.setString(1,\"\")");
|
||||||
params.put("field7", "prep.setString(2,\\\"\\\")");
|
params.put("field7", "prep.setString(2,\\\"\\\")");
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10a", params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true);
|
||||||
|
|
||||||
params.put("editor", "try {\r\n" +
|
params.put("editor", "try {\r\n" +
|
||||||
" Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" +
|
" Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" +
|
||||||
@ -29,9 +31,9 @@ public class SqlInjectionMitigation_TestHelper extends TestHelper {
|
|||||||
"} catch (Exception e) {\r\n" +
|
"} catch (Exception e) {\r\n" +
|
||||||
" System.out.println(\"Oops. Something went wrong!\");\r\n" +
|
" System.out.println(\"Oops. Something went wrong!\");\r\n" +
|
||||||
"}");
|
"}");
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10b", params, true);
|
checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true);
|
||||||
|
|
||||||
//checkResults(cookie, webgoatURL, "/SqlInjectionMitigations/");
|
//checkResults(webGoatCookie, webgoatURL, "/SqlInjectionMitigations/");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<configuration />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Enable below if you want to debug a unit test and see why the controller fails the configuration above is there
|
||||||
|
to keep the Travis build going otherwise it fails with too much logging.
|
||||||
|
//TODO we should use a different Spring profile for Travis
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<logger name="org.springframework.web" level="DEBUG"/>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
-->
|
@ -7,7 +7,6 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.web.bind.annotation.CookieValue;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
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;
|
||||||
@ -17,10 +16,12 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.springframework.util.StringUtils.*;
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the password reset assignment. Used to send the e-mail.
|
* Part of the password reset assignment. Used to send the e-mail.
|
||||||
|
*
|
||||||
* @author nbaars
|
* @author nbaars
|
||||||
* @since 8/20/17.
|
* @since 8/20/17.
|
||||||
*/
|
*/
|
||||||
@ -38,18 +39,20 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
|
|||||||
|
|
||||||
@RequestMapping(method = POST, value = "/create-password-reset-link")
|
@RequestMapping(method = POST, value = "/create-password-reset-link")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request, @CookieValue("JSESSIONID") String cookie) {
|
public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request) {
|
||||||
String resetLink = UUID.randomUUID().toString();
|
String resetLink = UUID.randomUUID().toString();
|
||||||
ResetLinkAssignment.resetLinks.add(resetLink);
|
ResetLinkAssignment.resetLinks.add(resetLink);
|
||||||
String host = request.getHeader("host");
|
String host = request.getHeader("host");
|
||||||
if (org.springframework.util.StringUtils.hasText(email)) {
|
if (hasText(email)) {
|
||||||
if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header.
|
if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header.
|
||||||
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
|
ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);
|
||||||
fakeClickingLinkEmail(host, resetLink);
|
fakeClickingLinkEmail(host, resetLink);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
sendMailToUser(email, host, resetLink);
|
sendMailToUser(email, host, resetLink);
|
||||||
} catch(Exception e) { return failed().output("E-mail can't be send. please try again.").build(); }
|
} catch (Exception e) {
|
||||||
|
return failed().output("E-mail can't be send. please try again.").build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return success().feedback("email.send").feedbackArgs(email).build();
|
return success().feedback("email.send").feedbackArgs(email).build();
|
||||||
@ -62,16 +65,10 @@ public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint {
|
|||||||
.title("Your password reset link")
|
.title("Your password reset link")
|
||||||
.contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink))
|
.contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink))
|
||||||
.sender("password-reset@webgoat-cloud.net")
|
.sender("password-reset@webgoat-cloud.net")
|
||||||
.recipient(username)
|
.recipient(username).build();
|
||||||
.time(LocalDateTime.now()).build();
|
|
||||||
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
|
this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We need to add the current cookie of the user otherwise we cannot distinguish in WebWolf for
|
|
||||||
* which user we need to trace the incoming request. In normal situation this HOST will be in your
|
|
||||||
* full control so every incoming request would be valid.
|
|
||||||
*/
|
|
||||||
private void fakeClickingLinkEmail(String host, String resetLink) {
|
private void fakeClickingLinkEmail(String host, String resetLink) {
|
||||||
try {
|
try {
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
|
@ -9,6 +9,8 @@ password-questions-wrong-user=You need to find a different user you are logging
|
|||||||
password-questions-unknown-user=User {0} is not a valid user.
|
password-questions-unknown-user=User {0} is not a valid user.
|
||||||
password-questions-one-successful=You answered one question successfully please try another one.
|
password-questions-one-successful=You answered one question successfully please try another one.
|
||||||
|
|
||||||
|
email.send=An e-mail has been send to {0}
|
||||||
|
|
||||||
password-reset-no-user=Please supply a valid e-mail address.
|
password-reset-no-user=Please supply a valid e-mail address.
|
||||||
password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0}
|
password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0}
|
||||||
password-reset-not-solved=Sorry but you did not redirect the reset link to WebWolf
|
password-reset-not-solved=Sorry but you did not redirect the reset link to WebWolf
|
||||||
|
@ -139,17 +139,6 @@
|
|||||||
<artifactId>secure-passwords</artifactId>
|
<artifactId>secure-passwords</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.rest-assured</groupId>
|
|
||||||
<artifactId>rest-assured</artifactId>
|
|
||||||
<version>4.0.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!--uncommment below to run/include lesson template in WebGoat Build-->
|
<!--uncommment below to run/include lesson template in WebGoat Build-->
|
||||||
<!--<dependency>-->
|
<!--<dependency>-->
|
||||||
<!--<groupId>org.owasp.webgoat.lesson</groupId>-->
|
<!--<groupId>org.owasp.webgoat.lesson</groupId>-->
|
||||||
@ -199,6 +188,22 @@
|
|||||||
<fork>true</fork>
|
<fork>true</fork>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<classifier>internal</classifier>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@ package org.owasp.webgoat;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point, this project is here to get all the lesson jars included to the final jar file
|
* Main entry point, this project is here to get all the lesson jars included to the final jar file
|
||||||
@ -36,10 +41,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class StartWebGoat {
|
public class StartWebGoat extends SpringBootServletInitializer {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
log.info("Starting WebGoat with args: {}", args);
|
log.info("Starting WebGoat with args: {}", args);
|
||||||
SpringApplication.run(WebGoat.class, args);
|
System.setProperty("spring.config.name", "application-webgoat");
|
||||||
|
SpringApplication.run(StartWebGoat.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
package org.owasp.webgoat;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.restassured.http.ContentType;
|
|
||||||
|
|
||||||
|
|
||||||
public class General_TestHelper extends TestHelper {
|
|
||||||
|
|
||||||
|
|
||||||
public void httpBasics(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "HttpBasics");
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("person", "goatuser");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack1", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("answer", "POST");
|
|
||||||
params.put("magic_answer", "33");
|
|
||||||
params.put("magic_num", "4");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, false);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("answer", "POST");
|
|
||||||
params.put("magic_answer", "33");
|
|
||||||
params.put("magic_num", "33");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, true);
|
|
||||||
|
|
||||||
checkResults(cookie, webgoatURL, "/HttpBasics/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void httpProxies(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "HttpProxies");
|
|
||||||
assertThat(given()
|
|
||||||
.when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true")
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
//.log().all()
|
|
||||||
.get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200).extract().path("lessonCompleted"), is(true));
|
|
||||||
|
|
||||||
checkResults(cookie, webgoatURL, "/HttpProxies/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cia(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "CIA");
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
|
|
||||||
params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database.");
|
|
||||||
params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers.");
|
|
||||||
params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed.");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/cia/quiz", params, true);
|
|
||||||
checkResults(cookie, webgoatURL, "/cia/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void securePasswords(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "SecurePasswords");
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("password", "ajnaeliclm^&&@kjn.");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SecurePasswords/assignment", params, true);
|
|
||||||
checkResults(cookie, webgoatURL, "SecurePasswords/");
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "AuthBypass");
|
|
||||||
params.clear();
|
|
||||||
params.put("secQuestion2", "John");
|
|
||||||
params.put("secQuestion3", "Main");
|
|
||||||
params.put("jsEnabled", "1");
|
|
||||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
|
||||||
params.put("userId", "12309746");
|
|
||||||
checkAssignment(cookie, webgoatURL + "/WebGoat/auth-bypass/verify-account", params, true);
|
|
||||||
checkResults(cookie, webgoatURL, "/auth-bypass/");
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "HttpProxies");
|
|
||||||
assertThat(given().when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true")
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
//.log().all()
|
|
||||||
.get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200).extract().path("lessonCompleted"), is(true));
|
|
||||||
checkResults(cookie, webgoatURL, "/HttpProxies/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void chrome(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "ChromeDevTools");
|
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("param1", "42");
|
|
||||||
params.put("param2", "24");
|
|
||||||
|
|
||||||
String result =
|
|
||||||
given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", cookie)
|
|
||||||
.header("webgoat-requested-by","dom-xss-vuln")
|
|
||||||
.header("X-Requested-With", "XMLHttpRequest")
|
|
||||||
.formParams(params)
|
|
||||||
.post(webgoatURL+"/WebGoat/CrossSiteScripting/phone-home-xss")
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.extract().path("output");
|
|
||||||
String secretNumber = result.substring("phoneHome Response is ".length());
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("successMessage", secretNumber);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/dummy", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("number", "24");
|
|
||||||
params.put("network_num", "24");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/network", params, true);
|
|
||||||
|
|
||||||
checkResults(cookie, webgoatURL, "/ChromeDevTools/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package org.owasp.webgoat;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SqlInjectionAdvanced_TestHelper extends TestHelper {
|
|
||||||
|
|
||||||
public void runTests(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "SqlInjectionAdvanced");
|
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("username_reg", "tom' AND substring(password,1,1)='t");
|
|
||||||
params.put("password_reg", "password");
|
|
||||||
params.put("email_reg", "someone@microsoft.com");
|
|
||||||
params.put("confirm_password", "password");
|
|
||||||
checkAssignmentWithPUT(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("username_login", "tom");
|
|
||||||
params.put("password_login", "thisisasecretfortomonly");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge_Login", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("userid_6b", "passW0rD");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6b", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
|
|
||||||
params.put("question_1_solution", "Solution 3: ?");
|
|
||||||
params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
|
|
||||||
params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
|
|
||||||
params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/quiz", params, true);
|
|
||||||
|
|
||||||
checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
package org.owasp.webgoat;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SqlInjection_TestHelper extends TestHelper {
|
|
||||||
|
|
||||||
private static final String sql_2 = "select department from employees where last_name='Franco'";
|
|
||||||
private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'";
|
|
||||||
private static final String sql_4_drop = "alter table employees drop column phone";
|
|
||||||
private static final String sql_4_add = "alter table employees add column phone varchar(20)";
|
|
||||||
private static final String sql_5 = "grant alter table to UnauthorizedUser";
|
|
||||||
private static final String sql_9_account = " ' ";
|
|
||||||
private static final String sql_9_operator = "or";
|
|
||||||
private static final String sql_9_injection = "'1'='1";
|
|
||||||
private static final String sql_10_login_count = "2";
|
|
||||||
private static final String sql_10_userid = "1 or 1=1";
|
|
||||||
|
|
||||||
private static final String sql_11_a = "Smith' or '1' = '1";
|
|
||||||
private static final String sql_11_b = "3SL99A' or '1'='1";
|
|
||||||
|
|
||||||
private static final String sql_12_a = "Smith";
|
|
||||||
private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith";
|
|
||||||
|
|
||||||
private static final String sql_13 = "%update% '; drop table access_log ; --'";
|
|
||||||
|
|
||||||
public void runTests(String webgoatURL, String cookie) {
|
|
||||||
|
|
||||||
startLesson(cookie, webgoatURL, "SqlInjection");
|
|
||||||
|
|
||||||
Map<String, Object> params = new HashMap<>();
|
|
||||||
params.clear();
|
|
||||||
params.put("query", sql_2);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack2", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("query", sql_3);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack3", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("query", sql_4_drop);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, false);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("query", sql_4_add);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("query", sql_5);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack5", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("operator", sql_9_operator);
|
|
||||||
params.put("account", sql_9_account);
|
|
||||||
params.put("injection", sql_9_injection);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5a", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("login_count", sql_10_login_count);
|
|
||||||
params.put("userid", sql_10_userid);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5b", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("name", sql_11_a);
|
|
||||||
params.put("auth_tan", sql_11_b);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack8", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("name", sql_12_a);
|
|
||||||
params.put("auth_tan", sql_12_b);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack9", params, true);
|
|
||||||
|
|
||||||
params.clear();
|
|
||||||
params.put("action_string", sql_13);
|
|
||||||
checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack10", params, true);
|
|
||||||
|
|
||||||
checkResults(cookie, webgoatURL, "/SqlInjection/");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package org.owasp.webgoat;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
import static org.hamcrest.CoreMatchers.everyItem;
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.hamcrest.CoreMatchers.startsWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.restassured.config.RestAssuredConfig;
|
|
||||||
import io.restassured.config.SSLConfig;
|
|
||||||
|
|
||||||
public class TestHelper {
|
|
||||||
|
|
||||||
//This also allows to test the application with HTTPS when outside testing option is used
|
|
||||||
protected RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
|
|
||||||
* @param cookie
|
|
||||||
* @param url
|
|
||||||
* @param lessonName
|
|
||||||
*/
|
|
||||||
public void startLesson(String cookie, String url, String lessonName) {
|
|
||||||
given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", cookie)
|
|
||||||
.get(url+"/WebGoat/"+lessonName+".lesson.lesson")
|
|
||||||
.then()
|
|
||||||
.statusCode(200);
|
|
||||||
|
|
||||||
given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", cookie)
|
|
||||||
.get(url+"/WebGoat/service/restartlesson.mvc")
|
|
||||||
.then()
|
|
||||||
.statusCode(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for most common type of test.
|
|
||||||
* POST with parameters.
|
|
||||||
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
|
||||||
* @param webgoatCookie
|
|
||||||
* @param url
|
|
||||||
* @param params
|
|
||||||
* @param expectedResult
|
|
||||||
*/
|
|
||||||
public void checkAssignment(String webgoatCookie, String url, Map<String, ?> params, boolean expectedResult) {
|
|
||||||
assertThat(
|
|
||||||
given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", webgoatCookie)
|
|
||||||
.formParams(params)
|
|
||||||
.post(url)
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.extract().path("lessonCompleted"), is(expectedResult));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for most common type of test.
|
|
||||||
* PUT with parameters.
|
|
||||||
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
|
||||||
* @param webgoatCookie
|
|
||||||
* @param url
|
|
||||||
* @param params
|
|
||||||
* @param expectedResult
|
|
||||||
*/
|
|
||||||
public void checkAssignmentWithPUT(String webgoatCookie, String url, Map<String, ?> params, boolean expectedResult) {
|
|
||||||
assertThat(
|
|
||||||
given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", webgoatCookie)
|
|
||||||
.formParams(params)
|
|
||||||
.put(url)
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.extract().path("lessonCompleted"), is(expectedResult));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method at the end of a lesson.
|
|
||||||
* Check if all path paramters are correct for the progress.
|
|
||||||
* Check if all are solved.
|
|
||||||
* @param webgoatCookie
|
|
||||||
* @param webgoatURL
|
|
||||||
* @param prefix
|
|
||||||
*/
|
|
||||||
public void checkResults(String webgoatCookie, String webgoatURL, String prefix) {
|
|
||||||
assertThat(given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", webgoatCookie)
|
|
||||||
.get(webgoatURL+"/WebGoat/service/lessonoverview.mvc")
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200).extract().jsonPath().getList("solved"),everyItem(is(true)));
|
|
||||||
|
|
||||||
assertThat(given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.cookie("JSESSIONID", webgoatCookie)
|
|
||||||
.get(webgoatURL+"/WebGoat/service/lessonoverview.mvc")
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.statusCode(200).extract().jsonPath().getList("assignment.path"),everyItem(startsWith(prefix)));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,162 +0,0 @@
|
|||||||
package org.owasp.webgoat;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
|
||||||
@SpringBootTest(classes=WebGoat.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
public class WebGoatIntegrationTest extends TestHelper {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unique port for http server. Database port is not yet overruled. But this is
|
|
||||||
* not a problem for the integration test.
|
|
||||||
*/
|
|
||||||
@LocalServerPort
|
|
||||||
int randomServerPort;
|
|
||||||
|
|
||||||
private General_TestHelper generalTestHelper = new General_TestHelper();
|
|
||||||
private SqlInjection_TestHelper sqlInjectionHelper = new SqlInjection_TestHelper();
|
|
||||||
private SqlInjectionAdvanced_TestHelper sqlInjectionAdvancedHelper = new SqlInjectionAdvanced_TestHelper();
|
|
||||||
private SqlInjectionMitigation_TestHelper sqlInjectionMitigationHelper = new SqlInjectionMitigation_TestHelper();
|
|
||||||
|
|
||||||
String webgoatURL = System.getProperty("WEBGOAT_URL","");
|
|
||||||
String webgoatUser = System.getProperty("WEBGOAT_USER","");
|
|
||||||
String webgoatPassword = System.getProperty("WEBGOAT_PASSWORD","password");
|
|
||||||
String cookie = "";
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void init() {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no system properties are set, the test runs against the random port
|
|
||||||
* of the webgoat application that starts with this test.
|
|
||||||
* If set you can use it to test an oustide running application. If testing
|
|
||||||
* against outside running applications, the tests that require WebWolf can be tested as well.
|
|
||||||
*/
|
|
||||||
//TODO add support for testing the lessons that require WebWolf as well.
|
|
||||||
if (webgoatURL.equals("")) {
|
|
||||||
webgoatURL = "http://127.0.0.1:"+randomServerPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If not defined a random user will be registered and used in the test.
|
|
||||||
* If you run against an outside application and want to visually see the results,
|
|
||||||
* you can set a username.
|
|
||||||
*/
|
|
||||||
if (webgoatUser.equals("")) {
|
|
||||||
webgoatUser = "tester"+Math.round(Math.random()*1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if user exists
|
|
||||||
String location = given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.formParam("username", webgoatUser)
|
|
||||||
.formParam("password", "password")
|
|
||||||
.post(webgoatURL+"/WebGoat/login")
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.cookie("JSESSIONID")
|
|
||||||
.statusCode(302)
|
|
||||||
.extract().header("Location");
|
|
||||||
|
|
||||||
//register when not existing, otherwise log in and save the cookie
|
|
||||||
if (location.endsWith("error")) {
|
|
||||||
|
|
||||||
cookie = given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.formParam("username", webgoatUser)
|
|
||||||
.formParam("password", "password")
|
|
||||||
.formParam("matchingPassword", "password")
|
|
||||||
.formParam("agree", "agree")
|
|
||||||
.post(webgoatURL+"/WebGoat/register.mvc")
|
|
||||||
.then()
|
|
||||||
.cookie("JSESSIONID")
|
|
||||||
.statusCode(302)
|
|
||||||
.extract()
|
|
||||||
.cookie("JSESSIONID");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
cookie = given()
|
|
||||||
.when()
|
|
||||||
.config(restConfig)
|
|
||||||
.formParam("username", webgoatUser)
|
|
||||||
.formParam("password", "password")
|
|
||||||
.post(webgoatURL+"/WebGoat/login")
|
|
||||||
.then()
|
|
||||||
//.log().all()
|
|
||||||
.cookie("JSESSIONID")
|
|
||||||
.statusCode(302)
|
|
||||||
.extract().cookie("JSESSIONID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGeneral_HttpBasics() {
|
|
||||||
|
|
||||||
generalTestHelper.httpBasics(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGeneral_HttpProxies() {
|
|
||||||
|
|
||||||
generalTestHelper.httpProxies(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGeneral_CIA() {
|
|
||||||
|
|
||||||
generalTestHelper.cia(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGeneral_Chrome() {
|
|
||||||
|
|
||||||
generalTestHelper.chrome(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSecurePassords() {
|
|
||||||
|
|
||||||
generalTestHelper.securePasswords(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSQLInjection() {
|
|
||||||
|
|
||||||
sqlInjectionHelper.runTests(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSQLInjectionAdvanced() {
|
|
||||||
|
|
||||||
sqlInjectionAdvancedHelper.runTests(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSQLInjectionMitigation() {
|
|
||||||
|
|
||||||
sqlInjectionMitigationHelper.runTests(webgoatURL, cookie);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -110,6 +110,22 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<classifier>internal</classifier>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
@ -1,29 +1,24 @@
|
|||||||
package org.owasp.webwolf;
|
package org.owasp.webwolf;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.owasp.webwolf.requests.WebWolfTraceRepository;
|
import org.owasp.webwolf.requests.WebWolfTraceRepository;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@Slf4j
|
public class WebWolf {
|
||||||
public class WebWolf extends SpringBootServletInitializer {
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TraceRepository traceRepository() {
|
public TraceRepository traceRepository() {
|
||||||
return new WebWolfTraceRepository();
|
return new WebWolfTraceRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static void main(String[] args) {
|
||||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
System.setProperty("spring.config.name", "application-webwolf");
|
||||||
return application.sources(WebWolf.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
SpringApplication.run(WebWolf.class, args);
|
SpringApplication.run(WebWolf.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ public class Email implements Serializable {
|
|||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
@JsonIgnore
|
||||||
private LocalDateTime time = LocalDateTime.now();
|
private LocalDateTime time = LocalDateTime.now();
|
||||||
@Column(length = 1024)
|
@Column(length = 1024)
|
||||||
private String contents;
|
private String contents;
|
||||||
|
@ -42,7 +42,7 @@ public class Requests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public ModelAndView get(HttpServletRequest request) {
|
public ModelAndView get() {
|
||||||
ModelAndView m = new ModelAndView("requests");
|
ModelAndView m = new ModelAndView("requests");
|
||||||
List<Tracert> traces = traceRepository.findAllTraces().stream()
|
List<Tracert> traces = traceRepository.findAllTraces().stream()
|
||||||
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList());
|
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList());
|
||||||
|
@ -7,7 +7,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.boot.actuate.trace.Trace;
|
import org.springframework.boot.actuate.trace.Trace;
|
||||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep track of all the incoming requests, we are only keeping track of request originating from
|
* Keep track of all the incoming requests, we are only keeping track of request originating from
|
||||||
@ -40,21 +43,9 @@ public class WebWolfTraceRepository implements TraceRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(Map<String, Object> map) {
|
public void add(Map<String, Object> map) {
|
||||||
Optional<String> host = getFromHeaders("host", map);
|
|
||||||
String path = (String) map.getOrDefault("path", "");
|
String path = (String) map.getOrDefault("path", "");
|
||||||
if (host.isPresent() && !isInExclusionList(path)) {
|
if (!isInExclusionList(path)) {
|
||||||
traces.add(new Trace(new Date(), map));
|
traces.add(new Trace(new Date(), map));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<String> getFromHeaders(String header, Map<String, Object> map) {
|
|
||||||
Map<String, Object> headers = (Map<String, Object>) map.get("headers");
|
|
||||||
if (headers != null) {
|
|
||||||
Map<String, Object> request = (Map<String, Object>) headers.get("request");
|
|
||||||
if (request != null) {
|
|
||||||
return Optional.ofNullable((String) request.get(header));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
|
|||||||
public class UserForm {
|
public class UserForm {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=20)
|
@Size(min=6, max=40)
|
||||||
private String username;
|
private String username;
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=10)
|
@Size(min=6, max=10)
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package org.owasp.webwolf.user;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.springframework.data.annotation.Id;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 8/20/17.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class WebGoatUserCookie implements Serializable {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private String username;
|
|
||||||
private String cookie;
|
|
||||||
}
|
|
@ -10,6 +10,7 @@ spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQ
|
|||||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
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
|
||||||
|
spring.jmx.enabled=false
|
||||||
|
|
||||||
logging.level.org.springframework=INFO
|
logging.level.org.springframework=INFO
|
||||||
logging.level.org.springframework.boot.devtools=WARN
|
logging.level.org.springframework.boot.devtools=WARN
|
Loading…
x
Reference in New Issue
Block a user