Webアプリケーションのフロント側の各種ブラウザへの対応は、開発の際に悩ましいものです。時には「Internet Explorerだけこの処理をさせたい!」というケースもあるでしょう。よくあるやり方は、User Agentやオブジェクト参照などで、四苦八苦しているかもしれません。ここで私が発見した手法は、そこそこに判定すると思われます。なぜならば、Internet ExplorerのJavaScriptエンジンの特有の挙動を応用する手法ですので、User Agentなどは偽装が出来ても、Internet Explorerでブラウジングしている以上は、さすがにJavaScriptエンジンまでは変えられませんよね。ちなみに、Internet ExplorerのJavaScriptエンジンはChakraと呼ばれています。
●概念実証
ここでは、Internet Explorerを検出したらダイアログを出し、新しいMicrosoft Edgeのダウンロードサイトへリダイレクトさせる、といったJavaScriptコードを書いています。それ以外のブラウザは、違うメッセージダイアログが表示されます。
- Internet Explorer を立ち上げてください。(例えば IE11です。Edgeではありません!)
スクリーンショットの真ん中のアイコンが目的のInternet Explorerです。 - 私が用意したデモページを開きます - http://sandbox.hack.vet/ie/
まことにInternet Explorerであれば、「IEですよ。」といったalert()が出てきます。その後、マイクロソフトのサイトにリダイレクトします。
(リダイレクト先: https://support.microsoft.com/ja-jp/help/4501095/download-the-new-microsoft-edge-based-on-chromium )
Internet Explorerではないブラウザの場合、次のようなalert()が出てきます。
スクリーンキャプチャも撮影したので、手元に環境がない方はこちらをご覧ください。
http://sandbox.hack.vet/ie/IE_Checker.mp4
音はありません。
後になって思いましたが、デモページがちゃちなフィッシングサイトっぽいですね。当の本人は全くそんなことをする気はないですし、もちろんInternet Explorerに対してネガティブキャンペーンをする意図など毛頭ないです。
●サンプルコード
ミニマムなサンプルコードは下記に示します。(cache-controlフィールドはおまけです)
◆index.html
上記のindex.htmlをInternet Explorerで開くと、alert(1)が実行されます。(通常、ローカルから実行すると、スクリプト実行の確認ダイアログが出てきます)その他のFirefox, Chrome, EdgeにおいてはJavaScriptは実行されません。つまり、ブランクページと同等の画面になります。
●テクニック解説
もし、文字エンコーディングに知見があるとするなら、既知のXSS攻撃手法と合わせて考えると良いかもしれません。今回は、これに関連する別件の記事にまとめて解説したいので、具体的な動作原理の解説は差し控えます。
さて、このテクニックは、Internet Explorer以外のブラウザはJavaScriptコードのシンタックスエラーが発生する、という挙動を逆手に取ったものです。注目すべきはまさしく、縺�=0; この部分です。Unicodeで見てみると次のような文字列です。
U+7E3AはUTF-8の文字コードをshift_jisで見るいわゆる文字化けでよく遭遇します。次にU+FFFDはSpecialsと呼ばれるブロックのREPLACEMENT CHARACTERです。これは、代替文字という意味で、文字コードを変更した時などに表現できない文字があった場合、この文字が使用されます。
サンプルのコードでは、このUnicode二文字「縺�」を変数名として使用しています。これは基本的にはシンタックスエラーになるでしょう。変数名としてU+FFFDは使用が禁止されているので、当然シンタックスエラーとなり、そのJavaScriptコードは実行されません。しかし、Internet Explorerはどうやら動作が違うようです。
ソースコードを表示すると、なんと当該部分が <script>膰削申=0;alert(1)</script> に変わっています。JavaScriptは 膰削申 という変数名は使用できますので、構文的には通ります。つまり、JavaScriptコードが実行されるということです。これは、文字エンコーディングが自動判別になった場合、EUCが選択されたため発生する現象です。Internet Explorerの文字エンコーディング自動判別は実行環境によっては変わる可能性があるため、必ずEUCになるとは限りません。しかしながら、Internet ExplorerのJavaScriptエンジンは変数名にU+FFFDを使用できるので、シンタックスエラーにならずにJavaScriptコードが実行されます。次にChromeではどのように表示されるでしょうか。
“正しく”シンタックスエラーとなり、JavaScriptコードは実行されませんでした。冒頭にも述べましたが、以上のことから、Internet Explorer以外のブラウザはJavaScriptコードのシンタックスエラーが発生するが、Internet Explorerは勝手に変数名が変わり、正しい構文となってしまうため、JavaScriptコードが実行できることを基準として、Internet Explorerかそれ以外かを判定しています。
ちなみに、「膰削申」は全く意味不明ですが、翻訳をかけてみると、肉を切るみたいな意味のようです。
●使い所
念の為に申し上げておきますが、まさかこの記事のコードをコピペしてプロダクトに組み込もうと思っていませんか?だいぶBuggyなので実験程度に留めておいてください。また、別件で調べている事があり、良くなさそうだった場合、この記事を非公開にするかもしれません。
●参照情報
以下、余談。
ここ最近、文字コード、特にUnicodeに興味関心が高くあり、面白そうなことを試行錯誤しています。合成文字(Combining)がホットなキーワードです。所感ですが、文字コードとWebセキュリティは割と密接な関係があると思いました。是非、“文字”のテクニックを調べてみてください。
Firefox(PC)からじゃないと見えないっぽい https://t.co/frW5BmNGw9 pic.twitter.com/uA3K6ZsILK
— りいんちゃん (@reinforchu) 2020年2月12日