rails でやりがちな脆弱性

  • 2020.06.15
  • IT
rails でやりがちな脆弱性

最近は趣味でrails も触るようになりましたが、rails 簡単すぎて意識しないと脆弱性が生まれちゃいます。

今回はやりがちな権限周りの脆弱性についてご紹介しようと思います。

しかし、自分のLocalのサービスで試してください!!普通のサイトでやったら犯罪です!!

脆弱性があるコード

class ArticleController < V4::ApplicationController
  
  def create
    @article = Article.new(create_params)
    @article.create!
  end

  private

  def create_params
    params
      .permit(:title, :image_id, :content)
      .merge(
        user_id: @current_user.id,
        image_id: image.id
      )
  end

  def image
    Image.find(params[:image_id])
  end

qiita や stackoverflow のようなユーザーが記事をかけるサービスを開発するとします。

シンプルに考えるために、記事(Article) モデルは記事のタイトルと、本文と、画像だけを持つとします。
画像はImage table があって、そこと外部キーで繋がっているとします。

その時に上記のように書くと脆弱性があるのですが、気がつくでしょうか?

ちょっと自分の頭で考えてみましょう。


。。。


。。。


。。。


正解はこちらです。

  def image
    Image.find(params[:image_id])
  end

ユーザーからのparamsを信じたらダメですよ。

こんなのimage_id をいじられたらおしまいです。
(id が連番でないのであればまだいいが、id なんて基本的にバレる想定はしておいてください)

image_id で1-1000まで試したら、自分のものではない、他人の画像を使うことができちゃいます。

SecurityBugの再現方法

まあ、そんなこと言ったって、やり方がわからなければイメージが湧きませんよね。

ということでBugの再現方法をお伝えします。

1.Chrome のディベロッパーツールを開く


2.Ariticle の作成をUI上で行う


3.その時のHTTP リクエストのcurlをコピーする

リクエストの上で右クリックして、copy as curl を押すとコピーできます。

大体こんな感じのがコピーできたと思います。

curl 'http://localhost/articles' \
  -H 'content-type: application/json' \
  .....
  --data-binary '{"image_id": 1, "title":"hello", "content":"world"}' \
  --compressed


4.コピーした内容をどこかにはり、image_id を自分がさわれない想定のものに変更する

例えばuser2を作って、user2でimageを作って、そのid に変更する感じです。

curl 'http://localhost/articles' \
  -H 'content-type: application/json' \
  .....
  --data-binary '{"image_id": 2, "title":"hello", "content":"world"}' \
  --compressed


5.変更したcurl を投げる

これをterminal にペーストして実行すると、、、

はい、これがSecurityBugですね。

対応策

  def image
    @current_user.images.find(params[:image_id])
  end

厳密にエラー出したかったりする場合もあるとは思いますが、まずはこんな感じで大丈夫です。

まとめ

簡単に実装ができるからこそ、Securityについては意識できるようにしましょう。
どんなに便利なサービスを作っても、事故ったら一発ですからね。

ちなみに、Webの脆弱性については徳丸本が有名です。

エンジニアなら一回は読むことをお勧めします。

*2018年に出版されてる第二版のものがお勧めです。