在Rails 4中通过隐藏标记传递params是否安全?

时间:2016-07-14 19:56:45

标签: ruby-on-rails security

我刚开始学习Rails并尝试制作我的第一个应用程序。 只是想知道是否可以使用像这样的结构

      <%= form_tag create_message_path, :method => :post do %>
          <%= text_area_tag "message", nil %>
          <%= hidden_field_tag "receiver", @order.printer.user.id %>
          <%= hidden_field_tag "order_id", @order.id %>
          <%= submit_tag "Submit" %>
      <% end %>

基本强大的参数。

class MessagesController < ApplicationController
  before_action :correct_user, only: [:update, :destroy]

  def create
    if current_user
      @message = current_user.messages.build(message_params)

      if @message.save
        flash[:success] = "Сообщение создано"
        redirect_to :back
      else
        redirect_to :back
      end
    else
      redirect_to login_path
    end
  end


  private
    def message_params
      params.permit(:message, :read, :receiver, :user_id, :printer_id, :order_id )
    end
    def correct_user
      @message = current_user.messages.find_by(id: params[:id])
      redirect_to root_url if @message.nil?
    end

end

不是一个线程吗?用户可以更改html输入值并发送一些信息(如要发送给其他订单的消息)吗?

编辑1:

  @order = Order.find(params[:id])
  message_item = {
    user_id: current_user.id,
    receiver: @order.printer.user.id,
    message: params[:message],
    order_id: @order.id
  }

  @message = current_user.messages.build(message_item)

4 个答案:

答案 0 :(得分:5)

首先,隐藏的参数可以更改,并且它们不适合任何敏感信息。

其次,从message_params方法中删除这些参数。你不想在params hash中允许它们(不允许你的表单上没有的参数):

git commit -S -m 'message'

此外,您可能希望删除:也读取,因为很可能您会在其他控制器操作中设置它。

第三,你通过分配设置这些参数:

params.permit(:message, :read)

注意,您不需要编写@message = current_user.messages.build(message_params) @message.receiver = @order.printer.user.id @message.order_id = @order.id ,因为它将由Rails为您完成。

答案 1 :(得分:4)

你是对的,术语hidden只描述了没有显示该输入的控件。但是,任何人都可以使用页面检查器将值或POST更改为具有任何所需值的表单的目标URL。您应始终确保通过隐藏字段接收的值在您允许的范围内。

答案 2 :(得分:2)

用户可以绝对更改这些值,并可以发送他们想要的任何数据。您不应该使用隐藏标记来传递任何真正敏感的数据,您应该假设攻击者可以将它们更改为他们想要的任何内容。在实践中,隐藏字段适用于传递一些配置/上下文信息,以及用于暴力攻击/ DoS保护令牌。例如,您可以使用隐藏字段传入一个值,指定这是一个搜索或登录请求,但不适合指定管理员发出请求,或者哪个用户正在发出请求。

答案 3 :(得分:2)

对于像这样的敏感数据,您应该使用服务器端会话变量(最简单)或使用HMAC来验证客户端是否更改了数据。

模板:

<input type=hidden name=foo value=bar>
<input type=hidden name=hmac value=<%=hmac($serverSecret + "foo=bar")%>>

然后在表单提交上,根据$serverSecret重新计算HMAC,并声明$foo的声明值,并确保它与声明的$hmac值相同