社団法人 電子情報通信学会
THE INSTITUTE OF ELECTRONICS,
INFORMATION AND COMMUNICATION ENGINEERS

信学技報
TECHNICAL REPORT OF IEICE.

インジェクション系攻撃防止ライブラリの評価
大久保隆夫†,††

田中 英彦††† (株) 富士通研究所 〒 211–8588 川崎市中原区上小田中 4–1–1†† 情報セキュリティ大学院大学 〒 221–0835 神奈川県横浜市神奈川区鶴屋町 2–14–1
E-mail: †okubo@jp.fujitsu.com, ††tanaka@iisec.ac.jp
あらましソフトウェアの脆弱性の中で、入力の中にプログラムへの指令を挿入することにより攻撃を可能にするイ

ンジェクション脆弱性は大きな割合を占める。インジェクション脆弱性の解決は、その確認手段までを含めると既存のプログラミング技法やライブラリでは不十分であった。筆者らは対策の確認容易性を考慮した、インジェクション攻
撃全般に適用可能なコーディング規約セットとライブラリを提案している。本報告では、提案したライブラリを Web
アプリケーションのサンプルプログラムに適用し、他の既存手法と比較する形で評価を行った。また、評価によって抽出された課題に基づきライブラリの改善を行った。
キーワード

ソフトウェア, 脆弱性, インジェクション攻撃, コーディング規約, ライブラリ

Evaluation of a library against injection attacks
Takao OKUBO†,†† and Hidehiko TANAKA††† Fujitsu Laboratories ltd. Kamikodanaka 4–1–1, Nakahara-ku, Kawasaki, 211–8588 Japan†† Institute of Information Security Tsuruyacho 2–14–1, Kanagawa-ku, Yokohama, 221–0835 Japan
E-mail: †okubo@jp.fujitsu.com, ††tanaka@iisec.ac.jp
Abstract Injection vulnerabilities, those enable attacks done by injecting command string into input data, havebig percentage of total software vulnerabilities. Existing Programming techniques and libraries are not sufficient topresent complete solution and easy testing methods. We have proposed general convention set and a secure library”SafeStatement” for preventing and testing injection attacks. In this papaer, the library are evalluated with somesample application programs, compared with other existing methods. And some improvement has done based on
the results.
Key words pLATEX 2ε class file, typesetting

1. は じ め に
近年、ソフトウェアの脆弱性が問題となっている。IPA がソフトウェアの既知の脆弱性を防止する対策としては、大別
して 2 種類あると考えられる。

•

開発者にある程度のセキュリティ知識があることを前提発表した「情報セキュリティ白書」[IPA07] によれば、2006 年とした対策。脆弱性を起こさないためのプログラミングノウハ

末までの Web アプリケーションの脆弱性の届出は累計 750 件

ウがこれに相当する。

(受理 704 件) に及んでいる。クロスサイトスクリプティングや•開発者にセキュリティの知識がなくても、開発の課程でSQL インジェクションのような脆弱性は、世間にも周知されつ

機械的に安全にできる仕組み。

つあり、これらの脆弱性を防止するためのプログラミング手法

筆者らは後者の対策について研究を行っている。理由は、(1) 前

も Web や書籍などで紹介されている。それにも関わらず、上者は開発者にある程度のセキュリティ知識を要求するが、現状記白書における 2006 年の脆弱性届出のデータは、クロスサイ

はすべての開発者にセキュリティ知識が浸透しているとはいえトスクリプティング (43%) と SQL インジェクション (23%) がない。このことは、前述のセキュリティ白書において未だに脆全体の 7 割近くを占めており、問題が解決されていないことを弱性の報告が減少していない事実が示している。セキュリティ示している。また、最近では著名な Web アプリケーションの知識を浸透させるには、セキュリティ教育を行っていく地道な基盤ソフトである Apache Tomcat にもクロスサイトスクリプ

努力が必要になる。(2) 後者であれば、セキュリティの知識が浸ティング脆弱性が発見され、衝撃を与えた [CVE07]。

透していない大規模なソフトウェア開発においても、コーディ—1—

ング規約やライブラリによって制約を加えることで一定のセ（ 4 ） プログラムで利用されるクエリの構文を解析し、許容

