fix: SQL advanced assignment 5 (#2047)
- Add and show correct hints - Fix solving the lesson immediately when you register as tom. Now uses `informationMessage` to display a message in the UI - Add Playwright test Closes: gh-2045
This commit is contained in:
@ -4,11 +4,9 @@
|
||||
*/
|
||||
package org.owasp.webgoat.container.assignments;
|
||||
|
||||
import org.owasp.webgoat.container.i18n.PluginMessages;
|
||||
|
||||
public class AttackResultBuilder {
|
||||
|
||||
private boolean lessonCompleted;
|
||||
private boolean assignmentCompleted;
|
||||
private Object[] feedbackArgs;
|
||||
private String feedbackResourceBundleKey;
|
||||
private String output;
|
||||
@ -16,15 +14,8 @@ public class AttackResultBuilder {
|
||||
private AssignmentEndpoint assignment;
|
||||
private boolean attemptWasMade = false;
|
||||
|
||||
public AttackResultBuilder lessonCompleted(boolean lessonCompleted) {
|
||||
this.lessonCompleted = lessonCompleted;
|
||||
this.feedbackResourceBundleKey = "lesson.completed";
|
||||
return this;
|
||||
}
|
||||
|
||||
public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) {
|
||||
this.lessonCompleted = lessonCompleted;
|
||||
this.feedbackResourceBundleKey = resourceBundleKey;
|
||||
public AttackResultBuilder assignmentCompleted(boolean lessonCompleted) {
|
||||
this.assignmentCompleted = lessonCompleted;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -55,7 +46,7 @@ public class AttackResultBuilder {
|
||||
|
||||
public AttackResult build() {
|
||||
return new AttackResult(
|
||||
lessonCompleted,
|
||||
assignmentCompleted,
|
||||
feedbackResourceBundleKey,
|
||||
feedbackArgs,
|
||||
output,
|
||||
@ -81,7 +72,7 @@ public class AttackResultBuilder {
|
||||
*/
|
||||
public static AttackResultBuilder success(AssignmentEndpoint assignment) {
|
||||
return new AttackResultBuilder()
|
||||
.lessonCompleted(true)
|
||||
.assignmentCompleted(true)
|
||||
.attemptWasMade()
|
||||
.feedback("assignment.solved")
|
||||
.assignment(assignment);
|
||||
@ -99,13 +90,13 @@ public class AttackResultBuilder {
|
||||
*/
|
||||
public static AttackResultBuilder failed(AssignmentEndpoint assignment) {
|
||||
return new AttackResultBuilder()
|
||||
.lessonCompleted(false)
|
||||
.assignmentCompleted(false)
|
||||
.attemptWasMade()
|
||||
.feedback("assignment.not.solved")
|
||||
.assignment(assignment);
|
||||
}
|
||||
|
||||
public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
|
||||
return new AttackResultBuilder().lessonCompleted(false).assignment(assignment);
|
||||
return new AttackResultBuilder().assignmentCompleted(false).assignment(assignment);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public class CourseConfiguration {
|
||||
|
||||
@Bean
|
||||
public Course course() {
|
||||
assignments.stream().forEach(this::attachToLesson);
|
||||
assignments.forEach(this::attachToLesson);
|
||||
|
||||
// Check if all assignments are attached to a lesson
|
||||
var assignmentsAttachedToLessons =
|
||||
@ -99,7 +99,7 @@ public class CourseConfiguration {
|
||||
|
||||
private List<String> findDiff() {
|
||||
var matchedToLessons =
|
||||
lessons.stream().flatMap(l -> l.getAssignments().stream()).map(a -> a.getName()).toList();
|
||||
lessons.stream().flatMap(l -> l.getAssignments().stream()).map(Assignment::getName).toList();
|
||||
var allAssignments = assignments.stream().map(a -> a.getClass().getSimpleName()).toList();
|
||||
|
||||
var diff = new ArrayList<>(allAssignments);
|
||||
|
@ -5,7 +5,7 @@
|
||||
package org.owasp.webgoat.lessons.sqlinjection.advanced;
|
||||
|
||||
import static org.owasp.webgoat.container.assignments.AttackResultBuilder.failed;
|
||||
import static org.owasp.webgoat.container.assignments.AttackResultBuilder.success;
|
||||
import static org.owasp.webgoat.container.assignments.AttackResultBuilder.informationMessage;
|
||||
|
||||
import java.sql.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -19,13 +19,17 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/8/17.
|
||||
*/
|
||||
@RestController
|
||||
@AssignmentHints(
|
||||
value = {"SqlInjectionChallenge1", "SqlInjectionChallenge2", "SqlInjectionChallenge3"})
|
||||
value = {
|
||||
"SqlInjectionChallenge1",
|
||||
"SqlInjectionChallenge2",
|
||||
"SqlInjectionChallenge3",
|
||||
"SqlInjectionChallenge4",
|
||||
"SqlInjectionChallenge5",
|
||||
"SqlInjectionChallenge6",
|
||||
"SqlInjectionChallenge7"
|
||||
})
|
||||
@Slf4j
|
||||
public class SqlInjectionChallenge implements AssignmentEndpoint {
|
||||
|
||||
@ -35,38 +39,34 @@ public class SqlInjectionChallenge implements AssignmentEndpoint {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@PutMapping("/SqlInjectionAdvanced/challenge")
|
||||
@PutMapping("/SqlInjectionAdvanced/register")
|
||||
// assignment path is bounded to class so we use different http method :-)
|
||||
@ResponseBody
|
||||
public AttackResult registerNewUser(
|
||||
@RequestParam String username_reg,
|
||||
@RequestParam String email_reg,
|
||||
@RequestParam String password_reg)
|
||||
throws Exception {
|
||||
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
|
||||
@RequestParam("username_reg") String username,
|
||||
@RequestParam("email_reg") String email,
|
||||
@RequestParam("password_reg") String password) {
|
||||
AttackResult attackResult = checkArguments(username, email, password);
|
||||
|
||||
if (attackResult == null) {
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
String checkUserQuery =
|
||||
"select userid from sql_challenge_users where userid = '" + username_reg + "'";
|
||||
"select userid from sql_challenge_users where userid = '" + username + "'";
|
||||
Statement statement = connection.createStatement();
|
||||
ResultSet resultSet = statement.executeQuery(checkUserQuery);
|
||||
|
||||
if (resultSet.next()) {
|
||||
if (username_reg.contains("tom'")) {
|
||||
attackResult = success(this).feedback("user.exists").build();
|
||||
} else {
|
||||
attackResult = failed(this).feedback("user.exists").feedbackArgs(username_reg).build();
|
||||
}
|
||||
attackResult = failed(this).feedback("user.exists").feedbackArgs(username).build();
|
||||
} else {
|
||||
PreparedStatement preparedStatement =
|
||||
connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)");
|
||||
preparedStatement.setString(1, username_reg);
|
||||
preparedStatement.setString(2, email_reg);
|
||||
preparedStatement.setString(3, password_reg);
|
||||
preparedStatement.setString(1, username);
|
||||
preparedStatement.setString(2, email);
|
||||
preparedStatement.setString(3, password);
|
||||
preparedStatement.execute();
|
||||
attackResult = success(this).feedback("user.created").feedbackArgs(username_reg).build();
|
||||
attackResult =
|
||||
informationMessage(this).feedback("user.created").feedbackArgs(username).build();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
attackResult = failed(this).output("Something went wrong").build();
|
||||
@ -75,13 +75,13 @@ public class SqlInjectionChallenge implements AssignmentEndpoint {
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) {
|
||||
if (StringUtils.isEmpty(username_reg)
|
||||
|| StringUtils.isEmpty(email_reg)
|
||||
|| StringUtils.isEmpty(password_reg)) {
|
||||
private AttackResult checkArguments(String username, String email, String password) {
|
||||
if (StringUtils.isEmpty(username)
|
||||
|| StringUtils.isEmpty(email)
|
||||
|| StringUtils.isEmpty(password)) {
|
||||
return failed(this).feedback("input.invalid").build();
|
||||
}
|
||||
if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) {
|
||||
if (username.length() > 250 || email.length() > 30 || password.length() > 30) {
|
||||
return failed(this).feedback("input.invalid").build();
|
||||
}
|
||||
return null;
|
||||
|
@ -9,7 +9,6 @@ import static org.owasp.webgoat.container.assignments.AttackResultBuilder.succes
|
||||
|
||||
import org.owasp.webgoat.container.LessonDataSource;
|
||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.container.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -17,13 +16,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@AssignmentHints(
|
||||
value = {
|
||||
"SqlInjectionChallengeHint1",
|
||||
"SqlInjectionChallengeHint2",
|
||||
"SqlInjectionChallengeHint3",
|
||||
"SqlInjectionChallengeHint4"
|
||||
})
|
||||
public class SqlInjectionChallengeLogin implements AssignmentEndpoint {
|
||||
private final LessonDataSource dataSource;
|
||||
|
||||
@ -31,20 +23,22 @@ public class SqlInjectionChallengeLogin implements AssignmentEndpoint {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@PostMapping("/SqlInjectionAdvanced/challenge_Login")
|
||||
@PostMapping("/SqlInjectionAdvanced/login")
|
||||
@ResponseBody
|
||||
public AttackResult login(
|
||||
@RequestParam String username_login, @RequestParam String password_login) throws Exception {
|
||||
@RequestParam("username_login") String username,
|
||||
@RequestParam("password_login") String password)
|
||||
throws Exception {
|
||||
try (var connection = dataSource.getConnection()) {
|
||||
var statement =
|
||||
connection.prepareStatement(
|
||||
"select password from sql_challenge_users where userid = ? and password = ?");
|
||||
statement.setString(1, username_login);
|
||||
statement.setString(2, password_login);
|
||||
statement.setString(1, username);
|
||||
statement.setString(2, password);
|
||||
var resultSet = statement.executeQuery();
|
||||
|
||||
if (resultSet.next()) {
|
||||
return ("tom".equals(username_login))
|
||||
return ("tom".equals(username))
|
||||
? success(this).build()
|
||||
: failed(this).feedback("ResultsButNotTom").build();
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user