6
8

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.

マスアサインメント(Mass Assigment)

Last updated at Posted at 2023-11-10

マスアサインメントとは?

マスアサインメントは特定のフレームワークを使用する時、HTTPリクエストを通じてクライアントから渡されたパラメータの値をプログラムコード内の変数やオブジェクトの属性に自動的に割り当てる機能を指します。これにより、エンジニアはコードの簡潔性を高め、各パラメータの値を手動でオブジェクトに割り当てる手間を大幅に減らせます。

マスアサインメントの例: Ruby on Rails

Ruby on Rails(バージョン7基準)は、このマスアサインメントの機能を利用して、1行のコードで簡単にパラメータの値をモデルの属性に割り当てることができるメカニズムを提供します。

例えば、ユーザーが会員登録フォームを通じて提出したデータはコントローラーに渡され、Userモデルの属性にマッピングされます。

View

# app/views/users/new.erb
<%= form_with(model: @user, url: users_path, method: "post") do |form| %>
  <%= form.label :email, "メール" %>
  <%= form.email_field :email %>

  <%= form.label :password, "パスワード" %>
  <%= form.password_field :password %>

  <%= form.submit "会員登録" %>
<% end %>

Controller - マスアサインメントを使用しない場合

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new
    @user.email = params[:user][:email]
    @user.password = params[:user][:password]

    if @user.save
      redirect_to success_page_path
    else
      render :new
    end
  end
end

Controller - マスアサインメントを使用する場合

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])

    if @user.save
      redirect_to success_page_path
    else
      render :new
    end
  end
end

マスアサインメントの脆弱性

マスアサインメントの手軽さの裏には、深刻なセキュリティリスクが存在します。例えば、ユーザーモデルに管理者権限を付与するis_adminフィルドがある場合は、悪意のあるユーザーがフォームデータを操作して自分のアカウントに管理者権限を付与することができます。

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new(params[:user]) # is_admin: trueキー値ペアが含まれています。
    if @user.save
      redirect_to success_page_path
    else
      render :new
    end
  end
end

上記のコードでコントローラーはクライアントから渡されたparams[:user]ハッシュにある全てのキー値ペアをUserインスタンスに割り当てます。この時、悪意のあるユーザーがHTTPリクエストを操作してis_adminの値をtrueに設定すると、コントローラーはこれをそのままデータベースに保存し、悪意のあるユーザーは簡単に管理者権限を取得することができます。

ウェブブラウザのようなクライアント環境はいつでもアクセスして開発者ツールやスクリプトなどでデータを操作することができるので、ここで悪意のあるユーザーは簡単にHTTPリクエストを操作することができます。例えば、元の会員登録フォームにはemailpasswordフィールドだけが公開されていますが、悪意のあるユーザーは次のような方法でis_adminフィールドを追加することができます。

  1. HTML操作でリクエスト

    開発者ツールのElementsパネルでis_admininputタグを追加後、フォームを送信してサーバーにリクエストを送ることができます。

    <input type="hidden" name="user[is_admin]" value="true">
    
  2. JavaScript操作でリクエスト

    開発者ツールのConsoleパネルでis_adminのフォームデータを生成し、fetch APIでサーバーにリクエストを送ることができます。

    // JavaScriptを利用してフォームデータを生成
    let formData = new FormData();
    formData.append('email', 'minimabot@example.com');
    formData.append('password', 'secure_password');
    formData.append('is_admin', 'true');
    
    // fetch APIでリクエスト
    fetch('/sign_up',
      method: 'POST',
      body: formData
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch((error) => console.error('Error:', error));
    
  3. 直接HTTPリクエスト

    開発者ツールのNetworkタブでフォーム送信のHTTPリクエストを分析します。そして、curlのようなツールでパラメータにis_adminを含めt直接サーバーにリクエストを送ることができます。

    curl -X POST -d "email=minimabot@example.com&password=secure_password&is_admin=true" https://example.com/sign_up
    

対応: Strong Parameter

Railsはこのような脆弱性を補強するためにRails4バージョンからStrong Parametersを導入しました。これにより、エンジニアは許可されたパラメータのみを明示的に宣言し、予期しないマスアサインメントを防ぐことができます。

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to success_page_path
    else
      render :new
    end
  end

  private

  def user_params
	# 許可されたパラメータのみ
    params.require(:user).permit(:email, :password)
  end
end

上記のuser_paramsメソッドは Strong parameters の良い例です。permitメソッドを使って、emailpasswordフィールドのみを許可し、他の全てのフィールドは無視されるか拒否されます。

結論

一括割り当ては開発の効率を高める便利な機能ですが、慎重に使う必要があります。RailsのStrong Parametersのようにフレームワークが提供するセキュリティ機能を正確に理解して適切に活用しましょう。 そうすれば、コードの簡潔性だけでなく、ウェブアプリケーションのセキュリティを大幅に向上させることができます。

参考

6
8
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
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?