Skip to content

Commit

Permalink
[vulnerability] Fix #242. Hook iframe.srcdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
t2ym committed Apr 17, 2018
1 parent 5096373 commit 5bbbc68
Show file tree
Hide file tree
Showing 20 changed files with 313 additions and 34 deletions.
37 changes: 37 additions & 0 deletions demo/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
let baseURI;
switch (self.constructor.name) {
case 'Window':
if (self === top) {
baseURI = location.href;
}
else {
baseURI = top.hook.parameters.baseURI;
}
hook.parameters.baseURI = baseURI;
break;
case 'ServiceWorkerGlobalScope':
baseURI = new URL(location.origin + new URL(location.href).searchParams.get('service-worker-initiator')).href;
hook.parameters.baseURI = baseURI;
break;
case 'DedicatedWorkerGlobalScope':
case 'SharedWorkerGlobalScope':
// For Hook Workers; Insignificant in hooked web workers
baseURI = new URL(location.origin +
(new URL(location.href).searchParams.has('service-worker-initiator')
? new URL(location.href).searchParams.get('service-worker-initiator')
: location.pathname
)
).href;
hook.parameters.baseURI = baseURI;
break;
default:
baseURI = location.href;
hook.parameters.baseURI = baseURI;
break;
}
hook.parameters.emptyDocumentUrl = new URL('./empty-document.html', baseURI);
hook.parameters.bootstrap = `<script>frameElement.dispatchEvent(new Event('srcdoc-load'))</script>`;
hook.parameters.onloadWrapper = `event.target.addEventListener('srcdoc-load', () => { $onload$ })`;
//console.log('bootstrap.js: location.href = ' + location.href + ' baseURI = ' + baseURI + ' bootstrap = ' + hook.parameters.bootstrap);
}
3 changes: 2 additions & 1 deletion demo/empty-document.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
<html>
<head>
<meta charset="utf-8">
<script src="../../thin-hook/hook.min.js?no-hook=true"></script>
<script src="../../thin-hook/hook.min.js?no-hook=true&hook-name=__hook__&context-generator-name=method&discard-hook-errors=false&fallback-page=index-fb.html&hook-property=true&hook-global=true&hook-prefix=_pp_&compact=true"></script>
<script context-generator src="no-hook-authorization.js?no-hook=true"></script>
<script context-generator src="context-generator.js?no-hook=true"></script>
<script context-generator src="bootstrap.js?no-hook=true"></script>
<script src="hook-callback.js?no-hook=true"></script>
<script src="hook-native-api.js?no-hook=true"></script>
</head>
Expand Down
37 changes: 32 additions & 5 deletions demo/hook-callback.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,8 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
'/components/thin-hook/demo/es6-module4.js,f,*': '@import.meta_reader,f',
'/components/polymer/lib/utils/async.html,script@566,timeOut,run': '@setTimeout_reader',
'/components/thin-hook/demo/,script@4861': '@document_writer',
'/components/thin-hook/demo/,script@5062': '@document_writer',
'/components/thin-hook/demo/,script@5063': '@document_writer',
'/components/thin-hook/demo/,script@5132': '@document_writer',
'/components/thin-hook/demo/,script@5133': '@document_writer',
'/components/thin-hook/demo/sub-document.html,*': '@document_writer',
'/components/thin-hook/demo/commonjs2.js': '@path_join_prohibited',
'/components/thin-hook/demo/commonjs2.js,tty': '@tty_prohibited',
Expand Down Expand Up @@ -640,7 +640,7 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
'/components/thin-hook/demo/normalize.js,createProperty,set': '@GetterSetterClass_creator',
'/components/thin-hook/demo/normalize.js,writeProperty': '@GetterSetterClass_writer',
'/components/thin-hook/demo/normalize.js,readProperty': '@GetterSetterClass_reader',
'/components/thin-hook/demo/my-view3.html,script@1841,attached': '@iframe_contentWindow_accessor',
'/components/thin-hook/demo/my-view3.html,*': '@iframe_contentWindow_accessor',
'/components/thin-hook/demo/sub-document.html,script@7853,onLoad': '@iframe_contentWindow_accessor',
'/components/thin-hook/demo/sub-document.html,script@7853,onLoad,*': '@iframe_contentWindow_accessor',
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js,41,o': '@iframe_contentWindow_accessor',
Expand Down Expand Up @@ -1855,7 +1855,28 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
},
},
// TODO: onload
contentDocument: '---',
contentDocument: {
[S_DEFAULT]: '---',
'@iframe_contentWindow_accessor': function _iframeContentDocumentAcl(normalizedThisArg,
normalizedArgs /* ['property', args], ['property', value], etc. */,
aclArgs /* [name, isStatic, isObject, property, opType, context] */,
hookArgs /* [f, thisArg, args, context, newTarget] */,
applyAcl /* for recursive application of ACL */) {
let opType = aclArgs[4];
if (!normalizedThisArg.getAttribute('src')) {
return false; // reject on empty src
}
if (this.contentWindow && !this.contentWindow.__hook__) {
return false; // reject on missing hook infrastructure
}
if (opType === 'r') {
let contentWindow = normalizedThisArg.contentWindow;
otherWindowObjects.set(contentWindow.Object, contentWindow);
otherWindowObjectsStatus.set = true;
}
return 'r--'[opTypeMap[opType]] === opType; // equivalent to 'r--' acl
},
},
contentWindow: {
[S_DEFAULT]: '---',
'@iframe_contentWindow_accessor': function _iframeContentWindowAcl(normalizedThisArg,
Expand All @@ -1864,6 +1885,12 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
hookArgs /* [f, thisArg, args, context, newTarget] */,
applyAcl /* for recursive application of ACL */) {
let opType = aclArgs[4];
if (!normalizedThisArg.getAttribute('src')) {
return false; // reject on empty src
}
if (this.contentWindow && !this.contentWindow.__hook__) {
return false; // reject on missing hook infrastructure
}
if (opType === 'r') {
let contentWindow = normalizedThisArg[normalizedArgs[0]]
otherWindowObjects.set(contentWindow.Object, contentWindow);
Expand Down Expand Up @@ -3863,7 +3890,7 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
}
}
// Handle exceptions
const errorReportBaseUrl = (new URL('errorReport.json', location)).pathname;
const errorReportBaseUrl = (new URL('errorReport.json', typeof window === 'object' ? top.location : location)).pathname;
const criticalErrorPageUrl = 'about:blank';
let hookCallbackCompatibilityTestDone = false;
const _caches = caches; // Take a backup just in case (still not robust)
Expand Down
1 change: 1 addition & 0 deletions demo/hook-native-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserv
'Node',
'Element',
'HTMLScriptElement',
'HTMLIFrameElement',
'HTMLAnchorElement',
'HTMLAreaElement',
'Document',
Expand Down
2 changes: 1 addition & 1 deletion demo/hook-worker.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
importScripts('../hook.min.js?no-hook=true', 'context-generator.js?no-hook=true');
importScripts('../hook.min.js?no-hook=true', 'context-generator.js?no-hook=true', 'bootstrap.js?no-hook=true');
onmessage = hook.hookWorkerHandler;
3 changes: 2 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
<html lang="en">
<head>
<meta charset="utf-8">
<script src="../../thin-hook/hook.min.js?version=491&no-hook-authorization=1f776c3e8a1542a9b9ec7dee61c0e59def2fc939d1b159673c1d7dfa27894c5c,2388d9729a99401a3a38004bb6aa7b6b30d960838b394a3f824d651489c55e70,b08b09b3cb1ff096c2117b133d38d848a0b486499e93fbd17b2f3ebf05f0c905,de5407e69386ad2e9aac39e5bc621ba098bd5b5678b0226696a895fc777cad79,ce8bd5917e14e8e138aecc6a61bc5779668fde1b3f762eb16e609f429d9f9475,a578e741369d927f693fedc88c75b1a90f1a79465e2bb9774a3f68ffc6e011e6,3fca6667e9d1a3f80b98dacb4ec10b4f5464c88785aea95ee61a123587633127,log-no-hook-authorization&sw-root=/&no-hook=true&hook-name=__hook__&context-generator-name=method&discard-hook-errors=false&fallback-page=index-fb.html&hook-property=true&hook-global=true&hook-prefix=_pp_&compact=true&service-worker-ready=false"></script></head></html><!--
<script src="../../thin-hook/hook.min.js?version=491&no-hook-authorization=a62c8bcab98286cea63ded67f38e0bda83f5388c10c20fe487dfda4e159d4d9a,acc24b5a5831b4843ec1af63320b10006b425682473290715b7efd4486c29816,b08b09b3cb1ff096c2117b133d38d848a0b486499e93fbd17b2f3ebf05f0c905,de5407e69386ad2e9aac39e5bc621ba098bd5b5678b0226696a895fc777cad79,ce8bd5917e14e8e138aecc6a61bc5779668fde1b3f762eb16e609f429d9f9475,a578e741369d927f693fedc88c75b1a90f1a79465e2bb9774a3f68ffc6e011e6,56f344a677bb34a8d3541e8f26bfc74d9b5848c4872bd9e86549e452f129767f,log-no-hook-authorization&sw-root=/&no-hook=true&hook-name=__hook__&context-generator-name=method&discard-hook-errors=false&fallback-page=index-fb.html&hook-property=true&hook-global=true&hook-prefix=_pp_&compact=true&service-worker-ready=false"></script></head></html><!--
<script context-generator src="no-hook-authorization.js?no-hook=true"></script>
<script context-generator src="context-generator.js?no-hook=true"></script>
<script context-generator src='bootstrap.js?no-hook=true'></script>
<script context-generator no-hook>
{
hook.parameters.cors = [
Expand Down
20 changes: 20 additions & 0 deletions demo/invalid-document.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!--
@license https://github.com/t2ym/thin-hook/blob/master/LICENSE.md
Copyright (c) 2017, 2018, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
try {
caches;
}
catch (e) {
}
</script>
</head>
<body>
<h1>Invalid-document in iframe (__hook__ is missing)</h1>
</body>
</html>
57 changes: 55 additions & 2 deletions demo/my-view3.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,23 @@
<h1>View Three</h1>
<p>Modus commodo minimum eum te, vero utinam assueverit per eu.</p>
<p>Ea duis bonorum nec, falli paulo aliquid ei eum.Has at minim mucius aliquam, est id tempor laoreet.Pro saepe pertinax ei, ad pri animal labores suscipiantur.</p>
<iframe src="sub-document.html" width="80%" height="400"></iframe>
<iframe id="subDocument" src="sub-document.html" width="80%" height="400"></iframe>
<iframe id="srcdocStaticEmpty" srcdoc="" width="80%" height="100"></iframe>
<iframe id="srcdocStaticFullHtml" srcdoc="<html><head><script src=&quot;../../chai/chai.js&quot;></script><script>chai.assert.throws(()=> { return caches; }, /^Permission Denied:/);</script></head><body><p1>srcdocStaticFullHtml</p1></body></html><script>console.log(`srcdocStaticFullHtml srcdoc loaded`);</script>" width="80%" height="100"></iframe>
<iframe id="srcdocStaticHtmlOnly" src="overidden.html" srcdoc="<html><script src=&quot;../../chai/chai.js&quot;></script><script>chai.assert.throws(()=> { return caches; }, /^Permission Denied:/);</script><p1>srcdocStaticHtmlOnly</p1></html>" width="80%" height="100"></iframe>
<iframe id="srcdocStaticBare" onload="console.log('srcdocStaticBare onload event', event);" srcdoc="<script src=&quot;../../chai/chai.js&quot;></script><script>chai.assert.throws(()=> { return caches; }, /^Permission Denied:/);</script><p1>srcdocStaticBare</p1>" width="80%" height="100"></iframe>

<iframe id="srcEmpty" width="80%" height="100"></iframe>

<iframe id="setSrcdocAttribute" width="80%" height="100"></iframe>

<iframe id="setSrcdocProperty" width="80%" height="100"></iframe>

<iframe id="setSrcAttributeJavascript" width="80%" height="100"></iframe>

<iframe id="setSrcPropertyJavascript" width="80%" height="100"></iframe>

<iframe id="srcEmptyOnload" onload="chai.assert.throws(() => { this.contentWindow }, /^Permission Denied:/); chai.assert.throws(() => { this.contentDocument }, /^Permission Denied:/)" width="80%" height="100"></iframe>
</div>

</template>
Expand All @@ -65,12 +81,49 @@ <h1>View Three</h1>
behaviors: [ BehaviorsStore.I18nBehavior ],

attached: function() {
let iframe = Polymer.dom(Polymer.dom(document.querySelector('my-app').root).querySelector('my-view3').root).querySelector('iframe');
let iframe = this.$.subDocument;
iframe.addEventListener('load', function (event) {
chai.assert.throws(() => {
iframe.contentWindow.caches;
}, /^Permission Denied:/);
});
this.$.srcdocStaticFullHtml.addEventListener('load', function (event) {
console.log('this.$.srcdocStaticFullHtml.addEventListener("load") event called');
});
chai.assert.throws(() => {
this.$.srcEmpty.contentWindow;
}, /^Permission Denied:/);
chai.assert.throws(() => {
this.$.srcEmpty.contentDocument;
}, /^Permission Denied:/);
this.$.setSrcdocAttribute.setAttribute('srcdoc',
'<script src="../../chai/chai.js"></scr' + 'ipt>' +
'<script>chai.assert.throws(() => { caches }, /^Permission Denied:/);</scr' + 'ipt><p1>setSrcdocAttribute</p1>');
this.$.setSrcdocProperty.srcdoc =
'<script src="../../chai/chai.js"></scr' + 'ipt>' +
'<script>chai.assert.throws(() => { caches }, /^Permission Denied:/);</scr' + 'ipt><p1>setSrcdocProperty</p1>';

// ignored
this.$.setSrcAttributeJavascript.setAttribute('src',
'javascript:document.write(`<script src="../../chai/chai.js"></scr' + 'ipt>' +
'<script>chai.assert.throws(() => { caches }, /^Permission Denied:/);</scr' + 'ipt><p1>setSrcAttribute</p1>`)');
chai.assert.throws(() => {
this.$.setSrcAttributeJavascript.contentWindow;
}, /^Permission Denied:/);
chai.assert.throws(() => {
this.$.setSrcAttributeJavascript.contentDocument;
}, /^Permission Denied:/);

// ignored
this.$.setSrcPropertyJavascript.src =
'javascript:document.write(`<script src="../../chai/chai.js"></scr' + 'ipt>' +
'<script>chai.assert.throws(() => { caches }, /^Permission Denied:/);</scr' + 'ipt><p1>setSrcAttribute</p1>`)';
chai.assert.throws(() => {
this.$.setSrcPropertyJavascript.contentWindow;
}, /^Permission Denied:/);
chai.assert.throws(() => {
this.$.setSrcPropertyJavascript.contentDocument;
}, /^Permission Denied:/);
}

});
Expand Down
5 changes: 3 additions & 2 deletions demo/no-hook-authorization.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
"9c84034cd3f81fcd3e39cf0065e297ba7dae755044aec3a1c4fc3b6ab418ccbd": true,
"01900ec53324619f252a30db6648af86628642fce1c0ddfa53601a2af910639f": true,
"7e0fcbf73f8a30d98082c497e4bec73f2b49e5bee70605bb8838aed035763868": true,
"fd5fa59d7cda70dfacccd177249b1f8c1342063085e2f21fc8964ab82173896e": true,
"4fd89b62d9ca6af49d8f619d659fe145beb65c566862abb6d67a0e03f38be494": true,
"de5407e69386ad2e9aac39e5bc621ba098bd5b5678b0226696a895fc777cad79": true,
"d29262c93fe669dc182326d1d6950138ebca658254270caef352367e76777aab": true,
"ce8bd5917e14e8e138aecc6a61bc5779668fde1b3f762eb16e609f429d9f9475": true,
"b08b09b3cb1ff096c2117b133d38d848a0b486499e93fbd17b2f3ebf05f0c905": true,
"2bd258fc61be5769230ad77bd4f4da232c26b2758b79a02db8cae95163abfdd4": true,
"db82c32a68bc3ddbb2232a947c3cdeb88f5ee7ba41d05d686146507687a6897f": true,
"85ee19dcfadf597919e073de9ecd071a2eb263d105524f45eace0318230e66a7": true
"e2e42b1f8c6c518b5878b5bd95d34c0f15e139a1afb6ab6a6642b6e81219d2c5": true,
"680dd69d4f9bce1ec9b5171f322788c5851cfd08141ec9edf2128090bd969f3a": true,
};
let hidden;
const passcode = 'XX02c107ea633ed697acc12e1b3de1bcf2f0ef7cafe4f048e29553c224656ecd7a';
Expand Down
3 changes: 2 additions & 1 deletion demo/original-index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
<html lang="en">
<head>
<meta charset="utf-8">
<script src="../../thin-hook/hook.min.js?version=491&no-hook-authorization=1f776c3e8a1542a9b9ec7dee61c0e59def2fc939d1b159673c1d7dfa27894c5c,2388d9729a99401a3a38004bb6aa7b6b30d960838b394a3f824d651489c55e70,b08b09b3cb1ff096c2117b133d38d848a0b486499e93fbd17b2f3ebf05f0c905,de5407e69386ad2e9aac39e5bc621ba098bd5b5678b0226696a895fc777cad79,ce8bd5917e14e8e138aecc6a61bc5779668fde1b3f762eb16e609f429d9f9475,a578e741369d927f693fedc88c75b1a90f1a79465e2bb9774a3f68ffc6e011e6,3fca6667e9d1a3f80b98dacb4ec10b4f5464c88785aea95ee61a123587633127,log-no-hook-authorization&sw-root=/&no-hook=true&hook-name=__hook__&context-generator-name=method&discard-hook-errors=false&fallback-page=index-fb.html&hook-property=true&hook-global=true&hook-prefix=_pp_&compact=true&service-worker-ready=true"></script>
<script src="../../thin-hook/hook.min.js?version=491&no-hook-authorization=a62c8bcab98286cea63ded67f38e0bda83f5388c10c20fe487dfda4e159d4d9a,acc24b5a5831b4843ec1af63320b10006b425682473290715b7efd4486c29816,b08b09b3cb1ff096c2117b133d38d848a0b486499e93fbd17b2f3ebf05f0c905,de5407e69386ad2e9aac39e5bc621ba098bd5b5678b0226696a895fc777cad79,ce8bd5917e14e8e138aecc6a61bc5779668fde1b3f762eb16e609f429d9f9475,a578e741369d927f693fedc88c75b1a90f1a79465e2bb9774a3f68ffc6e011e6,56f344a677bb34a8d3541e8f26bfc74d9b5848c4872bd9e86549e452f129767f,log-no-hook-authorization&sw-root=/&no-hook=true&hook-name=__hook__&context-generator-name=method&discard-hook-errors=false&fallback-page=index-fb.html&hook-property=true&hook-global=true&hook-prefix=_pp_&compact=true&service-worker-ready=true"></script>
<script context-generator src="no-hook-authorization.js?no-hook=true"></script>
<script context-generator src="context-generator.js?no-hook=true"></script>
<script context-generator src='bootstrap.js?no-hook=true'></script>
<script context-generator no-hook>
{
hook.parameters.cors = [
Expand Down
2 changes: 1 addition & 1 deletion demo/shared-worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
importScripts('../hook.min.js?no-hook=true', 'no-hook-authorization.js?no-hook=true', 'hook-callback.js?no-hook=true', 'hook-native-api.js?no-hook=true');
importScripts('../hook.min.js?no-hook=true', 'no-hook-authorization.js?no-hook=true', 'bootstrap.js?no-hook=true', 'hook-callback.js?no-hook=true', 'hook-native-api.js?no-hook=true');
onconnect = function(event) {
let port = event.ports[0];

Expand Down
2 changes: 2 additions & 0 deletions demo/sub-document.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<script src="../../thin-hook/hook.min.js?no-hook=true"></script>
<script context-generator src="no-hook-authorization.js?no-hook=true"></script>
<script context-generator src="context-generator.js?no-hook=true"></script>
<script context-generator src='bootstrap.js?no-hook=true'></script>
<script src="hook-callback.js?no-hook=true"></script>
<script src="hook-native-api.js?no-hook=true"></script>
<script src="../../chai/chai.js"></script>
Expand Down Expand Up @@ -84,5 +85,6 @@
<body>
<h1>Sub-document in iframe</h1>
<iframe src="sub-sub-document.html"></iframe>
<iframe src="invalid-document.html"></iframe>
</body>
</html>
1 change: 1 addition & 0 deletions demo/sub-sub-document.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<script src="../../thin-hook/hook.min.js?no-hook=true"></script>
<script context-generator src="no-hook-authorization.js?no-hook=true"></script>
<script context-generator src="context-generator.js?no-hook=true"></script>
<script context-generator src='bootstrap.js?no-hook=true'></script>
<script src="hook-callback.js?no-hook=true"></script>
<script src="hook-native-api.js?no-hook=true"></script>
</head>
Expand Down
1 change: 1 addition & 0 deletions demo/web-worker-module.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import '../hook.min.js?no-hook=true';
import './no-hook-authorization.js?no-hook=true';
import './bootstrap.js?no-hook=true';
import './hook-callback.js?no-hook=true';
import './hook-native-api.js?no-hook=true';
import Test from './es6-module.js';
Expand Down
2 changes: 1 addition & 1 deletion demo/web-worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
importScripts('../hook.min.js?no-hook=true', 'no-hook-authorization.js?no-hook=true', 'hook-callback.js?no-hook=true', 'hook-native-api.js?no-hook=true');
importScripts('../hook.min.js?no-hook=true', 'no-hook-authorization.js?no-hook=true', 'bootstrap.js?no-hook=true', 'hook-callback.js?no-hook=true', 'hook-native-api.js?no-hook=true');
try {
importScripts('invalid.json');
}
Expand Down
Loading

0 comments on commit 5bbbc68

Please sign in to comment.