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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,11 +37,9 @@ public abstract class IntegrationTest {
@BeforeClass
public static void beforeAll() {
if (WG_SSL) {
if (WG_SSL) {
WEBGOAT_URL = WEBGOAT_URL.replace("http:","https:");
}
if (!started) {
started = true;
if (!isAlreadyRunning(WG_PORT)) {
@ -238,8 +236,7 @@ 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()

View File

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

View File

@ -20,37 +20,28 @@ public class XXETest extends IntegrationTest {
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")));
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);
@ -64,10 +55,9 @@ public class XXETest extends IntegrationTest {
.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()
@ -78,8 +68,7 @@ public class XXETest extends IntegrationTest {
.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;
}
}

View File

@ -23,48 +23,40 @@
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();
}
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = '" + username_login + "' and password = '" + password_login + "'");
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();
if (resultSet.next()) {
@ -73,46 +65,6 @@ public class Assignment5 extends AssignmentEndpoint {
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);
}
}
}

View File

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

View File

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

View File

@ -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', '**********');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,28 +44,23 @@ 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);
@ -80,14 +71,14 @@ public class SqlInjectionChallenge extends AssignmentEndpoint {
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();
}
}
@ -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);
}
}
}

View File

@ -25,27 +25,30 @@ 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;
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 {
Connection connection = DatabaseUtilities.getConnection(webSession);
SqlInjectionChallenge.checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + SqlInjectionChallenge.USERS_TABLE_NAME + " where userid = ? and password = ?");
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();
@ -57,4 +60,5 @@ public class SqlInjectionChallengeLogin extends AssignmentEndpoint {
return failed().feedback("NoResultsMatched").build();
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
try {
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet results = statement.executeQuery(_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();
results.first();
if (results.getString("department").equals("Marketing")) {
output.append("<span class='feedback-positive'>" + _query + "</span>");
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());
}
} catch (Exception e) {
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
}
}
}

View File

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

View File

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

View File

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

View File

@ -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.*;
@ -41,6 +42,11 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
+ "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;
public SqlInjectionLesson5a(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/assignment5a")
@ResponseBody
@ -50,12 +56,9 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
protected AttackResult injectableQuery(String accountName) {
String query = "";
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
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_READ_ONLY)) {
try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
ResultSet results = statement.executeQuery(query);
if ((results != null) && (results.first())) {
@ -73,10 +76,8 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
}
} 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) {

View File

@ -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,6 +41,12 @@ import java.sql.*;
@AssignmentHints(value = {"SqlStringInjectionHint5b1", "SqlStringInjectionHint5b2", "SqlStringInjectionHint5b3", "SqlStringInjectionHint5b4"})
public class SqlInjectionLesson5b extends AssignmentEndpoint {
private final DataSource dataSource;
public SqlInjectionLesson5b(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostMapping("/SqlInjection/assignment5b")
@ResponseBody
public AttackResult completed(@RequestParam String userid, @RequestParam String login_count, HttpServletRequest request) throws IOException {
@ -46,15 +55,13 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
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);
try (Connection connection = dataSource.getConnection()) {
PreparedStatement query = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
int count = 0;
try {
count = Integer.parseInt(login_count);
} catch(Exception e) {
} catch (Exception e) {
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
"<br> Your query was: " + queryString.replace("?", login_count)).build());
}
@ -62,8 +69,6 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
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();
if ((results != null) && (results.first() == true)) {

View File

@ -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 = dataSource.getConnection()) {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
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());

View File

@ -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 = dataSource.getConnection()) {
try {
Connection connection = DatabaseUtilities.getConnection(getWebSession());
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,7 +89,8 @@ 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);
try (Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
) {
ResultSet results = statement.executeQuery(query);
results.first();
@ -95,9 +101,8 @@ public class SqlInjectionLesson9 extends AssignmentEndpoint {
} 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());
}
}

View File

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

View File

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

View File

@ -27,35 +27,32 @@ 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);
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");
@ -65,4 +62,5 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
}
return trackProgress(failed().build());
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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', '**********');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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