Resiliency Test - HTTP/HTTPS Hijack
Recently researching an internal tool to support resiliency testing, e.g. performing network delay on dependent redis/db/.., helps validate the service’s ability to handle and recover from unexpected network disruptions or delays in accessing external dependencies.
TCP layer network traffic can easily be classified and shaped using a Linux built-in tool called TC (traffic control).
But how can we hijack and manipulate encrypted outbound HTTPS traffic?
1. Traffic Takeover
Enable traffic through a proxy server via HTTP(S)_PROXY environment variable, and most standard libraries follow this convention.
export https_proxy=http://127.0.0.1:<port>;export http_proxy=http://127.0.0.1:<port>
After sending the CONNECT method request, the https_proxy
can proxy the TCP stream to and from the client by establishing a HTTP tunnel to the destination origin server.
2. Traffic Processing
Implement a lightweight HTTP proxy by native http.server module in Python.
HTTP (Transparent Proxy)
According to rfc7231. As long as the CONNECT
method request is handled, the proxy can forward the TCP stream to and from the client by establishing a HTTP tunnel.
HTTPS (Hijack)
As we know, the TLS encryption prevents us from inspecting the specific endpoints and headers within the encrypted traffic.
We must hijack HTTPS requests to determine the type of dependency service (such as ACM, OSS, etc.):
- Identity:
- client → server: ask for appropriate certificate
- server → client: provide server certificate (and intermediate)
- client: receive certificate and ensure Common Name(domain name) of request matching
- client: Confirm that the root certificate (valid Certificate Chain)
- Encryption:
- TLS handshake: asymmetric Encryption → generates a symmetric encryption key (the session key)
- Data transmission: session key → data encryption
Appropriate workflow (i.e. MITM attack):