Regular Exploitation of a Tesla Model 3 through Chromium RegExp

December 19, 2019 | Jasiel Spelman

This is the fourth in our series of Top 5 interesting cases from 2019. Each of these bugs has some element that sets them apart from the more than 1,000 advisories released by the program this year. Today, we look at the exploit used to win a Tesla Model 3 in Vancouver at Pwn2Own this year.


One of my favorite things about vulnerabilities is when multiple implementations have the exact same bug. In a similar vein, it’s amusing to me when certain components end up having a number of vulnerabilities across different implementations.

I wrote a blog back in March about a couple of vulnerabilities within Apple Safari regarding RegExp handling that the Fluoroacetate duo had brought to Pwn2Own Tokyo in 2018. I'd recommend giving it a read here.

Now, I’ll cover a RegExp vulnerability that the Fluoroacetate duo brought to Pwn2Own Vancouver this year, targeting the Tesla Model 3’s infotainment unit. You may have heard about it. This vulnerability is tracked as ZDI-19-921 and CVE-2019-13698.

Let's look at the proof-of-concept first:

The main thing that stands out is the second argument in the call to RegExp.prototype[@@replace]. It is an object with a custom toString method that modifies the RegExp object being operated on. Anytime you see something like this, you know there’s some sort of JavaScript reentrancy bug.

Now let's take a look at the code that is responsible for handling RegExp.prototype[@@replace]. Here is a snippet from src/runtime/runtime-regexp.cc:

The function continues on from there, but in our case, we’ll enter the if block and end up calling into RegExpReplace, so let's look at that implementation. It is conveniently in the same file:

See the issue? In Runtime_RegExpReplaceRT there is a check, IsUnmodifiedRegExp. This determines whether the RegExp object is in a pristine, unmodified state. If so, it can take advantage of the “fast path” code implemented in RegExpReplace. The trouble is, soon after entering RegExpReplace, the code calls Object::ToString to perform coercion on the value specified in the second argument to RegExp.prototype[@@replace]. This allows arbitrary JavaScript to run. The JavaScript modifies the RegExp object so that it no longer qualifies as an “unmodified” JavaScript object that can be properly handled by the fast path. In particular, it sets the lastIndex property to be a custom Object. Later within the fast path implementation, the value found in lastIndex will be coerced, resulting in a second round of unexpected JavaScript execution. That JavaScript adds a new property (x) to the regular expression object, thus modifying the regular expression object’s memory layout and breaking assumptions made by the fast path code.

Note, do not be confused by the comment that precedes the call to RegExpReplace. From the wording of the comment one might be initially led to believe that RegExpReplace is not intended for the case of unmodified RegExp objects. From examining the context however, it becomes clear that the true intent of the comment is that RegExpReplace should not be called when a callable function is provided as the replacement argument (“functional replace”), even if the RegExp is unmodified. Regardless, RegExpReplace is the fast path, and is intended exclusively for the case of unmodified RegExp objects.

Now let's take a look at how this was patched, which you can see here. We’re still interested in looking at src/runtime/runtime-regexp.cc:

The essential change is that the call to Object::ToString that coerces the replacement argument has been moved up one call level. Instead of the coercion being performed within RegExpReplace, it is now performed within Runtime_RegExpReplaceRT, where it can be done prior to the IsUnmodifiedRegExp check.

Exploitation of this vulnerability allows an attacker to execute arbitrary code within Chrome's renderer sandbox on the vehicle infotainment system. From there the attacker might be able to escape the sandbox and pivot to compromise other functions of the vehicle as well. Tesla rolled out updates to their vehicles as soon as the patch was made available.

Given that the Fluoroacetate duo has found vulnerabilities in RegExp handling in the past, it was no surprise to see them bring another in March. Now that you’ve seen a couple examples of issues that span multiple implementations, maybe you’ll find something to bring to a future contest.

You can find me on Twitter at @WanderingGlitch, and follow the team for the latest in exploit techniques and security patches. Stay tuned for the final Top 5 bug blog, which will be released tomorrow.