【问题标题】:CSRF safe Custom button linked to Apex method链接到 Apex 方法的 CSRF 安全自定义按钮
【发布时间】:2012-05-30 03:09:41
【问题描述】:

我正在寻找一种技术,通过添加到 Opportunity 对象的自定义按钮执行 Apex 代码,以保护用户免受 CSRF 的影响。

当前使用的方法来自问题 - Custom Button or Link to a Visualforce page with a custom controller。本质上:

  1. 有一个机会自定义按钮,其内容源设置为“Visualforce 页面”。
  2. 此按钮的内容设置为 Visualforce 页面,该页面使用标准控制器的机会,输入了扩展顶点类和该类中方法的操作
  3. 操作方法将 PageReference 返回到另一个自定义 Visualforce 页面,包括添加带有机会 ID 的参数。
  4. 第二个自定义 Visualforce 页面完成大部分实际工作,包括在将用户重定向回机会之前进行 Web 服务标注和执行 DML 操作。

这种方法的问题在于,第二个自定义 Visualforce 页面是通过 HTTP GET 检索的,从查询字符串中提取参数,并在没有 CSRF 保护的情况下执行更新/插入 DML 操作。 Force.com 安全源代码扫描程序正在收集此内容。

我应该补充一点,此顶点代码同时部署为托管和非托管包,因此使用 PageReference 重定向到目标 Visualforce 页面的额外工作。这样可以确保在需要时添加命名空间前缀。

如何避免 CSRF 问题?

我不想在第二个 visualforce 页面中添加一个表单,他们必须按下一个按钮来启动进程(因此在回发中获取 ViewStateCSRF 保护)。从用户的角度来看,他们已经按下了按钮来执行操作。

我之前在开发者论坛上问过这个问题,但没有提出解决方案 - Cross-Site Request Forgery (CSRF/XSRF) safe Custom Button action

也许我应该尝试将代码移出第二个视觉力页面的控制器,并改用支架控制器的扩展?

我可以切换到 Apex Web 服务的 Javascript 回调(如 Call a apex method from a custom buttonHow invoke APEX method from custom button 中所建议的那样),但它似乎有点混乱,我不确定我是否只是打开另一个范围Web 服务的安全问题。

【问题讨论】:

    标签: salesforce csrf apex-code visualforce


    【解决方案1】:

    我通过 Salesforce 预订了合作伙伴安全办公时间,并直接与他们讨论了这个问题。

    如果需要 CSRF 保护(即发布到 App Exchange),目前不支持我尝试执行的操作。他们提出了两种替代方法:

    1. 在触发敏感 Apex 代码的 Visualforce 页面中创建中间表单。因此选择了内置的 CSRF 保护。
    2. 覆盖商机详细信息页面(使用 apex:Details 显示类似信息)。这个新的 Visualforce 页面将包含一个类似的表单回发到选项 1,以调用敏感的 APEX 代码并获得自动 CSRF 保护。

    另一种不使用自定义按钮的方法是嵌入/内联 Visualforce 页面(请参阅Embed a Page on a Standard Layout),在标准页面布局中仅包含所需的按钮。

    嵌入的 Visualforce 页面必须使用标准对象控制器(在我的例子中为 Opportunity)才能出现在标准页面布局的可用 Visualforce 页面列表中。 Visualforce 页面本身可以非常小,只需在 <apex:form> 中添加一个命令按钮。 Visualforce 页面的标签也可以显示在页面布局中。

    <apex:page id="embeddedPage" StandardController="Opportunity" extensions="OpportunityExtensionController" showHeader="false" standardStylesheets="true">
    <apex:form >
        <apex:commandButton value="CSRF Safe Button" action="someMethodInTheExtensionClass" />
    </apex:form>
    

    public with sharing class OpportunityExtensionController {
    
        private final Opportunity opportunityFromController;
    
        public OpportunityExtensionController(ApexPages.StandardController controller) {
            opportunityFromController = (Opportunity)controller.getRecord();        
        }
    
        public PageReference someMethodInTheExtensionClass() {
    
            // Perform directly here within the postback rather than redirecting to another page to prevent against XSRF
    
            System.debug('opportunityFromController.Id:' + opportunityFromController.Id);
        }
    }
    

    这应该可以防止 CSRF,因为 commandButton 将拾取“com.salesforce.visualforce.ViewStateCSRF”隐藏输入,并在生成的 iframe 内将帖子发回服务器。


    我已经提出了这个想法 Invoking Apex code from the standard Entity Details pages with CSRF protection,看看他们是否可以使用自定义按钮直接添加对此的支持。

    【讨论】:

      【解决方案2】:

      为什么不首先使用 JavaScript 按钮来启动第二个页面?完全绕过第一页。

      Salesforce 将在呈现之前将合并应用到脚本(因此您可以使用 {!Opportunity.Id} 在第二个 URL 中包含 opp id),您可以简单地将浏览器重定向到您的第二个页面。

      【讨论】:

      • 我遇到的主要问题是,当用户通过 HTTP GET 请求到达第二页时,他们对 CSRF 开放,因为第二页将采用查询字符串参数并执行插入和更新操作以及 Web 服务标注。此外,由于命名空间前缀,我无法使用 Javascript 引用目标 visualforce 页面,这种方式在托管包内外都可以工作。
      • 好的,#1 你可以使用URLFOR$Page.pagename 或它们的组合来引用页面。这应该适合您的命名空间问题。其次,CSRF 应该只针对表单操作触发,据我了解,您在第 2 页中没有这样的内容,不是吗?本质上,您的扩展构造函数完成了所有工作?如果是这样,无论如何,您的页面仍然对 CSRF 开放,如果没有 salesforce 呈现表单(带有令牌)然后从onloaded 提交,您将无法解决这个问题。但是(这是一个很大的问题)你不能用这个解决 CSRF(见下一条评论)
      • 你没有解决它,因为知道你的页面的恶意网站仍然可以发送带有查询字符串的 GET 请求,并让销售人员为其创建一个令牌,并为他们提交它。
      • 感谢您的坚持。关于使用 Javascript,当我之前尝试在自定义按钮中使用带有 $Page.pagename 的 URLFOR 时 [我收到错误] (stackoverflow.com/questions/8497442/…)。也许我应该重新审视它,因为它现在可能有效?
      • 不幸的是,任何不依赖 Salesforce 呈现表单并且用户将其发回的解决方案都对 CSRF 开放。您只会使安全漏洞更加“异国情调”,但不会将其删除。对不起。
      猜你喜欢
      • 2019-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 2011-05-04
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多