そのブログでは、preg_replaceの第1引数(正規表現パターン)にユーザー入力を入れるのは避けた方がいいと書いてあるのであって、第2引数(比較文字列)に入れる分には問題ありません。
preg_matchでも同様ですし、その他、たとえばSQL関数でもSQL文としてにユーザー入力を入れるのは避けるのが定石です。
これはPHPに限ったことではありません。
「英数字のみかどうか」等、バリデートする方法は、第1引数を固定文字列にすればいいです。
preg_match('/^[a-z|A-Z]+$/', $text);
▽2
●
a-kuma3 ●33ポイント ベストアンサー |
これは、 preg_matchでも同様に、ユーザー入力を正規表現でそのまま評価することは、避けるべきものでしょうか?
質問で示されているブログで言及されているのは、preg_replace の e 修飾子がやべえって話です。
e (PREG_REPLACE_EVAL)
この修飾子を設定すると、 preg_replace() は、置換文字列において後方参照に関する通常の置換を行った後、 PHP コードとして評価し、検索文字列を置換するためにその結果を 使用します。 置換された後方参照においては、 単引用符や二重引用符、バックスラッシュ (\)および NULL 文字は バックスラッシュでエスケープされます。
http://www.php.net/manual/ja/reference.pcre.pattern.modifiers.php
preg_replace() の第二引数に書かれたコードを実行してしまう、というのが、相当にやばい。
# これについては、了解済み?
で、入力したデータをそのまま正規表現として扱う場合の話。
任意のユーザー入力をそのまま正規表現としてうけとると、容易に DoS(Denial of Service) が可能となるということはよく知られている事実であるから、任意のユーザー文字列を正規表現としてうけとっている時点で脆弱なサーバー実装になっている。
http://blog.64p.org/entry/2013/07/17/151532
当のブログの他の記事を見ても、どこまで分かって書いてるのか、(ぼくには)よく分からないのですけれど、多分、この辺りのことを書いているのだと思います。
http://msdn.microsoft.com/ja-jp/magazine/ff646973.aspx
http://www.hpenterprisesecurity.com/vulncat/ja/vulncat/objc/denial_of_service_regex_evaluation.html
これを気にするなら、置換が無い preg_match() も脆弱性に該当します。
サニタイズはちょっと難しいですけど、バリデーションという意味なら、グルーピングの表現をはじいてあげる感じになると思います。
if (preg_match('/[^\\\\]\(/', $input)) { グルーピングの表現がある! }
preg系は第二引数にeを指定する事だけでなく、ダブルクォーテーションのルールなど結構注意すべき脆弱性が多いです。
何げなく使っている表現(特にダブルクォート)のことなど、知らなければ以下のブログに一度目を通しておいた方がいいと思います。
http://d.hatena.ne.jp/hnw/20100815
http://labs.s-cubism.com/blog/2010/03/18/176/