キュリティ品質を確保することが容易になる。また制約を加えされるクエリの構文を定義するることで、一般には困難なセキュリティの確認作業を制約の遵

この手法の代表的な例としては AMNESIA [HO06] がある。

守の確認に単純化できる。筆者らは Web アプリケーションのイ

AMNESIA は、ソースプログラムを静的に解析し、プログラ

ンジェクション系攻撃 (SQL インジェクション、OS コマンド

ムが生成する可能性のある SQL クエリの構文を非決定性有限

インジェクション、クロスサイトスクリプティング (XSS)) に

オートマトン (NDFA) としてすべて抽出し構文モデルとして着目し、その性質と可能な制約について検討を行い、インジェ保存しておく。そしてプログラム実行時に実行されるクエリをクションの防止と確認に適したコーディング規約とライブラリ

監視し、構文モデルから外れるものを検出する。この手法は、の提案を行った。本報告では、提案したライブラリ Web アプリ

前述のホワイトリスト、ボラックリストよりも精度は高く、特ケーションのサンプルプログラムに適用し、他の既存手法と比に正常なクエリが拒否される可能性は低い。しかし、静的解析

較する形で評価を行った。また、評価によって抽出された課題が持つ曖昧さが原因で、抽出された構文パターンが攻撃可能なに基づきライブラリの改善を行った。以降、2. 節ではインジェ

クエリパターンを排除できない場合がある。

クション攻撃の防止に関する関連研究について、3. 節では筆者

上記に挙げた手法の中では、Java の PreparedStatement ならの提案方式について述べる。4. 節では提案方式で提案したラどの Serialization API を使う方法が広範に普及しており、セイブラリを SQL インジェクション対策として実装したものを、

キュアプログラミングのガイドラインでもこの API の利用がアプリケーションサンプルを用いて評価した結果について述べ

推奨されているものが多い。しかし、Serialization API には次る。5. 節では評価で明らかになった課題と、それに基づきライに挙げる問題がある。

•

ブラリに行った改善について述べ、6. 節で結論を述べる。

パラメータのバインド機構を利用しないプログラミング

2. 関 連 研 究が脆弱性を生じる

インジェクション系攻撃のうち SQL インジェクションにつ

力値などをパラメータ指定せずに通常のクエリとして構築する

いては、近年では様々な視点からの検出、防御手法が提案されと、パラメータのバインド時の無害化処理が機能せず、入力値ている。

の操作により SQL インジェクション攻撃が可能になってしま（ 1 ） 入力値を検査し、SQL において攻撃に悪用される危険う。このような脆弱性を生じる Java プログラムの例を Sourceな文字 (引用符など) を安全な文字にエスケープする方法

code1 に示す。

Java の PreparedStatement のクエリ文字列を構築する際、入個別の入力値に対してプログラマが行う必要がある。入力値の対処漏れ、記号の対処漏れなどを原因とする脆弱性を生じやString query = "SELECTÃ*ÃFROMÃuser_infoÃWHEREÃ
userid=\""Ã+ÃuseridÃ+Ã"\"ÃANDÃpassword=\""Ã+Ã
passwordÃ+Ã"\"";
PreparedStatement pstmnt = con.prepareStatement(
query);
ResultSet rs = pstmnt.executeQuery();1すい。
（ 2 ） Serialization API を用いる方法
動的なパラメータを埋めこむ位置があらかじめ指定された固定のテンプレートのクエリ文字列を事前に準備する。動的な値は、Source Code 1 バインド機構を利用しないプログラム

