我目前正在研究在 RoR 中进行重定向的解决方案,因为我在刹车员报告中收到一个错误,说我必须以正确的方式修复重定向。 我了解消息所说的内容以及如何在一个控制器操作中解决它。 但是现在我得到了以下内容。在新方法的实例化过程中,我设置了可以在创建操作中使用的HTTP_REFERER标头。
这给了我一个刹车员警告,可以在以下链接中找到
假设我得到了以下具有多个端点的控制器:
def new
@my_model_set = MyModel.new
@referer = request.env['HTTP_REFERER'] # We want to redirect to this referer after a create
end
def create
...
if @my_model_set.save
flash_message :success, t('notification.item_created', type: @my_model_set.model_name.human)
if params[:referer].present?
redirect_to params[:referer]
else
redirect_to admin_my_model_set_path
end
else
...
end
end
我已经尝试使用 RoR 中的redirect_back
方法来解决此问题,但这使用的是我不想使用的创建方法的引用链接。
if @my_model_set.save
flash_message :success, t('notification.item_created', type: @my_model_set.model_name.human)
redirect_back(fallback_location: admin_my_model_set_path)
else
...
end
代码中的主要问题是,用户(或为用户伪造链接的攻击者(可以通过将?referer=https://malicious.site
附加到 url 来将params[:referer]
设置为任意值。然后,您将重定向到该漏洞,这是一个开放的重定向漏洞。
你也可以争辩说referer
标头在技术上是用户输入,你将重定向到它,但我想说在大多数情况下和现代浏览器这可能是一个可以接受的风险,因为攻击者并没有真正利用它的方法(但这可能取决于确切的情况(。
对于类似情况,立即想到的一种解决方案是会话 - 但一方面,如果我理解正确,这是一个 rest api,因此没有会话,另一方面,对于从恶意域链接到您的#new
端点的攻击者来说,它仍然不安全。
我认为您应该在重定向到域之前对其进行验证。如果存在通用模式(例如,如果所有这些都是 yourdomain.com 的子域(,请验证该模式。或者,您可以让用户先注册其域,然后再重定向到该域(例如,请参阅 OAuth2 的工作原理,您必须先注册您的应用程序域,然后用户才能使用令牌重定向到那里(。
如果你的用户可能只是从任何地方来到#new
,而你想把他们送回去,无论他们来自哪里 - 我认为这不是一个好的要求,你可能不应该这样做,或者你应该仔细评估风险并有意识地接受它,如果你出于某种原因愿意。在大多数情况下,有一个更安全的解决方案。