アカウント名:
パスワード:
要するに、インストーラーがKnownDLLsにもSide-by-Sideアセンブリにも含まれないDLLを不用意に使っていたので、先にそのDLLと同名のファイルをダウンロードさせることができれば、ダウンロードフォルダからインストーラーを実行したときに、正規のインストーラーであるにもかかわらず任意のバイナリを読み込ませることができるわけだ。デスクトップアプリのインストーラーは通常管理者権限を持つから、確かに「攻撃手順は複雑だが、成功するとシステムを完全に乗っ取られる可能性がある」な。
もっとも攻撃の現実性はかなり疑わしいけど。これが成功する(リテラシーのユーザーを想定する)んだったら、もっとシンプルに改ざんしたインストーラーを実行させるだけで同じくらい成功すると思う。インストーラーの署名を確認すればいい? VirtualBoxのインストーラーは署名がSHA-1のままだから、ダウンロード時に表示されるダイアログでは署名されていないのと見分けがつかないしSmartScreenにブロックされてるぞ。マジで大丈夫かOracle。
>SetDllDirectory(_T(""));の一行を書いておけば防げる攻撃なのにまぁこの一行が必要なのはカレントディレクトリがdllの検索パスに含まれているという歴史的経緯のせいなんだが
> >SetDllDirectory(_T(""));> の一行を書いておけば防げる攻撃なのに
いや、以下の2点の理由により防げない。・ダウンロードフォルダーから実行すると、ダウンロードフォルダーがDLL検索パスで最優先の「アプリケーションのディレクトリ」になってしまう。これはSetDllDirectoryでは変更できない。・そもそも、暗黙にリンクされるDLLはバイナリが1バイトも実行されないうちにロードさせるので、プログラムコードに何か書いて防ぐことはできない。
対策としては、・インストーラーをexeにせず、MSIを使う。・どうしてもexeにする必要があるなら、KnownDLLsに含まれるDLL以外には暗黙にリンクしない。KnownDLLsはWindowsのバージョンによって微妙に異なるので、あまりギリギリを狙わず出来る限り暗黙にリンクするDLLを減らしたほうがいい(修正されたJavaのインストーラーはkernel32.dllとadvapi32.dllにのみリンクしている)。・comctl32.dllはKnownDLLsに含まれないけど、manifestでバージョン6.0の使用を宣言していれば問題ない(Side-by-Sideアセンブリも通常のDLL検索パスを無視する)。・明示的リンクするときは、システムディレクトリのフルパスを指定するか、LoadLibraryExにLOAD_LIBRARY_SEARCH_SYSTEM32を指定する。・CRTはバージョンなしのmsvcrtを使うか、静的リンクする(インストーラーなら言われるまでもなくそうなっていると思うけど)。
ユーザー側の対策は・インストーラーをダウンロードフォルダーから直接実行せず、ほかにファイルがないディレクトリに移動してから実行する。
> ・明示的リンクするときは、システムディレクトリのフルパスを指定するか、
これだけだと指定されたDLLが別のDLLを暗黙にリンクしているとき危険だった。LOAD_WITH_ALTERED_SEARCH_PATHと、あと結局SetDllDirectoryもいるな。LOAD_LIBRARY_SEARCH_SYSTEM32が使えるならそれが一番安全だ。
SetDllDirectory("")はアプリケーション側の対策ですが、レジストリの設定で、すべてのアプリケーションに対してカレントディレクトリを検索させないようにユーザ側で対策できます。
DLL 検索パス アルゴリズムを制御する新しい CWDIllegalInDllSearch レジストリ エントリについてhttps://support.microsoft.com/ja-jp/kb/2264107 [microsoft.com]
私は長年この設定で使っていますが、今のところ問題が起きるアプリに遭遇したことはないです。
だからこの問題はカレントディレクトリを検索させないようにしても防げないって。「大昔に発覚しているDLLハイジャックの問題に対応していないアホなインストーラーがまだあるの?」くらいに思っていて正しい対策が周知されていないとしたら、それ自体問題だな。
何となく、TCP_TIMEWAIT_LENの件 [linux.srad.jp]を思い出しました。
あーそりゃそうか。失礼。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
弘法筆を選ばず、アレゲはキーボードを選ぶ -- アレゲ研究家
DLLハイジャック (スコア:0)
要するに、インストーラーがKnownDLLsにもSide-by-Sideアセンブリにも含まれないDLLを不用意に使っていたので、先にそのDLLと同名のファイルをダウンロードさせることができれば、ダウンロードフォルダからインストーラーを実行したときに、正規のインストーラーであるにもかかわらず任意のバイナリを読み込ませることができるわけだ。デスクトップアプリのインストーラーは通常管理者権限を持つから、確かに「攻撃手順は複雑だが、成功するとシステムを完全に乗っ取られる可能性がある」な。
もっとも攻撃の現実性はかなり疑わしいけど。これが成功する(リテラシーのユーザーを想定する)んだったら、もっとシンプルに改ざんしたインストーラーを実行させるだけで同じくらい成功すると思う。インストーラーの署名を確認すればいい? VirtualBoxのインストーラーは署名がSHA-1のままだから、ダウンロード時に表示されるダイアログでは署名されていないのと見分けがつかないしSmartScreenにブロックされてるぞ。マジで大丈夫かOracle。
Re: (スコア:0)
>SetDllDirectory(_T(""));
の一行を書いておけば防げる攻撃なのに
まぁこの一行が必要なのはカレントディレクトリがdllの検索パスに含まれているという歴史的経緯のせいなんだが
Re:DLLハイジャック (スコア:4, 参考になる)
> >SetDllDirectory(_T(""));
> の一行を書いておけば防げる攻撃なのに
いや、以下の2点の理由により防げない。
・ダウンロードフォルダーから実行すると、ダウンロードフォルダーがDLL検索パスで最優先の「アプリケーションのディレクトリ」になってしまう。これはSetDllDirectoryでは変更できない。
・そもそも、暗黙にリンクされるDLLはバイナリが1バイトも実行されないうちにロードさせるので、プログラムコードに何か書いて防ぐことはできない。
対策としては、
・インストーラーをexeにせず、MSIを使う。
・どうしてもexeにする必要があるなら、KnownDLLsに含まれるDLL以外には暗黙にリンクしない。KnownDLLsはWindowsのバージョンによって微妙に異なるので、あまりギリギリを狙わず出来る限り暗黙にリンクするDLLを減らしたほうがいい(修正されたJavaのインストーラーはkernel32.dllとadvapi32.dllにのみリンクしている)。
・comctl32.dllはKnownDLLsに含まれないけど、manifestでバージョン6.0の使用を宣言していれば問題ない(Side-by-Sideアセンブリも通常のDLL検索パスを無視する)。
・明示的リンクするときは、システムディレクトリのフルパスを指定するか、LoadLibraryExにLOAD_LIBRARY_SEARCH_SYSTEM32を指定する。
・CRTはバージョンなしのmsvcrtを使うか、静的リンクする(インストーラーなら言われるまでもなくそうなっていると思うけど)。
ユーザー側の対策は
・インストーラーをダウンロードフォルダーから直接実行せず、ほかにファイルがないディレクトリに移動してから実行する。
Re: (スコア:0)
> ・明示的リンクするときは、システムディレクトリのフルパスを指定するか、
これだけだと指定されたDLLが別のDLLを暗黙にリンクしているとき危険だった。LOAD_WITH_ALTERED_SEARCH_PATHと、あと結局SetDllDirectoryもいるな。LOAD_LIBRARY_SEARCH_SYSTEM32が使えるならそれが一番安全だ。
Re: (スコア:0)
SetDllDirectory("")はアプリケーション側の対策ですが、レジストリの設定で、
すべてのアプリケーションに対してカレントディレクトリを検索させないようにユーザ側で対策できます。
DLL 検索パス アルゴリズムを制御する新しい CWDIllegalInDllSearch レジストリ エントリについて
https://support.microsoft.com/ja-jp/kb/2264107 [microsoft.com]
私は長年この設定で使っていますが、今のところ問題が起きるアプリに遭遇したことはないです。
Re: (スコア:0)
だからこの問題はカレントディレクトリを検索させないようにしても防げないって。
「大昔に発覚しているDLLハイジャックの問題に対応していないアホなインストーラーがまだあるの?」くらいに思っていて正しい対策が周知されていないとしたら、それ自体問題だな。
Re: (スコア:0)
何となく、TCP_TIMEWAIT_LENの件 [linux.srad.jp]を思い出しました。
Re: (スコア:0)
あーそりゃそうか。失礼。