よーでんのブログ

One for All,All for わんわんお!

file:/// の Origin について、一昔前のセキュリティリスク

この記事は IPFactory Advent Calendar 2022 の 8 日目の記事です。

qiita.com


LTネタの消化

こんにちは。y0d3nです。
先日サークル内で行われた LT大会で喋ったネタをブログにすることで Advent Calendarの枠を埋める作戦です。

まずは前提知識として Origin と SOP の簡単な概要について触れた後、それから思いついたことの検証の結果について述べます。

Origin

Webセキュリティを考えるうえでめちゃめちゃ重要な概念として挙げられる Origin 。

developer.mozilla.org

Origin はURL のスキーム (プロトコル)、ホスト (ドメイン)、ポートによって定義され、それら 3 つが全て一致したときのみ同一オリジンとして扱われます

https://example.com オリジン判定
https://example.com 同一
https://example.com/hoge/fuga 同一
https://example.com:443 同一
https://example.com:8080 異なる *1
http//example.com 異なる
http//www.example.com 異なる

ただ、Origin という概念があるだけでは仕方ありません。
Origin 単位でコンテンツを分離するセキュリティ機構として、SOPがあります。

Same Origin Policy

developer.mozilla.org

あるオリジンによって読み込まれた文書やスクリプトが、他のオリジンにあるリソースにアクセスできる方法を制限するセキュリティ機構です。
これだけでは少々わかりにくいので、図示してみましょう。

登場人物(?) は http://secret.comhttp://attacker.com です。

登場人物

それぞれ以下のようになっていると考えましょう。

  • http://secret.com : 利用者本人にしか開けないサイト
  • http://attacker.com : 攻撃者の用意した罠サイト

SOPがないWebでは以下のようなことが可能になってしまうことが考えられます。

SOPがないWeb

  1. 利用者が罠リンクか何かを踏んで http://attacker.com にアクセスする
  2. http://attacker.com のレスポンスとして、移行の手順を自動で行うスクリプトが返ってくる
    1. http://secret.com にアクセスする
    2. http://secret.com のレスポンスとして、利用者の秘密情報が返ってくる
    3. 秘密情報を http://attacker.com に送信する

こんなことができてしまったら、気軽にネットサーフィンもできませんね。

しかし、SOPがあることで、http://attacker.com を生成元とするスクリプトhttp://secret.comのレスポンスを取得できなくなります。(リクエスト自体は送信できる(実際は少し制限があるけど今回は気にしない))

SOPがあるWeb

SOP を利用することで安全にネットサーフィンができます。

Origin の継承

さて、ここからが本題です。
about:blankjavascript:のURLから実行されたスクリプトは、そのURLを開いた Origin を継承します。

url.spec.whatwg.org

例えば、以下のようにした href の中には明示的なオリジンがありません。

<a href="javascript:alert(document.domain)">alert</a>

javascript スキームでは Origin が継承されるため document.domain はその時に開いているドメインとなります。

alert

他のパターンも見てみましょう。
いくつかピックアップします。

  • http://example.com/... のように明示的なドメインが設定されている場合は Origin が新しいものに切り替わる
  • data: スキームでは "空"(empty) になる
  • file: スキームでは "不透明"(opaque) と表現されている

html.spec.whatwg.org

opaque というのは null でシリアル化された Origin のようです。
file: を使ってローカルファイルをブラウザで開いた際は opaque と呼ばれる特徴的な Origin になるらしいことがわかります。

Opaque

file: を使用してローカルファイルを開いた時のことを想像してみます。

  • 適当なパスを指摘してファイルを開くことができる
  • それらは全て null でシリアル化された Origin がセットされる

ここで「ローカルにダウンロードした悪意あるHTMLをブラウザで開いた際、ローカルの任意ファイルが同一オリジンとして扱われてしまうのでは?」という考えがよぎりました。
ダウンロードした得体の知れない exe は流石に開きませんが、htmlくらいだったらつい開いてしまいそうです。

file

試してみましょう。
「ダウンロードしたHTMLをブラウザで開く」という状況なので、ダウンロードフォルダに適当なHTMLファイルを作成します。

iframesecret.txt を読み込み、それを JS で盗むという流れを試してみます。

<body>
    <script>
        var iframe = document.createElement('iframe');
        iframe.onload = function () { alert(document.getElementsByTagName("iframe")[0]
       .contentWindow.document.documentElement.innerHTML); };
        iframe.src = './secret.txt';
        document.body.appendChild(iframe);
    </script>
</body>

blocked

ちゃんと、"null" の Origin からは cross-origin frame にアクセスできないようになっていました。

some browsers

developer.mozilla.org

このリンクは先ほども貼りましたが、一部引用します。

Note that the URL specification states that the origin of files is implementation-dependent, and some browsers may treat files in the same directory or subdirectory as same-origin even though this has security implications.

「... some browsers may treat files in the same directory or subdirectory as same-origin ...」の部分が興味深いですね。
こういう時の「some browsers」で想像するブラウザはなんでしょうか。

はい。IEですね。

Edge の IE モードを使用して試してみます。

iframe secret.txt

secret.txt の中身にアクセスできました。

さて、先ほど引用した mozilla の文章には「same directory or subdirectory」とありましたが、それも怪しいです。
任意ファイル開けるかな~と思って file:///C:/Windows/win.ini を開こうとしたら iframe で読み込んだ時点でダウンロードをしようとして来て焦りました。

iframe win.ini

ActiveXObjectを利用してレスポンスを取得し、alert するように書いてみました。

<body>
    <script>
        var httpReq = new ActiveXObject('Msxml2.XMLHTTP.6.0');
        httpReq.onreadystatechange = cons;
        httpReq.open('get', "file:///C:/Windows/win.ini", true);
        httpReq.send(null);

        function cons(e) {
            alert(httpReq.responseText)
        }
    </script>
</body>

ActiveXObject win.ini

ローカルの悪意あるHTMLファイルを開いただけで任意ファイルにアクセスできることが確認できました。
先ほども述べましたが、「exe とかは流石に開かないよ」って人もhtmlだったら平気で開きそうなので怖いですね。

IE等を使わないと再現しないため現代ではほぼ気にしなくてよさそうですが、他にもセキュリティリスクが眠っていることがありそうですのでダウンロードしたファイルは気を付けるようにしたいですね。
オリジン、とてもよくできていて関心することばかりです。


最後までご覧いただきありがとうございました。

この記事は IPFactory Advent Calendar 2022 の 8 日目の記事です。

qiita.com

昨日は HARU くんによる「ゲーム制作における画像素材の大変さ」でした。

qiita.com

作ったゲームを学校の文化祭で展示したり、他にもいろいろゲーム作ったりしていてすごいこです。ぜひご覧ください。

さて、明日の枠が埋まっていません。命のリレーは途切れてしまうのでしょうか。

そんなことを言っていたらまたまた HARU くんが命のリレーを引き継いでくれました。 たのしみですね

*1:IEではOriginにポート番号が考慮されないため、同一として扱われていました