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

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* 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;
@ -15,8 +15,9 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
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.HttpBasicsLessonPage;
import org.owasp.webgoat.playwright.webgoat.pages.lessons.HttpBasicsLessonPage;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
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-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.Page;

View File

@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: Copyright © 2025 WebGoat authors
* 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;
@ -14,7 +14,7 @@ import org.assertj.core.api.Assertions;
import org.owasp.webgoat.container.lessons.LessonName;
@Getter
class LessonPage {
public class LessonPage {
private final Page page;
@ -65,4 +65,8 @@ class LessonPage {
public Locator getAssignmentOutput() {
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;
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);
}
}

View File

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

View File

@ -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;

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.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 {

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.not.solved=Sorry the solution is not correct, please try again.
RestartLesson=Restart this Lesson

View File

@ -1,5 +1,4 @@
#General
lesson.completed=Herzlichen Gl\u00fcckwunsch! Sie haben diese Lektion 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.

View File

@ -1,5 +1,4 @@
#General
lesson.completed=F\u00e9licitations. Vous avez termin\u00e9 cette le\u00e7on avec succ\u00e9s.
RestartLesson=Recommencer cette le\u00e7on
SolutionVideos=Solution vid\u00e9os
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.not.solved=Sorry de oplossing is niet correct, probeer het nog eens.
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.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.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">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
th:action="@{/SqlInjectionAdvanced/Challenge_Login}"
th:action="@{/SqlInjectionAdvanced/login}"
role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
@ -115,7 +115,7 @@
</form>
<form id="register-form" class="attack-form" accept-charset="UNKNOWN"
method="PUT" name="form"
th:action="@{/SqlInjectionAdvanced/challenge}"
th:action="@{/SqlInjectionAdvanced/register}"
style="display: none;" role="form">
<div class="form-group">
<input type="text" name="username_reg" id="username" tabindex="1"

View File

@ -3,12 +3,8 @@
2.sql.advanced.title=SQL Injection (advanced)
3.sql.mitigation.title=SQL Injection (mitigation)
SqlInjectionChallenge1=Look at the different response you receive from the server
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!
NoResultsMatched=Wrong username or password. Try again.
ResultsButNotTom=Try to log in as Tom!
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.
@ -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-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.
SqlInjectionChallengeHint2=Find the field which is vulnerable to SQL injection use that to change the password.
SqlInjectionChallengeHint3=Change the password through an UPDATE Statement.
SqlInjectionChallengeHint4=The vulnerable field is the username field of the register form.
SqlInjectionChallenge1=Look at the different response you receive from the server when you try different entries
SqlInjectionChallenge2=Does the register form give you any indication a user already exists?
SqlInjectionChallenge3=Try to guess the password of the user 'tom' one character at a time
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-1=Spaces are rejected, try to find a way around this restriction

View File

@ -1,7 +1,7 @@
#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.
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.
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

View File

@ -1,7 +1,7 @@
#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.
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.
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.

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 ].