TOP情報セキュリティ> 【セキュリティ最前線】セキュリティホールをついて遊ぶ> 第2回:PHPのSQLインジェクションを実体験 (2/3)

【セキュリティ最前線】セキュリティホールをついて遊ぶ

【セキュリティ最前線】
セキュリティホールをついて遊ぶ

第2回:PHPのSQLインジェクションを実体験

著者:大垣 靖男

公開日:2008/1/18(金)

何故不正なSQL文が実行されたのか?

Webブラウザに表示されたSQLクエリには「・」という、おかしな文字が表示されている(リスト7)。この文字は実際には「0x95,0x27」の2バイトのデータであり、文字化けが発生したことが原因で、このように表示されている。

実は「0x95」はShift SJIS文字エンコーディングのマルチバイト文字のはじまりバイトの1つであり、本来はそれに続く「0x27」で最初のLIKE条件の文字列が終了するはずが、「0x95,0x27」で1つのマルチバイト文字として取り扱われたため、2つ目のLIKE句条件で不正なSQL文の挿入を許してしまったのである。

つまり上記のクエリは実際にはリスト8のように、3つのSQL文として実行されていたことになる。

対策済みのPostgreSQLで実行した場合

PHPスクリプトは変更せず、データベースサーバを最新版のPostgreSQL 8.2.6にして同じテストを行うと、リスト9のエラーメッセージが表示される。

さらに「http://localhost/sql.php?q1=%95&q2=;DROP%20TABLE%20table2;--」のクエリ文字列の中で「%95」を「'」に変更し、「http://localhost/sql.php?q1='&q2=;DROP%20TABLE%20table2;--」という状態で実行すると、別のエラーが表示される(リスト10)。

このようにPostgreSQLは不正なマルチバイト文字エンコーディングを正しく検出し、SQLインジェクションを防止してくれる。

リスト7:SQLクエリの実行結果(再掲)
SELECT * FROM table1 WHERE field1 LIKE '・ or field2 LIKE ';DROP TABLE table2;--';

リスト8:SQLクエリの実行内容
SELECT * FROM table1 WHERE field1 LIKE '・ or field2 LIKE ';
DROP TABLE table2;

リスト9:PostgreSQL 8.2.6でのエラーメッセージ
Warning: pg_query() [function.pg-query]: Query failed: ERROR: invalid byte value for encoding "SQL_ASCII": 0x95 in /home/yohgaki/public_html/sql.php on line 20

SELECT * FROM table1 WHERE field1 LIKE '・ or field2 LIKE ';DROP TABLE table2;--';

リスト10:「%95」を「'」に変更した際のエラー表示
Warning: pg_query() [function.pg-query]: Query failed: ERROR: unsafe use of \' in a string literal
LINE 1: SELECT * FROM table1 WHERE field1 LIKE '\'' or field2 LIKE '...
                                               ^
HINT: Use '' to write quotes in strings. \' is insecure in client-only encodings. in /home/yohgaki/public_html/sql.php on line 20

文字エンコーディングベースのSQLインジェクション

この実験では不正なShift JISマルチバイト文字となるデータを生成してSQLインジェクションを実行した。

この方法以外にも「正しい」マルチバイト文字を利用する方法がある。例えば、Shift JISの「表」は「0x95,0x5c」の2バイトで表現される。「0x5c」はASCII文字の「\」のため、文字エンコーディングを考慮しないaddslashes関数でエスケープすると、本来はマルチバイト文字1文字である「表」の後半に余計な「\」を追加してしまう。

この結果として、クオートで囲まれたSQLクエリパラメータは「'+0x95+0x5c+0x5c' ('表\')」といった文字列となる。この文字列はShift JISとして正しいために、サーバ側ではユーザが意図したクエリなのか、SQLインジェクション攻撃の可能性がある不正なデータなのかを判別できない。

文字エンコーディングを利用したSQLインジェクションは、データベースの仕様や設定、PHPスクリプトなどの条件が整わないと実行できないタイプの攻撃だ。しかし、外部から脆弱性が存在しないか確認することは難しくない。このため、通常のSQLインジェクション対策と同様に注意が必要といえる。 次のページ




大垣靖男(OHGAKI, Yasuo)
著者プロフィール
大垣靖男(OHGAKI, Yasuo)
University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て、エレクトロニック・サービス・イニシアチブ有限会社を設立。Linuxはバージョン0.9xの黎明期から利用してるが、オープンソースシステム開発やコミュニティへの参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトのPostgreSQLモジュールのメンテナ、日本PostgreSQLユーザ会の四国地域での活動等を担当している。


INDEX
第2回:PHPのSQLインジェクションを実体験
  PHPでSQLインジェクションを実体験
何故不正なSQL文が実行されたのか?
  文字エンコーディングベースのSQLインジェクションの防止方法