静的プレースホルダと動的プレースホルダとセキュリティ
セキュリティ勉強会に参加して気になる事があったので、プレースホルダ周りだけ切り出して考えてみようと思ったけど、読み直していたら普通に書いてあって恥ずかしかったので、こっちに置く。
前提確認
そもそも、Railserとしてはプレースホルダに静的も動的もあるの?という感じだったので確認する。
静的プレースホルダと動的プレースホルダ
静的プレースホルダは、アプリケーションからDBMSに送るSQLが固定である状態のプレースホルダだと思うんですが、 SQLのプレースホルダとはそういうものではないのか、という気がして違和感ありまくりでした。
なんとなく自分の感覚に合うように書き下すと、アプリケーションからDBMSに送るSQLに対応する符号に対して、 SQLの文構造が固定である、という感じらしいです。
もう少し具体的に書くと、DBMS側に変数の入っていないSQLを事前にコンパイルさせておいて、後で、変数の部分を再度アプリケーションから送ってバインドさせる方式だそうで、これはプリアドステートメントというそうです。
一方、動的プレースホルダは、ライブラリ側で変数部分のリテラル処理を行って、DBMSにSQLを送る前にSQLの変数前を埋めてしまいます。
こっちは、変数を埋め込んだ後にSQLのコンパイルが行われるので、変数にSQLの構造を変えてしまうような文字列が含まれていた場合、SQLの構造が変わって、たとえば、意図せぬselect文やupdate文が挿入されてしまったりします。
ポイントは、変数に';'や'''を挿入して文や変数を区切って余分な文を入れた後、そのままだと変数の数が合わないなどのエラーがでやすいので'--'を入れて後ろの部分をコメントアウトする事ですかね...。
ちなみに、動的にプレースホルダを作成し、作成したSQLをその都度プリアドステートメントとして処理させるものが安全な対策として紹介されていますが、ここで列名にユーザの入力値を入れさせるようにすると元の木阿弥になりますね。
普段使っているのは、Railsを使っているサーバサイドエンジニアの場合、だいたい動的プレースホルダになります。
動的プレースホルダはDBMSに送るたびに構文解析されるので文構造が崩れる恐れがあるのですが、皆が使っているライブラリなら、誰かが適切にリテラル化するようにコードを書いてくれると期待しているっぽいですね。
理由としては、静的プレースホルダにするためのコードが下のDBMSに強く依存して大変だからとかその辺とは聞きましたが、コード追う気になれない...。