| SQLインジェクション対策はおすみですか? 開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、 脆弱性発見後の適切な対策まで |
2008-12-22
●JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性
今年のBlack Hat Japanには、はせがわようすけ氏が「趣味と実益の文字コード攻撃」と題して講演され話題となった。その講演資料が公開されているので、私は講演は聞き逃したが、資料は興味深く拝見した。その講演資料のP20以降には、「多対一の変換」と題して、UnicodeのU+00A5(通貨記号としての¥)が、他の文字コードに変換される際にバックスラッシュ「\」(日本語環境では通貨記号)の0x5Cに変換されることから、パストラバーサルが発生する例が紹介されている。
しかし、バックスラッシュと言えばSQLインジェクションの可能性も見逃すことができない。そこで、本資料をきっかけとして、U+00A5を使ったSQLインジェクションの可能性について調査し、Java(JDBC)とMySQLの組み合わせにおいて、発生する場合があることを確認したので報告する。
U+00A5を用いたSQLインジェクションとは
ここで、U+00A5を用いたSQLインジェクションとはどのようなものかを説明しよう。UnicodeのU+00A5はバックスラッシュとは独立に扱える日本円の通貨記号として割り当てられている。この文字をShift_JISやEUC-JPなどに変換する際に、ASCIIの0x5Cに変換される(場合がある)。すると、バックスラッシュをSQLのエスケープに使用するデータベース、具体的にはMySQLとPostgreSQLにおいて、SQLインジェクションが発生する場合がある
具体例を用いて説明しよう。検査パターンとして以下の文字列を使用する。以下、U+00A5を表記する場合には赤色全角の通貨記号「¥」を用いる
¥'OR 1=1#
先頭の文字がU+00A5である。これをMySQLのルールでエスケープすると、シングルクォートが「\'」と変換され、以下のようになる。
¥\'OR 1=1#
ややこしいが、最初の通貨記号がU+00A5、二番目の通貨記号が0x5Cである。これをShift_JISあるいはEUC-JPに変換すると以下のように、二文字とも0x5Cになる。
\\'OR 1=1#
これをSQLとして解釈すると、最初の「\\」が「\」をエスケープしたものと見なされ、「'」はエスケープされない状態となる。すなわち、SQLインジェクションされたことになる。
どのような場合に問題になるか
このタイプのSQLインジェクションが発生するのは、以下のようなケースが典型的な場合であろう。
- 外部とのインターフェースにUnicode(典型的にはUTF-8)を用いていて、U+00A5を入力することができる
- アプリケーションの内部でもUnicode(UCS-2、UTF-16、UTF-8など)を用いている
- SQLのエスケープはUnicodeの状態で実行している
- アプリケーションからデータベースのクエリ実行までのどこかで、Unicode以外の文字コード(典型的には、Shift_JISかEUC-JP)に変換されている
内部コードとしてUnicodeを用いる言語は現在では数多いが、筆者はJavaとPerl(use utf8;)を用いて検証した。その結果、JavaとMySQLの組み合わせの場合にSQLインジェクションが発生する場合があることを確認した
検証コードの説明
以下のような検証コードを用いてテストした。
import java.sql.*;
public class MyA5Injection {
public static void main(String[] args) {
try {
String charEncoding = "sjis"; // or "utf8"
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost/tokumaru?user=xxx&password=xxxx&useUnicode=true&characterEncoding=" + charEncoding);
Statement stmt = con.createStatement();
String param = "\u00a5'or 1=1#";
// MySQL用のエスケープ
String e_param = param.replaceAll("\\\\", "\\\\\\\\"); // \ → \\
e_param = e_param.replaceAll("'", "\\\\'"); // ' → \'
String sql = "SELECT * FROM test WHERE name='" + e_param + "'";
System.out.println("sql = " + sql);
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
System.err.println(id + " " + name);
}
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
実行結果は以下の通り
C:\HOME\Java>java MyA5Injection sql = SELECT * FROM test WHERE name='\\'or 1=1#' 〜 検索結果の表示 〜
テスト結果
U+00A5を用いたSQLインジェクションは、JDBCのgetConnectionメソッドに指定するオプションパラメータcharacterEncodingに依存するようだ。このパラメタがUTF-8の場合はSQLインジェクションは発生しない。一方、Shift_JISやEUC-JPの場合はSQLインジェクションが発生する。create tableのdefault charset設定には依存しないようだ。これらを下表にまとめた。
| UTF-8のテーブル | Shift_JISのテーブル | |
|---|---|---|
| characterEncoding=utf8 | 正常処理 | エラー(*1) |
| characterEncoding=sjis | SQLインジェクション | SQLインジェクション |
検証に用いた環境 MySQL 5.0 および 5.1 MySQL Connector/J 5.1.7 JDK6 Update11 Windows XP Professional (*1) java.sql.SQLException: Illegal mix of collations (sjis_japanese_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='
現実的に脆弱となる組み合わせはどの程度使用されているか
現実にSQLインジェクションが発生するは、JavaとMySQLの組み合わせすべではなく、characterEncodingの指定が明示的あるいは暗黙にutf8以外の値になっている場合と考えられる。筆者が試した範囲では、MySQLのコンフィグレーション・ウィザードで「Best Support for Multilingualism MySQL」を指定した場合にはUTF-8が利用されるが、それ以外の場合はlatin1、あるいはユーザが指定した文字エンコーディング(Shift_JISなど)が設定される。また、GoogleでgetConnectionを検索すると、characterEncoding=sjisと記述した例が多数ヒットしている。そのような状況では、characterEncodingとしてUTF-8以外が指定されている比率は割合に多いのではないかと予想する。
その他の言語とDBの組み合わせの場合はどうか
筆者が他の組み合わせで試した範囲では、Java+PostgreSQLやPerl+MySQLではSQLインジェクションにはならなかった。Java+PostgreSQLの場合はエラーになり、Perlの場合はU+00A5が「?」に変換されるようで、やはりSQLインジェクションにはならなかった。しかし、筆者が試したものと別の条件ではSQLインジェクションが発生する可能性はゼロではない。
対策
はせがわようすけ氏の講演資料には以下のような対策が推奨されている
- Unicodeのまま文字列を扱い、変換しない
- (変換するとしても)検査後には変換しない
SQLインジェクション対策としても「変換しない」というガイドラインは有効である。すなわち、以下を推奨する。
- characterEncoding=utf8を明示する(必須)
- create tableの際のdefault charsetにもutf8を設定する(推奨)
追記(2008/12/22 14:00)
金床氏から「例のコードがPreparedStatementじゃないのは何故だろう」という指摘を受けた。原理を示すためにはエスケープの方が分かりやすいと思ったからだが、PreparedStatementでも試してみた。主なコードの変更点は以下の通り(エスケープ処理は必要なくなる)。
String sql = "SELECT * FROM test where name=?";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1, param);
ResultSet rs = stmt.executeQuery();
結果は、エスケープの時とまったく同じであった。MySQL 5.1でも直っていない…というか、これは仕様かもしれない。やはり、文字エンコーディングはアプリからDBまでそろえよう。
追記(2008/12/24 00:00)
へぼへぼCTO日記さんからトラックバックを頂戴した。Connector/JでサーバーサイドのpreparedStatementを使用するには、オプションuseServerPrepStmts=trueを指定しなければならないとのこと。手元の環境でテストしたところ、同オプションを指定したところU+00A5によるSQLインジェクションは再現しなくなった。ご指摘ありがとうございます。
http://www.tokumaru.org/d/20081222.html#p01 PreparedStatementに関することが書いていないので、参考まで。 http://d.hatena.ne.jp/ikepyon/20061215#p2 http://d.hatena.ne.jp/ikepyon/20070216#p1 http://d.hatena.ne.jp/ikepyon/20061208#p2 ま、一文だけだけどなw
UnicodeのU+00A5問題
JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性
なるほど。この問題は初耳だったので驚いた。
しかも、PreparedStatementを使っても解...
ここ数日「MySQL + Connector/J(JDBCドライバ) + プリペアードステートメント」の話題がちらほら出ています。正確に把握はしていないですがSQLインジェクション対策→PreparedStatementという流れできた話のようです。 徳丸浩の日記 - JavaとMySQLの組み合わせでUnicodeのU+
PreparedStatement使ってるのにSQLインジェクションが起きるんですけど?という話題。徳丸浩の日記 - JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性より。 再現したのでバグレポート投げておきました。MySQL Bugs: #41730: SQL Injection w
以前のエントリで紹介したMySQLのJDBCドライバConnector/J 5.1.7のSQLインジェクション脆弱性ですが、ようやくパッチができたようです。 public void setString(int parameterIndex, String x) throws SQLException { … for (int i = 0; i < stringLength; ++i) { … c
前回に引き続き、U+00A5に起因するXSSの可能性とその対策について検討します。
- http://php.designlinkdatabase.net/data/frame_21350... ×5 : 3, 2
- http://clip.nifty.com/entry/531e0f11b3b826fcfe8655... ×4 : 3, 1
- http://php.designlinkdatabase.net/data/frame_20624... ×2
- http://search.auone.jp/?q=java ラベル付ループ&sr=0001&lin... ×1
- http://php.designlinkdatabase.net/data/frame_20684... ×1
- http://clip.nifty.com/entry/aa202f42f3cdc64a8c4626... ×1
- http://www.tokumaru.org/ ×433
- http://www.hash-c.co.jp/ ×181
- http://www.tokumaru.org/JavaScript/ ×137
- http://www.geminium.com/chiba_blog/2008/12/23/33/ ×61
- http://b.hatena.ne.jp/entry/http://www.tokumaru.or... ×53
- http://www.doyouphp.jp/book/book_hajimete.shtml ×53
- http://d.hatena.ne.jp/ockeghem/20090307/p1 ×42
- http://d.hatena.ne.jp/sh2/20081224 ×42
- http://www.ideaxidea.com/archives/2008/10/php_1.ht... ×41
- http://look2.jp/r.php?id=supportkaiseki&no=6648514... ×39
- http://d.hatena.ne.jp/InoHiro/20081220/1230074998 ×39
- http://d.hatena.ne.jp/ockeghem/20090221/p1 ×36
- http://bakera.jp/ebi/topic/3469 ×34
- http://bakera.jp/ebi ×33
- http://b.hatena.ne.jp/hotentry/it ×29
- http://okyuu.com/ja/tips/986 ×25
- http://d.hatena.ne.jp/ockeghem/ ×25
- http://d.hatena.ne.jp/mir/20081224/p2 ×23
- http://b.hatena.ne.jp/entry/11389813/徳丸浩の日記 - Java... ×19
- http://d.hatena.ne.jp/ockeghem/20080622/p1 ×18
- http://ja.reddit.com/r/ja ×18
- http://www.reddit.com/r/ja/comments/7kza1/徳丸浩の日記/ ×18
- http://d.hatena.ne.jp/ockeghem/20090221 ×18
- http://d.hatena.ne.jp/ockeghem/20071021/1192986523... ×17
- http://d.hatena.ne.jp/ockeghem/20071210/p1 ×17
- http://ideaup.seesaa.net/article/108141154.html ×16
- http://codezine.jp/bookmark/ ×15
- http://www.hash-c.co.jp/d/ ×14
- http://okyuu.com/ja/tips/2803 ×14
- http://d.hatena.ne.jp/ockeghem/20081112/p1 ×13
- http://d.hatena.ne.jp/ockeghem/20081101/p1 ×13
- http://www.tokumaru.org/was/ ×12
- http://d.hatena.ne.jp/ockeghem/20090302/p1 ×12
- http://b.hatena.ne.jp/nihen/ ×12
- http://d.hatena.ne.jp/ripjyr/20080819/1219108676 ×12
- http://okyuu.com/ja/tips/1546 ×12
- http://d.hatena.ne.jp/ockeghem/about ×12
- http://memo.hirosiki.jp/article/108099626.html ×12
- http://d.hatena.ne.jp/teracc/20070715 ×12
- http://www.tokumaru.org/techterm/ ×11
- http://anond.hatelabo.jp/keyword/リファレンス ×11
- http://buzzurl.jp/entry/徳丸浩の日記 - JavaとMySQLの組み合わせで... ×10
- http://kago.in/hatena/index.php?mozi=SQLインジェクション ×10
- http://yamagata.int21h.jp/d/ ×10
- http://db.designiddatabase.net/data/frame_242844.a... ×10
- http://www.tokumaru.org/d/20080502.html ×9
- http://www.tokumaru.org/d/20080822.html ×9
- http://labo.shimi-zoo.com/?q=node/32 ×9
- http://www.tokumaru.org ×9
- http://b.hatena.ne.jp/entry/6660206/徳丸浩の日記 - [Java... ×8
- http://b.hatena.ne.jp/hotentry/20081222 ×8
- http://ja.reddit.com/r/ja/ ×8
- http://www.devnull.jp/tdiary/ ×8
- http://blog.ohgaki.net/session-adoption-attack ×8
- http://bakera.jp/ebi/topic/2986 ×8
- http://d.hatena.ne.jp/ockeghem/20070224 ×8
- http://secure.ddo.jp/~kaku/tdiary/200810.html ×8
- http://d.hatena.ne.jp/m383m/20070918/1190100985 ×8
- http://b.hatena.ne.jp/hotentry/daily ×7
- http://b.hatena.ne.jp/entry/http://blog.ohgaki.net... ×7
- http://blog.ohgaki.net/php-session ×7
- http://labs.cybozu.co.jp/blog/takesako/2007/08/lls... ×7
- http://www.trekdevel.net/archives/500 ×7
- http://kinshachi.ddo.jp/blog/comp/archives/000807.... ×7
- http://blog.webcreativepark.net/2008/10/24-201629.... ×7
- http://b.hatena.ne.jp/entry/11389813/徳丸浩の日記 - Java... ×7
- http://bakera.jp/ebi/topic/3133 ×7
- http://www.tokumaru.org/d/20070717.html ×7
- http://www.reddit.com/r/ja/ ×7
- http://b.hatena.ne.jp/entry/8817669/徳丸浩の日記 - SQLイン... ×6
- http://www.tokumaru.org/JavaScript/index.htm ×6
- http://www.tokumaru.org/d/20070905.html ×6
- http://b.hatena.ne.jp/hasegawayosuke/ ×6
- http://tokumaru.org/was/ ×6
- http://www.math.sansu.org/u/diary/?date=200706 ×6
- http://d.hatena.ne.jp/ockeghem/20081109/p1 ×6
- http://stressfulangel.cocolog-nifty.com/stressful_... ×6
- http://d.hatena.ne.jp/ockeghem/?of=15 ×6
- http://blog.ohgaki.net/-13 ×6
- http://www.reddit.com/r/ja ×6
- http://labs.unoh.net/2008/10/php_53.html ×6
- http://labs.ceek.jp/hbnews/ ×5
- http://codezine.jp/bookmark/?dt=20081222 ×5
- http://secure.ddo.jp/~kaku/tdiary/200805.html ×5
- http://tokumaru.org/d/20080601.html ×5
- http://209.85.175.132/search?q=cache:FC8LJ8TBxK4J:... ×5
- http://labs.cybozu.co.jp/blog/kazuho/archives/2007... ×5
- http://search.live.com/results.aspx?q=rebinding ×5
- http://gp.ath.cx/unco//page?page_id=345 ×5
- http://clip.livedoor.com/page/3393371/徳丸浩の日記 - Jav... ×5
- http://d.hatena.ne.jp/ockeghem/?of=10 ×5
- http://d.hatena.ne.jp/teracc/20080914 ×5
- http://javascriptist.net/docs/news.html ×5
- http://bakera.jp/ebi/topic/3221 ×5
- http://zapanet.info/new/hatebu4/ ×5
- http://takagi-hiromitsu.jp/diary/20080620.html ×4
- http://search.live.com/results.aspx?q=imagefight ×4
- http://labs.ceek.jp/hbnews/list.cgi ×4
- http://www.geminium.com/chiba_blog/ ×4
- http://koteitan.seesaa.net/article/95301330.html ×4
- WAF ×56 / キーワード不明 ×52 / 徳丸浩 ×51 / SQL エスケープ ×49 / javascript break ×35 / session_set_save_handler ×26 / sql エスケープ ×19 / waf ×16 / sql エスケープ文字 ×14 / postgres sql エスケープ ×14 / 画像 XSS ×13 / SQLインジェクション 対策 ×10 / 徳丸 浩 ×10 / sqlインジェクション 対策 ×9 / PHP 携帯 ×9 / PHP×携帯サイト デベロッパーズバイブル ×9 / php 携帯 ×8 / javascript ラベル ×8 / はじめてのPHPプログラミング ×7 / sqlインジェクション エスケープ ×7 / ホワイトリスト ×7 / php 携帯電話 セッション管理 ×7 / sql escape ×7 / WAF 徳丸 ×7 / 徳丸 XSS 画像 ×6 / セッション管理 携帯 HTTP ×5 / 画像XSS ×5 / U+00A5 ×5 / DNS アプレット キャッシュ ×5 / SQLインジェクション エスケープ ×5 / 佐名木 徳丸 ×5 / 携帯 サイト 書籍 ×5 / php 携帯 ログイン管理 ×5 / バインド機構 Oracle ×5 / パストラバーサル ×4 / character Encoding sjis ×4 / はじめてのphpプログラミング ×4 / mod_imagefight ×4 / PHP 1 はじめてのPHPプログラミング ×4 / xFFxD8 ×4 / Webアプリケーションの脆弱性とその対策 ×4 / ホワイトリスト 入力 ×4 / javascript switch ×4 / プリペアードステートメント java SQLインジェクション ×4 / php 携帯サイト ×4 / SQL ESCAPE ×3 / escape sqlserver ×3 / XSS 対策 ×3 / sqlインジェクション エスケープ java ×3 / IE 画像 XSS ×3 / javascript if break ×3 / sql ' エスケープ ×3 / standard_conforming_strings SQLインジェクション ×3 / 携帯端末用サイト クロスサイト ×3 / XSS ×3 / javascript 画像 たて ×3 / SQLSERVER エスケープ SQLインジェクション ×3 / Oracle 暗黙変換 リリースノート ×3 / はせがわ unicode ×3 / 金床 セキュリティ ×3 / SQLインジェクション エスケープ 徳丸 ×3 / SQLの複文 ×3 / JavaScript XSS 徳丸 ×3 / エスケープとは sql server ×3 / php携帯 ×3 / 画像 スクリプト 埋め込み ×3 / ファイル攻撃 XSS ×3 / web テスト javascript エスケープ ×3 / sql-server エスケープ ×3 / sqlserver エスケープ文字 ×3 / PHPプログラミング ×3 / XSS チェック方法 ×3 / はじめてのPHPプログラミング基本編 5.3対応 ×3 / mysql sqlインジェクション 対象文字 ×3 / Escape 関数組合せ ×3 / 携帯電話 セッション管理 個体識別番号 ×3 / mysql 複文 ×3 / 画像xss イベントハンドラ ×3 / SQL 2005 エスケープ文字 ×3 / IEEE754 ×3 / mysql 入力出来ない日本語 解決 java ×3 / php 携帯 ×3 / XSS 検証 javascript ×3 / XSS 検査 ×3 / oracle sql エスケープ文字 ×3 / 携帯サイト Webアプリ セキュリティ ×3 / SQL % エスケープ ×3 / waf ホワイトリスト ブラックリスト ×3 / Java Unicode ×3 / SQLエスケープ ×3 / 画像のXSS ×3 / java replaceall postgres エスケープ ×3 / java mysql server ×3 / プリペアードステートメント mysql like検索 java ×3 / 非正規化数 IEEE754 ×3 / U+00A5 unicode ×3 / 徳丸 WAF ×3 / http://www.tokumaru.org/d/20080819.html ×2 / mysql バックスラッシュ ×2 / sql リテラル バインド ×2
| SQLインジェクション対策はおすみですか? 開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、 脆弱性発見後の適切な対策まで |