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:
Nanne Baars 2025-03-02 20:31:05 +01:00 committed by GitHub
parent c37a8e8c19
commit e9f79cc739
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 189 additions and 97 deletions

View File

@ -15,17 +15,16 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
startLesson("SqlInjectionAdvanced"); startLesson("SqlInjectionAdvanced");
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.clear();
params.put("username_reg", "tom' AND substring(password,1,1)='t"); params.put("username_reg", "tom' AND substring(password,1,1)='t");
params.put("password_reg", "password"); params.put("password_reg", "password");
params.put("email_reg", "someone@microsoft.com"); params.put("email_reg", "someone@microsoft.com");
params.put("confirm_password", "password"); params.put("confirm_password", "password");
checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge"), params, true); checkAssignmentWithPUT(webGoatUrlConfig.url("SqlInjectionAdvanced/register"), params, false);
params.clear(); params.clear();
params.put("username_login", "tom"); params.put("username_login", "tom");
params.put("password_login", "thisisasecretfortomonly"); params.put("password_login", "thisisasecretfortomonly");
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/challenge_Login"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/login"), params, true);
params.clear(); params.clear();
params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
@ -59,7 +58,5 @@ public class SqlInjectionAdvancedIntegrationTest extends IntegrationTest {
"question_4_solution", "question_4_solution",
"Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true); checkAssignment(webGoatUrlConfig.url("SqlInjectionAdvanced/quiz"), params, true);
checkResults("SqlInjectionAdvanced");
} }
} }

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
package org.owasp.webgoat.playwright.webgoat; package org.owasp.webgoat.playwright.webgoat.lessons;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@ -15,8 +15,9 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.owasp.webgoat.container.lessons.LessonName; import org.owasp.webgoat.container.lessons.LessonName;
import org.owasp.webgoat.playwright.webgoat.PlaywrightTest;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication; import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
import org.owasp.webgoat.playwright.webgoat.pages.HttpBasicsLessonPage; import org.owasp.webgoat.playwright.webgoat.pages.lessons.HttpBasicsLessonPage;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class HttpBasicsLessonUITest extends PlaywrightTest { public class HttpBasicsLessonUITest extends PlaywrightTest {

View File

@ -0,0 +1,120 @@
/*
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.owasp.webgoat.playwright.webgoat.lessons;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Page.GetByRoleOptions;
import com.microsoft.playwright.options.AriaRole;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.lessons.LessonName;
import org.owasp.webgoat.playwright.webgoat.PlaywrightTest;
import org.owasp.webgoat.playwright.webgoat.helpers.Authentication;
import org.owasp.webgoat.playwright.webgoat.pages.lessons.LessonPage;
public class SqlInjectionAdvancedUITest extends PlaywrightTest {
private LessonPage lessonPage;
@BeforeEach
void navigateToLesson(Browser browser) {
var lessonName = new LessonName("SqlInjectionAdvanced");
var page = Authentication.sylvester(browser);
this.lessonPage = new LessonPage(page);
lessonPage.resetLesson(lessonName);
lessonPage.open(lessonName);
}
@Test
@DisplayName("Login as Tom with incorrect password")
void loginAsTomWithIncorrectPassword() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Login")).click();
page.locator("[name='username_login']").fill("tom");
page.locator("[name='password_login']").fill("test");
page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Log In")).click();
assertThat(lessonPage.getAssignmentOutput())
.containsText("Wrong username or password. Try again.");
}
@Test
@DisplayName("Login as Tom with correct password")
void loginAsTomWithCorrectPassword() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Login")).click();
page.locator("[name='username_login']").fill("tom");
page.locator("[name='password_login']").fill("thisisasecretfortomonly");
page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Log In")).click();
lessonPage.isAssignmentSolved(5);
}
@Test
@DisplayName("Register as Tom should show error that Tom already exists")
void registerAsTomShouldDisplayError() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click();
page.locator("[name='username_reg']").fill("tom");
page.locator("[name='email_reg']").fill("tom@tom.org");
page.locator("[name='password_reg']").fill("test");
page.locator("[name='confirm_password_reg']").fill("test");
page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click();
assertThat(lessonPage.getAssignmentOutput()).containsText("User tom already exists");
}
@Test
@DisplayName(
"Using SQL Injection to register as Tom to guess the password and the guess is correct")
void startGuessingCorrect() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click();
page.locator("[name='username_reg']").fill("tom' AND substring(password,1,1)='t");
page.locator("[name='email_reg']").fill("tom@tom.org");
page.locator("[name='password_reg']").fill("test");
page.locator("[name='confirm_password_reg']").fill("test");
page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click();
assertThat(lessonPage.getAssignmentOutput())
.containsText("User tom' AND substring(password,1,1)='t already exists");
}
@Test
@DisplayName(
"Using SQL Injection to register as Tom to guess the password and the guess is incorrect")
void startGuessingIncorrect() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.LINK, new GetByRoleOptions().setName("Register")).click();
page.locator("[name='username_reg']").fill("tom' AND substring(password,1,1)='a");
page.locator("[name='email_reg']").fill("tom@tom.org");
page.locator("[name='password_reg']").fill("test");
page.locator("[name='confirm_password_reg']").fill("test");
page.getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Register Now")).click();
assertThat(lessonPage.getAssignmentOutput())
.containsText(
"User tom' AND substring(password,1,1)='a created, please proceed to the login page.");
}
@Test
@DisplayName("Should display correct hints")
void shouldDisplayCorrectHints() {
lessonPage.navigateTo(5);
var page = lessonPage.getPage();
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Show hints")).click();
assertThat(lessonPage.getAssignmentOutput()).containsText("Look at the different");
}
}

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
package org.owasp.webgoat.playwright.webgoat.pages; package org.owasp.webgoat.playwright.webgoat.pages.lessons;
import com.microsoft.playwright.Locator; import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page; import com.microsoft.playwright.Page;

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors * SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
package org.owasp.webgoat.playwright.webgoat.pages; package org.owasp.webgoat.playwright.webgoat.pages.lessons;
import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl; import static org.owasp.webgoat.playwright.webgoat.PlaywrightTest.webGoatUrl;
@ -14,7 +14,7 @@ import org.assertj.core.api.Assertions;
import org.owasp.webgoat.container.lessons.LessonName; import org.owasp.webgoat.container.lessons.LessonName;
@Getter @Getter
class LessonPage { public class LessonPage {
private final Page page; private final Page page;
@ -65,4 +65,8 @@ class LessonPage {
public Locator getAssignmentOutput() { public Locator getAssignmentOutput() {
return page.locator("#lesson-content-wrapper"); return page.locator("#lesson-content-wrapper");
} }
public Locator getHintsOutput() {
return page.locator("#lesson-hint");
}
} }

View File

@ -4,11 +4,9 @@
*/ */
package org.owasp.webgoat.container.assignments; package org.owasp.webgoat.container.assignments;
import org.owasp.webgoat.container.i18n.PluginMessages;
public class AttackResultBuilder { public class AttackResultBuilder {
private boolean lessonCompleted; private boolean assignmentCompleted;
private Object[] feedbackArgs; private Object[] feedbackArgs;
private String feedbackResourceBundleKey; private String feedbackResourceBundleKey;
private String output; private String output;
@ -16,15 +14,8 @@ public class AttackResultBuilder {
private AssignmentEndpoint assignment; private AssignmentEndpoint assignment;
private boolean attemptWasMade = false; private boolean attemptWasMade = false;
public AttackResultBuilder lessonCompleted(boolean lessonCompleted) { public AttackResultBuilder assignmentCompleted(boolean lessonCompleted) {
this.lessonCompleted = lessonCompleted; this.assignmentCompleted = lessonCompleted;
this.feedbackResourceBundleKey = "lesson.completed";
return this;
}
public AttackResultBuilder lessonCompleted(boolean lessonCompleted, String resourceBundleKey) {
this.lessonCompleted = lessonCompleted;
this.feedbackResourceBundleKey = resourceBundleKey;
return this; return this;
} }
@ -55,7 +46,7 @@ public class AttackResultBuilder {
public AttackResult build() { public AttackResult build() {
return new AttackResult( return new AttackResult(
lessonCompleted, assignmentCompleted,
feedbackResourceBundleKey, feedbackResourceBundleKey,
feedbackArgs, feedbackArgs,
output, output,
@ -81,7 +72,7 @@ public class AttackResultBuilder {
*/ */
public static AttackResultBuilder success(AssignmentEndpoint assignment) { public static AttackResultBuilder success(AssignmentEndpoint assignment) {
return new AttackResultBuilder() return new AttackResultBuilder()
.lessonCompleted(true) .assignmentCompleted(true)
.attemptWasMade() .attemptWasMade()
.feedback("assignment.solved") .feedback("assignment.solved")
.assignment(assignment); .assignment(assignment);
@ -99,13 +90,13 @@ public class AttackResultBuilder {
*/ */
public static AttackResultBuilder failed(AssignmentEndpoint assignment) { public static AttackResultBuilder failed(AssignmentEndpoint assignment) {
return new AttackResultBuilder() return new AttackResultBuilder()
.lessonCompleted(false) .assignmentCompleted(false)
.attemptWasMade() .attemptWasMade()
.feedback("assignment.not.solved") .feedback("assignment.not.solved")
.assignment(assignment); .assignment(assignment);
} }
public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) { public static AttackResultBuilder informationMessage(AssignmentEndpoint assignment) {
return new AttackResultBuilder().lessonCompleted(false).assignment(assignment); return new AttackResultBuilder().assignmentCompleted(false).assignment(assignment);
} }
} }

View File

@ -84,7 +84,7 @@ public class CourseConfiguration {
@Bean @Bean
public Course course() { public Course course() {
assignments.stream().forEach(this::attachToLesson); assignments.forEach(this::attachToLesson);
// Check if all assignments are attached to a lesson // Check if all assignments are attached to a lesson
var assignmentsAttachedToLessons = var assignmentsAttachedToLessons =
@ -99,7 +99,7 @@ public class CourseConfiguration {
private List<String> findDiff() { private List<String> findDiff() {
var matchedToLessons = 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 allAssignments = assignments.stream().map(a -> a.getClass().getSimpleName()).toList();
var diff = new ArrayList<>(allAssignments); var diff = new ArrayList<>(allAssignments);

View File

@ -5,7 +5,7 @@
package org.owasp.webgoat.lessons.sqlinjection.advanced; package org.owasp.webgoat.lessons.sqlinjection.advanced;
import static org.owasp.webgoat.container.assignments.AttackResultBuilder.failed; 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 java.sql.*;
import lombok.extern.slf4j.Slf4j; 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.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/**
* @author nbaars
* @since 4/8/17.
*/
@RestController @RestController
@AssignmentHints( @AssignmentHints(
value = {"SqlInjectionChallenge1", "SqlInjectionChallenge2", "SqlInjectionChallenge3"}) value = {
"SqlInjectionChallenge1",
"SqlInjectionChallenge2",
"SqlInjectionChallenge3",
"SqlInjectionChallenge4",
"SqlInjectionChallenge5",
"SqlInjectionChallenge6",
"SqlInjectionChallenge7"
})
@Slf4j @Slf4j
public class SqlInjectionChallenge implements AssignmentEndpoint { public class SqlInjectionChallenge implements AssignmentEndpoint {
@ -35,38 +39,34 @@ public class SqlInjectionChallenge implements AssignmentEndpoint {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@PutMapping("/SqlInjectionAdvanced/challenge") @PutMapping("/SqlInjectionAdvanced/register")
// assignment path is bounded to class so we use different http method :-) // assignment path is bounded to class so we use different http method :-)
@ResponseBody @ResponseBody
public AttackResult registerNewUser( public AttackResult registerNewUser(
@RequestParam String username_reg, @RequestParam("username_reg") String username,
@RequestParam String email_reg, @RequestParam("email_reg") String email,
@RequestParam String password_reg) @RequestParam("password_reg") String password) {
throws Exception { AttackResult attackResult = checkArguments(username, email, password);
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
if (attackResult == null) { if (attackResult == null) {
try (Connection connection = dataSource.getConnection()) { try (Connection connection = dataSource.getConnection()) {
String checkUserQuery = 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(); Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(checkUserQuery); ResultSet resultSet = statement.executeQuery(checkUserQuery);
if (resultSet.next()) { if (resultSet.next()) {
if (username_reg.contains("tom'")) { attackResult = failed(this).feedback("user.exists").feedbackArgs(username).build();
attackResult = success(this).feedback("user.exists").build();
} else {
attackResult = failed(this).feedback("user.exists").feedbackArgs(username_reg).build();
}
} else { } else {
PreparedStatement preparedStatement = PreparedStatement preparedStatement =
connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)"); connection.prepareStatement("INSERT INTO sql_challenge_users VALUES (?, ?, ?)");
preparedStatement.setString(1, username_reg); preparedStatement.setString(1, username);
preparedStatement.setString(2, email_reg); preparedStatement.setString(2, email);
preparedStatement.setString(3, password_reg); preparedStatement.setString(3, password);
preparedStatement.execute(); preparedStatement.execute();
attackResult = success(this).feedback("user.created").feedbackArgs(username_reg).build(); attackResult =
informationMessage(this).feedback("user.created").feedbackArgs(username).build();
} }
} catch (SQLException e) { } catch (SQLException e) {
attackResult = failed(this).output("Something went wrong").build(); attackResult = failed(this).output("Something went wrong").build();
@ -75,13 +75,13 @@ public class SqlInjectionChallenge implements AssignmentEndpoint {
return attackResult; return attackResult;
} }
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) { private AttackResult checkArguments(String username, String email, String password) {
if (StringUtils.isEmpty(username_reg) if (StringUtils.isEmpty(username)
|| StringUtils.isEmpty(email_reg) || StringUtils.isEmpty(email)
|| StringUtils.isEmpty(password_reg)) { || StringUtils.isEmpty(password)) {
return failed(this).feedback("input.invalid").build(); 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 failed(this).feedback("input.invalid").build();
} }
return null; return null;

View File

@ -9,7 +9,6 @@ import static org.owasp.webgoat.container.assignments.AttackResultBuilder.succes
import org.owasp.webgoat.container.LessonDataSource; import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.container.assignments.AssignmentEndpoint; import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
import org.owasp.webgoat.container.assignments.AssignmentHints;
import org.owasp.webgoat.container.assignments.AttackResult; import org.owasp.webgoat.container.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; 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; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@AssignmentHints(
value = {
"SqlInjectionChallengeHint1",
"SqlInjectionChallengeHint2",
"SqlInjectionChallengeHint3",
"SqlInjectionChallengeHint4"
})
public class SqlInjectionChallengeLogin implements AssignmentEndpoint { public class SqlInjectionChallengeLogin implements AssignmentEndpoint {
private final LessonDataSource dataSource; private final LessonDataSource dataSource;
@ -31,20 +23,22 @@ public class SqlInjectionChallengeLogin implements AssignmentEndpoint {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@PostMapping("/SqlInjectionAdvanced/challenge_Login") @PostMapping("/SqlInjectionAdvanced/login")
@ResponseBody @ResponseBody
public AttackResult login( 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()) { try (var connection = dataSource.getConnection()) {
var statement = var statement =
connection.prepareStatement( connection.prepareStatement(
"select password from sql_challenge_users where userid = ? and password = ?"); "select password from sql_challenge_users where userid = ? and password = ?");
statement.setString(1, username_login); statement.setString(1, username);
statement.setString(2, password_login); statement.setString(2, password);
var resultSet = statement.executeQuery(); var resultSet = statement.executeQuery();
if (resultSet.next()) { if (resultSet.next()) {
return ("tom".equals(username_login)) return ("tom".equals(username))
? success(this).build() ? success(this).build()
: failed(this).feedback("ResultsButNotTom").build(); : failed(this).feedback("ResultsButNotTom").build();
} else { } else {

View File

@ -1,4 +1,3 @@
lesson.completed=Congratulations. You have successfully completed this lesson.
assignment.solved=Congratulations. You have successfully completed the assignment. assignment.solved=Congratulations. You have successfully completed the assignment.
assignment.not.solved=Sorry the solution is not correct, please try again. assignment.not.solved=Sorry the solution is not correct, please try again.
RestartLesson=Restart this Lesson RestartLesson=Restart this Lesson

View File

@ -1,5 +1,4 @@
#General #General
lesson.completed=Herzlichen Gl\u00fcckwunsch! Sie haben diese Lektion erfolgreich abgeschlossen.
assignment.solved=Herzlichen Gl\u00fcckwunsch! Sie haben diesen Auftrag erfolgreich abgeschlossen. assignment.solved=Herzlichen Gl\u00fcckwunsch! Sie haben diesen Auftrag erfolgreich abgeschlossen.
assignment.not.solved=Die L\u00f6sung ist nicht korrekt, versuchen Sie es erneut. assignment.not.solved=Die L\u00f6sung ist nicht korrekt, versuchen Sie es erneut.

View File

@ -1,5 +1,4 @@
#General #General
lesson.completed=F\u00e9licitations. Vous avez termin\u00e9 cette le\u00e7on avec succ\u00e9s.
RestartLesson=Recommencer cette le\u00e7on RestartLesson=Recommencer cette le\u00e7on
SolutionVideos=Solution vid\u00e9os SolutionVideos=Solution vid\u00e9os
ErrorGenerating=Error generating ErrorGenerating=Error generating

View File

@ -1,4 +1,3 @@
lesson.completed=Gefeliciteerd, je hebt deze les succesvol afgerond.
assignment.solved=Gefeliciteerd, je hebt deze opdracht succesvol afgerond. assignment.solved=Gefeliciteerd, je hebt deze opdracht succesvol afgerond.
assignment.not.solved=Sorry de oplossing is niet correct, probeer het nog eens. assignment.not.solved=Sorry de oplossing is niet correct, probeer het nog eens.
RestartLesson=Herstart de les RestartLesson=Herstart de les

View File

@ -10,7 +10,7 @@ challenge9.title=Changing password
challenge.solved=Congratulations, you solved the challenge. Here is your flag: {0} challenge.solved=Congratulations, you solved the challenge. Here is your flag: {0}
challenge.close=This is not the correct password for Larry, please try again. challenge.close=This is not the correct password for Larry, please try again.
email.send=An e-mail has been send to {0} email.send=An e-mail has been sent to {0}
user.exists=User {0} already exists please try to register with a different username. user.exists=User {0} already exists please try to register with a different username.
user.created=User {0} created, please proceed to the login page. user.created=User {0} created, please proceed to the login page.

View File

@ -1,2 +0,0 @@
EnterYourName=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u0438\u043c\u044f
Go!=\u0412\u043f\u0435\u0440\u0451\u0434!

View File

@ -79,7 +79,7 @@
<div class="col-lg-12"> <div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN" <form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form" method="POST" name="form"
th:action="@{/SqlInjectionAdvanced/Challenge_Login}" th:action="@{/SqlInjectionAdvanced/login}"
role="form"> role="form">
<div class="form-group"> <div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1" <input type="text" name="username_login" id="username4" tabindex="1"
@ -115,7 +115,7 @@
</form> </form>
<form id="register-form" class="attack-form" accept-charset="UNKNOWN" <form id="register-form" class="attack-form" accept-charset="UNKNOWN"
method="PUT" name="form" method="PUT" name="form"
th:action="@{/SqlInjectionAdvanced/challenge}" th:action="@{/SqlInjectionAdvanced/register}"
style="display: none;" role="form"> style="display: none;" role="form">
<div class="form-group"> <div class="form-group">
<input type="text" name="username_reg" id="username" tabindex="1" <input type="text" name="username_reg" id="username" tabindex="1"

View File

@ -3,12 +3,8 @@
2.sql.advanced.title=SQL Injection (advanced) 2.sql.advanced.title=SQL Injection (advanced)
3.sql.mitigation.title=SQL Injection (mitigation) 3.sql.mitigation.title=SQL Injection (mitigation)
NoResultsMatched=Wrong username or password. Try again.
SqlInjectionChallenge1=Look at the different response you receive from the server ResultsButNotTom=Try to log in as Tom!
SqlInjectionChallenge2=The vulnerability is on the register form
SqlInjectionChallenge3=Use tooling to automate this attack
NoResultsMatched=No results matched, try again.
ResultsButNotTom=Try To login as Tom!
sql-injection.2.success=You have succeeded! sql-injection.2.success=You have succeeded!
sql-injection.2.failed=Something went wrong! You got no results, check your SQL Statement and the table above. sql-injection.2.failed=Something went wrong! You got no results, check your SQL Statement and the table above.
@ -100,10 +96,13 @@ SqlStringInjectionHint-mitigation-13-2=Intercept the request and try to specify
SqlStringInjectionHint-mitigation-13-3=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens SqlStringInjectionHint-mitigation-13-3=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens
SqlStringInjectionHint-mitigation-13-4=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens SqlStringInjectionHint-mitigation-13-4=Use for example "(case when (true) then hostname else id end)" in the order by and see what happens
SqlInjectionChallengeHint1=The table name is randomized at each start of WebGoat, try to figure out the name first. SqlInjectionChallenge1=Look at the different response you receive from the server when you try different entries
SqlInjectionChallengeHint2=Find the field which is vulnerable to SQL injection use that to change the password. SqlInjectionChallenge2=Does the register form give you any indication a user already exists?
SqlInjectionChallengeHint3=Change the password through an UPDATE Statement. SqlInjectionChallenge3=Try to guess the password of the user 'tom' one character at a time
SqlInjectionChallengeHint4=The vulnerable field is the username field of the register form. SqlInjectionChallenge4=Use substring(column, start, length) to get the password of the user 'tom' one character at a time
SqlInjectionChallenge5=Use tom' AND substring(password,1,1)='a for the guess of the first character of the password
SqlInjectionChallenge6=It is important to look at the different responses you receive from the server when you try different entries
SqlInjectionChallenge7=You can use tooling to automate this attack
SqlOnlyInputValidation-failed=Using spaces is not allowed! SqlOnlyInputValidation-failed=Using spaces is not allowed!
SqlOnlyInputValidation-1=Spaces are rejected, try to find a way around this restriction SqlOnlyInputValidation-1=Spaces are rejected, try to find a way around this restriction

View File

@ -1,7 +1,7 @@
#StringSqlInjection.java #StringSqlInjection.java
StringSqlInjectionSecondStage=Da sie nun erfolgreich eine SQL Injection durchgef\u00fchrt haben, versuchen Sie denselben Typ von Angriff auf eine parametrisierte Anfrage. Starten Sie Diese Lektion neu, wenn Sie zur verwundbaren SQL Anfrage gelangen m\u00f6chten. StringSqlInjectionSecondStage=Da sie nun erfolgreich eine SQL Injection durchgef\u00fchrt haben, versuchen Sie denselben Typ von Angriff auf eine parametrisierte Anfrage. Starten Sie Diese Lektion neu, wenn Sie zur verwundbaren SQL Anfrage gelangen m\u00f6chten.
EnterLastName=Geben Sie Ihren Nachnamen ein: EnterLastName=Geben Sie Ihren Nachnamen ein:
NoResultsMatched=Keine Resultate gefunden, versuchen Sie es erneut NoResultsMatched=Falscher Benutzername oder falsches Passwort. Versuchen Sie es erneut.
SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command. SqlStringInjectionHint1=The application is taking your input and inserting it at the end of a pre-formed SQL command.
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

View File

@ -1,7 +1,7 @@
#StringSqlInjection.java #StringSqlInjection.java
StringSqlInjectionSecondStage=Maintenant que vous avez r\u00e9alis\u00e9 une injection SQL avec succ\u00e8s, essayer le m\u00eame type d'attaque sur une requ\u00eate param\u00e9tr\u00e9e. Red\u00e9marrez la le\u00e7on si vous souhaitez revenir \u00e0 la requ\u00eate injectable. StringSqlInjectionSecondStage=Maintenant que vous avez r\u00e9alis\u00e9 une injection SQL avec succ\u00e8s, essayer le m\u00eame type d'attaque sur une requ\u00eate param\u00e9tr\u00e9e. Red\u00e9marrez la le\u00e7on si vous souhaitez revenir \u00e0 la requ\u00eate injectable.
EnterLastName=Entrez votre nom : EnterLastName=Entrez votre nom :
NoResultsMatched=Aucun r\u00e9sultat correspondant. Essayez encore. NoResultsMatched=Aucun nom d'utilisateur ou mot de passe incorrect. Essayez encore.
SqlStringInjectionHint1=L'application r\u00e9cup\u00e8re votre saisie et l'ins\u00e8re \u00e0 la fin d'une commande SQL pr\u00e9-form\u00e9e. SqlStringInjectionHint1=L'application r\u00e9cup\u00e8re votre saisie et l'ins\u00e8re \u00e0 la fin d'une commande SQL pr\u00e9-form\u00e9e.
SqlStringInjectionHint2=Voici le code de la requ\u00eate assembl\u00e9e et ex\u00e9cut\u00e9e par WebGoat :<br><br> "SELECT * FROM user_data WHERE last_name = "accountName" SqlStringInjectionHint2=Voici le code de la requ\u00eate assembl\u00e9e et ex\u00e9cut\u00e9e par WebGoat :<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
SqlStringInjectionHint3=Les commandes SQL compos\u00e9es peuvent \u00eatre assembl\u00e9es en associant de multiples conditions au moyen de mots-cl\u00e9 tels que AND et OR. Essayez d'assembler une condition qui sera toujours r\u00e9solue \u00e0 vrai. SqlStringInjectionHint3=Les commandes SQL compos\u00e9es peuvent \u00eatre assembl\u00e9es en associant de multiples conditions au moyen de mots-cl\u00e9 tels que AND et OR. Essayez d'assembler une condition qui sera toujours r\u00e9solue \u00e0 vrai.

View File

@ -1,8 +0,0 @@
#StringSqlInjection.java
StringSqlInjectionSecondStage=\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0430\u0447\u043d\u043e \u043f\u0440\u043e\u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c SQL-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u044e, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0443\u0440\u043e\u043a \u0437\u0430\u043d\u043e\u0432\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0432\u043d\u043e\u0432\u044c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0435 \u043f\u043e\u043b\u0435.
EnterLastName=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u0444\u0430\u043c\u0438\u043b\u0438\u044e:
NoResultsMatched=\u041d\u0435\u0442 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430.
SqlStringInjectionHint1=\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0435\u0440\u0451\u0442 \u0442\u043e \u0447\u0442\u043e \u0432\u044b \u0432\u0432\u043e\u0434\u0438\u0442\u0435 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u043a\u043e\u043d\u0435\u0446 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u0430.
SqlStringInjectionHint2=\u0412\u043e\u0442 \u043a\u043e\u0434 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f WebGoat`\u043e\u043c:<br><br> "SELECT * FROM user_data WHERE last_name = "accountName"
SqlStringInjectionHint3=\u0426\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0434\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0430\u043a\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432 \u043a\u0430\u043a AND \u0438 OR. \u041f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u043e\u0435 SQL-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0438\u0441\u0442\u0438\u043d\u0443.
SqlStringInjectionHint4=\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0432\u0432\u0435\u0441\u0442\u0438 [ smith' OR '1' = '1 ].