none
アプリケーション(EXE)におけるATL の脆弱性について RRS feed

  • 質問

  • VC++2008

    現在、Windowsファイアウォールの制御を行うアプリケーション(拡張子がEXE)の開発を行っています。この、アプリケーションを実行すると「ATL.DLL」がロードされているのでATL の脆弱性(MS09-035)に該当するか調査を行っています。
    このアプリケーションを開発するにあたってCOMのOCXやActiveX,コンポーネントは使用せずにPlatformSDKのクラスやAPIを直接使用しています。ATLのクラスを使用しているのは、CComBSTR(BSTRのラッパークラス)くらいです。
    以下のサイトの影響をうけるかどうかのフローを見ると該当しないように思います。
    http://msdn.microsoft.com/ja-jp/visualc/ee309358.aspx

    アプリケーションの場合も脆弱性に該当するのでしょうか?
    ご存じの方がいらっしゃいましたらアドバイスをお願いします。

    よろしくお願いします。
    2009年8月3日 15:29

回答

  • ATLだけの話のように書かれていますが,
    修正されたソースと前のものを比べてみると,
    脆弱性の本質はATLの仕組みそのものではなく,
    ATL を使っていなくても
    Variant型で IStreamインタフェースを扱っている 場合で,
    型 や CLSID を,前もって想定したものと比べてから扱う
    ようにしていない場合は,
    外部から(COMで言うところの)ストリームを受け取る場合は
    影響を受ける可能性がありそうですね。

    そもそもATLの実装だけに限って起きる話ではないので,
    ActiveXコントロールに限った話ではないです。
    なので,
    COM仕様を公開していない,平のアプリでも
    実装しだいでは影響がありますね。
    COM仕様になっているもので,
    IE上にロードされるものは,危険が高いってだけです。



    稍丼 / yayadon
    • 編集済み yayadon 2009年8月5日 5:09 "Variant型 で" を削除<del>
    • 回答としてマーク 高橋 春樹 2009年8月12日 2:23
    2009年8月4日 14:44
  • > IStreamインタフェース のreadメソッドにてデータを読み取るというような
    > イメージで考えればよいのでしょうか?

    そのタイミングです。

    ストリームを送る側は,
    IPersistStream::GetClassID -> WriteClassStm関数 -> IPersistStream::Save
    の流れか,
    ヘルパー関数の OleSaveToStream を呼び出して,
    COMオブジェクトの CLSID をストリーム(に埋め込ん)で渡せます。

    で,
    ATL での今回該当するマクロやメソッドを使っていないとしても,
    読み出すときに,楽をするために,
    ヘルパー関数の OleLoadFromStream を呼び出している場合があります。

    ※void** ppvObj ポインタのポインタは,このときに受け取りに指定できるのは
    受け取りに使用するインタフェースポインタの REFIID だけということに注目

    呼び出しの結果,
    ストリームから,実際に作成されたCOMオブジェクトのインスタンスからの
    指定したインタフェースへのポインタを取得できます。

    で,よく考えてみると,
    そのインタフェースの REFIID が
    IUnknown や IDispatch インタフェースの場合,
    ストリームから作成されたインスタンスが
    自分が想定していたクラスのインスタンスからの インタフェースポインタとは限らないですよね?

    なので,
    ヘルパー関数 OleLoadFromStream を使っている場合は,
    呼び出す前に,
    ReadClassStm関数 でストリームから CLSID を取得して,
    想定した CLSID になっているか?を確認する必要があります。


    ヘルパー関数を使っていない場合でも,
    ストリームから ReadClassStm関数 を呼び出したときに,
    想定した CLSID か?を確認して
    CoCreateInstance(Ex)
    (or CoGetClassObject -> IClassFactory::CreateInstance)
    へ進まないといけません。


    このことは,以下のことに似ています。

    メモリ上のバッファをぺろ~んとコピーする時,
    今は,サイズを指定しないといけないですよね?

    それと同じで
    ストリームからCOMをインスタンス化する時は,
    CLSID の確認がいつでも必要ってことです。

    ATL に限った話ではないのはそのためです。



    > もしそうであれば、修正前と修正後のソースを参照することができるのでしょうか?

    ATL のソースは,ヘッダーの中に実装も書かれています。
    ふつうに使っているヘッダーの中を見ればわかります。

    すでにパッチをあててしまっていると思うので
    修正前のものはわからないですが,

    vtExpected
    cclsidAllowed
    ClassesAllowedInStream (これは クラス(union))

    を検索すれば,該当箇所は分かります。
    (たぶん,漏れはないと思うけど確認したわけではありません)

    旧ソースを取ってある場合は,
    WinDiff で違いを確認できます。


    追記&修正:
    上でVariant型と書きましたが,
    Variant型 を使用しているかどうかは,
    よく考えてみると,今回の件とは直接は関係なかったです。
    一番上のレスでの発言を訂正しておきます。




    稍丼 / yayadon
    2009年8月5日 1:12
  • あと,
    MS09-04
    http://www.microsoft.com/japan/technet/security/bulletin/ms09-034.mspx
    の方もATLの脆弱性絡みと書かれていますが,
    こちらは,
    MS内部だけで使われているATLのプライベートバージョンの
    タイプミスから来ているという話
    http://blogs.msdn.com/sdl/archive/2009/07/28/atl-ms09-035-and-the-sdl.aspx
    だそう なので
    公開されているATLとは関係ないんじゃないかと思います。

    稍丼 / yayadon
    2009年8月5日 3:09

