CVE-2020-7780 (published 2020-11-27T17:15Z)

This affects the package com.softwaremill.akka-http-session:core_2.13 before 0.5.11; the package com.softwaremill.akka-http-session:core_2.12 before 0.5.11; the package com.softwaremill.akka-http-session:core_2.11 before 0.5.11. For older versions, endpoints protected by randomTokenCsrfProtection could be bypassed with an empty X-XSRF-TOKEN header and an empty XSRF-TOKEN cookie.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/softwaremill/akka-http-session
commit_details: repo_url: https://github.com/softwaremill/akka-http-session
author: Jaroslaw Kijanowski
author_date: 2020-03-11 18:09:06+01:00
msg: Fix CSRF protection bypass #74
repository: repo_url: https://github.com/softwaremill/akka-http-session
repo_name: softwaremill/akka-http-session
description: Web & mobile client-side akka-http sessions, with optional JWT support
repo_language: Scala
owner: softwaremill
file_changes: filename: CsrfDirectives.scala
change_type: ModificationType.MODIFY
diff: @@ -23,7 +23,7 @@ trait CsrfDirectives {
         // that the token matches.
         get.recover { _ =>
           submittedCsrfToken(checkMode).flatMap { submitted =>
-            if (submitted == cookie) {
+            if (submitted == cookie && !cookie.isEmpty) {
               pass
             } else {
               reject(checkMode.csrfManager.tokenInvalidRejection).toDirective[Unit]

programming_language: Scala
filename: CsrfDirectivesTest.scala
change_type: ModificationType.MODIFY
diff: @@ -81,6 +81,20 @@ class CsrfDirectivesTest extends FlatSpec with ScalatestRouteTest with Matchers
     }
   }
 
+  it should "reject requests if the csrf cookie and the header are empty" in {
+    Get("/site") ~> routes ~> check {
+      responseAs[String] should be("ok")
+
+      Post("/transfer_money") ~>
+        addHeader(Cookie(cookieName, "")) ~>
+        addHeader(sessionConfig.csrfSubmittedName, "") ~>
+        routes ~>
+        check {
+          rejections should be(List(AuthorizationFailedRejection))
+        }
+    }
+  }
+
   it should "accept requests if the csrf cookie matches the header value" in {
     Get("/site") ~> routes ~> check {
       responseAs[String] should be("ok")

programming_language: Scala
filename: CsrfDirectivesTest.java
change_type: ModificationType.MODIFY
diff: @@ -135,6 +135,33 @@ public class CsrfDirectivesTest extends HttpSessionAwareDirectivesTest {
 
     }
 
+    @Test
+    public void shouldRejectRequestsIfTheCsrfCookieAndTheHeaderAreEmpty() {
+        // given
+        final Route route = createCsrfRouteWithCheckHeaderMode();
+
+        // when
+        TestRouteResult testRouteResult = testRoute(route)
+          .run(HttpRequest.GET("/site"));
+
+        // then
+        testRouteResult
+          .assertStatusCode(StatusCodes.OK);
+
+        /* second request */
+        // when
+        TestRouteResult testRouteResult2 = testRoute(route)
+          .run(HttpRequest.POST("/transfer_money")
+            .addHeader(Cookie.create(csrfCookieName, ""))
+            .addHeader(RawHeader.create(csrfSubmittedName, ""))
+          );
+
+        // then
+        testRouteResult2
+          .assertStatusCode(StatusCodes.FORBIDDEN);
+
+    }
+
     @Test
     public void shouldAcceptRequestsIfTheCsrfCookieMatchesTheHeaderValue() {
         // given

programming_language: Java