# Enter "Sandbreak" - Vulnerability In vm2 Sandbox Module Enables Remote Code Execution (CVE-2022-36067)
Yuval Ostrovsky
Architect
Gal Goldstein
Security Researcher
The Oxeye research team has found "Sandbreak", a critical remote code
execution vulnerability in the popular sandbox library
[vm2](https://github.com/patriksimek/vm2). The vulnerability was disclosed to
the project owners and was rapidly patched in version 3.9.11. GitHub has
issued
[CVE-2022-36067](https://github.com/patriksimek/vm2/security/advisories/GHSA-
mrgp-mrhc-5jrq) for this critical vulnerability and the maximum CVSS score of
10.0.
![](https://images.seebug.org/1669000282397-w331s)
## What Is The Potential Impact of this Vulnerability?
vm2 is a widely used JavaScript sandbox - according to the NPM package
manager, it has more than 16 million monthly downloads and offers an isolated
environment where applications can run untrusted code.
A threat actor who exploits this vulnerability will be able to bypass the vm2
sandbox environment and run shell commands on the machine hosting the sandbox.
Sandboxes serve different purposes in modern applications, such as examining
attached files in email servers, providing an additional security layer in web
browsers, or isolating running applications in certain operating systems.
Given the nature of the use cases for sandboxes, itas clear that the vm2
vulnerability can have dire consequences for applications that use it.Â
 The fact that this vulnerability has the maximum CVSS score of 10.0 and is
extremely popular means its potential impact is widespread and critical.
## Sandbox 101
An application may sometimes require the execution of untrusted code provided
by the user as part of its business logic. This is considered dangerous since
the user can abuse this mechanism to take over the application. Utilizing a
sandbox mechanism such as vm2 helps to eliminate this risk.Â
The term “sandbox” refers to an isolated environment within which the untrusted code can run in an attempt to mitigate the risk of malicious code affecting the host machine running it. While sandboxes are extremely useful as isolation mechanisms, they should be used with caution since it is possible to bypass the restrictions, as demonstrated below.
## Technical deep dive
#### Background
The guiding principles behind our choice of research topics are:
1. Pervasiveness - how wide-reaching is the vulnerability?
2. Impact - how severe can the consequences be if the vulnerability is exploited?
As we looked for potential vulnerabilities to dig deeper into, the idea of
sandboxes came up. By their very definition, sandboxes are considered safe
places and trusted as mechanisms that isolate potentially dangerous code from
our applications. But what would happen if this trust was compromised? This
thesis drove our explorations and eventually led us to discover the vm2
sandbox vulnerability.
#### Laying the groundwork:
Our usual approach when evaluating a given software's security is first to
analyze the previous security lapses discovered in the same software. This
helps us better grasp the available attack surface and may also lead to low-
hanging bugs stemming from incomplete fixes. It also helps us come up with
techniques to bypass the implemented fixes. While reviewing the previous bugs
disclosed to the vm2 maintainers, we noticed an interesting technique: the bug
reporter abused the error mechanism in Node.js to escape the sandbox.
Node.js allows the application developer to customize the call stack of an error that occurred in the application. Customizing the call stack can achieve this by implementing the “prepareStacktrace” method under the global “Error” object. This means that when an error occurs and the “stack” property of the thrown error object is accessed, Node.js will call this method while providing it with a string representation of the error alongside an array of “CallSite” objects as arguments. The following screenshot shows Node.js attempting to call the “prepareStackTrace” function:
![](https://images.seebug.org/1669000284142-w331s)
Each “CallSite” object in the array represents a different stack frame. Together, they comprise the call stack state when the error occurred. One of the methods exposed by the “CallSite” objects is “getThis” which is responsible for returning the “this” object that was available in the related stack frame. This behavior may lead to sandbox escapes as some of the “CallSite” objects may return objects created outside the sandbox when invoking the “getThis” method. After gaining hold of a “CallSite” object created outside the sandbox, it might be possible to access Node’s global objects and execute arbitrary system commands from there.
The vm2 maintainers were aware that overriding “prepareStackTrace” could lead to a sandbox escape and tried to mitigate this escape path by wrapping the Error object and the “prepareStackTrace” method with their own implementation, which prevents the users from overriding this method.
The reporter’s POC bypassed the logic above since vm2 missed wrapping specific methods related to the “WeakMap” JavaScript built-in type. This allowed the attacker to provide their own implementation of “prepareStackTrace”, then trigger an error, and escape the sandbox.
#### Escaping the sandbox
By this step, we understand that the prepareStackTrace function of the Error
object is the function we want to override. Providing our own implementation
of it while triggering an error would result in a sandbox escape.
That got us thinking about what would happen if we tried to use a similar escape technique, but instead of finding a way to override “prepareStackTrace” itself, we would simply try to override the global Error object with our own object, which implements the prepareStackTrace function.
The following code would result in our own implementation being called:
![](https://images.seebug.org/1669000286180-w331s)
The only thing left to do here is to access the CallSite object of a frame that resides outside the sandbox; from there, we can access Node’s global members and access the currently executing process, which allows us to execute commands:
![](https://images.seebug.org/1669000287922-w331s)
![](https://images.seebug.org/1669000290129-w331s)
## Takeaway
Although sandboxes are meant to run untrusted code within your application,
you shouldnat automatically assume that they are safe. If the use of a
sandbox is unavoidable, it is recommended to separate the logical sensitive
part of your application from the microservice that runs the sandbox code so
if a threat actor successfully breaks out from the sandbox, the attack surface
is limited to the isolated microservice.
Moreover, avoid using a sandbox that relies on a dynamic programming language
such as JavaScript when possible. The dynamic nature of the language widens
the attack surface for a potential attacker, making defending against such
attacks much harder.
Vulnerability researchers are more likely to look at the high-profile
dependencies of your application, resulting in more frequent vulnerabilities
within the dependency. Make sure to monitor your application dependencies
frequently and upgrade their versions accordingly.
## Discovery and Disclosure Timeline
![](https://images.seebug.org/1669000291635-w331s)
暂无评论