2013年12月26日木曜日

SQL識別子エスケープのバグの事例

昨日のエントリに続いてSQL識別子のエスケープの話題で、今回は著名アプリケーションにおけるSQL識別子のエスケープ処理のバグについてです。

MySQL Workbenchには識別子のエスケープに関するバグがあった

以下の画面は、MySQLが提供するMySQL Workbenchの旧バージョン(5.2.34)の様子です(CentOS6.5上で動作)。MySQL WorkbenchはWebアプリケーションではなく、下図からも分かるようにGUIツールです。

下図では a`b というテーブルの内容を表示しようとして、エラーが表示されています。


生成されているSQL文は下記の通りです。
SELECT * FROM `db`.`a`b`;
これは駄目ですね。SQL識別子中に引用符がある場合は、引用符を重ねるのがルールでした。つり、正しくは以下であるべきです。
SELECT * FROM `db`.`a``b`;
ということで、これはMySQL Workbench 5.2.34のバグですね。最新の6.0.8(Windows版)で確認したところ、テーブル名は正しくエスケープされていました。MySQL謹製のソフトで、まさか、識別子のエスケープを考慮していないなんてとびっくりしました。

識別子のエスケープ漏れによるSQLインジェクション

上記の例では、「b`」の部分が識別子から「あふれた」状態になっていてSQL文としては不正なためにエラーになっていますが、この部分のつじつまを合わせてやることで、SQLインジェクション攻撃(?)が可能になりそうです。
その具体例として、bbs.usersというテーブルがあったとして、その内容をUNION SELECTを用いて読み出してみましょう。できあがりのSQL文は下記を想定します。
SELECT * FROM `db`.`a`union select * from bbs.`users`;
これを実現するには、上記の赤字部分を名前とするテーブルを作ればよいことになります。テーブルの定義はどうでもよく、名前だけが問題ですので、例えば下記によりテーブルを作成します。ここでは、識別子中の「`」のエスケープをお忘れなく。
CREATE TABLE `a``union select * from bbs.``users` (x int);
次に、aというテーブルが必要です。bbs.usersと列の数と型を合わせて、以下によりテーブルaを作成します。
CREATE TABLE a  (x varchar(64), y varchar(64), z varchar(64));
ここまで準備をして、テーブル「a`union select * from bbs.`users」をMySQL Workbenchにて表示させると、このテーブルではなく、bbs.usersが表示されます(下図)。x, y, zとして、ID、パスワード、メールアドレスが表示されています。


SQL文の構造が変化しているので、SQLインジェクションの一種と言えそうですが、これが脆弱性かというと微妙なところです。利用者は元々 bbs.users を閲覧する権限があるからです(下図)。


MySQL Workbenchの識別子エスケープ漏れは脆弱性か?

ここで、このバグが脆弱性としてどの程度の影響度があるかについて検討します。前回のエントリでは、識別子のエスケープミスに起因して、SQLインジェクション攻撃によりデータの削除ができる例を示しましたが、SQLインジェクション攻撃によりデータの漏えいも可能でした。これらは、利用者が元々持っている権限を越えた操作ができることが問題でした。

一方、MySQL Workbenchの場合は、識別子のエスケープバグを使わなくても、利用者は元々任意のSQL文を実行できます。すなわち、わざわざSQLインジェクションというややこしいテクニックを使う動機が利用者にはありません。別の言い方をすると、「SQLインジェクション脆弱性があっても脅威は増加しない」ということです。このことから、MySQL Workbenchのエスケープバグは、重大な脆弱性とまでは言えない、と考えられます。

識別子のエスケープ漏れと脆弱性の関係

さて、私がMySQL Workbenchの識別子エスケープバグを紹介した理由は、識別子のエスケープバグと脆弱性の関係を整理する上で役に立つと考えたからです。

そもそも、SQL識別子のエスケープを意識しなければならないケースというのは、外部からSQL識別子(表名、列名など)を指定できるアプリケーションであると考えられます。そして、識別子を利用者が自由に指定できるか、識別子に関して制限があるかが問題になります。

利用者が識別子を自由に設定できるケースの典型例がデータベース管理ツール(phpMyAdminやMySQL Workbench等)であり、この場合は元々利用者が任意のSQL文を実行する権限を持っているので、仮にSQLインジェクションができたとしても、それ単独では重大な脆弱性とまでは言えません。

一方、利用者が自由にSQL識別子を指定できるが、利用者はDBに限定的なアクセス権しか与えられていないケースです。これは、前回紹介した「観光協会のホームページ」がそのケースに該当しますが、「自由にSQL識別子を指定できる」こと自体が問題という結論でした。

まとめ

SQL識別子のエスケープを考慮しなければならないケースの典型例として、DB管理ツールがありますが、DB管理ツールは利用者が任意のSQL文を実行できる権限があるため、SQLインジェクションが単体では重大な脆弱性とは言えません。一方、一般のアプリケーションにおいては、利用者は任意のSQL文を実行する権限がありませんが、この場合、利用者が自由にSQL識別子を指定できることが問題なのではないかと考えました。
次回は、この問題をさらに整理して、SQL識別子のエスケープをどのように考えればよいかを検討します。


0 件のコメント:

コメントを投稿

フォロワー