Apply formatting
This will make sure we have a consistent style across our project and the PRs are only concerned with actual changes and no longer about style.
This commit is contained in:
@@ -35,13 +35,13 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class SpoofCookie extends Lesson {
|
||||
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.A1;
|
||||
}
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.A1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "spoofcookie.title";
|
||||
}
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "spoofcookie.title";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@
|
||||
package org.owasp.webgoat.lessons.spoofcookie;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.owasp.webgoat.container.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.container.assignments.AttackResult;
|
||||
@@ -49,73 +47,79 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RestController
|
||||
public class SpoofCookieAssignment extends AssignmentEndpoint {
|
||||
|
||||
private static final String COOKIE_NAME = "spoof_auth";
|
||||
private static final String COOKIE_INFO = "Cookie details for user %s:<br />" + COOKIE_NAME + "=%s";
|
||||
private static final String ATTACK_USERNAME = "tom";
|
||||
private static final String COOKIE_NAME = "spoof_auth";
|
||||
private static final String COOKIE_INFO =
|
||||
"Cookie details for user %s:<br />" + COOKIE_NAME + "=%s";
|
||||
private static final String ATTACK_USERNAME = "tom";
|
||||
|
||||
private static final Map<String, String> users = Map.of(
|
||||
"webgoat", "webgoat",
|
||||
"admin", "admin",
|
||||
ATTACK_USERNAME, "apasswordfortom");
|
||||
private static final Map<String, String> users =
|
||||
Map.of("webgoat", "webgoat", "admin", "admin", ATTACK_USERNAME, "apasswordfortom");
|
||||
|
||||
@PostMapping(path = "/SpoofCookie/login")
|
||||
@ResponseBody
|
||||
@ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
|
||||
public AttackResult login(
|
||||
@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
@CookieValue(value = COOKIE_NAME, required = false) String cookieValue,
|
||||
HttpServletResponse response) {
|
||||
@PostMapping(path = "/SpoofCookie/login")
|
||||
@ResponseBody
|
||||
@ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
|
||||
public AttackResult login(
|
||||
@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
@CookieValue(value = COOKIE_NAME, required = false) String cookieValue,
|
||||
HttpServletResponse response) {
|
||||
|
||||
if (StringUtils.isEmpty(cookieValue)) {
|
||||
return credentialsLoginFlow(username, password, response);
|
||||
} else {
|
||||
return cookieLoginFlow(cookieValue);
|
||||
}
|
||||
if (StringUtils.isEmpty(cookieValue)) {
|
||||
return credentialsLoginFlow(username, password, response);
|
||||
} else {
|
||||
return cookieLoginFlow(cookieValue);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(path = "/SpoofCookie/cleanup")
|
||||
public void cleanup(HttpServletResponse response) {
|
||||
Cookie cookie = new Cookie(COOKIE_NAME, "");
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
private AttackResult credentialsLoginFlow(
|
||||
String username, String password, HttpServletResponse response) {
|
||||
String lowerCasedUsername = username.toLowerCase();
|
||||
if (ATTACK_USERNAME.equals(lowerCasedUsername)
|
||||
&& users.get(lowerCasedUsername).equals(password)) {
|
||||
return informationMessage(this).feedback("spoofcookie.cheating").build();
|
||||
}
|
||||
|
||||
@GetMapping(path = "/SpoofCookie/cleanup")
|
||||
public void cleanup(HttpServletResponse response) {
|
||||
Cookie cookie = new Cookie(COOKIE_NAME, "");
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
String authPassword = users.getOrDefault(lowerCasedUsername, "");
|
||||
if (!authPassword.isBlank() && authPassword.equals(password)) {
|
||||
String newCookieValue = EncDec.encode(lowerCasedUsername);
|
||||
Cookie newCookie = new Cookie(COOKIE_NAME, newCookieValue);
|
||||
newCookie.setPath("/WebGoat");
|
||||
newCookie.setSecure(true);
|
||||
response.addCookie(newCookie);
|
||||
return informationMessage(this)
|
||||
.feedback("spoofcookie.login")
|
||||
.output(String.format(COOKIE_INFO, lowerCasedUsername, newCookie.getValue()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private AttackResult credentialsLoginFlow(String username, String password, HttpServletResponse response) {
|
||||
String lowerCasedUsername = username.toLowerCase();
|
||||
if (ATTACK_USERNAME.equals(lowerCasedUsername) && users.get(lowerCasedUsername).equals(password)) {
|
||||
return informationMessage(this).feedback("spoofcookie.cheating").build();
|
||||
}
|
||||
return informationMessage(this).feedback("spoofcookie.wrong-login").build();
|
||||
}
|
||||
|
||||
String authPassword = users.getOrDefault(lowerCasedUsername, "");
|
||||
if (!authPassword.isBlank() && authPassword.equals(password)) {
|
||||
String newCookieValue = EncDec.encode(lowerCasedUsername);
|
||||
Cookie newCookie = new Cookie(COOKIE_NAME, newCookieValue);
|
||||
newCookie.setPath("/WebGoat");
|
||||
newCookie.setSecure(true);
|
||||
response.addCookie(newCookie);
|
||||
return informationMessage(this).feedback("spoofcookie.login").output(String.format(COOKIE_INFO, lowerCasedUsername, newCookie.getValue())).build();
|
||||
}
|
||||
|
||||
return informationMessage(this).feedback("spoofcookie.wrong-login").build();
|
||||
}
|
||||
|
||||
private AttackResult cookieLoginFlow(String cookieValue) {
|
||||
String cookieUsername;
|
||||
try {
|
||||
cookieUsername = EncDec.decode(cookieValue).toLowerCase();
|
||||
} catch (Exception e) {
|
||||
// for providing some instructive guidance, we won't return 4xx error here
|
||||
return failed(this).output(e.getMessage()).build();
|
||||
}
|
||||
if (users.containsKey(cookieUsername)) {
|
||||
if (cookieUsername.equals(ATTACK_USERNAME)) {
|
||||
return success(this).build();
|
||||
}
|
||||
return failed(this).feedback("spoofcookie.cookie-login").output(String.format(COOKIE_INFO, cookieUsername, cookieValue)).build();
|
||||
}
|
||||
|
||||
return failed(this).feedback("spoofcookie.wrong-cookie").build();
|
||||
private AttackResult cookieLoginFlow(String cookieValue) {
|
||||
String cookieUsername;
|
||||
try {
|
||||
cookieUsername = EncDec.decode(cookieValue).toLowerCase();
|
||||
} catch (Exception e) {
|
||||
// for providing some instructive guidance, we won't return 4xx error here
|
||||
return failed(this).output(e.getMessage()).build();
|
||||
}
|
||||
if (users.containsKey(cookieUsername)) {
|
||||
if (cookieUsername.equals(ATTACK_USERNAME)) {
|
||||
return success(this).build();
|
||||
}
|
||||
return failed(this)
|
||||
.feedback("spoofcookie.cookie-login")
|
||||
.output(String.format(COOKIE_INFO, cookieUsername, cookieValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
return failed(this).feedback("spoofcookie.wrong-cookie").build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ package org.owasp.webgoat.lessons.spoofcookie.encoders;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.security.crypto.codec.Hex;
|
||||
|
||||
@@ -36,63 +35,54 @@ import org.springframework.security.crypto.codec.Hex;
|
||||
|
||||
public class EncDec {
|
||||
|
||||
// PoC: weak encoding method
|
||||
// PoC: weak encoding method
|
||||
|
||||
private static final String SALT = RandomStringUtils.randomAlphabetic(10);
|
||||
private static final String SALT = RandomStringUtils.randomAlphabetic(10);
|
||||
|
||||
private EncDec() {
|
||||
private EncDec() {}
|
||||
|
||||
public static String encode(final String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String encode(final String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String encoded = value.toLowerCase() + SALT;
|
||||
encoded = revert(encoded);
|
||||
encoded = hexEncode(encoded);
|
||||
return base64Encode(encoded);
|
||||
}
|
||||
|
||||
String encoded = value.toLowerCase() + SALT;
|
||||
encoded = revert(encoded);
|
||||
encoded = hexEncode(encoded);
|
||||
return base64Encode(encoded);
|
||||
public static String decode(final String encodedValue) throws IllegalArgumentException {
|
||||
if (encodedValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String decode(final String encodedValue) throws IllegalArgumentException {
|
||||
if (encodedValue == null) {
|
||||
return null;
|
||||
}
|
||||
String decoded = base64Decode(encodedValue);
|
||||
decoded = hexDecode(decoded);
|
||||
decoded = revert(decoded);
|
||||
return decoded.substring(0, decoded.length() - SALT.length());
|
||||
}
|
||||
|
||||
String decoded = base64Decode(encodedValue);
|
||||
decoded = hexDecode(decoded);
|
||||
decoded = revert(decoded);
|
||||
return decoded.substring(0, decoded.length() - SALT.length());
|
||||
}
|
||||
private static String revert(final String value) {
|
||||
return new StringBuilder(value).reverse().toString();
|
||||
}
|
||||
|
||||
private static String revert(final String value) {
|
||||
return new StringBuilder(value)
|
||||
.reverse()
|
||||
.toString();
|
||||
}
|
||||
private static String hexEncode(final String value) {
|
||||
char[] encoded = Hex.encode(value.getBytes(StandardCharsets.UTF_8));
|
||||
return new String(encoded);
|
||||
}
|
||||
|
||||
private static String hexEncode(final String value) {
|
||||
char[] encoded = Hex.encode(value.getBytes(StandardCharsets.UTF_8));
|
||||
return new String(encoded);
|
||||
}
|
||||
private static String hexDecode(final String value) {
|
||||
byte[] decoded = Hex.decode(value);
|
||||
return new String(decoded);
|
||||
}
|
||||
|
||||
private static String hexDecode(final String value) {
|
||||
byte[] decoded = Hex.decode(value);
|
||||
return new String(decoded);
|
||||
}
|
||||
|
||||
private static String base64Encode(final String value) {
|
||||
return Base64
|
||||
.getEncoder()
|
||||
.encodeToString(value.getBytes());
|
||||
}
|
||||
|
||||
private static String base64Decode(final String value) {
|
||||
byte[] decoded = Base64
|
||||
.getDecoder()
|
||||
.decode(value.getBytes());
|
||||
return new String(decoded);
|
||||
}
|
||||
private static String base64Encode(final String value) {
|
||||
return Base64.getEncoder().encodeToString(value.getBytes());
|
||||
}
|
||||
|
||||
private static String base64Decode(final String value) {
|
||||
byte[] decoded = Base64.getDecoder().decode(value.getBytes());
|
||||
return new String(decoded);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user