正規表現
Rubyの正規表現でよくある落とし穴は、より安全な\Aや\zがあることを知らずに危険な^や$を使ってしまうことです。
Rubyの正規表現では、文字列の冒頭や末尾にマッチさせる方法が他の言語と若干異なります
。このため、多くのRuby本やRails本でもこの点について間違った記載があります。どのようなセキュリティ問題が生じるのでしょうか。たとえば、URLフィールドの入力が有効かどうかを検証するのに、以下のような単純な正規表現を使ったとします。
/^https?:\/\/[^\n]+$/i
これは一部の言語では正常に動作しますが、Rubyの^や$は、入力全体の冒頭と末尾ではなく「行の」冒頭と末尾にマッチしてしまいます
。従って、以下のように改行を含む毒入りURLはフィルタを通過してしまいます。
javascript:exploit_code();/*
http://hi.com
*/
上のURLをフィルタで検出できない理由は、入力の2行目にマッチしてしまうからです。つまり、1行目と3行目にどんな文字列があってもフィルタを通過してしまいます。フィルタをすり抜けてしまったURLが、ビューの以下の箇所で表示されたとします。
link_to "Homepage", @user.homepage
表示されるリンクは一見無害に見えますが、クリックすると、攻撃者が送り込んだ悪質なexploit_code()関数を初めとする任意のJavaScriptコードが実行されてしまいます。
これらの正規表現に含まれる危険な^や$は、以下のように安全な\Aや\zに置き換える必要があります。
/\Ahttps?:\/\/[^\n]+\z/i
^
や$
をうっかり使ってしまうミスが頻発したため、Railsのフォーマットバリデータ(validates_format_of)では、正規表現の冒頭の^や末尾の$に対して例外を発生するようになりました。めったにないと思われますが、どうしても\Aや\zではなく^や$を使いたい場合は、以下のように:multilineオプションをtrueに設定することも可能
です。
この文字列のどの行にも"Meanwhile"という文字が含まれている必要がある
validates :content, format: { with: /^Meanwhile$/, multiline: true }
この機能は、フォーマットバリデータ利用時に起きがちなミスから保護するだけのものであり、それ以上のものではない点にご注意ください。^や$はRubyでは 1つの行 に対してマッチし、文字列全体にはマッチしないということを開発者が十分理解しておくことが重要
です。
出典
気づかせてもらった記事
感想
まさか正規表現の勉強をしていてRubyの仕様を学ぶことができるとは思わなかった。。
これからも頑張っていきたい。