JavaScript library downloaded 3m times a week exposes apps to hijacking via evil proxy configs

PAC mania


A popular NPM code library called Pac-Resolver has been updated to eliminate a severe remote-code execution vulnerability. Developers who have incorporated the package into their applications should make sure to update their dependencies to be rid of the bug, and provide necessary updates to users to secure them.

Essentially, any app using the vulnerable code to handle internet proxies potentially can end up executing malicious code if it is given booby-trapped proxy configuration information, which can come from multiple sources.

On Tuesday, Tim Perry, who makes a developer tool called HTTP Toolkit, explained how he found the flaw, disclosed about a week ago as CVE-2021-23406, when adding proxy support to his software.

Pac-Resolver, downloaded more than three million times per week, provides support for "Proxy Auto-Config" (PAC) files, which tell HTTP clients which proxy to use for a given hostname.

"PAC files provide a way to distribute complex proxy rules, as a single file that maps a variety of URLs to different proxies," Perry explains in an advisory. "They're widely used in enterprise environments, and so often need to be supported in any software that might run in an enterprise environment."

These files may be distributed from a local network server, over HTTP, or from a remote server, a method common enough that there's a standard called WPAD (Web Proxy Auto-Discovery Protocol) to automate PAC file discovery.

Observing that PAC files date back to Netscape Navigator 2.0 in 1996, Perry explains, "It's a JavaScript file you have to execute to connect to the internet, which is loaded remotely, often insecurely and/or from a location that can be silently decided by your local network. 1996 was truly a simpler time. What could go wrong?"

Well, one thing would be to create a sandboxed function using Node.js's vm module, which includes the following warning in its documentation: "The vm module is not a security mechanism. Do not use it to run untrusted code."

The vm module's problem, as Perry explains, is that if you include a function like this in the PAC file JavaScript code...

// Here's the real PAC function:
function FindProxyForURL(url, host) {
    return "DIRECT";
}

// And here's some bonus arbitrary code:
const f = this.constructor.constructor(`
    // Here, we're running outside the sandbox!
    console.log('Read system env vars:', process.env);
    console.log('!!! PAC file is running arbitrary code !!!');
    process.exit(1); // Kill the HTTP client process remotely
    // ...steal data, break things, etc etc etc
`);
f();

...this points to vm.runInContext, which creates a sandbox built from an object parameter in the external Node.js environment. That provides a way to run code outside of the sandbox.

But say you were to miss that module warning. Then, like the creator of Pac-Resolver, which is used in Pac-Proxy-Agent, which in turn is used in Proxy-Agent, you'd be revising your code and issuing a fix.

"Unfortunately however, Pac-Proxy-Agent doesn't sandbox PAC scripts correctly," says Perry, adding that the library relies on modules Pac-Resolver and Degenerator to create the PAC function. "Every time you make a request using the PAC file, it can run arbitrary code and do anything on your system. If it's malicious, you're in big trouble."

Anyone using a version of Pac-Resolver, Pac-Proxy-Agent, or Proxy-Agent before version 5.0 is potentially vulnerable to loading a malicious PAC file.

How can it be exploited? A booby-trapped config file could be served by a rogue network administrator to compromise the device, or someone could intercept an insecure fetch of the file and rewrite it to achieve remote code execution. In fact, Perry listed a number of routes in his write-up:

* You read your proxy configuration from a config file, API endpoint, command line argument or environment variable and somebody manages to add their malicious PAC file's URL there.

* You load a trusted PAC URL insecurely, and somebody else on your network changes its contents in transit.

* You securely use a trusted PAC URL, but somebody successfully attacks the PAC file host and changes the file.

* WPAD is enabled on your system (as it is by default on Windows), somebody on your local network abuses it to configure your system with their PAC file URL, and you use that system configuration (Node doesn't use system proxy config by default, but many implementations will do so explicitly).

* You take proxy configuration in any other happy-go-lucky way, under the reasonable misapprehension that doing so can only risk exposing insecure traffic that you explicitly send via the proxy, and that that's acceptable for your case.

The fix, available in v5+ of any of these packages, was made further down the dependency tree in Pac-Resolver's Degenerator package.

Perry sees this incident as a testament to the value of reviewing your code dependencies.

"In many cases, especially for large applications with complex dependencies, that's not possible for all dependencies, but at least reviewing your most sensitive dependencies (like automatic proxy configuration) will help you catch these unintentional bugs and help get them fixed for everybody," he said. ®

Similar topics


Other stories you might like

Biting the hand that feeds IT © 1998–2021