「プリペアードクエリが基本だけど、動的に SQL を組み立てる場合もあるから、そういう場合に備えてエスケープも知っておいたほうがいいかも」

15
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho で、Oracleは関数はSQL標準の128バイトまでしか識別子エスケープはサポートしていないので4000バイトまでエスケープできるエスケープ関数のサンプルが載っていたりします。

2013-12-10 18:48:48
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho しかもご丁寧にリテラルのエスケープ関数としても使えるようにもなってます。 この仕様は何故?と思いましたが。

2013-12-10 18:51:38
Kazuho Oku @kazuho

「SQL識別子のエスケープはどうすればいいですか」に対する正しい答えは「識別子は静的なSQLの中に静的に記述するようにしましょう。実行時に識別子をエスケープするようなプログラムは設計として間違いです」だよね

2013-12-10 18:54:03
Kazuho Oku @kazuho

(phpmyadminみたいなRDB管理ツールを作っている場合を除く)

2013-12-10 18:54:41
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho DBスキーマを管理するプログラムには絶対に必要ですよ。

2013-12-10 18:57:33
Yasuo Ohgaki (大垣靖男) @yohgaki

タイムラインがエスケープだらけ。犯人は自分か。

2013-12-10 18:58:57
Kazuho Oku @kazuho

.@yohgaki ええ。そして、そのようなプログラムは管理者が使うものなので、そもそもウェブアプリケーション開発における脆弱性に関する議論とは関係ないですね

2013-12-10 18:59:07
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho 例えば、WordPressのインストールプログラムはテーブルプレフィクスを指定してDBを作成します。こういうアプリは普通です。DB共有していたりする環境ではインジェクションできるとよろしくないです。

2013-12-10 19:01:21
Kazuho Oku @kazuho

.@yohgaki 予約語と衝突可能性を生む可能性があるような設計がそもそもセキュアではありません。どうしてもテーブル名に任意の単語を指定可能としたいのであれば、識別子をエスケープするのではなく、適切な「エンコード」を行って衝突可能性を排除すべきです

2013-12-10 19:03:56
Yasuo Ohgaki (大垣靖男) @yohgaki

穴は塞ごう、でないとハマる(事もある)「事もある」をセキュリティを教える1人としては、レアだから無視、とか言っていたらお客さんに怒られます。

2013-12-10 19:04:43
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho 大方のDBは識別子をエスケープすればどんな文字列でもOKです。勿論、予約語でも。

2013-12-10 19:05:56
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho あれ、リプライしたつもりが無いですね。クオート&エスケープすれば大方のDBはどんな文字列でも識別子にできますよ。勿論、識別子も。

2013-12-10 19:12:04
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho 上級者でも間違えるのだから、教えないとならないと思います。

2013-12-10 19:14:52
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho エスケープの知識は必要。それで良いじゃないですか。そこら中の出力先にエスケープは必要ですし。

2013-12-10 19:19:40
Kazuho Oku @kazuho

.@yohgaki 識別子エスケープに頼るよりも、テーブル名のエンコードや、ユーザー入力由来の情報と機械的に発番したテーブル名(例:t0001)の対応表を管理してそちらを使う等、識別子エスケープに頼らない、脆弱性を防止するより確実な手法が存在するのでそちらを使うべきということです

2013-12-10 19:27:27
Yasuo Ohgaki (大垣靖男) @yohgaki

追記しないと「プリペアードクエリさえ使えばOK」と同じ誤認識を生みかねないので「出力セキュリティの鉄則」を追加しました。 http://t.co/0ybfhcW7bj

2013-12-10 19:30:37
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho でも、その手法はDBスキーマを触るプログラムだと困ったことになります。リレーショナルモデルとしてはテーブル名など何でも良いのですが、汎用機時代のデータベースみたいになりますね。古臭いとか気にしない方なのですが、古臭くないですか?

2013-12-10 19:36:11
Kazuho Oku @kazuho

.@yohgaki 皆がちゃんとエスケープできるわけではないから、脆弱性が産まれるのです。エスケープより安全な手法があるなら、そちらを使うべきです

2013-12-10 19:43:00
Kazuho Oku @kazuho

.@yohgaki ユーザーの識別をアカウント名でなく内部idで行うという意味で、むしろ自然な方法かと思います

2013-12-10 19:44:57
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho プリペアードクエリで少なくともパラメータ、SQL語句でのSQLインジェクションが無くなっていたなら同意できるのですが、セキュリティを語る者としては理想でなく現実を見なければなりません。

2013-12-10 19:48:25
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho アプリが対応しなければならないので難しいですね。WordPress、Drupal、Modx、etc に対応して、と言っても無理だと思います。

2013-12-10 19:50:49
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho DBMSは内部的にはテーブルをIDで管理していて、ユーザーは分り易いテーブル名を使用するようなっているのに、更にアプリでテーブル名をIDで管理してフレンドリー名を別に置く、という設計もなんだかなあと思えます。

2013-12-10 19:54:52
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho 結構いろいろな条件や現実を理解・吟味した上で達した結論なので、鉄壁とまでは思っていませんが、論理的・現実的な背景はかなり分厚いです。もし、更に良い案があったら直ぐに乗り換えますけど。

2013-12-10 19:58:43
Yasuo Ohgaki (大垣靖男) @yohgaki

@kazuho JavaScriptはこれから書くので、間違いがあったらグサっと来るツッコミどころがあると思います。その時はお願い致します。

2013-12-10 20:04:23
Kazuho Oku @kazuho

.@yohgaki テーブル名を発番すれば、ある入力値に対して正しく動きさえすれば脆弱性がないことが保証される、そこが設計として優れているのです。エスケープで脆弱性が産まれがちなのは、入力値によって動いたり脆弱になったりするためです。この点を無視した類推は誤りです

2013-12-10 20:09:10