2008年09月25日(木)

MySQLのカラム切り捨て脆弱性

カテゴリ: セキュリティ, プログラミング このエントリーを含むはてなブックマーク はてなブックマーク - MySQLのカラム切り捨て脆弱性

WordPress 2.6.2で修正された「mt_srand and not so random numbers」と「MySQL and SQL Column Truncation Vulnerabilities」のうち、MySQLの方は他のアプリケーションでも影響しているものがありそうな感じがする。セキュリティ上の問題まで行かなくても、意図しない挙動になっていたりしないだろうか。

この問題はMySQLの以下の2つの挙動によって起る。

  • INSERT、UPDATE文でカラムの長さ以上の文字列を挿入しても、エラーにせず文字列末尾を切り捨てたものを挿入する
  • WHERE句での文字列の比較は、文字列末尾のスペースを切り捨てたもので行われる

論理削除を行えるようにした場合、カラムに一意制約を付けられないため、アプリケーション側で一意性チェックを行うことで、一意性が保証されるようにすることがある。が、この2つの挙動を利用すると、データ登録時の一意性チェックをすり抜けることが出来てしまう。 まず、重複させようとする値の末尾にカラムの最大長までスペースを付け、その後ろにスペースでない文字を付けたものを用意する。一意性チェックでは、テーブルを検索して同じ値がないことを確認する訳だが、スペースではないものは切り捨てられないので、この文字列は既存の値とはマッチしない。一意でないことが確認できたので、この文字列はテーブルに挿入される。すると末尾の文字が切り捨てられ、末尾はスペースのみになる。MySQLは末尾のスペースを無視して検索するので、データを取り出す時には、スペース有り無しの両方がマッチしてしまう。1件しかマッチしないという前提で作られた処理がどうなるかは実装次第だ。

入力時に文字列の長さチェックを行っている場合、末尾の切り捨てが起るような文字列が挿入されることがないため、この問題はかろうじて回避されている。根本的な解決方法は、MySQLのSQLモードにSTRICT_ALL_TABLESかSTRICT_TRANS_TABLESを指定して、カラムに不正値を挿入した時にエラーになるようにすることである。その他のMySQL独特の挙動を抑制するためにTRADITIONALを指定する方が良い感じではあるが、アプリケーションがその挙動に依存している可能性もあるので、変更するのは難しいかもしれない。

ちなみにカラム切り捨ての方は、文字コードを指定せずにテーブルを作った場合に問題になる場合がある。たとえばMobavle Typeのエントリータイトルに255文字以上入力して保存すると、末尾の文字が化けてしまう場合がある。これはMovable Type側はUTF-8の文字列を送っているが、MySQL側はISO-8859-1として扱うので、UTF-8の途中のバイトで切り捨てられてしまうためである。

コメントを投稿する





このエントリへのトラックバックURL