すべての返信

  • ATLだけの話のように書かれていますが,
    修正されたソースと前のものを比べてみると,
    脆弱性の本質はATLの仕組みそのものではなく,
    ATL を使っていなくても
    Variant型で IStreamインタフェースを扱っている 場合で,
    型 や CLSID を,前もって想定したものと比べてから扱う
    ようにしていない場合は,
    外部から(COMで言うところの)ストリームを受け取る場合は
    影響を受ける可能性がありそうですね。

    そもそもATLの実装だけに限って起きる話ではないので,
    ActiveXコントロールに限った話ではないです。
    なので,
    COM仕様を公開していない,平のアプリでも
    実装しだいでは影響がありますね。
    COM仕様になっているもので,
    IE上にロードされるものは,危険が高いってだけです。



    稍丼 / yayadon
    • 編集済み yayadon 2009年8月5日 5:09 "Variant型 で" を削除<del>
    • 回答としてマーク 高橋 春樹 2009年8月12日 2:23
    2009年8月4日 14:44
  • yayadonさん 貴重な情報ありがとうございます。

    開発中のアプリは、Variant型のIStreamインタフェースは使用していないということと、ファイアウォールからのポート情報の読み込み,書き込みを行うアプリであることから影響を受ける確率としては低いと考えています。
    外部からストリームを受け取るというのは、IStreamインタフェースのreadメソッドにてデータを読み取るというようなイメージで考えればよいのでしょうか?IStreamインタフェースについては使用したことがない為、イメージがよくつかめませんでした。

    >修正されたソースと前のものを比べてみると,
    >脆弱性の本質はATLの仕組みそのものではなく,
     これは、パッチで修正される部分についての修正前と修正後のソースということでしょうか?もしそうであれば、修正前と修正後のソースを参照することができるのでしょうか?

    度々、ご質問してしまい申し訳ありませんが、よかったら情報の提供をお願いします。

    2009年8月4日 15:43
  • > IStreamインタフェース のreadメソッドにてデータを読み取るというような
    > イメージで考えればよいのでしょうか?

    そのタイミングです。

    ストリームを送る側は,
    IPersistStream::GetClassID -> WriteClassStm関数 -> IPersistStream::Save
    の流れか,
    ヘルパー関数の OleSaveToStream を呼び出して,
    COMオブジェクトの CLSID をストリーム(に埋め込ん)で渡せます。

    で,
    ATL での今回該当するマクロやメソッドを使っていないとしても,
    読み出すときに,楽をするために,
    ヘルパー関数の OleLoadFromStream を呼び出している場合があります。

    ※void** ppvObj ポインタのポインタは,このときに受け取りに指定できるのは
    受け取りに使用するインタフェースポインタの REFIID だけということに注目

    呼び出しの結果,
    ストリームから,実際に作成されたCOMオブジェクトのインスタンスからの
    指定したインタフェースへのポインタを取得できます。

    で,よく考えてみると,
    そのインタフェースの REFIID が
    IUnknown や IDispatch インタフェースの場合,
    ストリームから作成されたインスタンスが
    自分が想定していたクラスのインスタンスからの インタフェースポインタとは限らないですよね?

    なので,
    ヘルパー関数 OleLoadFromStream を使っている場合は,
    呼び出す前に,
    ReadClassStm関数 でストリームから CLSID を取得して,
    想定した CLSID になっているか?を確認する必要があります。


    ヘルパー関数を使っていない場合でも,
    ストリームから ReadClassStm関数 を呼び出したときに,
    想定した CLSID か?を確認して
    CoCreateInstance(Ex)
    (or CoGetClassObject -> IClassFactory::CreateInstance)
    へ進まないといけません。


    このことは,以下のことに似ています。

    メモリ上のバッファをぺろ~んとコピーする時,
    今は,サイズを指定しないといけないですよね?

    それと同じで
    ストリームからCOMをインスタンス化する時は,
    CLSID の確認がいつでも必要ってことです。

    ATL に限った話ではないのはそのためです。



    > もしそうであれば、修正前と修正後のソースを参照することができるのでしょうか?

    ATL のソースは,ヘッダーの中に実装も書かれています。
    ふつうに使っているヘッダーの中を見ればわかります。

    すでにパッチをあててしまっていると思うので
    修正前のものはわからないですが,

    vtExpected
    cclsidAllowed
    ClassesAllowedInStream (これは クラス(union))

    を検索すれば,該当箇所は分かります。
    (たぶん,漏れはないと思うけど確認したわけではありません)

    旧ソースを取ってある場合は,
    WinDiff で違いを確認できます。


    追記&修正:
    上でVariant型と書きましたが,
    Variant型 を使用しているかどうかは,
    よく考えてみると,今回の件とは直接は関係なかったです。
    一番上のレスでの発言を訂正しておきます。




    稍丼 / yayadon
    2009年8月5日 1:12
  • あと,
    MS09-04
    http://www.microsoft.com/japan/technet/security/bulletin/ms09-034.mspx
    の方もATLの脆弱性絡みと書かれていますが,
    こちらは,
    MS内部だけで使われているATLのプライベートバージョンの
    タイプミスから来ているという話
    http://blogs.msdn.com/sdl/archive/2009/07/28/atl-ms09-035-and-the-sdl.aspx
    だそう なので
    公開されているATLとは関係ないんじゃないかと思います。

    稍丼 / yayadon
    2009年8月5日 3:09
  • yayadon様
    レスが遅くなり申し訳ありません。自宅からしかレスできないので今の時間になってしまいました。
    丁寧に情報をいただき本当にありがとうございます。

    Windowsファイアウォールからのデータの取得やデータの書き込みは、SDKのクラスのメソッドで行っている為、そのメソッドの中で同様な処理が行われているかは不明です。
    現状では、自分が作成した箇所にストリーム経由の入出力はない為、影響がでる確率はあまり高くないと考えています。どうするかについては、上司と話し合いあいたいと思っています。
    yayadonさんからいただいた情報は、今後ストリームを使用する場合にとても役にたつ情報だと思います。

    ATLのソースの確認方法もわかりました。パッチはまだインストールしていませんでしたので新ソースとの違いまではわかりませんでしたがインストール後に確認するつもりです。

    2009年8月5日 12:48
  • こんにちは、フォーラムオペレータの高橋春樹です。

    yayadonさん、初めまして。アドバイスありがとうございました。

    しのさん、初めまして。MSDNフォーラムのご利用ありがとうございます。

    yayadonさんから、アドバイスを頂いたと思うのですが、問題解決に繋がりましたでしょうか?
    今回yayadonさんから頂いた情報が有用なものだと思いましたので、
    勝手ながら、回答マークを付けさせてもらいました。
    また、ご質問がありましたら、新たに投稿して頂ければと思います。

    今後ともMSDNフォーラムを、よろしくお願いします。


    マイクロソフト株式会社 フォーラム オペレータ 高橋春樹
    2009年8月12日 2:23