Prevents padding headers from being indexed

This commit is contained in:
klzgrad 2020-05-23 22:22:33 +08:00
parent 9313cff51d
commit 9ca803e3bb
2 changed files with 51 additions and 5 deletions

View File

@ -16,6 +16,7 @@
#include "net/base/ip_address.h" #include "net/base/ip_address.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/log/net_log.h" #include "net/log/net_log.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
namespace net { 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. // A plain 200 is 10 bytes. Expected 48 bytes. "Padding" uses up 7 bytes.
constexpr int kMinPaddingSize = 30; constexpr int kMinPaddingSize = 30;
constexpr int kMaxPaddingSize = kMinPaddingSize + 32; 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 } // namespace
HttpProxySocket::HttpProxySocket( HttpProxySocket::HttpProxySocket(
@ -40,7 +59,9 @@ HttpProxySocket::HttpProxySocket(
was_ever_used_(false), was_ever_used_(false),
header_write_size_(-1), header_write_size_(-1),
net_log_(transport_->NetLog()), net_log_(transport_->NetLog()),
traffic_annotation_(traffic_annotation) {} traffic_annotation_(traffic_annotation) {
InitializeNonindexCodes();
}
HttpProxySocket::~HttpProxySocket() { HttpProxySocket::~HttpProxySocket() {
Disconnect(); Disconnect();
@ -308,7 +329,13 @@ int HttpProxySocket::DoHeaderWrite() {
handshake_buf_ = base::MakeRefCounted<IOBuffer>(header_write_size_); handshake_buf_ = base::MakeRefCounted<IOBuffer>(header_write_size_);
char* p = handshake_buf_->data(); char* p = handshake_buf_->data();
std::memcpy(p, kResponseHeader, kResponseHeaderSize); 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); std::memcpy(p + kResponseHeaderSize + padding_size, "\r\n\r\n", 4);
return transport_->Write(handshake_buf_.get(), header_write_size_, return transport_->Write(handshake_buf_.get(), header_write_size_,

View File

@ -58,6 +58,7 @@
#include "net/socket/udp_server_socket.h" #include "net/socket/udp_server_socket.h"
#include "net/ssl/ssl_key_logger_impl.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/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/naive_proxy.h"
#include "net/tools/naive/redirect_resolver.h" #include "net/tools/naive/redirect_resolver.h"
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
@ -392,7 +393,18 @@ class ProxyServer;
namespace { namespace {
class NaiveProxyDelegate : public ProxyDelegate { class NaiveProxyDelegate : public ProxyDelegate {
public: 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, void OnResolveProxy(const GURL& url,
const std::string& method, const std::string& method,
const ProxyRetryInfoMap& proxy_retry_info, const ProxyRetryInfoMap& proxy_retry_info,
@ -401,8 +413,14 @@ class NaiveProxyDelegate : public ProxyDelegate {
void OnBeforeTunnelRequest(const ProxyServer& proxy_server, void OnBeforeTunnelRequest(const ProxyServer& proxy_server,
HttpRequestHeaders* extra_headers) override { HttpRequestHeaders* extra_headers) override {
extra_headers->SetHeader("Padding", std::string padding(base::RandInt(16, 32), nonindex_codes_[16]);
std::string(base::RandInt(16, 32), '.')); // 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); extra_headers->MergeFrom(params_.extra_headers);
} }
@ -414,6 +432,7 @@ class NaiveProxyDelegate : public ProxyDelegate {
private: private:
const Params& params_; const Params& params_;
uint8_t nonindex_codes_[17];
}; };
std::unique_ptr<URLRequestContext> BuildCertURLRequestContext(NetLog* net_log) { std::unique_ptr<URLRequestContext> BuildCertURLRequestContext(NetLog* net_log) {