CVE-2019-11921 (published 2019-07-25T21:15Z)

An out of bounds write is possible via a specially crafted packet in certain configurations of Proxygen due to improper handling of Base64 when parsing malformed binary content in Structured HTTP Headers. This issue affects versions of proxygen prior to v2019.07.22.00.

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

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/facebook/proxygen
commit_details: repo_url: https://github.com/facebook/proxygen
author: Aman Sharma
author_date: 2019-07-19 16:38:48-07:00
msg: Fix SEGV in StructuredHeaders::decodeBase64

Summary:
The existing code can potentially cause a SEGV due to an out of bounds write.

This fixes CVE-2019-11921.

Reviewed By: knekritz

Differential Revision: D12983120

fbshipit-source-id: 1d48063595c8d518fd8afcbc941de260af7e37fd
repository: repo_url: https://github.com/facebook/proxygen
repo_name: facebook/proxygen
description: A collection of C++ HTTP libraries including an easy to use HTTP server.
repo_language: C++
owner: facebook
file_changes: filename: StructuredHeadersUtilities.cpp
change_type: ModificationType.MODIFY
diff: @@ -9,11 +9,10 @@
  */
 
 #include "StructuredHeadersUtilities.h"
-#include <boost/archive/iterators/binary_from_base64.hpp>
-#include <boost/archive/iterators/base64_from_binary.hpp>
-#include <boost/archive/iterators/transform_width.hpp>
 #include "StructuredHeadersConstants.h"
 
+#include "proxygen/lib/utils/Base64.h"
+
 namespace proxygen {
 namespace StructuredHeaders {
 
@@ -107,31 +106,23 @@ std::string decodeBase64(
 
   if (encoded.size() == 0) {
     // special case, to prevent an integer overflow down below.
-    return "";
+    return std::string();
   }
 
-  using namespace boost::archive::iterators;
-  using b64it =
-    transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
-
-  std::string decoded = std::string(b64it(std::begin(encoded)),
-                                    b64it(std::end(encoded)));
-
-  uint32_t numPadding = std::count(encoded.begin(), encoded.end(), '=');
-  decoded.erase(decoded.end() - numPadding, decoded.end());
+  int padding = 0;
+  for (auto it = encoded.rbegin();
+       padding < 2 && it != encoded.rend() && *it == '=';
+       ++it) {
+    ++padding;
+  }
 
-  return decoded;
+  return Base64::decode(encoded, padding);
 }
 
 std::string encodeBase64(const std::string& input) {
-  using namespace boost::archive::iterators;
-  using b64it = base64_from_binary<transform_width<const char*, 6, 8>>;
-
-  auto data = input.data();
-  std::string encoded(b64it(data), b64it(data + (input.length())));
-  encoded.append((3 - (input.length() % 3)) % 3, '=');
-
-  return encoded;
+  return Base64::encode(folly::ByteRange(
+                            reinterpret_cast<const uint8_t*>(input.c_str()),
+                            input.length()));
 }
 
 }

programming_language: C++