定められた位置のパラメータに値をバインドすることによって行う。Java の PreparedStatement、Perl の DBI、PHP,Pythonの ADOldb、VisualBASIC の SQLCommand などがこれに相当する。
（ 3 ） ブラックリスト、またはホワイトリストによる異常なSQL クエリの排除
リストに登録されたクエリパターンに基づき、疑わしいパターンを遮断する方式である。遮断に用いるリストには、ブラック
リストとホワイトリストの 2 通りがある。また、検査手法については、SQLBlock のようにデータベースの直前でクエリそのものを検査する手法と、Web アプリケーションファイアウォー
ルのように HTTP リクエストのパラメータを検査する手法とがある。ブラックリスト、ホワイトリストいずれの手法についても、クエリの種類が少なければ効果を発揮するが、クエリが•クエリが動的に変化する場合、静的なテンプレートを用意するのが困難になる
条件分岐、ループによって発行するクエリが実行ごとに動的に変化する場合。分岐やループの組み合わせの数だけ、静的なク
エリのテンプレートを用意しなければならず、コーディング量が増加し、保守性低下、バグ発生率の増加を招く。下記の Java
プログラム (Source code1) はキーワード検索の例であるが、キーの種類が 6 種類だったとすると、1 から 5 までのキーの組
み合わせ総数 62 通りの SQL クエリテンプレートを用意する必要がある。
上記で述べたように、現在までに提案されている SQL インジェ
クション対策では、検出精度、対応可能なアプリケーションの網羅性などで問題がある。

複雑化すると、禁止パターンと正常パターンの衝突が発生し、制限を厳密にすると正常なクエリが拒否されたり、逆に制限を緩めると攻撃のパターンを検出できなくなってしまう可能性がある。また、プログラムの変更によりクエリのパターンが増え

3. 提 案 方 式
筆者らは、セキュリティの制約と確認容易性の関連に着目し、コーディング規約とライブラリの両面から制約をかけることをる場合はリストを変更する必要がある。

—2—

2

7

12

17

Statement stmnt = con.createStatement();
String query = "SELECTÃ*ÃFROMÃuser_infoÃ";Set keyset = map.keySet();Iterator iter = keyset.iterator();boolean first = true;
while (iter.hasNext()) {String key =(String) iter.next();
String[] value = (String[]) map.get(key);if(value[0] != ""){
if(!first) {query+= "ÃORÃ";} else {query+= "ÃWHEREÃ";}query+= key + "=\""Ã+Ãvalue[0]Ã+Ã"\"";
first = false;}}
ResultSet rs = stmnt.executeQuery(query);䉝䊒䊥䉬䊷䉲䊢䊮
ᢥⷐ⚛䈱ㅊട

ᢥ䈱ታⴕቯᢙ䈱ᬌ಴䈮䉋䉎
䊌䊤䊜䊷䉺䈱⼂೎䊁䊮䊒䊧䊷䊃
ᢥ䈱᭴▽

ෳᾖ

ቯ⟵

䉮䊙䊮䊄ᢥ
ቯᢙ
䉪䊤䉴

䊌䊤䊜䊷䉺䈱଻ሽ
Serialization API䈱ታⴕᢥ䈱⸳ቯ䊌䊤䊜䊷䉺䉕฽䉃ᢥ䈱࿕ቯൻ

䊌䊤䊜䊷䉺
䈱⸳ቯ

䊌䊤䊜䊷䉺䈱ήኂൻ

ෳᾖ

䊡䊷䉱ቯ⟵
ቯᢙ
䉪䊤䉴

ឭ᩺
䊤䉟䊑䊤䊥

ᢥ䈱ታⴕ

Serialization API

Source Code 2 クエリが動的に変化するプログラム
Figure 1 提案ライブラリの構成検討し、インジェクション攻撃の防止、確認に有効な規約、フレームワークについて提案を行った。以下ではその概要について述べる。

規約案とした。

•

外部プログラムに渡す引数の文字列は、定数 (事前に定インジェクション攻撃とは、サーバプログラムがクライアン

義され、変更がない) のみで構成されていなければならない。

トから入力されたデータに基づいて、外部プログラムに何かの次に、既存のライブラリについて、規約を遵守する場合のアプコマンドを送信する際に、攻撃者が入力データにコマンドのリケーションの実現可能性という観点から検討した。既存のア一部を挿入することにより、外部プログラムに意図しない動作

プリケーションについて調査した結果、クエリのテンプレートをさせる攻撃をいう。外部プログラムがリレーショナルデータとバインド機構を用いた Serialization API を用いれば、大部分

ベースの場合、コマンドは SQL であり、それを利用した攻撃のアプリケーションは規約に遵守する形で構築できることが分は SQL インジェション攻撃と呼ばれる。同様に、OS コマンド

かった。しかし、前節で述べたように、Serialization API では

インジェクション攻撃では外部プログラムが OS で、コマンド対応が困難なアプリケーション (Source Code1、Source Code2

が OS コマンドに相当する。一般には別の攻撃に分類されるク等のパターン) が存在することも分かった。

