XSS lesson completion fixes (#669)
* XSS lesson completion fixes * removed log all * lesson progress capable of deprecated assignments in the database * fixed unit test for lesson progress
This commit is contained in:
parent
45c7949118
commit
0319c477b1
@ -45,6 +45,7 @@ public class Assignment {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private List<String> hints;
|
private List<String> hints;
|
||||||
|
|
||||||
@ -64,4 +65,14 @@ public class Assignment {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
this.hints = hints;
|
this.hints = hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set path is here to overwrite stored paths.
|
||||||
|
* Since a stored path can no longer be used in a lesson while
|
||||||
|
* the lesson (name) itself is still part of the lesson.
|
||||||
|
* @param pathName
|
||||||
|
*/
|
||||||
|
public void setPath(String pathName) {
|
||||||
|
this.path = pathName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ package org.owasp.webgoat.service;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
import org.owasp.webgoat.lessons.Category;
|
import org.owasp.webgoat.lessons.Category;
|
||||||
import org.owasp.webgoat.lessons.LessonMenuItem;
|
import org.owasp.webgoat.lessons.LessonMenuItem;
|
||||||
import org.owasp.webgoat.lessons.LessonMenuItemType;
|
import org.owasp.webgoat.lessons.LessonMenuItemType;
|
||||||
@ -45,6 +46,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +90,8 @@ public class LessonMenuService {
|
|||||||
lessonItem.setLink(lesson.getLink());
|
lessonItem.setLink(lesson.getLink());
|
||||||
lessonItem.setType(LessonMenuItemType.LESSON);
|
lessonItem.setType(LessonMenuItemType.LESSON);
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||||
lessonItem.setComplete(lessonTracker.isLessonSolved());
|
boolean lessonSolved = lessonCompleted(lessonTracker.getLessonOverview(), lesson);
|
||||||
|
lessonItem.setComplete(lessonSolved);
|
||||||
categoryItem.addChild(lessonItem);
|
categoryItem.addChild(lessonItem);
|
||||||
}
|
}
|
||||||
categoryItem.getChildren().sort((o1, o2) -> o1.getRanking() - o2.getRanking());
|
categoryItem.getChildren().sort((o1, o2) -> o1.getRanking() - o2.getRanking());
|
||||||
@ -97,4 +100,27 @@ public class LessonMenuService {
|
|||||||
return menu;
|
return menu;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This determines if the lesson is complete based on data in the database
|
||||||
|
* and the list of assignments actually linked to the existing current lesson.
|
||||||
|
* This way older removed assignments will not prevent a lesson from being completed.
|
||||||
|
* @param map
|
||||||
|
* @param currentLesson
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
|
boolean result = true;
|
||||||
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
|
Assignment storedAssignment = entry.getKey();
|
||||||
|
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||||
|
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||||
|
result = result && entry.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public class LessonProgressService {
|
|||||||
String successMessage = "";
|
String successMessage = "";
|
||||||
boolean lessonCompleted = false;
|
boolean lessonCompleted = false;
|
||||||
if (lessonTracker != null) {
|
if (lessonTracker != null) {
|
||||||
lessonCompleted = lessonTracker.isLessonSolved();
|
lessonCompleted = lessonCompleted(lessonTracker.getLessonOverview(),webSession.getCurrentLesson());
|
||||||
successMessage = "LessonCompleted"; //@todo we still use this??
|
successMessage = "LessonCompleted"; //@todo we still use this??
|
||||||
}
|
}
|
||||||
json.put("lessonCompleted", lessonCompleted);
|
json.put("lessonCompleted", lessonCompleted);
|
||||||
@ -70,19 +70,56 @@ public class LessonProgressService {
|
|||||||
List<LessonOverview> result = Lists.newArrayList();
|
List<LessonOverview> result = Lists.newArrayList();
|
||||||
if ( currentLesson != null ) {
|
if ( currentLesson != null ) {
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
||||||
result = toJson(lessonTracker.getLessonOverview());
|
result = toJson(lessonTracker.getLessonOverview(), currentLesson);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LessonOverview> toJson(Map<Assignment, Boolean> map) {
|
private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
List<LessonOverview> result = new ArrayList();
|
List<LessonOverview> result = new ArrayList();
|
||||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
result.add(new LessonOverview(entry.getKey(), entry.getValue()));
|
Assignment storedAssignment = entry.getKey();
|
||||||
|
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||||
|
if (lessonAssignment.getName().equals(storedAssignment.getName())
|
||||||
|
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
|
||||||
|
//here a stored path in the assignments table will be corrected for the JSON output
|
||||||
|
//with the value of the actual expected path
|
||||||
|
storedAssignment.setPath(lessonAssignment.getPath());
|
||||||
|
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||||
|
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//assignments not in the list will not be put in the lesson progress JSON output
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the lesson completed based on Assignment data from the database
|
||||||
|
* while ignoring assignments no longer in the application.
|
||||||
|
* @param map
|
||||||
|
* @param currentLesson
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
|
boolean result = true;
|
||||||
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
|
Assignment storedAssignment = entry.getKey();
|
||||||
|
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||||
|
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||||
|
result = result && entry.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package org.owasp.webgoat.session;
|
package org.owasp.webgoat.session;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
import org.owasp.webgoat.users.WebGoatUser;
|
import org.owasp.webgoat.users.WebGoatUser;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
@ -37,9 +37,9 @@ import java.sql.SQLException;
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
public class WebSession implements Serializable {
|
||||||
public class WebSession {
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4270066103101711560L;
|
||||||
private final WebGoatUser currentUser;
|
private final WebGoatUser currentUser;
|
||||||
private final WebgoatContext webgoatContext;
|
private final WebgoatContext webgoatContext;
|
||||||
private Lesson currentLesson;
|
private Lesson currentLesson;
|
||||||
|
@ -50,7 +50,7 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal
|
|||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class LessonMenuServiceTest {
|
public class LessonMenuServiceTest {
|
||||||
|
|
||||||
@Mock
|
@Mock(lenient=true)
|
||||||
private LessonTracker lessonTracker;
|
private LessonTracker lessonTracker;
|
||||||
@Mock
|
@Mock
|
||||||
private Course course;
|
private Course course;
|
||||||
|
@ -76,6 +76,7 @@ public class LessonProgressServiceTest {
|
|||||||
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
||||||
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
||||||
when(websession.getCurrentLesson()).thenReturn(lesson);
|
when(websession.getCurrentLesson()).thenReturn(lesson);
|
||||||
|
when(lesson.getAssignments()).thenReturn(List.of(assignment));
|
||||||
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
|
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
|
||||||
this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTrackerRepository, websession)).build();
|
this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTrackerRepository, websession)).build();
|
||||||
}
|
}
|
||||||
|
@ -123,4 +123,20 @@ public class GeneralLessonTest extends IntegrationTest {
|
|||||||
|
|
||||||
checkResults("/ChromeDevTools/");
|
checkResults("/ChromeDevTools/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authByPass() {
|
||||||
|
startLesson("AuthBypass");
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("secQuestion2", "John");
|
||||||
|
params.put("secQuestion3", "Main");
|
||||||
|
params.put("jsEnabled", "1");
|
||||||
|
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||||
|
params.put("userId", "12309746");
|
||||||
|
checkAssignment(url("/auth-bypass/verify-account"), params, true);
|
||||||
|
checkResults("/auth-bypass/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -238,5 +238,18 @@ public abstract class IntegrationTest {
|
|||||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
|
||||||
|
Assert.assertThat(
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.queryParams(params)
|
||||||
|
.get(url)
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class XSSTest extends IntegrationTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crossSiteScriptingAssignments() {
|
||||||
|
startLesson("CrossSiteScripting");
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.clear();
|
||||||
|
params.put("answer_xss_1", "yes");
|
||||||
|
checkAssignment(url("/CrossSiteScripting/attack1"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("QTY1", "1");
|
||||||
|
params.put("QTY2", "1");
|
||||||
|
params.put("QTY3", "1");
|
||||||
|
params.put("QTY4", "1");
|
||||||
|
params.put("field1", "<script>alert('XSS+Test')</script>");
|
||||||
|
params.put("field2", "111");
|
||||||
|
checkAssignmentWithGet(url("/CrossSiteScripting/attack5a"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("DOMTestRoute", "start.mvc#test");
|
||||||
|
checkAssignment(url("/CrossSiteScripting/attack6a"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("param1", "42");
|
||||||
|
params.put("param2", "24");
|
||||||
|
|
||||||
|
String result =
|
||||||
|
RestAssured.given()
|
||||||
|
.when()
|
||||||
|
.config(restConfig)
|
||||||
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||||
|
.header("X-Requested-With", "XMLHttpRequest")
|
||||||
|
.formParams(params)
|
||||||
|
.post(url("/CrossSiteScripting/phone-home-xss"))
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.extract().path("output");
|
||||||
|
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("successMessage", secretNumber);
|
||||||
|
checkAssignment(url("/CrossSiteScripting/dom-follow-up"), params, true);
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.put("question_0_solution", "Solution 4: No because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious.");
|
||||||
|
params.put("question_1_solution", "Solution 3: The data is included in dynamic content that is sent to a web user without being validated for malicious content.");
|
||||||
|
params.put("question_2_solution", "Solution 1: The script is permanently stored on the server and the victim gets the malicious script when requesting information from the server.");
|
||||||
|
params.put("question_3_solution", "Solution 2: They reflect the injected script off the web server. That occurs when input sent to the web server is part of the request.");
|
||||||
|
params.put("question_4_solution", "Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that the browser executes.");
|
||||||
|
checkAssignment(url("/CrossSiteScripting/quiz"), params, true);
|
||||||
|
|
||||||
|
checkResults("/CrossSiteScripting/");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -27,15 +27,18 @@ import org.jsoup.Jsoup;
|
|||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
//@RestController
|
||||||
|
@Deprecated
|
||||||
|
//TODO This assignment seems not to be in use in the UI
|
||||||
|
// it is there to make sure the lesson can be marked complete
|
||||||
|
// in order to restore it, make it accessible through the UI and uncomment RestController
|
||||||
@AssignmentHints(value = {"xss-mitigation-3-hint1", "xss-mitigation-3-hint2", "xss-mitigation-3-hint3", "xss-mitigation-3-hint4"})
|
@AssignmentHints(value = {"xss-mitigation-3-hint1", "xss-mitigation-3-hint2", "xss-mitigation-3-hint3", "xss-mitigation-3-hint4"})
|
||||||
public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
||||||
|
|
||||||
@PostMapping("CrossSiteScripting/attack3")
|
@PostMapping("/CrossSiteScripting/attack3")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String editor) {
|
public AttackResult completed(@RequestParam String editor) {
|
||||||
String unescapedString = org.jsoup.parser.Parser.unescapeEntities(editor, true);
|
String unescapedString = org.jsoup.parser.Parser.unescapeEntities(editor, true);
|
||||||
|
@ -24,28 +24,26 @@ package org.owasp.webgoat.xss;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.tools.*;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@RestController
|
//@RestController
|
||||||
|
@Deprecated
|
||||||
|
//TODO This assignment seems not to be in use in the UI
|
||||||
|
//it is there to make sure the lesson can be marked complete
|
||||||
|
//in order to restore it, make it accessible through the UI and uncomment RestController@Slf4j
|
||||||
|
@Slf4j
|
||||||
@AssignmentHints(value = {"xss-mitigation-4-hint1"})
|
@AssignmentHints(value = {"xss-mitigation-4-hint1"})
|
||||||
public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
||||||
|
|
||||||
@PostMapping("CrossSiteScripting/attack4")
|
@PostMapping("/CrossSiteScripting/attack4")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String editor2) {
|
public AttackResult completed(@RequestParam String editor2) {
|
||||||
|
|
||||||
String editor = editor2.replaceAll("\\<.*?>", "");
|
String editor = editor2.replaceAll("\\<.*?>", "");
|
||||||
System.out.println(editor);
|
log.debug(editor);
|
||||||
|
|
||||||
if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"") || editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"") || editor.contains(".scan(newComment, new File(\"antisamy-slashdot.xml\")")) &&
|
if ((editor.contains("Policy.getInstance(\"antisamy-slashdot.xml\"") || editor.contains(".scan(newComment, \"antisamy-slashdot.xml\"") || editor.contains(".scan(newComment, new File(\"antisamy-slashdot.xml\")")) &&
|
||||||
editor.contains("new AntiSamy();") &&
|
editor.contains("new AntiSamy();") &&
|
||||||
@ -53,10 +51,10 @@ public class CrossSiteScriptingLesson4 extends AssignmentEndpoint {
|
|||||||
editor.contains("CleanResults") &&
|
editor.contains("CleanResults") &&
|
||||||
editor.contains("MyCommentDAO.addComment(threadID, userID") &&
|
editor.contains("MyCommentDAO.addComment(threadID, userID") &&
|
||||||
editor.contains(".getCleanHTML());")) {
|
editor.contains(".getCleanHTML());")) {
|
||||||
System.out.println("true");
|
log.debug("true");
|
||||||
return trackProgress(success().feedback("xss-mitigation-4-success").build());
|
return trackProgress(success().feedback("xss-mitigation-4-success").build());
|
||||||
} else {
|
} else {
|
||||||
System.out.println("false");
|
log.debug("false");
|
||||||
return trackProgress(failed().feedback("xss-mitigation-4-failed").build());
|
return trackProgress(failed().feedback("xss-mitigation-4-failed").build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,15 +25,11 @@ package org.owasp.webgoat.xss;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints(value = {"xss-reflected-5a-hint-1", "xss-reflected-5a-hint-2", "xss-reflected-5a-hint-3", "xss-reflected-5a-hint-4"})
|
@AssignmentHints(value = {"xss-reflected-5a-hint-1", "xss-reflected-5a-hint-2", "xss-reflected-5a-hint-3", "xss-reflected-5a-hint-4"})
|
||||||
|
@ -25,14 +25,11 @@ package org.owasp.webgoat.xss;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints(value = {"xss-reflected-6a-hint-1", "xss-reflected-6a-hint-2", "xss-reflected-6a-hint-3", "xss-reflected-6a-hint-4"})
|
@AssignmentHints(value = {"xss-reflected-6a-hint-1", "xss-reflected-6a-hint-2", "xss-reflected-6a-hint-3", "xss-reflected-6a-hint-4"})
|
||||||
|
@ -34,7 +34,7 @@ public class CrossSiteScriptingQuiz extends AssignmentEndpoint {
|
|||||||
String[] solutions = {"Solution 4", "Solution 3", "Solution 1", "Solution 2", "Solution 4"};
|
String[] solutions = {"Solution 4", "Solution 3", "Solution 1", "Solution 2", "Solution 4"};
|
||||||
boolean[] guesses = new boolean[solutions.length];
|
boolean[] guesses = new boolean[solutions.length];
|
||||||
|
|
||||||
@PostMapping("/cross-site-scripting/quiz")
|
@PostMapping("/CrossSiteScripting/quiz")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String[] question_0_solution, @RequestParam String[] question_1_solution, @RequestParam String[] question_2_solution, @RequestParam String[] question_3_solution, @RequestParam String[] question_4_solution) throws IOException {
|
public AttackResult completed(@RequestParam String[] question_0_solution, @RequestParam String[] question_1_solution, @RequestParam String[] question_2_solution, @RequestParam String[] question_3_solution, @RequestParam String[] question_4_solution) throws IOException {
|
||||||
int correctAnswers = 0;
|
int correctAnswers = 0;
|
||||||
@ -59,7 +59,7 @@ public class CrossSiteScriptingQuiz extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/cross-site-scripting/quiz")
|
@GetMapping("/CrossSiteScripting/quiz")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public boolean[] getResults() {
|
public boolean[] getResults() {
|
||||||
return this.guesses;
|
return this.guesses;
|
||||||
|
@ -28,7 +28,6 @@ import org.owasp.webgoat.session.UserSessionData;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -24,14 +24,10 @@ package org.owasp.webgoat.xss;
|
|||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jason on 11/23/16.
|
* Created by jason on 11/23/16.
|
||||||
*/
|
*/
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.xss;
|
package org.owasp.webgoat.xss.mitigation;
|
||||||
|
|
||||||
import org.owasp.webgoat.lessons.Category;
|
import org.owasp.webgoat.lessons.Category;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
@ -20,7 +20,7 @@
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.xss;
|
package org.owasp.webgoat.xss.stored;
|
||||||
|
|
||||||
import org.owasp.webgoat.lessons.Category;
|
import org.owasp.webgoat.lessons.Category;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
@ -20,23 +20,21 @@
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.xss;
|
package org.owasp.webgoat.xss.stored;
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jason on 11/23/16.
|
* Created by jason on 11/23/16.
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
|
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
|
||||||
|
|
||||||
@PostMapping("/CrossSiteScripting/stored-xss-follow-up")
|
//TODO This assignment seems not to be in use in the UI
|
||||||
|
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String successMessage) {
|
public AttackResult completed(@RequestParam String successMessage) {
|
||||||
UserSessionData userSessionData = getUserSessionData();
|
UserSessionData userSessionData = getUserSessionData();
|
@ -20,7 +20,7 @@
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.xss;
|
package org.owasp.webgoat.xss.stored;
|
||||||
|
|
||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@ -30,20 +30,18 @@ import org.joda.time.DateTime;
|
|||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
|
import org.owasp.webgoat.xss.Comment;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.owasp.encoder.*;
|
|
||||||
|
|
||||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class StoredXssComments extends AssignmentEndpoint {
|
public class StoredXssComments extends AssignmentEndpoint {
|
||||||
@ -64,7 +62,8 @@ public class StoredXssComments extends AssignmentEndpoint {
|
|||||||
comments.add(new Comment("guest", DateTime.now().toString(fmt), "Can you post a comment, calling webgoat.customjs.phoneHome() ?"));
|
comments.add(new Comment("guest", DateTime.now().toString(fmt), "Can you post a comment, calling webgoat.customjs.phoneHome() ?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/CrossSiteScripting/stored-xss", produces = MediaType.APPLICATION_JSON_VALUE, consumes = ALL_VALUE)
|
//TODO This assignment seems not to be in use in the UI
|
||||||
|
@GetMapping(path = "/CrossSiteScriptingStored/stored-xss", produces = MediaType.APPLICATION_JSON_VALUE, consumes = ALL_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Collection<Comment> retrieveComments() {
|
public Collection<Comment> retrieveComments() {
|
||||||
List<Comment> allComments = Lists.newArrayList();
|
List<Comment> allComments = Lists.newArrayList();
|
||||||
@ -77,7 +76,8 @@ public class StoredXssComments extends AssignmentEndpoint {
|
|||||||
return allComments;
|
return allComments;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/CrossSiteScripting/stored-xss")
|
//TODO This assignment seems not to be in use in the UI
|
||||||
|
@PostMapping("/CrossSiteScriptingStored/stored-xss")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult createNewComment(@RequestBody String commentStr) {
|
public AttackResult createNewComment(@RequestBody String commentStr) {
|
||||||
Comment comment = parseJson(commentStr);
|
Comment comment = parseJson(commentStr);
|
@ -182,7 +182,7 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<form id="quiz-form" class="attack-form" accept-charset="UNKNOWN"
|
<form id="quiz-form" class="attack-form" accept-charset="UNKNOWN"
|
||||||
method="POST" name="form"
|
method="POST" name="form"
|
||||||
action="/WebGoat/cross-site-scripting/quiz"
|
action="/WebGoat/CrossSiteScripting/quiz"
|
||||||
enctype="application/json;charset=UTF-8" role="form">
|
enctype="application/json;charset=UTF-8" role="form">
|
||||||
<div id="q_container"></div>
|
<div id="q_container"></div>
|
||||||
<br />
|
<br />
|
||||||
|
@ -28,6 +28,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
|
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
|
||||||
|
import org.owasp.webgoat.xss.stored.StoredXssComments;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
@ -53,7 +54,7 @@ public class StoredXssCommentsTest extends AssignmentEndpointTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void success() throws Exception {
|
public void success() throws Exception {
|
||||||
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScripting/stored-xss")
|
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScriptingStored/stored-xss")
|
||||||
.content("{\"text\":\"someTextHere<script>webgoat.customjs.phoneHome()</script>MoreTextHere\"}")
|
.content("{\"text\":\"someTextHere<script>webgoat.customjs.phoneHome()</script>MoreTextHere\"}")
|
||||||
.contentType(MediaType.APPLICATION_JSON));
|
.contentType(MediaType.APPLICATION_JSON));
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ public class StoredXssCommentsTest extends AssignmentEndpointTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void failure() throws Exception {
|
public void failure() throws Exception {
|
||||||
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScripting/stored-xss")
|
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScriptingStored/stored-xss")
|
||||||
.content("{\"text\":\"someTextHere<script>alert('Xss')</script>MoreTextHere\"}")
|
.content("{\"text\":\"someTextHere<script>alert('Xss')</script>MoreTextHere\"}")
|
||||||
.contentType(MediaType.APPLICATION_JSON));
|
.contentType(MediaType.APPLICATION_JSON));
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ public class StoredXssCommentsTest extends AssignmentEndpointTest {
|
|||||||
@Test
|
@Test
|
||||||
public void isNotEncoded() throws Exception {
|
public void isNotEncoded() throws Exception {
|
||||||
//do get to get comments after posting xss payload
|
//do get to get comments after posting xss payload
|
||||||
ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScripting/stored-xss"));
|
ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScriptingStored/stored-xss"));
|
||||||
MvcResult mvcResult = taintedResults.andReturn();
|
MvcResult mvcResult = taintedResults.andReturn();
|
||||||
assert(mvcResult.getResponse().getContentAsString().contains("<script>console.warn"));
|
assert(mvcResult.getResponse().getContentAsString().contains("<script>console.warn"));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user