Windows Installer手引書 Extra.1

# Extra.1 インストーラーの脆弱性
## 概要
今回は番外として、インストーラーの脆弱性を取り上げます。

## インストーラーセキュリティの動向
[JVN(Japan Vulnerability Notes)](https://jvn.jp/)の新着リストは一般に流通しているPCアプリの脆弱性の最新情報を確認するのに役立ちます。情報が日本語であるところもありがたいところです。最近立て続けにインストーラー関連のレポートが続いたので、インストーラーの脆弱性について調べてみました。JVNの検索機能を使って「インストーラ」でフィルタすると、この記事を執筆している時点で「DLL読み込みに関する脆弱性[^1]」が180件中100件あり、圧倒的に多いでので今回の記事では主にこれを取り上げます。

## 対策
JVNのレポート[「Windows アプリケーションによる DLL 読み込みやコマンド実行に関する問題」](http://jvn.jp/ta/JVNTA91240916/index.html)にあるように、主なインストーラー作成ツールは対応が済んでいるので、最新版に差し替えることが対策となります。ここにあるリンク先をじっくり読めば、どのような問題なのか、インストーラー作成ツールがどのような対策をしているのか、理解できるようになっています。JVNでDLL読み込みに関する脆弱性のレポートが一気に増えたのも、各インストーラー作成ツールの対策が同時に進められたからなのでしょう[^2]。

## 問題の背景
そもそもこの問題が起きる理由は、Windowsがプログラムを動かす仕組みそのものにあります。私は、下記2点に問題が集約されていると考えています。

- インストーラーを含めた全てのプログラムは、起動のために既知のDLL[^3]を読み込む必要がある
- 一番最初にDLLを探す場所がプログラムが置かれたフォルダである

そしてインストーラーにとって不利なのは、現代のインストーラーの多くがインターネットを経由してダウンロードフォルダに格納される、ということです。このため、ダウンロードフォルダからインストーラーが起動される可能性が高まり、攻撃者が悪意あるDLLをダウンロードフォルダに置いてしまえば[^4]攻撃が成立します。ほとんどのインストーラーが管理者権限を必要とするので、攻撃者は何でもやり放題になってしまいます。

こういった事情から、各インストーラー作成ツールでは、プログラムが置かれたフォルダとカレントフォルダをデフォルトのDLL検索順序から削除する対策を行っています。

## セットアップランチャーの脆弱性
ここから私の感覚的に、情報の確度が少し下がります。とはいえ、あちこちに情報があるので触れておきます。守っておいた方が無難、程度の話しではないかと思います。

Windows Installerを使ったインストーラーでは、Windows Installerの仕様の制約からセットアップランチャーと共に配布されることが多くあります。先の各インストーラー作成ツールが行った脆弱性対策の中に、セットアップランチャーのファイル名に"setup.exe"を使うな、というものがあります。"setup.exe"という名前のプログラムを起動すると、アプリケーション互換性ツールの１機能である"Shim"を介して**必要もないのに[^5]OSが勝手に**version.dll, uxtheme.dllなどのDLLを読み込む、という仕様があるそうです([Prevent DLL Hijacking Burn with Clean Room](http://wixtoolset.org/development/wips/5184-burn-clean-room/)、[Installer Vulnerability](https://www.advancedinstaller.com/dll-hijacking.html)、[Demystifying Shims – or – Using the App Compat Toolkit to make your old stuff work with your new stuff](https://blogs.technet.microsoft.com/askperf/2011/06/17/demystifying-shims-or-using-the-app-compat-toolkit-to-make-your-old-stuff-work-with-your-new-stuff/)等参照)。例えば、偽のVERSION.DLLをsetup.exeと同じフォルダに置くと、偽のDLLが読み込まれるそうです。そして、唯一の対策が、"Setup.exe"というファイル名を使わないことである、ということです。

歯切れの悪い書き方で済みません・・・いや、別にどうしても"setup.exe"というファイル名が使いたいわけではないのですが、プログラムが置かれたフォルダとカレントフォルダをデフォルトのDLL検索順序から削除しているんだったら影響受けない気がするのですが、"Shim"はDLL読み込みの仕組みが違うんでしょうか。いまだに論理的、仕組み的な裏付けが見つけられないので、ご存知の方は情報をいただけるとありがたいです。

## DLL のプリロード攻撃に備える
セットアップランチャーがインストール処理をせず、単にmsiexecを起動するだけなら、セットアップランチャーに管理者権限を付けない方が安全です。セットアップランチャーが偽DLLを読み込んでしまっても、重要なシステム領域に影響を及ぼしません。

要するに、偽のDLLが読み込まれると、際限なく攻撃の手法が広がる、ということですね。このあたりになってくると、2重3重の防御の話しになってきます。

## インターネットからダウンロードされたデータファイルを開く
インストーラーとは直接関係ありませんが、DLLの検索順を原因とした脆弱性の懸念について１つ解説しておきます。データファイルの拡張子をレジストリに登録すると、指定したプログラムでデータを開けるようになります。この場合、データファイルをダブルクリックして開くと、データファイルが置かれたフォルダがカレントフォルダとなります。データファイルをダウンロードフォルダに置いたまま利用すると、ダウンロードフォルダをカレントフォルダとしてしまうため、ダウンロードフォルダに置かれた偽のDLLを読み込む懸念がありました。しかしこれは、Windows XP Service Pack 2以降で、カレントフォルダがシステムフォルダよりもあとに検索されるよう変更されたため、問題が解消されました。[^6]

## インストーラーから利用できるVBScriptやJScriptについて
Windowsの開発者にとってVBScriptやJScriptは「手軽に利用できる便利なツール」ですが、システム管理者にとっては「ウィルスを媒介する厄介者」です。特にインストーラー内でCustom Actionを記述する場合、標準的に利用できるスクリプト言語はVBScriptとJScriptだけです。ここでインストーラー作成者は悩むことになります。VBScriptやJScriptでCustom Actionを記述したインストーラーは、セキュリティ的に大丈夫だろうか、と。

私の意見ですが、スクリプトをMSIのテーブル内に書く（Custom ActionのType37やType38）など、外部から乗っ取られない工夫ができるなら安全ではないかと思います。しかし問題はこの点ではなく、システム管理者がVBScriptやJScriptを動かせないようにできる、ということです。そうすると、インストーラーが期待通り動かない環境が存在することになります。結論としては、「製品には使わないほうが良い」ということになります。C言語でCustom Actionを書くのが最も無難ではないでしょうか。

・・・と言っておきながら、私はデバッグ用途でよくVBScriptを使います。例えば、下記のようなPropertyの内容を確認するコードはよく使います。

```xml
 1: <CustomAction Id="prPropAct" Script="vbscript">
 2:   <![CDATA[MsgBox(Session.Property("ProductCode"))]]>
 3: </CustomAction>
```

ただし、製品に紛れ込ませないよう注意が必要です。

[**目次へ**](https://qiita.com/tohshima/items/dc4c4721d50a2ad70c7a)

[^1]: 他に「任意のコードを実行される脆弱性」や「DLL をプリロードされる脆弱性」なども加えています。
[^2]: 言うまでもなく、JVNで報告されるレポートは対策が済んだものです。このレポートの脆弱性は、まず「インストーラー作成ツールの対策」、その次に「それを使うインストーラーの対策」と順に対策を行った結果、ようやくレポートされたことになります。早期に不具合に対応するために、インストーラー作成ツールのベンダーが出す情報は定期的にチェックする方が良いと思います。
[^3]: Windowsのシステムで使われるDLLは当然固有のファイル名を持っています。
[^4]: 攻撃者がダウンロードフォルダに悪意あるDLLを置けなければ攻撃も成立しない、という言い方もできます。
[^5]: 必要もないのに読み込む、だけだったら悪意のあるコードをどのように起動するのでしょうね。
[^6]: ずいぶん昔の話ですが、ネット上に古い情報が残っているかもしれないので、念のため書いておきます。