ロスサイトスクリプティング (XSS) 攻撃も、外部プログラム

そこで筆者らは、Serialization API で対応が困難なアプリ

を HTML レンダラ (ブラウザ)、コマンドを HTML と考えれケーションでも上記規約を満たすような実装を可能とするようば、本質的な構造はインジェクション攻撃と同じである。SQL

なライブラリを提案した。提案ライブラリは以下の特徴を持つ。

インジェクションの典型的な例を以下に示す。サーバプログラ•

Serialization API を内部で利用するが、固定のテンプ

ムが、認証時にデータベースに問い合わせを行い、ユーザ ID,

レートを事前に定義するのではなく、実行ごとに動的に生成

パスワードに一致するデータが存在すればそれを返すことを想する。

定して構築されたクエリである。。

•

コマンド文字列の構成時に、構成要素が静的要素か、パSELECT * FROM utable WHERE userid="(ユーザ ID)"

ラメータ要素かの区別を、定数として定義されているかを識別

AND password="(パスワード)"することによって行なう。

上記の () で括った部分には入力データが入る。ここで、攻撃提案ライブラリを SQL インジェクション向けに、Java で実装

者が” or ”a”=”a という文字列をパスワードとして入力させるしたものの構成を Figure 1 に示す。提案ライブラリは、文字列と、サーバプログラムが発行するクエリは以下のように変更さ追加の API と、コマンド文実行の API を持つ。文字列追加のれてしまう。

引数には、通常の文字列クラスか、ライブラリによって許可さ

SELECT * FROM utable WHERE userid="dummy"

れた型の定数しか利用できない。許可されている定数は、予めAND password="" OR "a"="a"

定義されている SQL 文の構文要素か、プログラマが独自に追上記のクエリは、条件が常に真になるため、データベースの加できるユーザ定数のいずれかである。各 API はそれぞれ下utable 上の任意のユーザにマッチしてしまい、認証を回避して記のように動作する。

ログインすることが可能になってしまう。

（ 1 ） 文字列追加 API は、追加する文字列の型を検査し、定筆者らは、インジェクション攻撃の本質は「ユーザ入力によっ数であればクエリの文字列にそのまま追加する。定数でない文てコマンドの構文が変えられてしまうこと」と定義し、それに字列はパラメータとみなし、パラメータのリストに保存し、ク従って攻撃を防止するための要件を「入力値によって、元のコ

エリの文字列にはパラメータが挿入される位置を示す’？’ を挿マンドの構文が変えられないこと」と規定した。次に、要件を入する。

満たす制約の中から、確認が最も容易と考えられる次の制約を（ 2 ） コマンド文実行 API は蓄積されているクエリ文字—3—

列をもとに PreparedStatement を生成し、別に保存されて
い る パ ラ メ ー タ を 順 に PreparedStatement に バ イ ン ド し 、PreparedStatement#executeQuery() を実行する。

4. 提案ライブラリの評価
提案したライブラリの SQL インジェクション向け実装を Javaを用いて試作し、サンプルの Web アプリケーションによる動作を検証、評価を行った。評価の目的は、筆者らの提案するライブラリが他の実装方式と比較して、SQL インジェクション
の防止、検出の点でより有効であるかを検証することである。
比較対象とする実装方式は、(1)Statement クラスによる実装、(2)PreparedStatement による実装、(3) 本提案ライブラリによFigure 2 サンプルアプリケーションのログイン画面

る実装、(4)AMNESIA による実装の 4 種類である。ただし、AMNESIA のみは今回入手できなかったため、机上による検証
による攻撃はすべて成功したことが確認された。

のみ行った。
動作検証に用いた環境は以下の通りである。

（ 2 ） PreparedStatement による正しい実装•

JavaVM:JDK1.5.11

PreparedStatement クラスのパラメータのバインド機構を正し•Servlet コンテナ:Tomcat5.5.23

く使い、実装したコードの一部を Source Code4 に示す。Source•

データベース:MYSQL 5.0.41

2 に示すブラウザ画面からパスワード入力欄に SQL インジェ

