diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java index 532e723a2..5231895c7 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java @@ -5,7 +5,7 @@ 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.plugin.introduction.SqlInjectionLesson5a; +import org.owasp.webgoat.plugin.introduction.SqlInjectionLesson8; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -72,7 +72,7 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint { ResultSetMetaData resultsMetaData = results.getMetaData(); StringBuffer output = new StringBuffer(); - output.append(SqlInjectionLesson5a.writeTable(results, resultsMetaData)); + output.append(SqlInjectionLesson8.generateTable(results)); if(! (query.toLowerCase().contains("union") || query.toLowerCase().contains("join")) ) output.append("There is also a way to retrieve the Data by using a UNION or JOIN. Can you figure out, how this is done?"); results.last(); diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java deleted file mode 100644 index 1237e3c27..000000000 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson5a.java +++ /dev/null @@ -1,128 +0,0 @@ - -package org.owasp.webgoat.plugin.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.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.io.IOException; -import java.sql.*; - - -/*************************************************************************************************** - * - * - * 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. - * - * For details, please see http://webgoat.github.io - * - * @author Bruce Mayhew WebGoat - * @created October 28, 2003 - */ -@AssignmentPath("/SqlInjection/attack5a") -@AssignmentHints(value = {"SqlStringInjectionHint5a1", "SqlStringInjectionHint5a2", "SqlStringInjectionHint5a3", "SqlStringInjectionHint5a4", "SqlStringInjectionHint5a5"}) -public class SqlInjectionLesson5a extends AssignmentEndpoint { - - @RequestMapping(method = RequestMethod.POST) - public - @ResponseBody - AttackResult completed(@RequestParam String account) { - return injectableQuery(account); - } - - protected AttackResult injectableQuery(String accountName) { - try { - Connection connection = DatabaseUtilities.getConnection(getWebSession()); - String query = "SELECT userid, first_name, last_name, CC_Number, CC_Type, Cookie, Login_Count FROM user_data WHERE last_name = '" + accountName + "'"; - - try { - Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - ResultSet results = statement.executeQuery(query); - - if ((results != null) && (results.first())) { - ResultSetMetaData resultsMetaData = results.getMetaData(); - StringBuffer output = new StringBuffer(); - - output.append(writeTable(results, resultsMetaData)); - results.last(); - - // If they get back more than one user they succeeded - if (results.getRow() >= 6) { - return trackProgress(success().feedback("sql-injection.5a.success").feedbackArgs(output.toString()).build()); - } else { - return trackProgress(failed().output(output.toString()).build()); - } - } else { - return trackProgress(failed().feedback("sql-injection.5a.no.results").build()); - - } - } catch (SQLException sqle) { - - return trackProgress(failed().output(sqle.getMessage()).build()); - } - } catch (Exception e) { - return trackProgress(failed().output(this.getClass().getName() + " : " + e.getMessage()).build()); - } - } - - public static String writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, - SQLException { - int numColumns = resultsMetaData.getColumnCount(); - results.beforeFirst(); - StringBuffer t = new StringBuffer(); - t.append("
");
-
- if (results.next()) {
- for (int i = 1; i < (numColumns + 1); i++) {
- t.append(resultsMetaData.getColumnName(i));
- t.append(", ");
- }
-
- t.append("
");
- results.beforeFirst();
-
- while (results.next()) {
-
- for (int i = 1; i < (numColumns + 1); i++) {
- t.append(results.getString(i));
- t.append(", ");
- }
-
- t.append("
");
- }
-
- } else {
- t.append("Query Successful; however no data was returned from this query.");
- }
-
- t.append("
USERID, FIRST_NAME"))); + .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.8.one"))))) + .andExpect(jsonPath("$.output", containsString("
"))); } @Test - public void unknownAccount() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a") - .param("account", "Smithh")) - - .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")) + public void multipleAccounts() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8") + .param("name", "Smith") + .param("auth_tan", "3SL99A' OR '1' = '1")) .andExpect(status().isOk()) .andExpect(jsonPath("lessonCompleted", is(true))) - .andExpect(jsonPath("$.feedback", containsString("You have succeeded"))) + .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.8.success"))))) + .andExpect(jsonPath("$.output", containsString(" | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
96134<\\/td> | Bob<\\/td> | Franco<\\/td> | Marketing<\\/td> | 83700<\\/td> | LO9S2V<\\/td><\\/tr>")));
+ }
+
+ @Test
+ public void wrongNameReturnsNoAccounts() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
+ .param("name", "Smithh")
+ .param("auth_tan", "3SL99A"))
+
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("lessonCompleted", is(false)))
+ .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.8.no.results")))))
.andExpect(jsonPath("$.output").doesNotExist());
}
@Test
- public void sqlInjectionWrongShouldDisplayError() throws Exception {
- mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5a")
- .param("account", "smith' OR '1' = '1'"))
+ public void wrongTANReturnsNoAccounts() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
+ .param("name", "Smithh")
+ .param("auth_tan", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
- .andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))
- .andExpect(jsonPath("$.output", is("malformed string: '1''")));
+ .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.8.no.results")))))
+ .andExpect(jsonPath("$.output").doesNotExist());
+ }
+
+ @Test
+ public void malformedQueryReturnsError() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
+ .param("name", "Smith")
+ .param("auth_tan", "3SL99A' OR '1' = '1'"))
+
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("lessonCompleted", is(false)))
+ .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.error")))))
+ .andExpect(jsonPath("$.output", containsString("feedback-negative")));
+ }
+
+ private String modifySpan(String message) {
+ return message.replace("", "<\\/span>");
}
}
diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson9Test.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson9Test.java
new file mode 100644
index 000000000..5e81a26b7
--- /dev/null
+++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson9Test.java
@@ -0,0 +1,179 @@
+package org.owasp.webgoat.plugin.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.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;
+
+/**
+ * @author Benedikt Stuhrmann
+ * @since 11/07/18.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SqlInjectionLesson9Test extends LessonTest {
+
+ @Autowired
+ private WebgoatContext context;
+
+ private String completedError = "JSON path \"lessonCompleted\"";
+
+ @Before
+ public void setup() {
+ SqlInjection sql = new SqlInjection();
+ when(webSession.getCurrentLesson()).thenReturn(sql);
+ when(webSession.getWebgoatContext()).thenReturn(context);
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ }
+
+ @Test
+ public void oneAccount() throws Exception {
+ try {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
+ .param("name", "Smith")
+ .param("auth_tan", "3SL99A"))
+
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("lessonCompleted", is(false)))
+ .andExpect(jsonPath("$.feedback", is(this.modifySpan(messages.getMessage("sql-injection.9.one")))))
+ .andExpect(jsonPath("$.output", containsString("
|