From 2d3c331f93dcb62689e0b02431414eb5d8f53989 Mon Sep 17 00:00:00 2001 From: klzgrad Date: Sat, 23 May 2020 22:22:33 +0800 Subject: [PATCH] Prevents padding headers from being indexed --- src/net/tools/naive/http_proxy_socket.cc | 31 ++++++++++++++++++++++-- src/net/tools/naive/naive_proxy_bin.cc | 25 ++++++++++++++++--- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/net/tools/naive/http_proxy_socket.cc b/src/net/tools/naive/http_proxy_socket.cc index 3fc4377276..50405c5fc4 100644 --- a/src/net/tools/naive/http_proxy_socket.cc +++ b/src/net/tools/naive/http_proxy_socket.cc @@ -16,6 +16,7 @@ #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/log/net_log.h" +#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" namespace net { @@ -27,6 +28,24 @@ constexpr int kResponseHeaderSize = sizeof(kResponseHeader) - 1; // A plain 200 is 10 bytes. Expected 48 bytes. "Padding" uses up 7 bytes. constexpr int kMinPaddingSize = 30; constexpr int kMaxPaddingSize = kMinPaddingSize + 32; + +bool g_nonindex_codes_initialized; +uint8_t g_nonindex_codes[17]; + +void InitializeNonindexCodes() { + if (g_nonindex_codes_initialized) + return; + g_nonindex_codes_initialized = true; + unsigned i = 0; + for (const auto& symbol : spdy::HpackHuffmanCodeVector()) { + if (symbol.id >= 0x20 && symbol.id <= 0x7f && symbol.length >= 8) { + g_nonindex_codes[i++] = symbol.id; + if (i >= sizeof(g_nonindex_codes)) + break; + } + } + CHECK(i == sizeof(g_nonindex_codes)); +} } // namespace HttpProxySocket::HttpProxySocket( @@ -40,7 +59,9 @@ HttpProxySocket::HttpProxySocket( was_ever_used_(false), header_write_size_(-1), net_log_(transport_->NetLog()), - traffic_annotation_(traffic_annotation) {} + traffic_annotation_(traffic_annotation) { + InitializeNonindexCodes(); +} HttpProxySocket::~HttpProxySocket() { Disconnect(); @@ -308,7 +329,13 @@ int HttpProxySocket::DoHeaderWrite() { handshake_buf_ = base::MakeRefCounted(header_write_size_); char* p = handshake_buf_->data(); std::memcpy(p, kResponseHeader, kResponseHeaderSize); - std::memset(p + kResponseHeaderSize, '.', padding_size); + std::memset(p + kResponseHeaderSize, g_nonindex_codes[16], padding_size); + // Prevents index reuse + uint64_t bits = base::RandUint64(); + for (int i = 0; i < 16; i++) { + p[kResponseHeaderSize + i] = g_nonindex_codes[bits & 0b1111]; + bits >>= 4; + } std::memcpy(p + kResponseHeaderSize + padding_size, "\r\n\r\n", 4); return transport_->Write(handshake_buf_.get(), header_write_size_, diff --git a/src/net/tools/naive/naive_proxy_bin.cc b/src/net/tools/naive/naive_proxy_bin.cc index ed1424bb76..159a1d3033 100644 --- a/src/net/tools/naive/naive_proxy_bin.cc +++ b/src/net/tools/naive/naive_proxy_bin.cc @@ -57,6 +57,7 @@ #include "net/socket/udp_server_socket.h" #include "net/ssl/ssl_key_logger_impl.h" #include "net/third_party/quiche/src/quic/core/quic_versions.h" +#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/tools/naive/naive_proxy.h" #include "net/tools/naive/redirect_resolver.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -389,7 +390,18 @@ class ProxyServer; namespace { class NaiveProxyDelegate : public ProxyDelegate { public: - NaiveProxyDelegate(const Params& params) : params_(params) {} + NaiveProxyDelegate(const Params& params) : params_(params) { + unsigned i = 0; + for (const auto& symbol : spdy::HpackHuffmanCodeVector()) { + if (symbol.id >= 0x20 && symbol.id <= 0x7f && symbol.length >= 8) { + nonindex_codes_[i++] = symbol.id; + if (i >= sizeof(nonindex_codes_)) + break; + } + } + CHECK(i == sizeof(nonindex_codes_)); + } + void OnResolveProxy(const GURL& url, const std::string& method, const ProxyRetryInfoMap& proxy_retry_info, @@ -398,8 +410,14 @@ class NaiveProxyDelegate : public ProxyDelegate { void OnBeforeTunnelRequest(const ProxyServer& proxy_server, HttpRequestHeaders* extra_headers) override { - extra_headers->SetHeader("Padding", - std::string(base::RandInt(16, 32), '.')); + std::string padding(base::RandInt(16, 32), nonindex_codes_[16]); + // Prevents index reuse + uint64_t bits = base::RandUint64(); + for (int i = 0; i < 16; i++) { + padding[i] = nonindex_codes_[bits & 0b1111]; + bits >>= 4; + } + extra_headers->SetHeader("Padding", padding); extra_headers->MergeFrom(params_.extra_headers); } @@ -411,6 +429,7 @@ class NaiveProxyDelegate : public ProxyDelegate { private: const Params& params_; + uint8_t nonindex_codes_[17]; }; std::unique_ptr BuildCertURLRequestContext(NetLog* net_log) {