SQLインジェクション

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

SQLインジェクション: SQL Injection)とは、アプリケーションのセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法のこと。また、その攻撃を可能とする脆弱性のこと。

SQLに別のSQL文を「注入 (inject)」されることから、「ダイレクトSQLコマンドインジェクション」とも呼ばれる。

原理と対策[編集]

アプリケーションが入力値を適切にエスケープしないままSQL中に展開することで発生する。

次のようなSQLを発行することを考える。

SELECT * FROM users WHERE name = '(入力値)';

ここで入力値に "t' OR 't' = 't" という文字列を与えた場合を考えると、SQL文は次のように展開される。

SELECT * FROM users WHERE name = 't' OR 't' = 't';

このSQL文では条件が常に真となるため、nameカラムの値にかかわらず、全レコードが選択される。このような攻撃は、入力値が1つだけのものには限られない。

これを応用したものに、SELECTの条件式にデータベース内の情報を確認するようなサブクエリーを含ませ、その抽出の成否によって本来参照することのできないデータベース内の情報(テーブル名など)を知るといった、ブラインドSQLインジェクションと呼ばれる手法も存在する[1]。例えば、テーブル名の1文字目がaのテーブルは存在するか?aで始まり2文字目がbのテーブルは存在するか?などの情報を確認するサブクエリーを含め、その抽出の成否を丹念に集めていけば、テーブル名や項目名を確認できるといった具合である。

また、複数のSQL文を注入することによるデータの破壊や改竄、ストアドプロシージャを実行されることによる情報の漏洩や改竄、OSコマンドの実行などを引き起こすこともできる場合がある。

SQLインジェクションは、入力値を適切にエスケープすることで防ぐことができる。上述の文字列中への展開では、メタ文字 ''' (単一引用符2つ)にエスケープすることにより、次のようなSQLになり、意図されたとおりnameカラムが "t' OR 't' = 't" という値を持つレコードが選択される。

(単一引用符を2回連続して記述すると、ひとつの ' という文字リテラルとして認識される。)

SELECT * FROM users WHERE name = 't'' OR ''t'' = ''t';

但し、データベースシステムによっては、単一引用符以外の囲み文字を用いて文字列リテラルを示すことができるものが存在する。例えば、MySQLでは動作モードによっては二重引用符を文字列の囲み文字として使用可能である[2]。このような環境下において、上記のようなSQL文の生成を行うプログラム中で二重引用符を囲み文字を用いているなら、二重引用符をエスケープする必要がある。

他には、文字列リテラル中の単一引用符を表現する方法が複数存在するものもある。例えばMySQLやPostgreSQLのバージョンや設定次第では、エスケープシーケンスプレフィックスとしてバックスラッシュを使用して特殊文字を表現することが可能である。この方法を用いると \'\047 (注:047は単一引用符の8進表記)という文字列が文字列リテラル中の単一引用符を表すことになる。このようなデータベースシステムにおいて、単純に単一引用符を2重化するだけではSQLインジェクション対策としては不充分である。例えば入力値に "\' OR 1=1 --" という文字列を与え、そこに含まれる単一引用符を単純に2重化すると、上述のSQLは以下のように解釈される。

SELECT * FROM users WHERE name = '\'' OR 1=1 --';

2重化された単一引用符のうち、前者は前置されたバックスラッシュと合わさって文字列リテラル中の単一引用符を意味することになり、後者は文字列リテラルの終端を意味することになる。ここで -- 以降がコメントと見なされれば、このSQLの条件は常に真となり、SQLインジェクションが成立することになる。つまり、バックスラッシュもエスケープを必要とするわけである。

更には、文字コードによっては2バイト目にバックスラッシュが含まれる文字を有するものが存在し、エスケープ処理を行うライブラリによっては日本語をうまく扱えないために、前述のようなエスケープシーケンスとしてバックスラッシュが機能することもありえる。データベースにSQLを発行する言語側の事情により、文字コード変換が自動的に発生することに伴って、前述のようなエスケープシーケンスとしてバックスラッシュが機能することもありえる[3]

このように、SQLインジェクションを防ぐには入力値を適切にエスケープできればよいといっても、適切にエスケープする方法はそんなに単純なものではない。データベースシステムやライブラリによっては、バインド機構と呼ばれる仕組みを用いてエスケープ処理不要で安全にSQLを発行する方法が設けられているものがあり、対策もれを防ぐ上で有用である。

文字列リテラル以外では適切なエスケープ法がSQL標準に定義されていないので、ホワイトリスト(許可リスト)方式による入力値の検証を行うことで代用とする。例えば、整数値であれば0から9までの数字のみで構成された入力値のみを認めると言った具合である。

なお、SQLインジェクションには準備された文 (prepared statement) が有効であると説明される場合があるが、正確な意味では、正しくないので注意が必要である。 本来SQLの本来のPrepared文(Prepared statement)とは、下記の様な表記を言う。

PREPARE ps( text ) AS INSERT INTO example( VALUE ) VALUES( $1 ); /* psというPrepared文を作成する */
 
/* psを実行する。 */
EXECUTE ps( 'value1' );
EXECUTE ps( 'value2' );

SQL本来のPrepared文は、その他のSQL文と同様単なるSQLでしかない。このためSQLのPrepared文の使用を徹底した所でSQLインジェクションを防ぐことは出来ない。俗に推奨されている「準備された文 (prepared statement) 」とは、SQLのPrepared文ではなく、JDBCといったライブラリやDB付属のライブラリにより提供されているバインド機構を備えたPrepared文のラッパー機能のことである。本来のPrepared文(Prepared statement)と俗に言う「準備された文 (prepared statement) 」では危険性が大きく違うので注意が必要である。

また、ラッパーライブラリにより提供されるPrepared文のバインド機構でも完全に安全とは言えないので注意が必要である。例えばJavaでよく使われるJDBCの仕様には、Prepared文のバインド機構がエスケープ処理(サニタイジング)をしなければならないと明記されていない。仮にエスケープ処理不十分な実装であっても仕様上は問題ないのである。特にJDBCに限った話ではないが、近年まで多くのDBMSはバイナリー文字の一貫した対策をしていなかった。特にNULL文字の扱いはライブラリによって大きく変わる。例えば、MySQLにおいてはバインド機構を使っていても文字列中にNULL文字列を持たせることが出来る。対照的にPostgreSQLではNULLが含まれていればエラーとなる。この様な差異をバインド機構の利用者が見落としていた場合脆弱性の原因となりうる。

JavaではSQLインジェクション対策としてPrepared文が多用されがちである。しかしPrepared文は、本来事前にSQLを内部形式に変換しその後の呼び出しを軽減する事を目的とした機能である。このためwhere句で関数が呼び出されるようなSQL発行時にしか最適化がしづらい場合では劇的に速度が低下する。特にインデックスが効かなくなるため指数的に速度が低下するようになる。この様な問題があるため現実ではPrepared文に頼り切る事は出来ない。DBMSの提供元がSQLインジェクション対策として仕様に明記しているようなPrepared文に依存しない対策方法を知っておくことが重要である。

実例[編集]

  • 2005年3月に発生した、クラブツーリズムのクレジットカード情報を含む個人情報漏洩
    同年6月にクラブツーリズムを含む14社への不正アクセスの疑いで中国人留学生が逮捕された。
  • 2005年5月に発生した、価格.comのWebサイト改竄
    手口は、公式には秘匿されているが、SQLインジェクションによるものであるという説がある。クラブツーリズム事件の犯人は価格.comへの不正アクセスも行っていた。
  • 2005年6月に判明した、アデコの個人情報漏洩 - クラブツーリズム事件と同一犯
  • 2005年8月に判明した、静岡新聞社アットエスの個人情報漏洩 - クラブツーリズム事件と同一犯
  • 2005年11月に発生した、ワコールオンラインショップのクレジットカード情報を含む個人情報漏洩
  • 2005年11月に発生した、キッズオンラインのアカウント情報漏洩
  • 2006年1月に判明した、スカイソフトのクレジットカード情報を含む個人情報漏洩
    スカイソフトは閉店へと追い込まれた。
  • 2006年4月に発生した、るるぶのアカウント情報漏洩
  • 2006年6月に発生した、日本体育協会のWebサイト改竄
  • 2007年7月に判明した、@SOLAショップのクレジットカード情報を含む個人情報漏洩
  • 2008年3月に発生した、トレンドマイクロ@niftyクリエイティブメディアのWebサイト改竄
  • 2008年3月に発生した、サウンドハウスのクレジットカード情報を含む個人情報漏洩
    過去に設置された不正プログラムを経由して不正アクセスが行われた疑いがある。
  • 2008年4月に発生した、カービューのWebサイト改竄
  • 2008年5月に発生した、アイドラッグストアーアイビューティーストアーのクレジットカード情報を含む個人情報漏洩
  • 2008年5月に発生した、富士山マガジンサービスのWebサイト改竄
  • 2008年6月に発生した、アイリスプラザのクレジットカード情報漏洩
  • 2008年7月に判明した、ナチュラムのクレジットカード情報を含む個人情報漏洩
    過去に設置された不正プログラムを経由して不正アクセスが行われた疑いがある。
  • 2008年7月に発生した、米国向けPlayStationのWebサイト改竄
  • 2008年7月に発生した、独立行政法人石油天然ガス・金属鉱物資源機構のWebサイト改竄
  • 2008年10月に発生した、ゴルフダイジェスト・オンラインのWebサイト改竄
  • 2010年1月に発生した、モンベルのクレジットカード情報漏洩
  • 2010年7月に発生した、コーエーテクモホールディングスのGAMECITY会員の個人情報漏洩[4]
  • 2011年4月から発生している、ソニーのPlayStation Networkの個人情報漏洩に始まる、ソニーグループの個人情報漏洩。
  • 2013年4月に判明した、エクスコムグローバルのクレジットカード情報漏洩
    10万9112件のカード名義人名、カード番号、カード有効期限、セキュリティコード、申込者住所が外部へ流出したことを確認。

2008年3月頃より、SQLインジェクションによるWebサイトの改竄が多発している[5]

情報が流出した場合には企業存続の危機につながりかねない。情報処理推進機構(IPA)はSQLインジェクションによる被害からの復旧コストは1億円を超えうるとしており[6]、実際にサウンドハウスの事例では補償のみでも122884名に1000円相当の期限付きクレジットを負担している。補償のほかにも専門家による調査、システムの入れ替え、顧客対応、一時閉鎖による営業機会の逸失、風評被害といった負担があり、SQLインジェクションも含めセキュリティ対策は厳密に行うべきである。しかしながら、NRIセキュアが企業を対象に2007年度に行ったセキュリティ診断の統計では、41%のWebサイトが不正アクセス可能であり、そのうち22%でSQLインジェクション攻撃に対する脆弱性があった[7]。また、この統計において、SQLインジェクションの脆弱性のうち84%が、対策を行っていたが抜け穴があるというものであった。

脚注[編集]

  1. ^ Blind SQL Injection white paper”. 2011年7月6日閲覧。
  2. ^ MySQL 5.1 リファレンスマニュアル 8.1.1 文字列”. 2011年7月6日閲覧。
  3. ^ 異なる文字集合への変換がぜい弱性につながる”. 2011年7月6日閲覧。
  4. ^ コーエーテクモホールディングス株式会社 - 不正アクセスによるお客様個人情報漏洩のお詫びとご報告、2010年7月20日。
  5. ^ JPCERT / CCによる注意喚起
  6. ^ Internet Watch - SQLインジェクションの復旧コスト、1億円超える事例も~IPAが報告書、2006年11月29日。
  7. ^ NRIセキュア - Webサイトのセキュリティ診断:傾向分析レポート2008、2008年7月28日。

関連項目[編集]

外部リンク[編集]