String query = "SELECTÃ*ÃfromÃuserinfoÃWHEREÃuserid=?ÃAND
Ãpassword=?";PreparedStatement pstmnt = con.prepareStatement(query);pstmnt.setString(1, userid);
pstmnt.setString(2, password);
ResultSet rs = pstmnt.executeQuery();

クション攻撃を行う文字列を実際に入力して、攻撃が成功する

Source Code 4 PreapredStatement による実装 (1)4. 1 認証機能を持つアプリケーションを用いた検証
ユーザ ID とパスワードを入力させ、ログインする機能を持つ
アプリケーションを各実装方法により実装後動作させ、Figure2

かどうかの検証を行った。
検証に用いた攻撃パターンは以下の 3 通りである。攻撃が成した。これは、パラメータとして入力されるデータは単なる文（ 1 ） 秘密の属性による検索

字列として扱われるため、攻撃文字列はクエリの一部としては

攻撃手法：パスワード欄に「” or sex=”female」と入力機能しないためである。

攻撃の確認方法：ユーザ情報の中で、sex が female に該当する（ 3 ） PreparedStatement による誤った実装

ユーザのみが表示される。

PreparedStatement クラスを用いているものの、パラメータの（ 2 ） 秘密データの検索

バインド機構を使っていない、誤った実装コードを用いて検証

攻 撃 手 法：パ ス ワ ー ド 欄 に「”;SELECT * from admininfoを行う。用いたサンプルは、前述の Source Code1 と同じもの

WHERE ”a”=”a」と入力である。

攻撃の確認方法：管理者テーブル (admininfo) にある管理者情1

Code4 の動作検証では、攻撃パターン 1〜3 による攻撃は失敗

功したかどうかの確認方法はそれぞれの場合で異なる。

動作検証では、攻撃パターン (1)〜(3) による攻撃は成功が確

報がすべて表示される。

認された。PreparedStatement が SQL インジェクション防止（ 3 ） データの破壊として機能しない理由は、このコードではパラメータのバイン

攻撃手法：パスワード欄に「”;DELETE * FROM userinfo

ド機能を使っていないために無害化機能が働かないことと、テ

WHERE ”a”=”a」と入力

ンプレートとなる SQL のクエリの構文が、入力値による変更

攻撃の確認方法：実行後、データベース上のユーザ情報テーブを許してしまっているためである。

ル (userinfo) のデータがすべて消去される（ 4 ） 提案ライブラリによる正しい実装（ 1 ） Statement クラスによる実装

提案ライブラリを用い、静的要素は定数を用いて正しく実Statement クラスによる実装コードの一部を Source Code3 以

装したコードの一部を Source Code5 に示す。Source Code5下に示す。Source Code3 の動作検証では、攻撃パターン 1〜3

で、”SELECT * FROM userinfo WHERE userid=”というStatement stmnt = con.createStatement();
String query = "SELECTÃ*ÃFROMÃuserinfoÃWHEREÃuserid=\""+ÃuseridÃ+Ã"\"ÃANDÃpassword=\""Ã+ÃpasswordÃ+Ã"\"";
ResultSet rs = stmnt.executeQuery(query);

文字列が MYQUERY1、” AND password=”という文字列がMYQUERY2 という、ユーザ定義の定数として定義されており、提案ライブラリでは、SafeStatement クラスへの静的要素の追加はこの定数クラスを用いて行われている。それ以外の、

Source Code 3 Statement クラスによる実装

userid やパスワードなどの動的要素はそのまま追加されてい

—4—

5

SafeStatement sstmnt = new SafeStatement();
sstmnt.add(UserConstValue.MYQUERY1); //SELECT * FROM
userinfo WHERE userid=sstmnt.add(userid);sstmnt.add(UserConstValue.MYQUERY2); // AND password=
sstmnt.add(password);
ResultSet rs = sstmnt.prepareAndExecute(con);

SELECT*

FROM

utableSource Code 5 提案ライブラリによる実装 (1)WHERE userid

=

“

㱎

“

る。このコードの動作検証では、攻撃パターン (1)〜(3) によANDる攻撃は失敗した。SafeStatement クラスが、追加要素の型

password =

“

㱎

“

の識別によって自動的に静的要素とパラメータに振り分けてPreparedStatement に渡しているためである。
（ 5 ） 提案ライブラリによる誤った実装

