0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rubyにおいて正規表現 \Aと^の違い

Last updated at Posted at 2023-01-23

正規表現

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の仕様を学ぶことができるとは思わなかった。。
これからも頑張っていきたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?