Not long ago, freelance software developer Tim Perry, creator of the HTTP toolkit for intercepting and debugging web traffic …
… decided to add proxy support to your product, which, like many current programs, is written using Node.js
.
ICYMI, Node.js
is the project that removed the JavaScript language from your browser and turned it into a complete application development system, in its own way, similar to Java (which, by the way, has nothing to do with JavaScript, because everything that names sound).
In addition to the JavaScript core, which uses the JavaScript V8 engine of the Google Chromium project, Node.js
the software is usually also based on NPM, el Node package manager, and the NPM register, a huge repository of open source tools and programming libraries.
The NPM register covers from basic text format to full facial recognition and just about anything in between.
Instead of writing all, or even most, of your project code, simply reference the add-on packages you want to use and NPM will get them, along with the additional packages the chosen package needs. …
… and all packages that need these packages, following the file turtles packages until all the add-on codes needed to complete the puzzle are automatically located and installed.
Alphabet soup
As you can imagine, this is a potential nightmare.
Adding a package to your own project may require a lot of additional packages, each of which may have been written by a different person you don’t know, who has never known, and who probably never will.
This alphabet soup is known as software dependency tree, and we have already written about the risky side effects of this approach to software building, noting that:
You may be able to write a five-line JavaScript program that is elegantly simple, but only if the Node package manager drags tens or even hundreds of thousands of lines of third-party software. Automatically. From all over the Internet. And it keeps it up to date. Automatically, from all over the Internet.
Proxy support is a problem
Perry rediscovered this risk recently, when he decided to use a popular NPM package called Proxy-Agent
to provide the proxy support you wanted to your HTTP Toolkit product.
Fortunately, Perry didn’t just search, install, and start going blind Proxy-Agent
and the entire dependency tree without reviewing the newly acquired components in your project.
Thus, a security flaw, now called CVE-2021-23406, was encountered in one Proxy-Agent
called dependency Pac-Resolver
, which is a subcomponent that helps your code cope with the PAC process, or proxy autoconfiguration (see sidebar below).
A proxy server is the one that makes outbound connections on your behalf, usually for security (for example, to filter web traffic), for performance (for example, to keep local copies of files that are downloaded frequently, or to regulate the use of bandwidth during busy periods), or for both. Connect to the proxy server and tell it where you want to go; makes you the back connection, collects the answers and returns them to you. Many corporate networks are configured so that certain outbound connections, especially HTTP requests, are only possible from a designated proxy. This ensures that all network users send their traffic through the proxy server, rather than going directly to external sites. There are numerous corporate-style tools to help network teams automatically locate their official internal proxies, including PAC, short for proxy autoconfiguration, and WPAD, short for automatic web proxy discovery.
Believe it or not
PAC files, believe it or not, are not just lists of IP number data or server names where the official proxies on your network are located.
Because they were meant to be ingested and used in your browser, PAC files were deliberately designed to be more flexible than a simple list of static data.
In fact, a PAC file consists of JavaScript that can dynamically determine if a proxy server is needed and, if so, where to find it on the network.
As Perry points out, the PAC file format dates back a quarter of a century and first appeared as a “feature” in the Netscape browser:
PAC files provide a way to distribute complex proxy rules, such as a single file that assigns multiple URLs to different proxies. They are widely used in business environments and therefore often need to support any software that can run in a business environment. [… A PAC file is] a JavaScript file that you must run to connect to the Internet, which is uploaded remotely, often insecurely, and / or from a location that your local network can quietly decide. 1996 was really an easier time. What could go wrong?
Of course, Perry did not plan to run PAC files within the strict restrictions of a browser, but as part of his HTTP Toolkit software, which runs like a normal application, potentially giving JavaScript that launches much more scope and power than this script. the code enters the browser.
So he decided to take a look at how the programmers of the proxy configuration code he had chosen had addressed the security implications of retrieving and running external JavaScript.
He discovered that the code used a component called Node vm
, abbreviation of virtual machine, which allows you to configure a new instance or state of JavaScript, where you will not interfere with code running on other Node instances of your application.
This is a handy precaution if you want two parts of the code to do separate things so that they cannot be stepped on by mistake.
In the words of vm
library documentation:
He
vm
The module allows you to compile and execute code in V8 virtual machine contexts. […] JavaScript code can be compiled and executed immediately or compiled, saved and executed later. A common use case is to run the code in a different V8 context. This means that the invoked code has a different global object than the invoked code.
Security is good, but security is better
Perry realized that the original programmer, whose code he had now adopted, was using the vm
library for both programmatic and security security, apparently assuming it is a new one vm
the instance was not only separate from the others vm
instances in the application, but also strictly saved in its own little isolated JavaScript world.
However, like the vm
the documentation makes it clear, aloud, in bold:
He
vm
The module is not a security mechanism. Do not use it to run untrusted code.
Perry quickly discovered how to use a regular JavaScript programming technique to run code within the new vm
instance that had full access to the external data of its principal Node.js
application.
Technically, this constitutes an RCE error in the proxy configuration process, where RCE is short for remote code execution.
Freely speaking, RCE means that unreliable content obtained from an unreliable source can deliberately do something treacherous that is not supposed to be allowed, without first warning or pop-up dialogues appearing.
Is it really a problem?
As some commenters pointed out about Perry’s discovery, exploiting this error usually means altering the official proxy PAC file of a private network to include trapped JavaScript.
But if you already have the ability to alter an organization’s proxy settings, you can redirect all network users to a fake proxy anyway, with or without JavaScript errors in the equation …
… and if you can silently redirect all browsers on the network, are you sure you already have more than enough cybercrime control to wreak havoc on your organization?
Therefore, according to some commentators, CVE-2021-23406 is little more than a storm in a cup of tea.
Unless redirecting everyone’s browsers using a fake proxy server, as risky as it is ultimately, is not as dangerous as having the power to run an arbitrary program on all computers on the network as a side effect of server configuration. intermediaries …
… while leaving the original proxy settings unchanged, so everything else seems to work as usual
Hacking a network openly reconfiguring all computers to start using a different proxy server is much more likely to produce problematic side effects that will be noticed, reported, and investigated.
Contemporary cybercriminals like to stay “under the radar” by avoiding changes that regular users might notice even if they weren’t paying attention to cybersecurity incidents.
What to do?
- Do you have any Node.js software that you use
Pac-Resolve
,Pac-Proxy-Agent
, oProxy-Agent
? If so, make sure you have version 5.0.0 or later of these packages. - Check the many regularly
Node.js
modules on which your products are based? If not, make plans to do so. This means taking into account the extra time and experience in the software launch process. Fast forward and break things it could be a useful motto for prototypes and internal experiments, but it is a reckless way to build shipping products. - Explore the security limitations of the libraries you use? If not, you should. Creating a new JavaScript virtual machine instance sounds like it should improve security, because each “virtual machine” runs separately, but this is not the same as running in a security-controlled sandbox or walled garden , and the documentation makes it clear.
- Do you assume that widely used packages can be treated as safe? If so, don’t. CVE-2021-23406 is not the type of error that is likely to occur in regular use, unlike a buffer overflow that can be revealed due to unexpected crashes. Some mistakes are only found because someone decided to take a careful look, as Tim Perry did here.
For what it’s worth, Perry points out that packages in this story receive about 3,000,000 downloads a week, so popularity alone is no guarantee of correction.
Never forget, when it comes to so-called supply chain errors of this type, that you can outsource coding, but you can’t outsource the responsibility.