Connector/JのSQLインジェクション脆弱性 つづき
以前のエントリで紹介したMySQLのJDBCドライバConnector/J 5.1.7のSQLインジェクション脆弱性ですが、ようやくパッチができたようです。
public void setString(int parameterIndex, String x) throws SQLException { … for (int i = 0; i < stringLength; ++i) { … case '\u00a5': case '\u20a9': // escape characters interpreted as backslash if(charsetEncoder != null) { CharBuffer cbuf = CharBuffer.allocate(1); ByteBuffer bbuf = ByteBuffer.allocate(1); cbuf.put(c); cbuf.position(0); charsetEncoder.encode(cbuf, bbuf, true); if(bbuf.get(0) == '\\') { buf.append('\\'); } } // fall through default: buf.append(c); } }
性能重視のブラックリスト形式ですね。円記号(U+00A5)と韓国のウォン記号(U+20A9)に対してのみ、変換後の文字がバックスラッシュになるかどうかをチェックしています。また、変換後がバックスラッシュにならないキャラクタセットの組み合わせではcharsetEncoderがあらかじめnullになっており、チェックルーチンを通らないようになっています。そのため今回の脆弱性と無関係な環境においては、性能劣化が低く抑えられています。
私はUnicodeに特別詳しいわけではないので、ブラックリストに漏れがないかとか、今後変換対象の文字が増えたらどうするのか、とかは分かりません。すいません。何かお気づきの点があれば、上記バグレポートに早めにコメントをつけていただければと思います。
他の多くのRDBMSのように、SQLバインド機構として最初からServer-Side PreparedStatementしかないのであれば何も起こらなかったのですが、MySQLは歴史的にClient-SideのPreparedStatementが先にできてしまったので苦労していますね。それにBrian AkerがあまりServer-Side PreparedStatementに興味なさそうですしね…。
2009/07/29追記
この脆弱性はConnector/J 5.1.8で修正されました。関連記事を以下に示します。