CVE-2021-24029 (published 2021-03-15T22:15Z)

A packet of death scenario is possible in mvfst via a specially crafted message during a QUIC session, which causes a crash via a failed assertion. Per QUIC specification, this particular message should be treated as a connection error. This issue affects mvfst versions prior to commit a67083ff4b8dcbb7ee2839da6338032030d712b0 and proxygen versions prior to v2021.03.15.00.

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

Weakness information:
cwe_id: CWE-617
cwe_name: Reachable Assertion
description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
extended_description: 
            While assertion is good for catching logic errors and reducing the chances of reaching more serious vulnerability conditions, it can still lead to a denial of service.
            For example, if a server handles multiple simultaneous connections, and an assert() occurs in one single connection that causes all other connections to be dropped, this is a reachable assertion that leads to a denial of service.
         
         

Fix information:
repo_url: https://github.com/facebookincubator/mvfst
commit_details: repo_url: https://github.com/facebookincubator/mvfst
author: Yang Chi
author_date: 2021-02-23 16:40:17-08:00
msg: Close connection if we derive an extra 1-rtt write cipher

Summary: Fixes CVE-2021-24029

Reviewed By: mjoras, lnicco

Differential Revision: D26613890

fbshipit-source-id: 19bb2be2c731808144e1a074ece313fba11f1945
repository: repo_url: https://github.com/facebookincubator/mvfst
repo_name: facebook/mvfst
description: An implementation of the QUIC transport protocol.
repo_language: C++
owner: facebookincubator
file_changes: filename: ServerStateMachine.cpp
change_type: ModificationType.MODIFY
diff: @@ -311,7 +311,10 @@ void updateHandshakeState(QuicServerConnectionState& conn) {
       conn.qLogger->addTransportStateUpdate(kDerivedOneRttWriteCipher);
     }
     QUIC_TRACE(fst_trace, conn, "derived 1-rtt write cipher");
-    CHECK(!conn.oneRttWriteCipher.get());
+    if (conn.oneRttWriteCipher) {
+      throw QuicTransportException(
+          "Duplicate 1-rtt write cipher", TransportErrorCode::CRYPTO_ERROR);
+    }
     conn.oneRttWriteCipher = std::move(oneRttWriteCipher);
 
     updatePacingOnKeyEstablished(conn);

programming_language: C++
filename: QuicServerTransportTest.cpp
change_type: ModificationType.MODIFY
diff: @@ -4265,6 +4265,21 @@ TEST_P(QuicServerTransportHandshakeTest, TestD6DStartCallback) {
   server->removeObserver(mockObserver.get());
 }
 
+TEST_F(QuicUnencryptedServerTransportTest, DuplicateOneRttWriteCipher) {
+  setupClientReadCodec();
+  recvClientHello();
+  recvClientFinished();
+  loopForWrites();
+  try {
+    recvClientHello();
+    recvClientFinished();
+    FAIL();
+  } catch (const std::runtime_error& ex) {
+    EXPECT_THAT(ex.what(), HasSubstr("Crypto error"));
+  }
+  EXPECT_TRUE(server->isClosed());
+}
+
 TEST_F(QuicServerTransportTest, TestRegisterAndHandleTransportKnobParams) {
   int flag = 0;
   server->registerKnobParamHandler(

programming_language: C++