Skip to content

Commit

Permalink
SQL: Cannot use apostrophe/quotes on string literals WebGoat#662
Browse files Browse the repository at this point in the history
  • Loading branch information
nbaars committed Oct 30, 2019
1 parent 2a6b3d1 commit e783c0c
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,18 @@ public class SqlInjectionLesson5 extends AssignmentEndpoint {

@PostMapping("/SqlInjection/attack5")
@ResponseBody
public AttackResult completed(@RequestParam String query) {
public AttackResult completed(@RequestParam("_query") String query) {
return injectableQuery(query);
}

protected AttackResult injectableQuery(String _query) {
protected AttackResult injectableQuery(String query) {
try {
String regex = "(?i)^(grant alter table to unauthorizedUser)(?:[;]?)$";
Boolean isCorrect = false;
String regex = "(?i)^(grant alter table to [\"']?unauthorizedUser[\"']?)(?:[;]?)$";
StringBuffer output = new StringBuffer();

// user completes lesson if the query is correct
if (_query.matches(regex)) {
output.append("<span class='feedback-positive'>" + _query + "</span>");
if (query.matches(regex)) {
output.append("<span class='feedback-positive'>" + query + "</span>");
return trackProgress(success().output(output.toString()).build());
} else {
return trackProgress(failed().output(output.toString()).build());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

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

}

@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\""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("grant")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}

@Test
public void grantSolutionWithSingleQuotes() 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 grantSolutionWrong() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("_query","grant alter table to me"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package org.owasp.webgoat.sql_injection.introduction;

import org.junit.Before;
import org.junit.Ignore;
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 org.springframework.util.LinkedMultiValueMap;

import java.util.Map;

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;

Expand All @@ -27,65 +22,50 @@
@RunWith(SpringJUnit4ClassRunner.class)
public class SqlInjectionLesson5aTest extends SqlLessonTest {

@Test
public void knownAccountShouldDisplayData() throws Exception {
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("account", "Smith");
map.add("operator", "");
map.add("injection", "");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(map))

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

@Ignore
@Test
public void unknownAccount() throws Exception {
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("account", "Smith");
map.add("operator", "");
map.add("injection", "");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(map))

.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(SqlInjectionLesson8Test.modifySpan(messages.getMessage("NoResultsMatched")))))
.andExpect(jsonPath("$.output").doesNotExist());
}
@Test
public void knownAccountShouldDisplayData() throws Exception {
var params = Map.of("account", "Smith", "operator", "", "injection", "");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(new LinkedMultiValueMap(params)))
.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 sqlInjection() throws Exception {
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("account", "'");
map.add("operator", "OR");
map.add("injection", "'1' = '1");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(map))
@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)))

.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("You have succeed")))
.andExpect(jsonPath("$.output").exists());
}
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(SqlInjectionLesson8Test.modifySpan(messages.getMessage("NoResultsMatched")))))
.andExpect(jsonPath("$.output").doesNotExist());
}

@Test
public void sqlInjectionWrongShouldDisplayError() throws Exception {
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("account", "Smith'");
map.add("operator", "OR");
map.add("injection", "'1' = '1'");
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.params(map))
@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)))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("You have succeed")))
.andExpect(jsonPath("$.output").exists());
}

.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.output", is("malformed string: '1''<br> Your query was: SELECT * FROM user_data WHERE" +
" first_name = 'John' and last_name = 'Smith' OR '1' = '1''")));
}
@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)))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.output", is("malformed string: '1''<br> Your query was: SELECT * FROM user_data WHERE" +
" first_name = 'John' and last_name = 'Smith' OR '1' = '1''")));
}
}

0 comments on commit e783c0c

Please sign in to comment.