2010年11月15日

バイナリプランティングの防止

IPAからも注意喚起が行われていますが、最近バイナリプランティング("Binary planting"、あるいは"DLL planting"、"DLL preloading"とも表現されます)という攻撃手法が問題になっています。これは(いわゆる"Known DLLs"を除く)絶対パス指定ではないDLLを検索するパスに"カレントディレクトリ"が含まれていて、状況によってはその優先順位が高いために攻撃者の用意した不正なDLLが実行プログラムにバインドされてしまう(通常はDLLをロードして初期化するだけでDLLMainが実行されてしまいますから、この時点で攻撃成立です)、というものです(これがが狭義の"DLL planting")。また類似の状況として、絶対パス指定ではない実行ファイルをCreateProcess/CreateProcessAsUser/CreateProcessWithLogonW/CreateProcessWithTokenW/ShellExecute/ShellExecuteExなどで起動することでも同様の問題が生じます。さらに問題を複雑なものにする要因として、Windows Vista/7ではKnown DLLsに含まれるDwmapi.dllがWindows 2000/XPには存在しないにもかかわらず一部のフレームワークがWindowsのバージョンを考慮せずにDwmapi.dllをロードしようとするために、カレントディレクトリに攻撃用のDwmapi.dllを配置することでこれがバインドされてしまい攻撃が成立してしまう、というものがあります(幸いにもVCLや.NET Frameworkは該当しませんが、MFC(Visual Studio 2005/2008/2010)は該当するようです)。上記のいずれの状況でも攻撃用のDLL/EXEはカレントディレクトリに配置するのが攻撃成立の条件になります(例えばSystem32にそんなものを置かれるようではどんな攻撃も可能ですから)ので、カレントディレクトリが外部に設定されてプログラムが起動するような場合、つまりファイルをダブルクリックして関連付けでプログラムが起動するような場合が最も危険である、ということになります(ショートカットでもカレントディレクトリは設定できますが)。

バイナリプランティングをプログラム側から防ぐには、
  • リンクするDLLや起動する実行ファイルは可能な限り完全修飾パス名を使用する。
  • SetDllDirectoryで""(空文字列)を指定してDLLの検索パスからカレントディレクトリを削除する(Windows XP以降)。
  • DLL/実行ファイルを検索するのにSearchPath (ja)はなるべく使用しない。使用するときはSetSearchPathModeBASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODEを設定する(Windows Vista以降)。
  • Windowsの特定のバージョン以降で"Known DLLs"に追加されたDLLをLoadLibraryするときはWindowsのバージョンチェックを行うか、完全修飾パス名を使用する。
といった対策をとる必要があります。

ということでSetDllDirectoryを使用してDLLの検索パスからカレントディレクトリを削除するサンプルです。なるべく早い時点で設定するのが望ましいので、プロジェクトファイルの先頭で行います。またSetDllDirectoryはWindows XP SP1以降にしか存在しないので、エントリの存在を確認して呼び出すようにしています。
program Project1;

uses
  Windows,
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

type
  TSetDllDirectoryFunc = function (lpPathName: PChar): BOOL; stdcall;

const
{$IFDEF Unicode}
  CSetDllDirectory = 'SetDllDirectoryW';
{$ELSE}
  CSetDllDirectory = 'SetDllDirectoryA';
{$ENDIF}

var
  S: String;
  SetDllDirectory: TSetDllDirectoryFunc;
begin

  @SetDllDirectory := GetProcAddress(GetModuleHandle(kernel32),
  CSetDllDirectory);
  if Assigned(SetDllDirectory) = True then
  begin
    S := '#0';
    SetDllDirectory(PChar(S));
  end;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

なおコンソールアプリケーションでグラスエフェクトを有効にするのサンプルコードもDwmapi.dllがWindows 2000/XPには存在しないことを利用したバイナリプランティングの影響を受けるため、修正してあります。

元ねたは以下の通り。

情報処理推進機構(IPA)マイクロソフトITpro(要登録)CodeZineNyaRuRuの日記

0 件のコメント: