shallow magic と名付けてみる修行

shallow magic
入力処理と出力処理の混同

概要

入力時にすべき処理と出力時にすべき処理が混じってしまっていること。そのコード。対応方法。PHP の magic quote にちなんで shallow magic と命名
場合によっては、本処理と入力処理、本処理と出力処理を混同しているものも含める。

弊害

  • 入力処理、本処理、出力処理、と意識して考えればすっきり簡単なのに、その思考を妨げる。
  • 仕様変更に弱く、バグの温床になる。

たとえば、出力されるものの文字コードの変更がある場合、三つの処理が分かれていれば、出力処理だけを変更するだけでいいはずだが、shallow magic が入っていると入力処理や本処理にまで影響範囲が及び、しかもデグる可能性が非常に高くなる。

症例 1

PHP の magic quote 機能を使うと、$_GET, $_POST, $_REQUEST などでリクエストパラメータを取得すると、すでに特殊文字エスケープされた状態になる。これは、$_GET で取った値をそのまま DB に渡せる、という親切設計。
だが、HTTP リクエストに対して行う入力処理 (リクエストパラメータをパラメータごとに分解、URL デコードして連想配列に格納) とともに、DBMS に対して行う出力処理 (SQL として意味を持つ文字のエスケープ) を行ってしまっている困った機能。

症例 2

PHP において、リクエストパラメータを取ってきた直後に htmlspecialchars() をかけ、その文字列に対して入力チェックや本処理などのさまざまな処理をしたあと、最終的に HTML 出力する。
これを「サニタイズする」と間違えて理解している人が多いので注意。データベースに < などが入っていたら、こいつの仕業。

症例 3

URL デコード前に HTML として意味を持ってしまう文字を取り除く (サニタイズ)。その後、URL デコードすると HTML として意味を持つ文字が発生し、XSS 脆弱性が生じる。

処方

新規にコードを書く際は、自分が書いているコードが入力処理、本処理、出力処理のどれなのかを意識すること。

  • 入力処理はできるだけ早い段階でまとめて行うこと。
  • 出力処理はできるだけ遅い段階でまとめて行うこと。
    • たとえば、htmlspecialchars() は、 という形でしか書かない、とか。

shallow magic がかかった既存のコードに手を入れるのは非常に困難だが、入力処理、本処理、出力処理を意識して、できるだけそれに沿う形で対処する。