From c7335fa242566cca13b96967c835ce0b00bbef0f Mon Sep 17 00:00:00 2001 From: mposolda Date: Tue, 26 Apr 2016 10:33:33 +0200 Subject: [PATCH] KEYCLOAK-2903 Fix WelcomeResource to not allow requests forwarded from proxy/loadbalancer --- .../org/keycloak/common/ClientConnection.java | 6 +++++- .../filters/KeycloakSessionServletFilter.java | 12 +++++++++++- .../services/resources/WelcomeResource.java | 18 +++++++++++++----- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/org/keycloak/common/ClientConnection.java b/common/src/main/java/org/keycloak/common/ClientConnection.java index 3c4b4498389..5afbed6741d 100755 --- a/common/src/main/java/org/keycloak/common/ClientConnection.java +++ b/common/src/main/java/org/keycloak/common/ClientConnection.java @@ -24,7 +24,11 @@ package org.keycloak.common; * @version $Revision: 1 $ */ public interface ClientConnection { + String getRemoteAddr(); String getRemoteHost(); - int getReportPort(); + int getRemotePort(); + + String getLocalAddr(); + int getLocalPort(); } diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java index d6a3f13dc94..282fd3186ab 100755 --- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java +++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java @@ -63,9 +63,19 @@ public class KeycloakSessionServletFilter implements Filter { } @Override - public int getReportPort() { + public int getRemotePort() { return request.getRemotePort(); } + + @Override + public String getLocalAddr() { + return request.getLocalAddr(); + } + + @Override + public int getLocalPort() { + return request.getLocalPort(); + } }; session.getContext().setConnection(connection); ResteasyProviderFactory.pushContext(ClientConnection.class, connection); diff --git a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java index 54becb930aa..d57f0fe2245 100755 --- a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java +++ b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java @@ -20,14 +20,11 @@ import org.keycloak.Config; import org.keycloak.common.ClientConnection; import org.keycloak.common.util.MimeTypeUtil; import org.keycloak.models.BrowserSecurityHeaders; -import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.services.ForbiddenException; import org.keycloak.services.ServicesLogger; import org.keycloak.services.managers.ApplianceBootstrap; -import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.util.CacheControlUtil; import org.keycloak.services.util.CookieHelper; import org.keycloak.theme.BrowserSecurityHeaderSetup; @@ -225,13 +222,24 @@ public class WelcomeResource { private boolean isLocal() { try { - InetAddress inetAddress = InetAddress.getByName(session.getContext().getConnection().getRemoteAddr()); - return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress(); + ClientConnection clientConnection = session.getContext().getConnection(); + InetAddress remoteInetAddress = InetAddress.getByName(clientConnection.getRemoteAddr()); + InetAddress localInetAddress = InetAddress.getByName(clientConnection.getLocalAddr()); + String xForwardedFor = headers.getHeaderString("X-Forwarded-For"); + logger.debugf("Checking WelcomePage. Remote address: %s, Local address: %s, X-Forwarded-For header: %s", remoteInetAddress.toString(), localInetAddress.toString(), xForwardedFor); + + // Access through AJP protocol (loadbalancer) may cause that remoteAddress is "127.0.0.1". + // So consider that welcome page accessed locally just if it was accessed really through "localhost" URL and without loadbalancer (x-forwarded-for header is empty). + return isLocalAddress(remoteInetAddress) && isLocalAddress(localInetAddress) && xForwardedFor == null; } catch (UnknownHostException e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } + private boolean isLocalAddress(InetAddress inetAddress) { + return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress(); + } + private String updateCsrfChecks() { String stateChecker = getCsrfCookie(); if (stateChecker != null) {