CVE-2019-11924 (published 2019-08-20T20:15Z)

A peer could send empty handshake fragments containing only padding which would be kept in memory until a full handshake was received, resulting in memory exhaustion. This issue affects versions v2019.01.28.00 and above of fizz, until v2019.08.05.00.

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

Weakness information:
cwe_id: CWE-770
cwe_name: Allocation of Resources Without Limits or Throttling
description: The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
extended_description: Code frequently has to work with limited resources, so programmers must be careful to ensure that resources are not consumed too quickly, or too easily.  Without use of quotas, resource limits, or other protection mechanisms, it can be easy for an attacker to consume many resources by rapidly making many requests, or causing larger resources to be used than is needed. When too many resources are allocated, or if a single resource is too large, then it can prevent the code from working correctly, possibly leading to a denial of service.
         

Fix information:
repo_url: https://github.com/facebookincubator/fizz
commit_details: repo_url: https://github.com/facebookincubator/fizz
author: Subodh Iyengar
author_date: 2019-08-08 11:38:29-07:00
msg: Coalesce handshake buffers

Summary:
It is possible that a peer might send us records in a manner such
that there is a 16KB record and only 1 byte of handshake message in
each record. Since we normally just trim the IOBuf, we would end up
holding 16K of data per actual byte of data. To prevent this we allocate a contiguous
buffer to copy over these bytes for handshake messages for now.

This is a partial fix for CVE-2019-11924

Reviewed By: ngoyal

Differential Revision: D16478044

fbshipit-source-id: 464bc68eaefda065d9a327818100427377293fbd
repository: repo_url: https://github.com/facebookincubator/fizz
repo_name: facebookincubator/fizz
description: C++14 implementation of the TLS-1.3 standard
repo_language: C++
owner: facebookincubator
file_changes: filename: EncryptedRecordLayer.cpp
change_type: ModificationType.MODIFY
diff: @@ -113,7 +113,7 @@ folly::Optional<TLSMessage> EncryptedReadRecordLayer::read(
     return folly::none;
   }
 
-  TLSMessage msg;
+  TLSMessage msg{};
   // Iterate over the buffers while trying to find
   // the first non-zero octet. This is much faster than
   // first iterating and then trimming.

programming_language: C++
filename: RecordLayer.cpp
change_type: ModificationType.MODIFY
diff: @@ -49,7 +49,31 @@ folly::Optional<Param> ReadRecordLayer::readEvent(
         }
       }
       case ContentType::handshake: {
-        unparsedHandshakeData_.append(std::move(message->fragment));
+        std::unique_ptr<folly::IOBuf> handshakeMessage =
+            unparsedHandshakeData_.move();
+        // It is possible that a peer might send us records in a manner such
+        // that there is a 16KB record and only 1 byte of handshake message in
+        // each record. Since we normally just trim the IOBuf, we would end up
+        // holding 16K of data. To prevent this we allocate a contiguous
+        // buffer to copy over these bytes. We supply kExtraAlloc bytes in
+        // order to avoid needing to re-allocate a lot of times if we receive
+        // a lot of small messages. There might be more optimal reallocation
+        // policies, but this should be fine.
+        message->fragment->coalesce();
+        constexpr size_t kExtraAlloc = 1024;
+        if (!handshakeMessage) {
+          handshakeMessage =
+              folly::IOBuf::create(message->fragment->length() + kExtraAlloc);
+        } else if (handshakeMessage->tailroom() < message->fragment->length()) {
+          handshakeMessage->reserve(
+              0, message->fragment->length() + kExtraAlloc);
+        }
+        memcpy(
+            handshakeMessage->writableTail(),
+            message->fragment->data(),
+            message->fragment->length());
+        handshakeMessage->append(message->fragment->length());
+        unparsedHandshakeData_.append(std::move(handshakeMessage));
         auto param = decodeHandshakeMessage(unparsedHandshakeData_);
         if (param) {
           VLOG(8) << "Received handshake message "

programming_language: C++
repo_url: https://github.com/facebookincubator/fizz
commit_details: repo_url: https://github.com/facebookincubator/fizz
author: Subodh Iyengar
author_date: 2019-08-08 11:38:29-07:00
msg: Reject zero length handshake records.

Summary:
Zero length (all padding) handshake are forbidden by RFC. Allowing
these was a regression in D13754697 (2c6f78a).

This is a partial fix for CVE-2019-11924

Reviewed By: xybu

Differential Revision: D16285100

fbshipit-source-id: 05a19d31ad74601ce89156a0e59517aaad8dd928
repository: repo_url: https://github.com/facebookincubator/fizz
repo_name: facebookincubator/fizz
description: C++14 implementation of the TLS-1.3 standard
repo_language: C++
owner: facebookincubator
file_changes: filename: EncryptedRecordLayer.cpp
change_type: ModificationType.MODIFY
diff: @@ -147,7 +147,7 @@ folly::Optional<TLSMessage> EncryptedReadRecordLayer::read(
           static_cast<ContentTypeType>(msg.type)));
   }
 
-  if (!msg.fragment) {
+  if (!msg.fragment || msg.fragment->empty()) {
     if (msg.type == ContentType::application_data) {
       msg.fragment = folly::IOBuf::create(0);
     } else {

programming_language: C++
filename: EncryptedRecordTest.cpp
change_type: ModificationType.MODIFY
diff: @@ -180,7 +180,7 @@ TEST_F(EncryptedRecordTest, TestAllPaddingHandshake) {
         expectSame(buf, "0123456789");
         return getBuf("16000000");
       }));
-  EXPECT_NO_THROW(read_.read(queue_));
+  EXPECT_ANY_THROW(read_.read(queue_));
 }
 
 TEST_F(EncryptedRecordTest, TestNoContentType) {

programming_language: C++