人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

preg_replaceが危険ということについて。

http://blog.64p.org/entry/2013/07/17/151532
こちらで、気になる表現があり、
「基本的に、任意のユーザー入力を正規表現として評価することはさけなければなりません。」
と書かれていました。

これは、 preg_matchでも同様に、ユーザー入力を正規表現でそのまま評価することは、避けるべきものでしょうか?

もしそうであれば、ユーザが入力した文字列を「英数字のみかどうか」等、バリデートする場合、どのように判定することが安全でしょうか?

何か見逃しがあると困るので、質問しました。

アドバイス頂けると助かります。

●質問者: onigirin
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● だわかき
●34ポイント

そのブログでは、preg_replaceの第1引数(正規表現パターン)にユーザー入力を入れるのは避けた方がいいと書いてあるのであって、第2引数(比較文字列)に入れる分には問題ありません。
preg_matchでも同様ですし、その他、たとえばSQL関数でもSQL文としてにユーザー入力を入れるのは避けるのが定石です。
これはPHPに限ったことではありません。

「英数字のみかどうか」等、バリデートする方法は、第1引数を固定文字列にすればいいです。

preg_match('/^[a-z|A-Z]+$/', $text);

onigirinさんのコメント
どうもありがとうございます。 第2引数であれば、とりあえず問題無いのは安心しました。 No2の方の情報から、気になっている危険性もわかってきました。

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)) {
 グルーピングの表現がある!
}

onigirinさんのコメント
どうもありがとうございます。 第2引数のことは了解済みです。 脆弱性の方も、参照URLで理解できました。 どの正規表現でも問題があるなら、とりあえずグループ表現をはじくと、こちらの対策はできそうということで、対策法がわかり安心しました。 いろいろなサイトやスクリプトのコードを見ていると、この対策がされていないような気もするのですが、ひとつDOS対策の知識が増えて助かりました。

3 ● kaji0120
●33ポイント

preg系は第二引数にeを指定する事だけでなく、ダブルクォーテーションのルールなど結構注意すべき脆弱性が多いです。
何げなく使っている表現(特にダブルクォート)のことなど、知らなければ以下のブログに一度目を通しておいた方がいいと思います。

http://d.hatena.ne.jp/hnw/20100815
http://labs.s-cubism.com/blog/2010/03/18/176/


onigirinさんのコメント
どうもありがとうございます。 ダブルクォートは見逃しそうなので注意したいですね。 preg系の正規表現は、とりあえずeを使わずにグルーピングを避けて、バリデート利用してみようと思います。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