400 likes | 510 Views
静的解析に基づく侵入検知システムの最適化. 大山 恵弘 (科学技術振興事業団) 王 維 (筑波大学) 加藤 和彦 (筑波大学・科学技術振興事業団). 背景. C 言語 = 大大大迷惑で危険な言語 世界に大きな脅威と経済的損失 ex1. バッファオーバフローで乗っ取り ex2. スタックやヒープが壊れて誤動作 しかし、今すぐ C 言語を駆逐するのは無理 支援システムで C 言語の欠陥を補いましょう. バッファオーバフロー. サイズを越えてデータをバッファに注入 スタック、ヒープの破壊 制御フローのねじ曲げ 突然 libc の exec に突入
E N D
静的解析に基づく侵入検知システムの最適化 大山 恵弘 (科学技術振興事業団) 王 維 (筑波大学) 加藤 和彦 (筑波大学・科学技術振興事業団)
背景 • C言語 = 大大大迷惑で危険な言語 • 世界に大きな脅威と経済的損失 • ex1. バッファオーバフローで乗っ取り • ex2. スタックやヒープが壊れて誤動作 • しかし、今すぐC言語を駆逐するのは無理 • 支援システムでC言語の欠陥を補いましょう
バッファオーバフロー • サイズを越えてデータをバッファに注入 • スタック、ヒープの破壊 • 制御フローのねじ曲げ • 突然libcのexecに突入 • 注入したバイナリコード先頭にジャンプ
Cプログラムを安全に実行するための方策 • 型安全性の導入 [Oiwa et al. 02] • Stack-smashing攻撃防止システムの導入[Cowan et al. 96], [Etoh] • 侵入検知システムの導入 • 他多数… 本研究
侵入検知システム • 基本的な動き • プログラムの実行を監視 • 侵入を検知 → 対策を取る • 検知方式 • シグネチャ検知: 「異常」の規則を保持 • ex. 原始的なAntivirus • 異常検知: 「正常」の規則を保持 本研究
異常検知システム • 方法 • プログラムのモデル(正しい動作を表す規則)を作成 • モデルに従わない動作 = 異常と判定 • 長所 • 未知の攻撃を検出可能
本研究の目的 • 実用的な異常検知システムの構築 • 小さいオーバヘッド • 高い検知精度 • 使用が容易
以降の流れ • 異常検知システムの設計軸 • 既存の方法 • 既存の方法の問題 • 本研究の方法 • 実験 • 議論・関連研究
異常検知システム作ろう!といっても色々考えることがある異常検知システム作ろう!といっても色々考えることがある • 何を監視するか? • モデル(正しい動作を表す規則)をどうやって作るか?
何を監視するか? • キータイプ • パケット • システムコール • 制御スタック • ヒープ 本研究
モデルをどうやって作るか? • 人間が頭をひねって書く • [Ko et al. 94], [Sekar et al. 99] • 問題: 計算機の専門知識が必要 • 過去の正常な実行を一般化・学習 • [Forrest et al. 96], [Sekar et al. 01] • 問題: 学習のためにプログラムを実行するのが面倒 • プログラムの静的解析による自動生成 • [Wagner et al. 01], [Giffin et al. 02] 本研究
本研究のアプローチ モデル = 制御フローの規則 • 制御フローを監視しながら実行 • モデルに無い制御フローを辿った → 異常 • システムコール呼び出し時に制御の状態を検査 • Wagnerらの方法 [Wagner et al. 01] の改良 main() { f(); if (…) { g(); } … }
Wagnerらのシステム コンパイラ プロセス main() { f(); if (…) { g(); } … } 実行可能コード システムコール モデル 侵入検知システム OS
モデル main() { stat(); if (…) { open(); } else { connect(); } close(); } main → stat; X; close X → open | connect 文脈自由文法 終端記号 = システムコール
実行の監視 プロセス open, stat, … 侵入検知システム= CFGパーザ パーズ可能 → 正常 パーズ不可能 → 異常 main → stat; X; close X → open | connect OS
問題点 • プログラムの内部状態を正確に把握しない • 制御の場所を非決定的に把握 sendmail open, stat, mmap, read, close, …
問題点1: オーバヘッドの増加 プロセス open, stat, … CFGパーザ open呼ぶ候補の数100! →全部考慮してパーズ 次にstat呼ぶ候補の数1000! →全部考慮してパーズ main → f | g | h | i | … f → open | … | … g → open | … | … h → open | … | … i → f | g | … OS
実用的とは言い難い性能 42分 1時間以上 1トランザクションあたりの 監視オーバヘッド (秒)
問題点2: 攻撃の見逃しの増加 プロセス open, stat, (buffer overflow), exec, … CFGパーザ open, stat, execを 生成可能な規則あり → プロセス内部がどうなって いようが正常と判断 main → f | g | h | i | … f → open | … | … g → open | … | … h → open | … | … i → f | g | … OS
我々の考え • 静的解析でモデルを作る着眼は良い • しかし、システムコール列のみを検査対象にするのはいかがなものか • プログラムの内部状態をもっと取得・活用してもいいのでは?
イメージ sendmail open, stat, mmap, read, close, …
提案方式 コンパイラ プロセス main() { f(); if (…) { g(); } … } 実行可能コード モデル システムコール 侵入検知システム OS
モデル • 制御の移動を表すオートマトン main() { open(); if (…) { f(); } else { g(); } close(); } main 入口 open f g close 出口
検査方法 • システムコールでプログラムを停止 • スタックを検査 • 前回停止時のスタックから現在のスタックへの制御フローがモデル中にあるかどうか調べる read fgets h open 遷移可能? 遷移可能? g printf connect f f p main main main
遷移可能性の検査 • 現在はナイーブなやり方 • スタックの各フレームごとに遷移の存在を検査 • popするパスの探索 • pushするパスの探索 read fgets open h printf g f f main main
実装 • モデル生成機能つきコンパイラ部 • GCCを改造して作成工数: 0.018人年 • 実行監視部 • 別プロセスによる監視 • カーネルモジュールによってプロセスを操作 • システムコールをフック • レジスタ・スタック情報の取得
特徴 • Wagnerらの方法 • 偽警報が出ない (正常を異常と誤判定しない) • モデルを作る手間がかからない • 加えて、本研究のシステム • Wagnerらの方法より • オーバヘッドが小さい(?) • 見逃す攻撃が少ない
実験 • 環境 • Pentium 4 (2.8GHz) 上のVMware • Red Hat Linux 7.1 • アプリケーション • wc: 22MBのファイルのカウント • cp: 22MBのファイルのコピー • tar: ソースツリーのtarファイルを作成
関連研究: バッファオーバフロー対策 • Non-executable stack, StackGuard [Cowan et al. 96], propolice [Etoh] • 関数ポインタを書き換える攻撃を防げない • Program shepherding [Kiriansky et al. 02] • 全ブランチ命令で安全性検査 • ex. ブランチが関数先頭に飛んでいるか • ex. retがcallの次の命令に飛んでいるか • 「ソースコード通りの制御フローを辿る」というポリシーは扱っていない
まとめ • ソースコード情報と実行時スタックの情報を両方活用する異常検知システムを提案
今後の課題 • 大規模なアプリケーションを用いて性能測定 • Wagnerらの方法との性能比較 • システムコールの引数情報の活用
議論: サンドボックスとの関係 • サンドボックスと侵入検知システムは似ている • 実行を監視、邪悪な操作を拒否 • サンドボックスがあれば十分? → No! • サンドボックスの適切なポリシーを定めることは簡単ではない • 厳しすぎるとプログラムが動かない • 緩すぎると危険
議論: mimicry attack[Wagner et al. 02] • 侵入検知システムによる検知を回避する攻撃 • ex. ダミーシステムコールを発行して正常を偽装 • システムコールだけを検査するシステム→ mimicry attackがやりやすい • 本研究のシステム→ mimicry attackがやりにくい • スタック内の制御情報も偽装する必要がある
議論: なぜシステムコールのタイミングで検査するのか? • オーバヘッドを(比較的)小さく抑えられる • 実装が楽 • システムコール呼び出しに検査が挟まるとハッカーは攻撃を成功させにくい
異常検知の投機的実行 • プログラムの未来の状態を予測 • 次に出るシステムコール • 次のスタック状態 • 次にどの状態が来たら正常/異常かを事前に計算しておく • アプリケーションの停止時間が短縮される
コンパイル処理に加わるオーバヘッド • wget-1.8.2のmakeにかかる時間 • 元のGCC: 12.3秒 • 改造GCC: 12.4秒