diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 4cc2d4c9..ff2a7862 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -111,8 +111,11 @@ Request getRedirect(final Request request, final Response userResponse) boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); boolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); - if (!sameScheme || !sameHost) { + boolean samePort = locationUrl.port() == requestUrl.port(); + if (!sameScheme || !sameHost || !samePort) { requestBuilder.removeHeader("Authorization"); + requestBuilder.removeHeader("Cookie"); + requestBuilder.removeHeader("Proxy-Authorization"); } // Response status code 303 See Other then POST changes to GET diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index e72a3faf..e07e533e 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -1,6 +1,8 @@ package com.microsoft.kiota.http.middleware; +import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import com.microsoft.kiota.http.KiotaClientFactory; import com.microsoft.kiota.http.middleware.options.RedirectHandlerOption; @@ -8,6 +10,7 @@ import okhttp3.*; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.Test; @@ -54,4 +57,54 @@ void redirectsCanBeDisabled() throws Exception { assertEquals(301, response.code()); } + + @Test + void crossHostRedirectLeaksCookies() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic ") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://evil.attacker.com/steal") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + Request result = new RedirectHandler().getRedirect(original, redirect); + assertNotNull(result); + assertEquals("evil.attacker.com", result.url().host()); + assertNull(result.header("Authorization")); // stripped (good) + assertNull(result.header("Cookie")); // stripped (good) + assertNull(result.header("Proxy-Authorization")); // stripped (good) + } + + @Test + void endToEndProof() throws Exception { + var evil = new MockWebServer(); + evil.start(); + evil.enqueue(new MockResponse().setResponseCode(200)); + var trusted = new MockWebServer(); + trusted.start(); + trusted.enqueue( + new MockResponse().setResponseCode(302).setHeader("Location", evil.url("/steal"))); + OkHttpClient client = + KiotaClientFactory.create(new Interceptor[] {new RedirectHandler()}).build(); + client.newCall( + new Request.Builder() + .url(trusted.url("/api")) + .addHeader("Cookie", "session=SECRET") + .build()) + .execute(); + trusted.takeRequest(); + RecordedRequest captured = evil.takeRequest(); + assertNull(captured.getHeader("Cookie")); + evil.shutdown(); + trusted.shutdown(); + } }