Finalizing Security Optimizations
This commit is contained in:
parent
dc12425611
commit
897252f9cd
1 changed files with 37 additions and 2 deletions
|
|
@ -9,6 +9,8 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Custom authentication entry point that handles unauthenticated requests.
|
||||
|
|
@ -45,9 +47,42 @@ public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint
|
|||
return;
|
||||
}
|
||||
|
||||
// HTML page requests should redirect to login
|
||||
// HTML page requests should redirect to login. The redirect parameter is built
|
||||
// from the original request URI so the login page can later send the user back.
|
||||
// We must restrict it to a single internal path — anything starting with "//" or
|
||||
// "/\" could be interpreted by browsers as a protocol-relative URL pointing at
|
||||
// an external host, turning this into an open redirect.
|
||||
log.debug("HTML page request - redirecting to /login");
|
||||
String redirectUrl = "/login?redirect=" + requestUri;
|
||||
String redirectUrl;
|
||||
if (isSafeInternalPath(requestUri)) {
|
||||
redirectUrl = "/login?redirect=" + URLEncoder.encode(requestUri, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
log.warn("Refusing to propagate suspicious redirect target: {}", requestUri);
|
||||
redirectUrl = "/login";
|
||||
}
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given path is a safe single-slash internal path that can be
|
||||
* round-tripped through a {@code redirect} query parameter without enabling an open
|
||||
* redirect. Rejects null/empty, anything not starting with {@code /}, and anything
|
||||
* starting with {@code //} or {@code /\} (both of which browsers may interpret as
|
||||
* protocol-relative URLs to a different host).
|
||||
*/
|
||||
private static boolean isSafeInternalPath(String path) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (path.charAt(0) != '/') {
|
||||
return false;
|
||||
}
|
||||
if (path.length() >= 2) {
|
||||
char second = path.charAt(1);
|
||||
if (second == '/' || second == '\\') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue