SQLインジェクション攻撃への対策|脆弱性を悪用する仕組みと具体例

 個人情報などの漏えい事故が、しばしばニュースになっています。情報漏えいにはさまざまな原因がありますが、サイバー攻撃によるものも一定の割合で存在します。サイバー攻撃の場合はシステムの脆弱性を悪用するケースが多く、その中でもSQLインジェクションの脆弱性がよく悪用されます。ここでは、SQLインジェクションとは何なのか、どのような対策をすればいいのかを説明していきます。

1:SQLインジェクションとは

 SQLインジェクションとは、情報セキュリティにおける脆弱性のひとつで、この脆弱性が悪用されると、データベース上であらゆる操作を行われてしまいます。その結果、データベースにある情報を盗み出されたり、改ざんされたり、消去されるといった被害を受ける可能性があります。脆弱性の中でも悪用された際の影響が大きい脆弱性といえるでしょう。
 米MITRE社が中心となって仕様策定された「共通脆弱性タイプ一覧(CWE:Common Weakness Enumeration)」では、CWE-89が割り当てられていますが、OWASP(The Open Web Application Security Project)Top 10などでは「インジェクション」に集約されています。また、主にWebアプリケーションにおいてSQLインジェクションの脆弱性が多く発見されています。

2:SQLインジェクションの仕組み

2-1:仕組みと具体例

 SQLインジェクションの「SQL」とは、SQLサーバを操作する命令文を指します。SQLサーバはデータベースサーバのことで、ECサイト(ショッピングサイト)や会員登録を行うサイトなどで利用されます。具体的には、ユーザIDとパスワードを入力するようなサイトです。このようなWebサイトとデータベースが連携するサイトのことを「データベースドリブンWebサイト 」と呼びますが、こうしたサイトがSQLインジェクションの標的になります。
 一般的に、ユーザIDやパスワードを入力するエリアには、文字列しか入力しません。しかし、この入力エリアにSQL文を含ませた文字列を入力した場合、脆弱性があるとSQL文を命令文として認識してしまい、データベースの操作を可能にしてしまいます。データベースには重要な個人情報が記録されていることが多いので、情報漏えいなどの被害につながってしまいます。

 実際の攻撃例は、次のようになります。また、C#やSQL、PHP、Perlなど、SQLサーバが使用している言語を選ばないことも、SQLインジェクションの危険度を高めています。

・C#の例

string userName = ctx.getAuthenticatedUserName();
string query = “SELECT * FROM items WHERE owner = ‘” + userName + “‘ AND itemname = ‘” + ItemName.Text + “‘”;
sda = new SqlDataAdapter(query, conn);
DataTable dt = new DataTable();
sda.Fill(dt);

Webアプリケーションに、上記のようなコードが書かれていたとします。これは、次のクエリ(データベースへの問い合わせ)を実行しようとするものです。(ユーザ名ごとに情報が分けられているデータベースから、指定したユーザ名に一致する情報を指定する)

SELECT * FROM items WHERE owner = <userName> AND itemname = <itemName>;

しかし、このコードには脆弱性があり、ここに「OR ‘a’=’a」 (aは変数。例えば 1 などでも可)を追加することで、WHEREを常に真にして、正しいユーザIDとパスワードを入力することなく、データベースにアクセスが可能になります。

SELECT * FROM items WHERE owner = ‘USER01’ AND itemname = ‘name’ OR ‘a’=’a’;

「OR ‘a’=’a’」はitemnameの値に関係なく、検索条件が真として成立してしまい、itemnameが常に返ってくる構文になるため、ログインを許可されていないユーザでもログイン可能な状態になってしまうのです。これにより、USER01の情報だけではなく 、itemsテーブルに格納されているすべてのデータを操作することができます。
 結果として、以下の構文が実行されることと同じことになります。

SELECT * FROM items;

・SQLの例

SQLでは、ユーザIDとパスワードの組み合わせは、次のような形でチェックされます。(userが’USER01’で、かつ、passが’PASSWORD01’のデータを選択する)

SELECT*FROM user-table
WHERE user=’USER01′ and pass=’PASSWORD01′;

しかし、C#の例と同様に「’or’1’=’1」を使うことでユーザ認証を回避できます。

WHERE user=’USER01′ and pass=”PASSWORD1”or’1’=’1′;

同じように、以下のようなSQL文を使うことでデータの消去も可能です。

name’; DELETE FROM items; SELECT * FROM items WHERE ‘a’=’a

・PHPの例
メッセージIDを指定してメッセージのサマリを出力する、次のコードがあるとします。

$id = $_COOKIE[“mid”];
mysql_query(“SELECT MessageID, Subject FROM messages WHERE MessageID = ‘$id'”);

この場合も、(MessageID:1432 があったとして)「1432’or’1’=’1」を入力することで脆弱性を悪用できます。

SELECT MessageID, Subject FROM messages WHERE MessageID = ‘1432’ or ‘1’ = ‘1’

結果はこのようになり、1432のIDに関する情報だけでなく、すべてのメッセージIDに関する情報を取得できます。

2-2:SQLインジェクションが引き起こす問題

 SQLインジェクションの脆弱性が悪用されると、外部からデータベースを操作されてしまいます。この結果、データベースに記録されたデータの閲覧や盗難、変更、消去などを行われる可能性があります。個人情報を盗み出されてしまえば情報漏えい事故になりますし、盗み出された情報をさらに悪用される二次被害も考えられます。また、データを削除されてしまうと、ビジネスを継続できなくなってしまいます。より深刻なケースでは、サーバ自体を乗っ取られてしまう可能性もあります。SQLインジェクションは、莫大な金額の損害賠償に発展するような、深刻な被害を受ける可能性があるのです。

2-3:SQLインジェクションにより影響を受ける範囲

 Webサイトと連携しているデータベースが影響を受ける可能性があります。また、WebアプリケーションにSQLインジェクションの脆弱性が存在するケースも多く、このケースでも連携しているデータベースが影響を受ける可能性があります。

3:SQLインジェクション対策

 SQLインジェクション攻撃に対してどのような対策を講じていけばよいのでしょうか。ここでは代表的な対策を4つ解説します。

3-1:サーバでの対策

 SQLインジェクションは、主にWebアプリケーションのプログラムに問題があります。その問題は、入力した文字列にSQL文を仕込まれた場合に、それを命令文と認識してしまうことです。そのため、SQL文を成り立たせない実装が有効になります。これを「エスケープ処理」といいます。具体的には、SQL文で特別な意味を持つ記号や文字列を、別の文字に置き換えたり削除したりします。
 例えば、入力された文字列の中に「’」(シングルクォート)があった場合には、これを「”」(ダブルクォート)に置き換えます。これにより、ログイン認証を回避する「’or’1’=’1」というコードが「”or”1”=”1」に変換され、無害な普通の文字列として認識されるようになります。また「’」だけでなく「/」(バックスラッシュ)にも、同様の処理を行います。
 言語によっては、バインド機構(SQL文に変数の場所を示す記号を置いた後に実際の数値を割り当てる仕組みのこと)を利用することで、独自にエスケープ処理を行う必要がなくなります。このほか、入力エリアに入力できる文字や文字数などに制限を設けることも有効です。

3-2:ネットワークでの対策

 SQLインジェクションに限らず、脆弱性が公表されたときには、その脆弱性を解消するためのパッチやアップデートが合わせて公開されます。これらをすぐに適用すれば、脆弱性を狙った攻撃から保護することができます。しかし、Webアプリケーションの場合は、ほかに動作している多くのアプリケーションに悪影響を及ぼしてしまう可能性があるため、適用の前に検証が必要になります。
 しかし、検証には時間がかかりますし、検証後すぐに適用することも難しいのが現状です。とはいえ、あまり時間が空いてしまうと、脆弱性を悪用した攻撃が行われる可能性もあります。そこで最近、ニーズが高まっているのが「WAF(Webアプリケーション・ファイアウォール)」です。
 WAFは、Webアプリケーションに送られる通信をチェックするのですが、WAFはさまざまな脆弱性に対する攻撃コードをシグネチャとして持っていて、これと合致するコードを無効化します。つまり、脆弱性を解消するのではなく、その脆弱性を悪用しようとする攻撃を検知して対策を行います。導入や管理・運用が容易なクラウド型のWAFも複数提供されているため、脆弱性対策として導入を検討することも方法のひとつです。

3-3:Webに脆弱性がないか検査する

 SQLインジェクションに限らず、Webアプリケーションの脆弱性は定期的にチェックしたいものです。ベストな対応は、Webサイトで使用しているすべてのソフトウェアやアプリケーションのバージョンを把握し、パッチやアップデートが公開されたら迅速に適用することですが、なかなか難しいのが現状です。
 そこで、外部から擬似的な攻撃を行い、悪用されると危険な脆弱性があるかどうかを確認する「脆弱性診断」というサービスがあります。検査する脆弱性の内容はサービスによって異なりますが、多く使用されているものや、「OWASP Top 10」などに挙げられているものには対応しているケースが多くなっています。別のサービスに付帯しているケースも多いので、調べてみるとよいでしょう。

3-4:それぞれの立場で対策を

3-4-1:開発者

 Webアプリケーションやデータベースの開発者は、SQLインジェクションを引き起こされないようプログラミングする必要があります。最近では、セキュアプログラミングやシフトレフトなどとも呼ばれますが、脆弱性を作り込んでしまわないことが重要です。ガイドライン も複数出ていますので、参考にするとよいでしょう。

・IPA:「安全なウェブサイトの作り方
・OWASP Top 10:「最も重大なウェブアプリケーションリスクトップ10(PDF)
・JSSEC:「Androidアプリのセキュア設計・セキュアコーディングガイド
・経済産業省:「開発者向けセキュリティ関連コンテンツ」(リンク集)

3-4-2:発注者、社内IT部門など

 Webアプリケーションやデータベースなどを発注する側は、依頼書や仕様書に脆弱性対策があることを確認しましょう。また、IT部門など利用する側は、サーバなどの脆弱性対策の確認、あるいは利用するWebアプリケーションやソフトウェアのバージョン管理、定期的な脆弱性診断などを行います。WAFによる攻撃防御も検討しましょう。

4:まとめ

 情報セキュリティ対策では、よく「CIAの三大要素」が重要であるといわれます。CIAとは、「C:Confidentiality(機密性)」「I:Integrity(完全性)」「A:Availability(可用性)」の略で、この3つの要素を意識して対策を行います。SQLインジェクション対策に当てはめると、機密性は個人情報などの機密情報を守ること、完全性は情報の改ざんを防ぐこと、可用性は情報にアクセスできる状態を保つことといえます。この3点を意識して対策を行うようにしましょう。

マカフィー株式会社 マーケティング本部