iframe sandbox は万能ではない

HTML5で導入されたiframe要素のsandbox属性は、そのiframe内のコンテンツに対しJavaScriptの実行を始め様々な制約を課すことでセキュリティの向上に役立つ機能である。例えば、以下のように指定されたiframeでは、iframe内からformのsubmitなどはできるが、iframe内でのJavaScriptの実行やtarget=_blankなどによってウィンドウを開くことなどは禁止される。

<iframe sandbox="allow-forms" src="..."></iframe>

sandbox属性に明示的に allow-scripts という値を指定しない限りはiframe内では直接的にはJavaScriptは実行できないが、かといってiframe内から間接的にJavaScriptを必ずしも実行させることが不可能かというとそうでもない。
sandbox属性にallow-top-navigationがついている場合を考える。

<iframe sandbox="allow-top-navigation" src="sandboxed.html"></iframe>

sandboxed.html内に記述したJavaScriptはiframe内での実行は阻止されるが、トップレベルのwindowへの干渉は可能である。そのため、sandboxed.htmlに以下のような記述を行いユーザーにクリックを促す。

<a target="_top" href="data:text/html,<script>alert(1);</script>">click me</a>

iframe内には "click me" の文字列が表示され、クリックすることでトップレベルのコンテンツがdata:スキームで指定されたHTMLに置き換わる。このdata:スキームはiframe内ではなくトップレベルウィンドウ内で表示されるので、そこに含まれるJavaScriptは当然ながらsandbox属性の影響を受けずに実行される。

もっとも、一般的なWebブラウザであればdata:スキームはもとのWebサイトのオリジン(iframeの親やiframe内のオリジン)ではなくnullオリジンで実行されるために、直接的にWebサイトへ影響を与えることは通常はない。
問題はElectronでこのような記述をしている場合である。

このような方法でElectronアプリによるXSSの被害を低減させていたとしても、sandbox属性にallow-top-navigationが指定されている場合には攻撃者によって作成されたJavaScriptの実行へとつながる可能性があり、その場合にはオリジンが異なっていたとしてもnode.jsと同等のローカルホスト上での任意のコード実行になり得る。実際に、攻撃者がiframe内のsandboxed.htmlとして以下のようなHTMLを生成できた場合には攻撃者は任意コードの実行ができる。

<a target="_blank" href="data:text/html,&lt;script&gt;1&lt;/script&gt;&lt;webview nodeintegration src=&quot;data:text/html,&lt;b&gt;webview&lt;/b&gt;
&lt;script&gt;require('child_process').exec('calc.exe',function(){})&lt;/script&gt;&quot;&gt;&lt;/webview&gt;">click me</a>

なお、sandbox属性の値としてallow-top-navigationだけでなく、allow-poopupsも同様である。

まとめ:ElectronアプリでXSSの脅威を低減するためにiframe sandboxを用いる場合は、allow-top-navigationおよびallow-popupsは避ける。