Added testcase for SQL injection lesson
This commit is contained in:
parent
9f12da1434
commit
129e9deba9
@ -25,11 +25,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.assignments;
|
package org.owasp.webgoat.assignments;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
import org.owasp.webgoat.i18n.PluginMessages;
|
import org.owasp.webgoat.i18n.PluginMessages;
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class AttackResult {
|
public class AttackResult {
|
||||||
|
|
||||||
public static class AttackResultBuilder {
|
public static class AttackResultBuilder {
|
||||||
@ -89,6 +88,11 @@ public class AttackResult {
|
|||||||
@Getter
|
@Getter
|
||||||
private String output;
|
private String output;
|
||||||
|
|
||||||
|
public AttackResult(boolean lessonCompleted, String feedback, String output) {
|
||||||
|
this.lessonCompleted = lessonCompleted;
|
||||||
|
this.feedback = StringEscapeUtils.escapeJson(feedback);
|
||||||
|
this.output = StringEscapeUtils.escapeJson(output);
|
||||||
|
}
|
||||||
|
|
||||||
public static AttackResultBuilder builder(PluginMessages messages) {
|
public static AttackResultBuilder builder(PluginMessages messages) {
|
||||||
return new AttackResultBuilder(messages);
|
return new AttackResultBuilder(messages);
|
||||||
|
@ -2,7 +2,7 @@ package org.owasp.webgoat.plugins;
|
|||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.owasp.webgoat.i18n.Language;
|
import org.owasp.webgoat.i18n.Language;
|
||||||
import org.owasp.webgoat.i18n.Messages;
|
import org.owasp.webgoat.i18n.PluginMessages;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||||
@ -30,7 +30,7 @@ public abstract class LessonTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected WebApplicationContext wac;
|
protected WebApplicationContext wac;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected Messages messages;
|
protected PluginMessages messages;
|
||||||
@MockBean
|
@MockBean
|
||||||
protected WebSession webSession;
|
protected WebSession webSession;
|
||||||
@MockBean
|
@MockBean
|
||||||
@ -38,7 +38,8 @@ public abstract class LessonTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
when(language.getLocale()).thenReturn(Locale.US);
|
when(webSession.getUserName()).thenReturn("unit-test");
|
||||||
|
when(language.getLocale()).thenReturn(Locale.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package org.owasp.webgoat.plugin;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.DatabaseUtilities;
|
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||||
@ -10,12 +11,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -47,28 +46,27 @@ import java.sql.*;
|
|||||||
* @created October 28, 2003
|
* @created October 28, 2003
|
||||||
*/
|
*/
|
||||||
@AssignmentPath("/SqlInjection/attack5a")
|
@AssignmentPath("/SqlInjection/attack5a")
|
||||||
|
@AssignmentHints(value = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"})
|
||||||
public class SqlInjectionLesson5a extends AssignmentEndpoint {
|
public class SqlInjectionLesson5a extends AssignmentEndpoint {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
public @ResponseBody AttackResult completed(@RequestParam String account, HttpServletRequest request) throws IOException {
|
public
|
||||||
|
@ResponseBody
|
||||||
|
AttackResult completed(@RequestParam String account) {
|
||||||
return injectableQuery(account);
|
return injectableQuery(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String accountName)
|
protected AttackResult injectableQuery(String accountName) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
||||||
String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
|
String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
||||||
ResultSet.CONCUR_READ_ONLY);
|
ResultSet.CONCUR_READ_ONLY);
|
||||||
ResultSet results = statement.executeQuery(query);
|
ResultSet results = statement.executeQuery(query);
|
||||||
|
|
||||||
if ((results != null) && (results.first() == true))
|
if ((results != null) && (results.first())) {
|
||||||
{
|
|
||||||
ResultSetMetaData resultsMetaData = results.getMetaData();
|
ResultSetMetaData resultsMetaData = results.getMetaData();
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
|
|
||||||
@ -76,42 +74,33 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
|
|||||||
results.last();
|
results.last();
|
||||||
|
|
||||||
// If they get back more than one user they succeeded
|
// If they get back more than one user they succeeded
|
||||||
if (results.getRow() >= 6)
|
if (results.getRow() >= 6) {
|
||||||
{
|
|
||||||
return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build());
|
return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().output(output.toString()).build());
|
return trackProgress(failed().output(output.toString()).build());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return trackProgress(failed().feedback("sql-injection.5a.no.results").build());
|
return trackProgress(failed().feedback("sql-injection.5a.no.results").build());
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (SQLException sqle)
|
} catch (SQLException sqle) {
|
||||||
{
|
|
||||||
|
|
||||||
return trackProgress(failed().output(sqle.getMessage()).build());
|
return trackProgress(failed().output(sqle.getMessage()).build());
|
||||||
}
|
}
|
||||||
} catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
||||||
SQLException
|
SQLException {
|
||||||
{
|
|
||||||
int numColumns = resultsMetaData.getColumnCount();
|
int numColumns = resultsMetaData.getColumnCount();
|
||||||
results.beforeFirst();
|
results.beforeFirst();
|
||||||
StringBuffer t = new StringBuffer();
|
StringBuffer t = new StringBuffer();
|
||||||
t.append("<p>");
|
t.append("<p>");
|
||||||
|
|
||||||
if (results.next())
|
if (results.next()) {
|
||||||
{
|
for (int i = 1; i < (numColumns + 1); i++) {
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(resultsMetaData.getColumnName(i));
|
t.append(resultsMetaData.getColumnName(i));
|
||||||
t.append(", ");
|
t.append(", ");
|
||||||
}
|
}
|
||||||
@ -119,11 +108,9 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
|
|||||||
t.append("<br />");
|
t.append("<br />");
|
||||||
results.beforeFirst();
|
results.beforeFirst();
|
||||||
|
|
||||||
while (results.next())
|
while (results.next()) {
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
for (int i = 1; i < (numColumns + 1); i++) {
|
||||||
{
|
|
||||||
t.append(results.getString(i));
|
t.append(results.getString(i));
|
||||||
t.append(", ");
|
t.append(", ");
|
||||||
}
|
}
|
||||||
@ -131,90 +118,11 @@ public class SqlInjectionLesson5a extends AssignmentEndpoint {
|
|||||||
t.append("<br />");
|
t.append("<br />");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
t.append("Query Successful; however no data was returned from this query.");
|
||||||
{
|
|
||||||
t.append ("Query Successful; however no data was returned from this query.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.append("</p>");
|
t.append("</p>");
|
||||||
return (t.toString());
|
return (t.toString());
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// protected Element parameterizedQuery(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
//
|
|
||||||
// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage"));
|
|
||||||
// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart"))
|
|
||||||
// {
|
|
||||||
// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1");
|
|
||||||
// return (injectableQuery(s));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ec.addElement(new BR());
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// Connection connection = DatabaseUtilities.getConnection(s);
|
|
||||||
//
|
|
||||||
// ec.addElement(makeAccountLine(s));
|
|
||||||
//
|
|
||||||
// String query = "SELECT * FROM user_data WHERE last_name = ?";
|
|
||||||
// ec.addElement(new PRE(query));
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE,
|
|
||||||
// ResultSet.CONCUR_READ_ONLY);
|
|
||||||
// statement.setString(1, accountName);
|
|
||||||
// ResultSet results = statement.executeQuery();
|
|
||||||
//
|
|
||||||
// if ((results != null) && (results.first() == true))
|
|
||||||
// {
|
|
||||||
// ResultSetMetaData resultsMetaData = results.getMetaData();
|
|
||||||
// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
|
|
||||||
// results.last();
|
|
||||||
//
|
|
||||||
// // If they get back more than one user they succeeded
|
|
||||||
// if (results.getRow() >= 6)
|
|
||||||
// {
|
|
||||||
// makeSuccess(s);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ec.addElement(getLabelManager().get("NoResultsMatched"));
|
|
||||||
// }
|
|
||||||
// } catch (SQLException sqle)
|
|
||||||
// {
|
|
||||||
// ec.addElement(new P().addElement(sqle.getMessage()));
|
|
||||||
// }
|
|
||||||
// } catch (Exception e)
|
|
||||||
// {
|
|
||||||
// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName());
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return (ec);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// protected Element makeAccountLine(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName")));
|
|
||||||
//
|
|
||||||
// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name");
|
|
||||||
// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString());
|
|
||||||
// ec.addElement(input);
|
|
||||||
//
|
|
||||||
// Element b = ECSFactory.makeButton(getLabelManager().get("Go!"));
|
|
||||||
// ec.addElement(b);
|
|
||||||
//
|
|
||||||
// return ec;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.owasp.webgoat.plugin;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.DatabaseUtilities;
|
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||||
@ -16,7 +16,6 @@ import java.io.IOException;
|
|||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -48,177 +47,53 @@ import java.sql.*;
|
|||||||
* @created October 28, 2003
|
* @created October 28, 2003
|
||||||
*/
|
*/
|
||||||
@AssignmentPath("/SqlInjection/attack5b")
|
@AssignmentPath("/SqlInjection/attack5b")
|
||||||
|
@AssignmentHints(value = {"SqlStringInjectionHint1", "SqlStringInjectionHint2", "SqlStringInjectionHint3", "SqlStringInjectionHint4"})
|
||||||
public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
public @ResponseBody AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException {
|
public
|
||||||
|
@ResponseBody
|
||||||
|
AttackResult completed(@RequestParam String userid, HttpServletRequest request) throws IOException {
|
||||||
return injectableQuery(userid);
|
return injectableQuery(userid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String accountName)
|
protected AttackResult injectableQuery(String accountName) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
||||||
String query = "SELECT * FROM user_data WHERE userid = " + accountName;
|
String query = "SELECT * FROM user_data WHERE userid = " + accountName;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
||||||
ResultSet.CONCUR_READ_ONLY);
|
ResultSet.CONCUR_READ_ONLY);
|
||||||
ResultSet results = statement.executeQuery(query);
|
ResultSet results = statement.executeQuery(query);
|
||||||
|
|
||||||
if ((results != null) && (results.first() == true))
|
if ((results != null) && (results.first() == true)) {
|
||||||
{
|
|
||||||
ResultSetMetaData resultsMetaData = results.getMetaData();
|
ResultSetMetaData resultsMetaData = results.getMetaData();
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
|
|
||||||
output.append(writeTable(results, resultsMetaData));
|
output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData));
|
||||||
results.last();
|
results.last();
|
||||||
|
|
||||||
// If they get back more than one user they succeeded
|
// If they get back more than one user they succeeded
|
||||||
if (results.getRow() >= 6)
|
if (results.getRow() >= 6) {
|
||||||
{
|
|
||||||
return trackProgress(success().feedback("sql-injection.5b.success").feedbackArgs(output.toString()).build());
|
return trackProgress(success().feedback("sql-injection.5b.success").feedbackArgs(output.toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().output(output.toString()).build());
|
return trackProgress(failed().output(output.toString()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return trackProgress(failed().feedback("sql-injection.5b.no.results").build());
|
return trackProgress(failed().feedback("sql-injection.5b.no.results").build());
|
||||||
|
|
||||||
// output.append(getLabelManager().get("NoResultsMatched"));
|
// output.append(getLabelManager().get("NoResultsMatched"));
|
||||||
}
|
}
|
||||||
} catch (SQLException sqle)
|
} catch (SQLException sqle) {
|
||||||
{
|
|
||||||
|
|
||||||
return trackProgress(failed().output(sqle.getMessage()).build());
|
return trackProgress(failed().output(sqle.getMessage()).build());
|
||||||
}
|
}
|
||||||
} catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
|
||||||
SQLException
|
|
||||||
{
|
|
||||||
int numColumns = resultsMetaData.getColumnCount();
|
|
||||||
results.beforeFirst();
|
|
||||||
StringBuffer t = new StringBuffer();
|
|
||||||
t.append("<p>");
|
|
||||||
|
|
||||||
if (results.next())
|
|
||||||
{
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(resultsMetaData.getColumnName(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
results.beforeFirst();
|
|
||||||
|
|
||||||
while (results.next())
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(results.getString(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.append ("Query Successful; however no data was returned from this query.");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("</p>");
|
|
||||||
return (t.toString());
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// protected Element parameterizedQuery(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
//
|
|
||||||
// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage"));
|
|
||||||
// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart"))
|
|
||||||
// {
|
|
||||||
// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1");
|
|
||||||
// return (injectableQuery(s));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ec.addElement(new BR());
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// Connection connection = DatabaseUtilities.getConnection(s);
|
|
||||||
//
|
|
||||||
// ec.addElement(makeAccountLine(s));
|
|
||||||
//
|
|
||||||
// String query = "SELECT * FROM user_data WHERE last_name = ?";
|
|
||||||
// ec.addElement(new PRE(query));
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE,
|
|
||||||
// ResultSet.CONCUR_READ_ONLY);
|
|
||||||
// statement.setString(1, accountName);
|
|
||||||
// ResultSet results = statement.executeQuery();
|
|
||||||
//
|
|
||||||
// if ((results != null) && (results.first() == true))
|
|
||||||
// {
|
|
||||||
// ResultSetMetaData resultsMetaData = results.getMetaData();
|
|
||||||
// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
|
|
||||||
// results.last();
|
|
||||||
//
|
|
||||||
// // If they get back more than one user they succeeded
|
|
||||||
// if (results.getRow() >= 6)
|
|
||||||
// {
|
|
||||||
// makeSuccess(s);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ec.addElement(getLabelManager().get("NoResultsMatched"));
|
|
||||||
// }
|
|
||||||
// } catch (SQLException sqle)
|
|
||||||
// {
|
|
||||||
// ec.addElement(new P().addElement(sqle.getMessage()));
|
|
||||||
// }
|
|
||||||
// } catch (Exception e)
|
|
||||||
// {
|
|
||||||
// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName());
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return (ec);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// protected Element makeAccountLine(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName")));
|
|
||||||
//
|
|
||||||
// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name");
|
|
||||||
// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString());
|
|
||||||
// ec.addElement(input);
|
|
||||||
//
|
|
||||||
// Element b = ECSFactory.makeButton(getLabelManager().get("Go!"));
|
|
||||||
// ec.addElement(b);
|
|
||||||
//
|
|
||||||
// return ec;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package org.owasp.webgoat.plugin;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.DatabaseUtilities;
|
import org.owasp.webgoat.session.DatabaseUtilities;
|
||||||
@ -10,10 +11,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
|
||||||
|
import static org.owasp.webgoat.plugin.SqlInjectionLesson5a.writeTable;
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
@ -47,30 +48,29 @@ import java.sql.*;
|
|||||||
* @created October 28, 2003
|
* @created October 28, 2003
|
||||||
*/
|
*/
|
||||||
@AssignmentPath("/SqlInjection/attack6a")
|
@AssignmentPath("/SqlInjection/attack6a")
|
||||||
|
@AssignmentHints(value = {"SqlStringInjectionHint5", "SqlStringInjectionHint6"})
|
||||||
public class SqlInjectionLesson6a extends AssignmentEndpoint {
|
public class SqlInjectionLesson6a extends AssignmentEndpoint {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
public @ResponseBody AttackResult completed(@RequestParam String userid_6a, HttpServletRequest request) throws IOException {
|
public
|
||||||
|
@ResponseBody
|
||||||
|
AttackResult completed(@RequestParam String userid_6a) throws IOException {
|
||||||
return injectableQuery(userid_6a);
|
return injectableQuery(userid_6a);
|
||||||
// The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data --
|
// The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data --
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String accountName)
|
protected AttackResult injectableQuery(String accountName) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
Connection connection = DatabaseUtilities.getConnection(getWebSession());
|
||||||
String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
|
String query = "SELECT * FROM user_data WHERE last_name = '" + accountName + "'";
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
|
||||||
ResultSet.CONCUR_READ_ONLY);
|
ResultSet.CONCUR_READ_ONLY);
|
||||||
ResultSet results = statement.executeQuery(query);
|
ResultSet results = statement.executeQuery(query);
|
||||||
|
|
||||||
if ((results != null) && (results.first() == true))
|
if ((results != null) && (results.first())) {
|
||||||
{
|
|
||||||
ResultSetMetaData resultsMetaData = results.getMetaData();
|
ResultSetMetaData resultsMetaData = results.getMetaData();
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
|
|
||||||
@ -78,146 +78,22 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint {
|
|||||||
results.last();
|
results.last();
|
||||||
|
|
||||||
// If they get back more than one user they succeeded
|
// If they get back more than one user they succeeded
|
||||||
if (results.getRow() >= 5)
|
if (results.getRow() >= 5) {
|
||||||
{
|
|
||||||
return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build());
|
return trackProgress(success().feedback("sql-injection.6a.success").feedbackArgs(output.toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().output(output.toString()).build());
|
return trackProgress(failed().output(output.toString()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return trackProgress(failed().feedback("sql-injection.6a.no.results").build());
|
return trackProgress(failed().feedback("sql-injection.6a.no.results").build());
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (SQLException sqle)
|
} catch (SQLException sqle) {
|
||||||
{
|
|
||||||
|
|
||||||
return trackProgress(failed().output(sqle.getMessage()).build());
|
return trackProgress(failed().output(sqle.getMessage()).build());
|
||||||
}
|
}
|
||||||
} catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
|
|
||||||
SQLException
|
|
||||||
{
|
|
||||||
int numColumns = resultsMetaData.getColumnCount();
|
|
||||||
results.beforeFirst();
|
|
||||||
StringBuffer t = new StringBuffer();
|
|
||||||
t.append("<p>");
|
|
||||||
|
|
||||||
if (results.next())
|
|
||||||
{
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(resultsMetaData.getColumnName(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
results.beforeFirst();
|
|
||||||
|
|
||||||
while (results.next())
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 1; i < (numColumns + 1); i++)
|
|
||||||
{
|
|
||||||
t.append(results.getString(i));
|
|
||||||
t.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("<br />");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.append ("Query Successful; however no data was returned from this query.");
|
|
||||||
}
|
|
||||||
|
|
||||||
t.append("</p>");
|
|
||||||
return (t.toString());
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// protected Element parameterizedQuery(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
//
|
|
||||||
// ec.addElement(getLabelManager().get("StringSqlInjectionSecondStage"));
|
|
||||||
// if (s.getParser().getRawParameter(ACCT_NAME, "YOUR_NAME").equals("restart"))
|
|
||||||
// {
|
|
||||||
// getLessonTracker(s).getLessonProperties().setProperty(STAGE, "1");
|
|
||||||
// return (injectableQuery(s));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ec.addElement(new BR());
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// Connection connection = DatabaseUtilities.getConnection(s);
|
|
||||||
//
|
|
||||||
// ec.addElement(makeAccountLine(s));
|
|
||||||
//
|
|
||||||
// String query = "SELECT * FROM user_data WHERE last_name = ?";
|
|
||||||
// ec.addElement(new PRE(query));
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE,
|
|
||||||
// ResultSet.CONCUR_READ_ONLY);
|
|
||||||
// statement.setString(1, accountName);
|
|
||||||
// ResultSet results = statement.executeQuery();
|
|
||||||
//
|
|
||||||
// if ((results != null) && (results.first() == true))
|
|
||||||
// {
|
|
||||||
// ResultSetMetaData resultsMetaData = results.getMetaData();
|
|
||||||
// ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
|
|
||||||
// results.last();
|
|
||||||
//
|
|
||||||
// // If they get back more than one user they succeeded
|
|
||||||
// if (results.getRow() >= 6)
|
|
||||||
// {
|
|
||||||
// makeSuccess(s);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ec.addElement(getLabelManager().get("NoResultsMatched"));
|
|
||||||
// }
|
|
||||||
// } catch (SQLException sqle)
|
|
||||||
// {
|
|
||||||
// ec.addElement(new P().addElement(sqle.getMessage()));
|
|
||||||
// }
|
|
||||||
// } catch (Exception e)
|
|
||||||
// {
|
|
||||||
// s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName());
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return (ec);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// protected Element makeAccountLine(WebSession s)
|
|
||||||
// {
|
|
||||||
// ElementContainer ec = new ElementContainer();
|
|
||||||
// ec.addElement(new P().addElement(getLabelManager().get("EnterLastName")));
|
|
||||||
//
|
|
||||||
// accountName = s.getParser().getRawParameter(ACCT_NAME, "Your Name");
|
|
||||||
// Input input = new Input(Input.TEXT, ACCT_NAME, accountName.toString());
|
|
||||||
// ec.addElement(input);
|
|
||||||
//
|
|
||||||
// Element b = ECSFactory.makeButton(getLabelManager().get("Go!"));
|
|
||||||
// ec.addElement(b);
|
|
||||||
//
|
|
||||||
// return ec;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,54 +3,33 @@
|
|||||||
<html xmlns:th="http://www.thymeleaf.org">
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_plan.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_plan.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content1.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content1.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content2.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content2.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content3.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content3.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content4.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content4.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content5.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5a.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content5a.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
|
|
||||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
action="/WebGoat/SqlInjection/attack5a"
|
action="/WebGoat/SqlInjection/attack5a"
|
||||||
@ -64,23 +43,15 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content5b.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content5b.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
action="/WebGoat/SqlInjection/attack5b"
|
action="/WebGoat/SqlInjection/attack5b"
|
||||||
@ -95,30 +66,19 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content6.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content6.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content6a.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content6a.adoc"></div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
action="/WebGoat/SqlInjection/attack6a"
|
action="/WebGoat/SqlInjection/attack6a"
|
||||||
@ -133,18 +93,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- using attack-form class on your form will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
|
||||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
|
||||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
action="/WebGoat/SqlInjection/attack6b"
|
action="/WebGoat/SqlInjection/attack6b"
|
||||||
@ -159,54 +112,36 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- do not remove the two following div's, this is where your feedback/output will land -->
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content7.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content7.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content8.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content8.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content9.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content9.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content10.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content10.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content11.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content11.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content12.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content12.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
<div class="lesson-page-wrapper">
|
||||||
<!-- reuse this lesson-page-wrapper block for each 'page' of content in your lesson -->
|
|
||||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
|
||||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
|
||||||
<div class="adoc-content" th:replace="doc:SqlInjection_content13.adoc"></div>
|
<div class="adoc-content" th:replace="doc:SqlInjection_content13.adoc"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ SqlStringInjectionHint1=The application is taking your input and inserting it at
|
|||||||
SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
|
SqlStringInjectionHint2=This is the code for the query being built and issued by WebGoat:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
|
||||||
SqlStringInjectionHint3=Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. Try appending a SQL statement that always resolves to true
|
SqlStringInjectionHint3=Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. Try appending a SQL statement that always resolves to true
|
||||||
SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ].
|
SqlStringInjectionHint4=Try entering [ smith' OR '1' = '1 ].
|
||||||
|
SqlStringInjectionHint5=Try adding a union to the query, the number of columns should match.
|
||||||
|
SqlStringInjectionHint6=Try entering [ Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- ].
|
||||||
|
|
||||||
sql-injection.5a.success=You have succeed: {0}
|
sql-injection.5a.success=You have succeed: {0}
|
||||||
sql-injection.5a.no.results=No results matched. Try Again.
|
sql-injection.5a.no.results=No results matched. Try Again.
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
|
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.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author nbaars
|
||||||
|
* @since 5/21/17.
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
public class SqlInjectionLesson5aTest extends LessonTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebgoatContext context;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
SqlInjection sql = new SqlInjection();
|
||||||
|
when(webSession.getCurrentLesson()).thenReturn(sql);
|
||||||
|
when(webSession.getWebgoatContext()).thenReturn(context);
|
||||||
|
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void knownAccountShouldDisplayData() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a")
|
||||||
|
.param("account", "Smith"))
|
||||||
|
.andDo(MockMvcResultHandlers.print())
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("lessonCompleted", is(false)))
|
||||||
|
.andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved"))))
|
||||||
|
.andExpect(jsonPath("$.output", containsString("<p>USERID, FIRST_NAME")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unknownAccount() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a")
|
||||||
|
.param("account", "Smithh"))
|
||||||
|
.andDo(MockMvcResultHandlers.print())
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("lessonCompleted", is(false)))
|
||||||
|
.andExpect(jsonPath("$.feedback", is(messages.getMessage("NoResultsMatched"))))
|
||||||
|
.andExpect(jsonPath("$.output").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sqlInjection() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a")
|
||||||
|
.param("account", "smith' OR '1' = '1"))
|
||||||
|
.andDo(MockMvcResultHandlers.print())
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("lessonCompleted", is(true)))
|
||||||
|
.andExpect(jsonPath("$.feedback", containsString("You have succeed")))
|
||||||
|
.andExpect(jsonPath("$.output").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sqlInjectionWrongShouldDisplayError() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a")
|
||||||
|
.param("account", "smith' OR '1' = '1'"))
|
||||||
|
.andDo(MockMvcResultHandlers.print())
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("lessonCompleted", is(false)))
|
||||||
|
.andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))
|
||||||
|
.andExpect(jsonPath("$.output", is("malformed string: '1''")));
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package org.owasp.webgoat.plugin;
|
|||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
@ -83,7 +82,7 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
|
|||||||
Comment comment = comments.parseXml(commentStr);
|
Comment comment = comments.parseXml(commentStr);
|
||||||
comments.addComment(comment, false);
|
comments.addComment(comment, false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
error = StringEscapeUtils.escapeJson(e.toString());
|
error = e.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt");
|
File logFile = new File(webGoatHomeDirectory, "/XXE/log" + webSession.getUserName() + ".txt");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user