WAS Forum Conference 2008 Developers Day SQLインジェクション 対 策 再 考 2008/07/05 HASHコンサルティング 株 式 会 社 代 表 取 締 役 徳 丸 浩 http://www.hash-c.co.jp/ Copyright 2008 HASH Consulting Corp. 1
アジェンダ 本 日 の 構 成 正 しくないSQLインジェクション 対 策 の 今 昔 SQLインジェクション 対 策 の 考 え 方 SQLインジェクション 対 策 の 実 際 議 論 の 焦 点 入 力 値 検 証 とは 何 か SQLのエスケープ 方 法 詳 細 数 値 項 目 の 対 策 最 近 のトピックス Copyright 2008 HASH Consulting Corp. 2
第 1 部 正 しくないSQLインジェクション 対 策 の 今 昔 Copyright 2008 HASH Consulting Corp. 3
正 しくない 例 1(2001 年 ) 正 しい これは 余 計 でもこれは 2001 年 の 記 事 だから 実 践! セキュアなWebプログラミング 日 経 オープンシステム2001 年 5 月 号 から 引 用 Copyright 2008 HASH Consulting Corp. 4
正 しくない 例 2(2007 年 ) (1) 入 力 値 のチェック 中 略 データベースで 扱 う 値 に 対 して 上 記 のような 文 字 種 文 字 数 等 の 条 件 を 明 確 にし ブラウザか ら 渡 された 値 が 入 力 値 として 正 しい 形 式 であるかどうかをチェックする 条 件 を 細 かく 設 定 し 厳 密 にチェックすることによって 任 意 のSQL 文 の 混 入 を 避 けることができる 場 合 もある (2) 特 殊 記 号 のエスケープ 1) シングルクォート ' のエスケープ 正 しい 中 略 3) セミコロン ; の 拒 否 次 の 特 殊 記 号 が 含 まれているときは パラメータを 受 理 しない わけにいかない ; 受 理 しない ; は SQL 文 のコマンドの 区 切 りに 使 用 される 中 略 5) その 他 の 特 殊 記 号 のエスケープ(Microsoft Jetエンジン) またMicrosoftのJetエンジンでは 次 の 文 字 も 機 能 をもつ 特 殊 記 号 として 扱 われる VBAステートメント 実 行 文 字 どうやってエスケープ? IPA ISEC セキュア プログラミング 講 座 :Webアプリケーション 編 第 6 章 入 力 対 策 :SQL 注 入 より 引 用 http://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/502.html Copyright 2008 HASH Consulting Corp. 5
正 しくない 例 3(2008 年 ) 前 提 1 Webアプリケーションは 文 字 列 を 入 力 として 受 理 できる リレーショナル データベース 管 理 システムと 連 携 入 力 の 例 DECLARE%20@S%20NVARCHAR(4000)SET%20@S=hogehoge EXEC(@S) 文 字 列 として 入 力 特 殊 文 字 を 文 字 として 扱 うために を 挿 入 パーセントエンコー ドをデコードしてか らでないと 無 意 味 むやみに を 挿 入 しても ; は 削 除 セミコロンを 勝 手 入 力 値 チェックの 結 果 に 削 除 しないで! DECLARE %20@S %20NVARCHAR (4000 )SET %20@S =hogehoge EXEC (@S ) 前 提 2 SQLクエリーはアプリケーションで 生 成 SQL 構 文 に 用 いるような 文 字 列 はユーザーの 入 力 としてはありえない 意 味 不 明 入 力 の 例 ( 入 力 値 チェックの 結 果 ) DECLARE %20@S %20NVARCHAR (4000 )SET %20@S =hogehoge EXEC (@S ) SQL 構 文 に 用 いられる 代 表 的 な 文 字 列 をフィルタリングして 削 除 アットマーク(@)はデータベース 上 で 変 数 の 識 別 子 やスクリプト の 実 行 に 用 いられることがあるため 削 除 サニタイズ!! サニタイジングの 例 %20S %20 (4000 ) %20S =hogehoge (S ) 被 害 が 続 くSQLインジェクション 攻 撃,もう 一 度 対 策 を 見 直 そうより 引 用 http://itpro.nikkeibp.co.jp/article/column/20080514/301660/ Copyright 2008 HASH Consulting Corp. 6
なぜ 誤 った 解 説 がなくならないのか 攻 撃 方 法 からの 発 想 攻 撃 に 使 用 する 文 字 文 字 列 を 削 除 改 変 するアプローチ いわゆる サニタイズ 脆 弱 性 が 混 入 する 根 本 原 因 からのアプローチではない 実 はアプリケーションなんか 書 いたことがない 人 が 説 明 している? セキュリティのプロが 全 員 アプリケーションを 書 けるとは 限 らない そのサンプルコード 動 かしてみた? でもテスト 環 境 構 築 するだけでも 大 変 だしぃ コピペの 悪 弊 昔 の 間 違 った 解 説 が 延 命 されられる みんな 攻 撃 が 大 好 きだww Copyright 2008 HASH Consulting Corp. 7
参 考 なぜセミコロン ; を 削 除 したがるのか? 実 はセミコロンの 削 除 には 実 効 的 な 意 味 はあまりない セミコロン 削 除 の 意 図 は 複 文 実 行 の 防 止 と 思 われる SELECT * FROM XXX WERE ID= ;UPDATE XXX SET SQLインジェクションの 文 脈 で 複 文 が 実 行 できるのは MS SQL とPostgreSQL 現 実 にMS SQLは 複 文 を 使 った 改 ざん 事 件 が 多 発 しかし MS SQLは セミコロンなしでも 複 文 が 書 ける SELECT * FROM XXX WERE ID= UPDATE XXX SET でもよい すなわち セミコロンの 削 除 で 保 険 的 にせよ 意 味 があるのは PostgreSQLの 場 合 だけ 続 きはWebで http://www.tokumaru.org/d/20080502.html http://www.tokumaru.org/d/20080627.html Copyright 2008 HASH Consulting Corp. 8
危 険 文 字 と 言 わないで Copyright 2008 HASH Consulting Corp. 9
第 2 部 SQLインジェクション 対 策 の 考 え 方 Copyright 2008 HASH Consulting Corp. 10
そもそもなぜSQLインジェクションが 発 生 するのか? 原 因 は リテラルとして 指 定 したパラメータが リテラルの 枠 をは み 出 し SQLの 一 部 として 解 釈 されること 文 字 列 リテラルの 場 合 シングルクォートで 囲 まれた(クォートされた) 範 囲 をはみ 出 す SELECT * FROM XXX WHERE A= OR A =A 数 値 リテラルの 場 合 数 値 でない 文 字 ( 空 白 英 字 記 号 など)を 使 う はみ 出 した 部 分 SELECT * FROM XXX WHERE A=1OR TRUE Copyright 2008 HASH Consulting Corp. 11
エスケープは 檻 にしっかり 入 れるイメージ 檻 に 入 っている 分 には 中 身 の 危 険 性 を 気 にする 必 要 なはい 危 険 性 がなくても 檻 から 出 てしまうのはバグ select * from animals whre kind=' ' 危 険 な 文 字 文 字 列 ; ' @ declare union xp_cmdshell @... Copyright 2008 HASH Consulting Corp. 12
SQLインジェクションは 檻 から 逃 げるイメージ パラメタがリテラルからはみ 出 し SQL 文 の 命 令 として 解 釈 される 状 態 select * from animals whre kind=' ' 危 険 な 文 字 文 字 列 ; ' @ declare union xp_cmdshell @... Copyright 2008 HASH Consulting Corp. 13
[プロの 礼 儀 作 法 としての 参 考 文 献 ] ライオン エスケープ http://www.rakuten.co.jp/torito/659325/660549/ から 引 用 Copyright 2008 HASH Consulting Corp. 14
第 3 部 SQLインジェクション 対 策 の 実 際 Copyright 2008 HASH Consulting Corp. 15
ではどうすればいいのか? 基 本 は リテラルをしっかりと 檻 に 閉 じ 込 めること 方 法 1:バインド 機 構 の 利 用 ( 推 奨 ) my $sth = $db->prepare("select ERRMSG FROM ERRINFO WHERE ERRNO=?"); my $rt = $sth->execute($n); バインド 機 構 の 実 装 にバグがない 限 り 安 心 (どうやって 確 認 する?) 方 法 2:SQLの 動 的 組 み 立 て+エスケープ ただし 数 値 の 場 合 は 別 の 方 法 が 必 要 Copyright 2008 HASH Consulting Corp. 16
第 二 の 選 択 肢 動 的 SQL 生 成 +エスケープ なぜバインド 機 構 を 利 用 しないのか プラットフォームの 制 約 フレームワークの 制 約 古 いアプリケーションの 保 守 Copyright 2008 HASH Consulting Corp. 17
動 的 SQL 生 成 の 場 合 は 文 字 列 と 数 値 で 対 応 が 変 わる 文 字 列 の 場 合 エスケープ 数 値 の 場 合 変 数 に 型 のある 言 語 Java C#など 数 値 型 を 使 っている 場 合 は 問 題 ない 文 字 列 型 を 使 って 数 値 を 処 理 する 場 合 は 変 数 に 型 のない 言 語 と 同 じ 方 法 変 数 に 型 のない 言 語 Perl PHP Ruby VBScript(ASP)など 数 値 の 妥 当 性 確 認 Copyright 2008 HASH Consulting Corp. 18
文 字 列 リテラルのエスケープ どの 文 字 をエスケープするのか? SQL 製 品 の 文 字 列 リテラルのルールに 従 う ISO 標 準 では ' '' MySQLとPostgreSQLは ' '' PostgreSQLの 場 合 は standard_conforming_stringsおよび backslash_quoteの 影 響 を 受 ける standard_conforming_strings=onの 場 合 は ISO 標 準 と 同 じ 方 法 になる backslash_quote=off の 場 合 は ' ' というエスケープがエラーになる Oracle MS SQL IBM DB2 MySQL PostgreSQL 元 の 文 字 エスケープ 後 または ( を 推 奨 ) Copyright 2008 HASH Consulting Corp. 19
参 考 商 用 RDBMSの 文 字 列 リテラルの 定 義 Oracle:cは データベース キャラクタ セットの 任 意 の 要 素 です リテラル 内 の 一 重 引 用 符 ( )の 前 には エスケープ 文 字 を 付 ける 必 要 があります リテラル 内 で 一 重 引 用 符 を 表 すには 一 重 引 用 符 を2つ 使 用 します http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/b19201-02/sql_elements.html#41297 DB2:ストリング 区 切 り 文 字 で 始 まりストリング 区 切 り 文 字 で 終 わる 文 字 のシー ケンス この 場 合 のストリング 区 切 り 文 字 はアポストロフィ( ) です 中 略 文 字 ストリング 内 で 1 つのストリング 区 切 り 文 字 を 表 したいときは ストリング 区 切 り 文 字 を 2 つ 連 続 して 使 用 します http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0000731.html MS SQL: 単 一 引 用 符 で 囲 まれた 文 字 列 に 単 一 引 用 符 を 埋 め 込 む 場 合 は 単 一 引 用 符 を 2 つ 続 けて 並 べることで 1 つの 単 一 引 用 符 を 表 します http://technet.microsoft.com/ja-jp/library/ms179899.aspx Copyright 2008 HASH Consulting Corp. 20
参 考 MySQLの 文 字 列 リテラルの 定 義 8.1.1. 文 字 列 一 部 のシーケンスは 個 々の 文 字 列 内 で 特 別 な 意 味 を 持 ちます これらのシーケンスは いず れも エスケープ 文 字 として 知 られるバックスラッシュ( )で 始 まります MySQLでは 次 の エスケープシーケンスが 認 識 されます 文 字 列 に 引 用 符 を 含 める 方 法 は いくつかあります で 囲 んだ 文 字 列 内 で を 使 用 する 場 合 と 記 述 することができます 後 略 MySQL :: MySQL 5.1 リファレンスマニュアル :: 8.1.1 文 字 列 から 引 用 http://dev.mysql.com/doc/refman/5.1/ja/string-syntax.html Copyright 2008 HASH Consulting Corp. 21
参 考 PostgreSQLの 文 字 列 リテラルの 定 義 4.1.2.1. 文 字 列 定 数 SQLにおける 文 字 列 定 数 は 単 一 引 用 符 ( )で 括 られた 任 意 の 文 字 の 並 びです 例 えば This is a string です 文 字 列 定 数 内 の 単 一 引 用 符 の 記 述 方 法 は 2つ 続 けて 単 一 引 用 符 を 記 述 することです 中 略 エスケープ 文 字 列 の 中 では バックスラッシュ 文 字 ( )によりC 言 語 のようなバック スラッシュシーケンスが 始 まります バックスラッシュと 続 く 文 字 の 組 み 合 わせが 特 別 なバイト 値 を 表 現 します bは 後 退 (バックスペース)を fは 改 頁 を nは 改 行 を rは 復 帰 (キャリッジリターン)を tはタブを 表 します また digitsという 形 式 もサポートし digitsは8 進 数 バイト 値 を 表 します xhexdigitsという 形 式 で は hexdigitsは16 進 数 バイト 値 を 表 します ( 作 成 するバイトの 並 びがサーバの 文 字 セット 符 号 化 方 式 として 有 効 かどうかはコード 作 成 者 の 責 任 です )ここに 示 した 以 外 のバックスラッシュの 後 の 文 字 はそのまま 解 釈 されます したがって バ ックスラッシュ 文 字 を 含 めるには 2つのバックスラッシュ( )を 記 述 してください また 通 常 の''という 方 法 以 外 に 'と 記 述 することで 単 一 引 用 符 をエスケープ 文 字 列 に 含 めることができます http://www.postgresql.jp/document/current/html/sql-syntax-lexical.html#sql-syntax-constants Copyright 2008 HASH Consulting Corp. 22
MySQLとPostgreSQLで のエスケープが 必 要 な 理 由 SELECT * FROM XXX WHERE ID='$id' $id として 'or 1=1# が 入 力 されると 'or 1=1# エスケープ( のエスケープをしない 場 合 ) ''or 1=1# 元 のSQLに 適 用 すると SELECT * FROM XXX WHERE ID=' '' or 1=1#' すなわち SQLの 構 文 が 改 変 された( で 一 文 字 と 見 なされる) Copyright 2008 HASH Consulting Corp. 23
Shift_JISの 問 題 DB 側 の 日 本 語 処 理 が 不 完 全 な 場 合 表 ' 0x95 0x5c 0x27 フロント 側 でのエスケープ 処 理 表 ' ' 0x95 0x5c 0x27 0x27 データベース 側 の 解 釈 0x95 0x95 0x5c 0x27 ' で' 一 文 字 0x27 ' がエスケープされずに 余 る フロント 側 の 日 本 語 処 理 が 不 完 全 な 場 合 表 ' 0x95 0x5c 0x27 フロント 側 でのエスケープ 処 理 (0x5cと0x27をそれぞれエスケープ) 0x95 0x5c 0x5c 0x27 データベース 側 の 解 釈 0x95 0x5c 表 一 文 字 0x5c 0x27 'で 一 文 字 0x27 0x27 ' がエスケープされずに 余 る Copyright 2008 HASH Consulting Corp. 24
文 字 コードの 問 題 例 えば Shift_JISを 避 ける 言 語 レベルで 文 字 コードを 意 識 したものを Java # 元 々 内 部 はUnicode Perl5.8 # それ use utf8; で PostgreSQLの 対 応 (8.1.4) 常 にサーバ 側 で 無 効 なコードのマルチバイト 文 字 を 拒 否 するように 修 正 されました (8.1 系 ~7.3 系 ) これにより 一 律 にすべての 文 字 エンコーディングのすべてのテキスト 入 力 に 対 して 検 査 が 行 わ れ 単 に 警 告 が 出 るのではなく 常 にエラーが 出 るようになりました この 変 更 は CVE-2006-2313 に 記 述 されているような SQLインジェクション 攻 撃 に 対 抗 するものです 文 字 列 リテラル 中 の 安 全 でない ' を 拒 否 する 機 能 が 追 加 されました (8.1 系 ~7.3 系 ) CVE-2006-2314 に 記 述 されている 類 のSQLインジェクション 攻 撃 をサーバ 側 で 防 ぐため SQL 文 字 列 リテラルとして だけを 受 け 付 け を 受 け 付 けないように 変 更 されました 中 略 この 振 る 舞 いを 調 整 するため 新 たな 設 定 パラメータbackslash_quote が 追 加 されました なお CVE-2006-2314 を 完 全 に 防 ぐには おそらくクライアント 側 の 修 正 も 必 要 です backslash_quote は 安 全 でないクライアントが 安 全 でない ことを 明 らかにするのを 目 的 として います http://www.sraoss.co.jp/postgresql/8.1.4/changes.html Copyright 2008 HASH Consulting Corp. 25
数 値 リテラルの 場 合 数 値 としての 妥 当 性 確 認 をSQL 組 み 立 て 時 に 行 うとよい 最 初 に 妥 当 性 検 証 していても 気 にしないで 再 度 検 証 する 大 したオーバーヘッドにはならない # 呼 び 出 し 例 eval { my $sql = "SELECT ERRMSG FROM ERRINFO WHERE ERRNO=". int_check($n);... } if ($@) { # エラー 発 生 時 の 処 理 }... # 整 数 チェック 関 数 の 例 sub int_check { my $val = shift; if ($val =~ /^-?[0-9]+$/) { return $val; } else { die " 整 数 値 エラー"; # エラーメッセージは$@に 格 納 } } Copyright 2008 HASH Consulting Corp. 26
SQLエスケープの 実 装 はどれを 使 う? 安 全 なウェブサイトの 作 り 方 改 定 第 3 版 (P7) には 以 下 の 記 述 があるが データベースエンジンによっては 専 用 のエスケープ 処 理 を 行 うAPI を 提 供 しているものがあります(たとえば Perl ならDBIモジュールのquote()な ど)ので それを 利 用 することをお 勧 めします DBIのquote()が 全 てDB 側 で 用 意 したAPIを 呼 んでいるわけでは ない DBD::PgPPでの 実 装 $s =~ s/(?=[ ])/ /g; # PostgreSQLのAPIを 呼 んでいない return "'$s'"; 安 全 なウェブサイトの 作 り 方 の 趣 旨 には 同 意 するが 具 体 的 に どの 関 数 メソッド APIなら 安 全 というガイドラインがないと 開 発 現 場 では 使 えない プロジェクトの 度 にコンサルタント 雇 って 調 べさせる? Copyright 2008 HASH Consulting Corp. 27
入 力 値 検 証 は 何 をすればよいか アプリケーションレベルで や ; を 削 除 あるいは 拒 否 するわ けにはいかない クォートやセミコロンも 正 しく 処 理 できるよう バインド 機 構 やエスケープを 用 いる ミドルウェアレベルでは 半 端 なマルチバイトコード や UTF-8 の 冗 長 表 現 をチェックし エラーにすべき アプリケーションレベルでは 業 務 要 件 にしたがって 入 力 値 検 証 する 結 果 としてSQLインジェクション 対 策 になる 場 合 もあれば ならない 場 合 も ある メタ 文 字 ではなく 制 御 文 字 (ヌル 文 字 を 含 む)のチェックは 必 要 ( 改 行 タブ 以 外 の 制 御 文 字 はミドルウェアレベルでチェックして 欲 しい) Copyright 2008 HASH Consulting Corp. 28
おまけ: 述 語 LIKEのワイルドカードのエスケープ 述 語 LIKEのワイルドカード _ % にも 注 意 狭 義 のSQLインジェクションとは 違 うが サーバーに 過 負 荷 をか ける 場 合 がある( 全 件 検 索 ) MySQL 以 外 の 場 合 はESCAPE 句 の 利 用 LIKE #%% ESCAPE # -- #% で 文 字 としての % を 示 す MySQLの 場 合 は によりエスケープ LIKE %% -- % で 文 字 としての % を 示 す 商 用 RDBMSの 場 合 は 全 角 の _ や % にも 注 意 Copyright 2008 HASH Consulting Corp. 29
まとめ 提 言 そろそろ 入 力 値 の 未 検 証 という 表 現 はやめよう バインド 機 構 の 利 用 促 進 正 しいエスケープ 方 法 の 普 及 安 全 なフレームワーク 安 全 なバインド 機 構 はどれ? 安 全 なエスケープ 関 数 はどれ? 安 全 なウェブサイトの 作 り 方 のさらに 具 体 的 なガイドライン の 必 要 性 Copyright 2008 HASH Consulting Corp. 30
ご 清 聴 ありがとうございました Copyright 2008 HASH Consulting Corp. 31