アカウント名:
パスワード:
どうみても仕様。こういうのをどや顔で脆弱性報告しちゃうのはどうかと思うし、受け付けちゃうのもびっくりする。日本のITスキルの水準がわかる事例。
インストーラの脆弱性なので。
どうみてもOSの脆弱性じゃないの?MSに報告しなきゃ(使命感)
Windows が使用する DLL 検索パス暗黙的なリンクと明示的なリンクの両方で、Windows は、Kernel32.dll や User32.dll などの "既知の DLL" を最初に検索します。 次に、以下に示す順序で DLL が検索されます。1.実行中のプロセスの実行形式モジュールがあるフォルダー。2.現在のフォルダー。3.Windows システム フォルダー。 このフォルダーへのパスは、GetSystemDirectory 関数が取得します。4.Windows ディレクトリ。 このフォルダーへのパスは、GetWindowsDirectory 関数が取得します。5.環境変数 PATH 内に記述されたフォルダー。
Windows が使用する DLL 検索パス
暗黙的なリンクと明示的なリンクの両方で、Windows は、Kernel32.dll や User32.dll などの "既知の DLL" を最初に検索します。 次に、以下に示す順序で DLL が検索されます。
1.実行中のプロセスの実行形式モジュールがあるフォルダー。2.現在のフォルダー。3.Windows システム フォルダー。 このフォルダーへのパスは、GetSystemDirectory 関数が取得します。4.Windows ディレクトリ。 このフォルダーへのパスは、GetWindowsDirectory 関数が取得します。5.環境変数 PATH 内に記述されたフォルダー。
MSが報告している内容をMSに報告してどうするのかw
いや、いくらなんでもその情報は古すぎ。(ネタかもしれないけど、一応)XP SP2以降はSafeDllSearchMode [microsoft.com]がデフォルトで有効なので、
1.実行中のプロセスの実行形式モジュールがあるフォルダー。2.Windows システム フォルダー。3.Windows ディレクトリ。4.現在のフォルダー。5.環境変数 PATH 内に記述されたフォルダー。
の順番です。
大昔のUnixにあったPATHに.を入れる慣習と同じくらい頭の悪い仕様に見えるんだが、気のせいかなあ。
そしてそのUnixでもさすがにLD_LIBRARY_PATHに.を入れるなんて暴挙は寡聞にして知らない。
> そしてそのUnixでもさすがにLD_LIBRARY_PATHに.を入れるなんて暴挙は寡聞にして知らない。shared libraryを自作しているときだけだな。
DLL Hell時代にシステムパスにあるDLLは互換性が不明だから必要なDLLは全部exeの隣に配置しておけば安心だねって文化がありまして。
Unix系にはずっとあるというか Unix というのか Linuxでの so って、かなり後になってから出来たもんだからね。利用方法は他のOSの失敗見て整理されてるところはある。
Winodws に関しては、最も初期から DLL が OS のAPIを提供するインターフェースなので完全にDLLを使わないというのは無理だけど、MFCだとか開発言語のランタイムは普通に静的リンクできる。.NET になってからは、厳密な署名でマイナーバージョンまで完全に一致しないとリンクしないとか、マイナーバージョンの違いは許すとか、互換あるかわからんけど、とりあえずリンクして動かしてみるけど、動くかはわからんってのが選べるようになってる。逆に静的なリンクは(公式には)なくなってる。
いや、今回の話はカレントディレクトリじゃないっすよ。exeと同一ディレクトリのほう。(カレントディレクトリはだいぶ前に優先順位が下げられてます)Windowsは大抵、実行ファイルを(PATHの通っていない)任意の場所に置くので、DLLを実行ファイルと同一ディレクトリから読めないと、アプリ固有のDLLが使えなくなります。(*nixなんかでも、「同一ディレクトリ中の別スクリプトを呼ぶの禁止」とかになったら困るよね?)
これについてはmacOSも同様なんだろうけど、あっちはそもそもapp形式の実体がディレクトリな上、バイナリ配布は大抵dmg(ディスクイメージ)で行うので、「同一ディレクトリ内に攻撃者のDLLが置かれる」という状況自体が発生しないのかも。
>(*nixなんかでも、「同一ディレクトリ中の別スクリプトを呼ぶの禁止」とかになったら困るよね?)
驚くべきことに、伝統的なUnixでは実行プロセス側から自分の実行ファイルがどのディレクトリにあるのか調べるAPIはそもそも存在しない。execve()で絶対パスを指定する形で起動されていたら自分の引数を見れば解決するのだが、そうでなければ$PATHを探すとかgetcwd()の結果を見るとかいった不確実な方法しかない。
実行ファイルの場所が調べられないってのはクソだと思う(実際、Linuxでは /proc の下を覗くと情報が取れるようになっている)けど、結果として「実行ファイルと同一ディレクトリの別スクリプトを呼ぶの禁止」なんて縛りは伝統的なUnixでは存在しえない、ということになる。
msiファイルを置いただけのフォルダからDLLを読む必要がどうしてあるんかね。仕様とは思えないが?
今回挙げられているMS製品のインストーラーは全てexe形式だと思います。msi形式のインストーラーも影響範囲に含まれるという情報を見つけられなかったのですが、どこで確認できますか?
MFC等のアプリで使用しているDLLを偽造してカレントに置いておけば、システムが勝手にカレントのDLLをロード(起動時に動的リンクされたライブラリを自動的に読み込む)してしまうのよ。
つまり、一切ランタイムを使わないでインストーラを作れって話になるんだけど。
システムディレクトリ等から読み込みたいのなら、そう指定すべきでは?元々カレントにあったDLLを上書きする、という話ならその通りですが。
動的リンクされたライブラリのロードは、OSがやります。その際、カレントディレクトリ、システムディレクトリの順で対象のDLLを探すので今回の話になるわけです。(動的リンクしたライブラリの読込場所は指定できない)
一応、動的リンクをやめて、全てのライブラリをloadlibraryで読み込む様にすれば、回避できるけど、普通はやらないね。(MFC等のクラスライブラリを使ってるとほぼ不可能だと思う)
一応。カレントディレクトリは「実行ファイルのディレクトリ」の意味で記載してます。
なるほど、普通にMFC等を使おうとするとそうコンパイルされるわけですね。LoadLibraryできちんと指定していすればいいとは聞いていたので、MS製品はやってるのだろうと思ってました。
>つまり、一切ランタイムを使わないでインストーラを作れって話になるんだけど。
https://micco.mars.jp/vul/2017/mhvi20170718.htm [micco.mars.jp]↑ここに詳しく載ってますが、KERNEL32.DLLやUSER32.DLL、またそれらから間接的に呼ばれるDLLであるNTDLL.DLLやSSPICLI.DLLすらヤバイので。KERNEL32.DLLを「使わない」のも「LoadLibraryで読む」のも不可能。USER32.DLLを「LoadLibraryで読む」のは可能っちゃ可能ですが、ものすげー面倒くさい。
拡張子がMSIなら、実行されるのはc:\windows\system32\msiexec.exe。ロードオーダーはEXEパス>カレントなので、たとえばMFC42.dllとかをダウンロードフォルダに置いても、c:\windows\system32\mfc42.dllとかに負けてしまうので該当しない、という話だよね。厳密にいえば、シリアルNOベリファイのためにカスタムDLLを読み込むようなMSIも作れたとは思うけど。
これって、exeやmsiを生でダウンロードさせるという慣習に問題があるのかも。zipとかで固めてあれば、当然解凍時に別ディレクトリ作るよね。だから、実行ファイルの同一ディレクトリに何かが紛れ込むことは基本的にないわけで。(解凍時に同一名のディレクトリが既にあったら混入の可能性はあるけど、さすがにそれは不用心すぎる)
昔はlzhとかzipで固めるのが普通だったと思うんだけど(cygwinのsetup.exeが生だったのに驚いた覚えが……)、いつの間にかexeを生で配ることが多くなってきたよね。その悪しき風習を改めるべきなのかもしれない。
もっとそれ以前の勝手にとりあえずダウンロード仕様が犯人だと思うんですよね。インジェクションの単体.dllがダウンロードフォルダに入り込まなければ問題は起きにくいので。
lzhやzipで固めていたのは、・消費帯域を減らすため・複数ファイルをまとめるため・ファイルが壊れていないかの破損チェックのためで、上2つは回線の高速化で自己解凍で済んで、破損チェックも電子署名すれば生exeで出来るからかも。
次期WindowsでマニフェストにシステムディレクトリからしかDLL読み込まないオプションとか付くのかね。そいつがディレクトリを掘って自己解凍すれば大分緩和されるかな。
次期Windows を期待せんでも、昔から 読込むDLLの署名要求できる。署名が違ったら同じバージョンでも読込まずに別のを探させることが出来る。
アプリの提供側が、その設定をやってるかどうかってことだけど、Windows って開発者がプラットホームの事を知らなさすぎるってケースが多いので、やってないが多いだろうな。
次期WindowsでマニフェストにシステムディレクトリからしかDLL読み込まないオプションとか付くのかね。
ほんとそれ欲しい。SetProcessMitigationPolicy [microsoft.com]で指定できるもの、全部マニフェストファイルで指定できるようになってくれたら助かる(今回のに関係するのはProcessImageLoadPolicyのPreferSystem32Images)。
今回の件に特定するのでなければ仕様そのものが脆弱である場合もあるので、仕様だから脆弱ではないということは言えない。
これは、脆弱と言ってもいいような気もするけど、じゃあどうするのって言うと困るなぁ
信用置けないフォルダはDLLの読み込みを止めたら良いのかね・・・
UAC回避できるんだったら脆弱性だよ。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
海軍に入るくらいなら海賊になった方がいい -- Steven Paul Jobs
イミフ (スコア:0)
どうみても仕様。こういうのをどや顔で脆弱性報告しちゃうのはどうかと思うし、受け付けちゃうのもびっくりする。日本のITスキルの水準がわかる事例。
Re:イミフ (スコア:2)
インストーラの脆弱性なので。
Re: (スコア:0)
どうみてもOSの脆弱性じゃないの?
MSに報告しなきゃ(使命感)
Re: (スコア:0)
MSが報告している内容をMSに報告してどうするのかw
Re: (スコア:0)
いや、いくらなんでもその情報は古すぎ。(ネタかもしれないけど、一応)
XP SP2以降はSafeDllSearchMode [microsoft.com]がデフォルトで有効なので、
1.実行中のプロセスの実行形式モジュールがあるフォルダー。
2.Windows システム フォルダー。
3.Windows ディレクトリ。
4.現在のフォルダー。
5.環境変数 PATH 内に記述されたフォルダー。
の順番です。
Re:イミフ (スコア:2, すばらしい洞察)
大昔のUnixにあったPATHに.を入れる慣習と同じくらい頭の悪い仕様に見えるんだが、気のせいかなあ。
そしてそのUnixでもさすがにLD_LIBRARY_PATHに.を入れるなんて暴挙は寡聞にして知らない。
Re:イミフ (スコア:2)
> そしてそのUnixでもさすがにLD_LIBRARY_PATHに.を入れるなんて暴挙は寡聞にして知らない。
shared libraryを自作しているときだけだな。
Re: (スコア:0)
DLL Hell時代にシステムパスにあるDLLは互換性が不明だから必要なDLLは全部exeの隣に配置しておけば安心だねって文化がありまして。
Re: (スコア:0)
UNIX系OSにはずっと昔からあるのに
カレントディレクトリから動的ロードしてしまう問題の直接の解決ではないけど
Re: (スコア:0)
Unix系にはずっとあるというか Unix というのか Linuxでの so って、かなり後になってから出来たもんだからね。利用方法は他のOSの失敗見て整理されてるところはある。
Winodws に関しては、最も初期から DLL が OS のAPIを提供するインターフェースなので完全にDLLを使わないというのは無理だけど、MFCだとか開発言語のランタイムは普通に静的リンクできる。
.NET になってからは、厳密な署名でマイナーバージョンまで完全に一致しないとリンクしないとか、マイナーバージョンの違いは許すとか、互換あるかわからんけど、とりあえずリンクして動かしてみるけど、動くかはわからんってのが選べるようになってる。
逆に静的なリンクは(公式には)なくなってる。
Re: (スコア:0)
いや、今回の話はカレントディレクトリじゃないっすよ。exeと同一ディレクトリのほう。
(カレントディレクトリはだいぶ前に優先順位が下げられてます)
Windowsは大抵、実行ファイルを(PATHの通っていない)任意の場所に置くので、DLLを実行ファイルと同一ディレクトリから読めないと、アプリ固有のDLLが使えなくなります。
(*nixなんかでも、「同一ディレクトリ中の別スクリプトを呼ぶの禁止」とかになったら困るよね?)
これについてはmacOSも同様なんだろうけど、あっちはそもそもapp形式の実体がディレクトリな上、バイナリ配布は大抵dmg(ディスクイメージ)で行うので、「同一ディレクトリ内に攻撃者のDLLが置かれる」という状況自体が発生しないのかも。
Re: (スコア:0)
>(*nixなんかでも、「同一ディレクトリ中の別スクリプトを呼ぶの禁止」とかになったら困るよね?)
驚くべきことに、伝統的なUnixでは実行プロセス側から自分の実行ファイルがどのディレクトリにあるのか調べるAPIはそもそも存在しない。execve()で絶対パスを指定する形で起動されていたら自分の引数を見れば解決するのだが、そうでなければ$PATHを探すとかgetcwd()の結果を見るとかいった不確実な方法しかない。
実行ファイルの場所が調べられないってのはクソだと思う(実際、Linuxでは /proc の下を覗くと情報が取れるようになっている)けど、結果として「実行ファイルと同一ディレクトリの別スクリプトを呼ぶの禁止」なんて縛りは伝統的なUnixでは存在しえない、ということになる。
Re: (スコア:0)
でも動いてるバイナリをmvで移動してもプロセスはそのまま動作し続ける(それどころかrmで消してもよい)のがUnixのセマンティクスだから実行ファイルの場所なんか知ってもしゃーないという気が
Re:イミフ (スコア:1)
msiファイルを置いただけのフォルダからDLLを読む必要がどうしてあるんかね。
仕様とは思えないが?
Re:イミフ (スコア:1)
今回挙げられているMS製品のインストーラーは全てexe形式だと思います。
msi形式のインストーラーも影響範囲に含まれるという情報を見つけられなかったのですが、どこで確認できますか?
Re: (スコア:0)
MFC等のアプリで使用しているDLLを偽造してカレントに置いておけば、システムが勝手にカレントのDLLをロード(起動時に動的リンクされたライブラリを自動的に読み込む)してしまうのよ。
つまり、一切ランタイムを使わないでインストーラを作れって話になるんだけど。
Re: (スコア:0)
システムディレクトリ等から読み込みたいのなら、そう指定すべきでは?
元々カレントにあったDLLを上書きする、という話ならその通りですが。
Re: (スコア:0)
動的リンクされたライブラリのロードは、OSがやります。
その際、カレントディレクトリ、システムディレクトリの順で対象のDLLを探すので今回の話になるわけです。(動的リンクしたライブラリの読込場所は指定できない)
一応、動的リンクをやめて、全てのライブラリをloadlibraryで読み込む様にすれば、回避できるけど、普通はやらないね。(MFC等のクラスライブラリを使ってるとほぼ不可能だと思う)
Re: (スコア:0)
一応。
カレントディレクトリは「実行ファイルのディレクトリ」の意味で記載してます。
Re: (スコア:0)
なるほど、普通にMFC等を使おうとするとそうコンパイルされるわけですね。
LoadLibraryできちんと指定していすればいいとは聞いていたので、MS製品はやってるのだろうと思ってました。
Re: (スコア:0)
>つまり、一切ランタイムを使わないでインストーラを作れって話になるんだけど。
https://micco.mars.jp/vul/2017/mhvi20170718.htm [micco.mars.jp]
↑ここに詳しく載ってますが、KERNEL32.DLLやUSER32.DLL、またそれらから間接的に呼ばれるDLLであるNTDLL.DLLやSSPICLI.DLLすらヤバイので。
KERNEL32.DLLを「使わない」のも「LoadLibraryで読む」のも不可能。
USER32.DLLを「LoadLibraryで読む」のは可能っちゃ可能ですが、ものすげー面倒くさい。
Re: (スコア:0)
拡張子がMSIなら、実行されるのはc:\windows\system32\msiexec.exe。ロードオーダーはEXEパス>カレントなので、たとえばMFC42.dllとかをダウンロードフォルダに置いても、c:\windows\system32\mfc42.dllとかに負けてしまうので該当しない、という話だよね。
厳密にいえば、シリアルNOベリファイのためにカスタムDLLを読み込むようなMSIも作れたとは思うけど。
Re: (スコア:0)
これって、exeやmsiを生でダウンロードさせるという慣習に問題があるのかも。
zipとかで固めてあれば、当然解凍時に別ディレクトリ作るよね。だから、実行ファイルの同一ディレクトリに何かが紛れ込むことは基本的にないわけで。
(解凍時に同一名のディレクトリが既にあったら混入の可能性はあるけど、さすがにそれは不用心すぎる)
昔はlzhとかzipで固めるのが普通だったと思うんだけど(cygwinのsetup.exeが生だったのに驚いた覚えが……)、いつの間にかexeを生で配ることが多くなってきたよね。
その悪しき風習を改めるべきなのかもしれない。
Re: (スコア:0)
もっとそれ以前の勝手にとりあえずダウンロード仕様が犯人だと思うんですよね。
インジェクションの単体.dllがダウンロードフォルダに入り込まなければ問題は起きにくいので。
lzhやzipで固めていたのは、
・消費帯域を減らすため
・複数ファイルをまとめるため
・ファイルが壊れていないかの破損チェックのため
で、上2つは回線の高速化で自己解凍で済んで、
破損チェックも電子署名すれば生exeで出来るからかも。
次期WindowsでマニフェストにシステムディレクトリからしかDLL読み込まないオプションとか付くのかね。
そいつがディレクトリを掘って自己解凍すれば大分緩和されるかな。
Re: (スコア:0)
次期Windows を期待せんでも、昔から 読込むDLLの署名要求できる。署名が違ったら同じバージョンでも読込まずに別のを探させることが出来る。
アプリの提供側が、その設定をやってるかどうかってことだけど、Windows って開発者がプラットホームの事を知らなさすぎるってケースが多いので、やってないが多いだろうな。
Re: (スコア:0)
次期WindowsでマニフェストにシステムディレクトリからしかDLL読み込まないオプションとか付くのかね。
ほんとそれ欲しい。SetProcessMitigationPolicy [microsoft.com]で指定できるもの、全部マニフェストファイルで指定できるようになってくれたら助かる(今回のに関係するのはProcessImageLoadPolicyのPreferSystem32Images)。
Re: (スコア:0)
今回の件に特定するのでなければ
仕様そのものが脆弱である場合もあるので、仕様だから脆弱ではないということは言えない。
これは、脆弱と言ってもいいような気もするけど、
じゃあどうするのって言うと困るなぁ
信用置けないフォルダはDLLの読み込みを止めたら良いのかね・・・
Re: (スコア:0)
UAC回避できるんだったら脆弱性だよ。