Figure 3 AMNESIA が生成する SQL 構文モデル

提案ライブラリを用いているものの、静的要素に定数を用いていない誤った実装コードの一部を Source Code6 に示す。

Source Code6 では、本来定数として追加されるべき”SELECT

4

SafeStatement sstmnt = new SafeStatement();
sstmnt.add("SELECTÃ*ÃFROMÃuser_infoÃWHEREÃuserid=");sstmnt.add(userid);sstmnt.add("ÃANDÃpassword=");sstmnt.add(password);
ResultSet rs = sstmnt.prepareAndExecute(con);
Source Code 6 提案ライブラリによる実装 (2)* FROM userinfo WHERE userid=”、および” AND password=”が、文字列リテラルとして追加されている。このコードの動作検証では、PreparedStatement の場合と異なり、攻撃

Figure 4 サンプルアプリケーションのブラウザ画面は失敗した。この場合、すべてが動的要素とみなされるため、

SafeStatement クラスが構築するクエリ文字列は攻撃パターン

攻撃の確認方法：不正なパスワードで認証が回避され、ログイ(1) では”? ? ? ?”となる。これが PreparedStatement のクエン後の画面が表示される。

リとして文法的に正しくないため、JDBC コネクタによるシン（ 2 ） 認証回避 (2)タックスエラー (SQLException 例外) が発生し、認証処理は成

攻 撃 手 法：パ ス ワ ー ド 欄 に「”;SELECT * from admininfo

功しないのである。

WHERE ”a”=”a」と入力（ 6 ） AMNESIA

