http80

Web security research

How to detect Internet Explorer based of JavaScript syntax errors / JavaScriptの構文エラーを応用したInternet Explorerの判定方法

f:id:reinforchu:20200212141339p:plain

 Webアプリケーションのフロント側の各種ブラウザへの対応は、開発の際に悩ましいものです。時には「Internet Explorerだけこの処理をさせたい!」というケースもあるでしょう。よくあるやり方は、User Agentやオブジェクト参照などで、四苦八苦しているかもしれません。ここで私が発見した手法は、そこそこに判定すると思われます。なぜならば、Internet ExplorerのJavaScriptエンジンの特有の挙動を応用する手法ですので、User Agentなどは偽装が出来ても、Internet Explorerでブラウジングしている以上は、さすがにJavaScriptエンジンまでは変えられませんよね。ちなみに、Internet ExplorerのJavaScriptエンジンはChakraと呼ばれています。

 

●概念実証

 ここでは、Internet Explorerを検出したらダイアログを出し、新しいMicrosoft Edgeのダウンロードサイトへリダイレクトさせる、といったJavaScriptコードを書いています。それ以外のブラウザは、違うメッセージダイアログが表示されます。

  1. Internet Explorer を立ち上げてください。(例えば IE11です。Edgeではありません!)

    f:id:reinforchu:20200212145141p:plain

    スクリーンショットの真ん中のアイコンが目的のInternet Explorerです。

  2. 私が用意したデモページを開きます - http://sandbox.hack.vet/ie/

    sandbox.hack.vet

    f:id:reinforchu:20200212145456p:plain

 まことにInternet Explorerであれば、「IEですよ。」といったalert()が出てきます。その後、マイクロソフトのサイトにリダイレクトします。

(リダイレクト先: https://support.microsoft.com/ja-jp/help/4501095/download-the-new-microsoft-edge-based-on-chromium )

 Internet Explorerではないブラウザの場合、次のようなalert()が出てきます。

f:id:reinforchu:20200212145817p:plain

 スクリーンキャプチャも撮影したので、手元に環境がない方はこちらをご覧ください。

http://sandbox.hack.vet/ie/IE_Checker.mp4

 音はありません。

  後になって思いましたが、デモページがちゃちなフィッシングサイトっぽいですね。当の本人は全くそんなことをする気はないですし、もちろんInternet Explorerに対してネガティブキャンペーンをする意図など毛頭ないです。

 

 ●サンプルコード

  ミニマムなサンプルコードは下記に示します。(cache-controlフィールドはおまけです)

◆index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="cache-control" content="no-cache, no-store">
        <meta http-equiv="pragma" content="no-cache">
        <meta name="expires" content="0">
    </head>
    <body>
        <script>�=0;alert(1)</script>
    </body>
</html>

f:id:reinforchu:20200212152337p:plain

  上記のindex.htmlをInternet Explorerで開くと、alert(1)が実行されます。(通常、ローカルから実行すると、スクリプト実行の確認ダイアログが出てきます)その他のFirefox, Chrome, EdgeにおいてはJavaScriptは実行されません。つまり、ブランクページと同等の画面になります。

 

●テクニック解説

 もし、文字エンコーディングに知見があるとするなら、既知のXSS攻撃手法と合わせて考えると良いかもしれません。今回は、これに関連する別件の記事にまとめて解説したいので、具体的な動作原理の解説は差し控えます。

 さて、このテクニックは、Internet Explorer以外のブラウザはJavaScriptコードのシンタックスエラーが発生する、という挙動を逆手に取ったものです。注目すべきはまさしく、縺�=0; この部分です。Unicodeで見てみると次のような文字列です。

f:id:reinforchu:20200212185519p:plain

 U+7E3AはUTF-8の文字コードをshift_jisで見るいわゆる文字化けでよく遭遇します。次にU+FFFDはSpecialsと呼ばれるブロックのREPLACEMENT CHARACTERです。これは、代替文字という意味で、文字コードを変更した時などに表現できない文字があった場合、この文字が使用されます。

 サンプルのコードでは、このUnicode二文字「縺�」を変数名として使用しています。これは基本的にはシンタックスエラーになるでしょう。変数名としてU+FFFDは使用が禁止されているので、当然シンタックスエラーとなり、そのJavaScriptコードは実行されません。しかし、Internet Explorerはどうやら動作が違うようです。

f:id:reinforchu:20200212195818p:plain

 ソースコードを表示すると、なんと当該部分が <script>膰削申=0;alert(1)</script> に変わっています。JavaScriptは 膰削申 という変数名は使用できますので、構文的には通ります。つまり、JavaScriptコードが実行されるということです。これは、文字エンコーディングが自動判別になった場合、EUCが選択されたため発生する現象です。Internet Explorerの文字エンコーディング自動判別は実行環境によっては変わる可能性があるため、必ずEUCになるとは限りません。しかしながら、Internet ExplorerのJavaScriptエンジンは変数名にU+FFFDを使用できるので、シンタックスエラーにならずにJavaScriptコードが実行されます。次にChromeではどのように表示されるでしょうか。

f:id:reinforchu:20200212200751p:plain

 “正しく”シンタックスエラーとなり、JavaScriptコードは実行されませんでした。冒頭にも述べましたが、以上のことから、Internet Explorer以外のブラウザはJavaScriptコードのシンタックスエラーが発生するが、Internet Explorerは勝手に変数名が変わり、正しい構文となってしまうため、JavaScriptコードが実行できることを基準として、Internet Explorerかそれ以外かを判定しています。

 ちなみに、「膰削申」は全く意味不明ですが、翻訳をかけてみると、肉を切るみたいな意味のようです。

 

 ●使い所

 念の為に申し上げておきますが、まさかこの記事のコードをコピペしてプロダクトに組み込もうと思っていませんか?だいぶBuggyなので実験程度に留めておいてください。また、別件で調べている事があり、良くなさそうだった場合、この記事を非公開にするかもしれません。

 

●参照情報

docs.microsoft.com

en.wikipedia.org

 

 以下、余談。

  ここ最近、文字コード、特にUnicodeに興味関心が高くあり、面白そうなことを試行錯誤しています。合成文字(Combining)がホットなキーワードです。所感ですが、文字コードとWebセキュリティは割と密接な関係があると思いました。是非、“文字”のテクニックを調べてみてください。