攻撃の確認方法：管理者テーブル (admininfo) にある管理者でStatement クラスによる実装コード (3 を AMNESIA で解析認証に成功し、ログイン後の画面が表示される。

した結果、得られる SQL 構文モデルは Figure 3 に示す通り（ 3 ） データの破壊になる。図中の”β”記号は、その要素がプログラム外部から攻撃手法：パスワード欄に「”;DELETE * FROM userinfo

来ていることを示す。検証に用いる攻撃パターン (1)(認証回

WHERE ”a”=”a」と入力

避) によって生成されるクエリは、”SELECT * FROM ustable

攻撃の確認方法：実行後、データベース上のユーザ情報テーブ

WHERE userid=”dummy” OR ”a”=”a””となり、その構文

ル (userinfo) のデータがすべて消去されるは Figure 3 のモデルを逸脱しているため、攻撃の検出が可能（ 1 ） Statement クラスによる実装と考えられる。。

Statement クラスによる実装コードは前述の Source Code2 と

4. 2 動的なクエリ構築を行うアプリケーションを用いた検証

同じものを用いている。HTTP リクエストパラメータのキー

次に、動的なクエリ構築を伴うアプリケーションによる検証の数だけクエリの条件が for ループによって追加される構造にを行う。用いるサンプルは、ブラウザで 5 種類の検索キーワー

なっているため、実行ごとにクエリの構文が変化することが分ドから任意の数のキーワードを選んで検索するアプリケーショ

かる。

ンである。ブラウザの入力画面を Figure 4 に示す。検証に用い動作検証では、攻撃パターン (1)〜(3) による攻撃は成功し、た攻撃パターンは以下の 3 通りである。攻撃が成功したかどう

テーブルのすべてのデータが表示された。

かの確認方法はそれぞれの場合で異なる。

（ 2 ） PreparedStatement による実装（ 1 ） 認証回避

PreparedStatement による実装を行う場合、「クエリが定数の攻撃手法：パスワード欄に「” or ”a”=”a」と入力—5—

みから構成される」という制約条件を満たすためには、まず、5 種類のキーワードの 1〜5 組の組み合わせのため、31 通りの

SELECT

FROM*

utableテンプレートのクエリを用意する必要がある。次に、動作時のキーワードの数と種類を判定し、上記制約条件を満たした実装

OR

㱎

OR

㱎

“

㱎

“

=

“

㱎

“

=

“

㱎

“

=

“

㱎

“

=

“

㱎

“

“
OR

㱎

OR

㱎

合、脆弱性を防止できているかどうかの確認が困難になってしまう。確認を容易に行うためには、「入力値によって、元のコマ=“ることになる。また一方、制約条件を満たさなければ、動的にクエリを構築する実装を行うことも可能である。しかしその場

㱎“を行い、動作検証を行えば攻撃を防止することは不可能ではない。しかし、それを実現するためには著しくコード量が増加す

WHERE

“

ンドの構文が変えられないこと」という要件を満たす別の制約が必要になる。
（ 3 ） 提案ライブラリによる実装

Figure 5 AMNESIA が生成する SQL 構文モデル

提案ライブラリを用いたコードの一部を Source Code7 に示す。Source Code7 では、Statement クラスによる実装 (Source

する。従って AMNESIA ではこの攻撃は排除できないと考え
られる。

4

9

14

19

24

SafeStatement sstmnt = new SafeStatement();
sstmnt.add(UserConstValue.SELECT);
Set keyset = map.keySet();Iterator iter = keyset.iterator();boolean first = true;
while (iter.hasNext()) {String key =(String) iter.next();
String[] value = (String[]) map.get(key);if(value[0] != ""){
if(!first) {sstmnt.add(UserConstValue.OR);} else {sstmnt.add(UserConstValue.WHERE);}//query+= key + "=\"" + value[0] + "\"";
UserConstValue constKey = findKey(key);if(constKey != null) {sstmnt.add(constKey);} else {sstmnt.add(key);}
sstmnt.add(UserConstValue.EQ);
sstmnt.add(value[0]);first = false;}}
ResultSet rs = sstmnt.prepareAndExecute(con);
Source Code 7 提案ライブラリによる実装

Code2) と同様に、for ループを用いて動的にクエリを構築している。Statement との違いは、add() で静的要素の場合は定数を用いていることのにである。コード行数も、Source Code2の 19 行に対し、27 行と、コード的にも大きな差は見られない。
動作検証では、攻撃パターン (1)〜(3) による攻撃は失敗したことが確認された。
（ 4 ） AMNESIAAMNESIA はソースコードを静的に解析するため、Source
Code2 のループ回数の定まらないループでは、有限のオートマトンとして記述することができない。また、仮にループの最大値が 5 個と決定していた場合、その構文モデルは Fig-ure 5 に示す通りになるが、このモデルは動作検証で用いている攻撃 1 によって構築されるクエリパターン”SELECT *FROM utable WHERE userid=”” OR sex=”female”を許容

4. 3 評 価 結 果
動作検証による比較評価結果をまとめたものを Table 1 に示す。表で、○は用意した攻撃データに対しては、攻撃の検出または防止が可能であったことを、△は防止する実装を行うことが困難であることを、×は用意した攻撃データのうち少なくとも一つで攻撃の検出、防止ができない例があったことを示す。

PreparedStatement はバインド機構を用いない誤った実装を行った場合に、SQL インジェクションの防止ができなかった。
また、動的にクエリを構築する場合では AMNESIA では攻撃パターンの検出ができず、PreparedStatement のみでの実装は不可能ではないがクエリのパターン数に比例してコーディング
量が増加するため、実装コストや保守性などの面で問題がある。
一方、提案ライブラリを用いた手法では、いずれの場合でも検出または防止が可能であり、比較対象とした既存の SQL イン
ジェクション対策手法のいずれに対しても、対象としたアプリ
ケーションのパターンでは攻撃防止に関してより有効であるという結果になった。

5. 課題とライブラリの改善
5. 1 課題

今回提案ライブラリを用いて実装を行ってみて、プログラミ
ングの観点からいくつか課題があることが分かった。
（ 1 ） リクエストパラメータの key の扱い

Source Code7 では SQL クエリの構築に HTTP リクエストパ
ラメータが用いられている。このアプリケーションではリクエ
ストパラメーターの key には固定の値が使われているが、そのままでは提案ライブラリに追加しても定数とはみなされないた
め、PreparedStatement においてパラメータ扱いになってしまう。従って提案ライブラリで用いるためには、このパラメータの値を定数の値と比較し、一致していたら定数に変換する必要がある。正しく実装すれば問題はないのだが、単純な定数、非定数の使い分けあけではなく、コーディングに工夫が必要になる。リクエストパラメータの扱いについては改善の余地があると考えられる。

—6—アプリケーション Statement PreparedStatement 提案ライブラリ AMNESIA
正しい実装

×

○

○

○

誤った実装

−

×

○

−

動的なクエリ構築

×

△

○

×

Table 1 評 価 結 果（ 2 ） 誤った実装の場合の検出が不完全

はその SQL インジェクション向け実装について、他の既存の提案ライブラリで誤った実装 (静的要素を定数として追加しな手法と比較し、評価を行った。特に他の手法では検出や防止がかった) の場合でも、JDBC でシンタックスエラーになる場合

困難なアプリケーションについて、本提案ライブラリが有効でとならない場合がある。Source Code6 の場合はクエリ文字列

あることが確認できた。

が”? ? ? ?”となりシンタックスエラーになったが、5 で最初

一方、プログラミング容易性については、改善すべきいくつの文字列のみ定数を用いた場合、クエリ文字列は”SELECT *かの課題があることが明らかになった。また、今回のサンプル

FROM utable WHERE userid=? ? ?”となるが、この場合のアプリケーションは筆者らが設計、実装したものであり、プロ実行では MySQL の JDBC はシンタックスエラーにならない。

グラミングのし易さ、コーディングの自由度としては第三者的

ただし、SQL インジェクション攻撃自体は成功しない。このよな評価が必要であると考える。また、提案方式の性能的な評価

うに、プログラミングの誤り方によっては、うまくエラーが検も今後の課題である。

出できない場合もある。この対策としては、デバッグモードでReferences

生成クエリの文法チェックを行い、”SELECT * FROM utable[CVE07] National Vulnerability Database, common Vulnerabilities and Exposures, CVE–2007–1355, http://cve.mitre.
org/cgi-bin/cvename.cgi?name=CVE-2007-1355(2007).
[HO06] William G. J. Halfond, Alessandro Orso, Preventing SQL
injection attacks using AMNESIA, Proceeding of the 28th
international conference on Software engineering,pp.795798(2006).
[IPA07] 情 報 処 理 推 進 機 構, 情 報 セ キュリ ティ白 書 2007
年 度 版, http://www.ipa.go.jp/security/vuln/20070309_
ISwhitepaper.html(2007).
[OT07] Takao Okubo, Hidehiko Tanaka, Secure Sofoware Development through Coding Conventions and Frameworks, The
Second International Conference on Availability, Reliability
and Security (ARES’07), pp.1042-1051(2007).
[SQLB07] SQLBlock, http://www.sqlblock.com/(2007).

WHERE userid=? ? ?”のようなパターンを許容しないようにすればプログラミングの誤りの検出精度は挙がると考えられる。
（ 3 ） ライブラリ定義の定数はほぼ不要
ライブラリが提供する定数は要素単位のため、それを繋げたク
エリの文字列を構築するには要素数分の add() 処理を行う必要があり、非常にコーディングが煩雑になる。実際には、ユーザ定義の定数だけを使っていれば十分であることが分かった。
（ 4 ） 定数を変更した場合、再コンパイルが必要データベー
スのテーブル名に変更があった場合など、ユーザ定義の定数を変更しなければならない。現在のライブラリの実装では、ユーザ定義変数は Java 5 以降の enum を用いて定義されている。
これを変更する場合は Java クラス中の文字列を変更しなければならないため、再コンパイルが必要になる。ただし、この問題は提案ライブラリに特有ではなく、SQL 呼び出しを行うアプ
リケーション一般について言えることである。

5. 2 ライブラリの改善
上記に挙げた課題のうち、最後の課題についてユーザ定義定数クラスを改善し、定数の初期化の際に properties ファイルから値を読みこむようにした。これより、値が変わっても、再コンパイルの必要はなくなった。
ただし、ここで注意しなければならないのは、改善された
ユーザ定義定数クラスサーバ側のファイルやクラスに対する攻撃がないという前提条件が必要であるという点である。なんらかの手段で properties ファイルの内容が書きかえられてしまった場合、ファイルに攻撃文字列を挿入することで SQL インジェ
クションが可能になる恐れがある。また、ユーザ定義定数クラスを攻撃者によって置きかえられてしまうと、やはりインジェ
クション攻撃が可能になる。

6. お わ り に
筆者らは確認容易性に着目したインジェクション防止のためのコーディング規約とライブラリを提案しているが、本報告で—7—