跨站点伪造 (CSRF) 和 Public 应用程序接口

Cross-Site Forgeries (CSRF) and Public Application Interface

希望加强安全性并防止跨站点请求伪造攻击。了解表单的标记化,但不太清楚对象实例。

根据 OWASP 利用标准包括 1. Web 用户需要进行身份验证和 2. CSRF 攻击专门针对状态更改请求。

问题: 我有一个 public 面向数据库驱动内容的照片库。应用程序通过数据库进行身份验证,但不是 Web 用户。

在初始页面加载(初始状态)时,查看器 (HTML) 从应用程序请求缩略图灯箱。 Web 用户单击缩略图以加载与图库关联的图像。单击事件重新加载页面,将 GET 变量(画廊 ID)传递给控制器​​脚本。控制器创建 params 数组的新实例。

应用程序启动会话,而不是查看器 html。

这是应用程序的 public 界面,其他所有内容都是受保护或私有的。

viewer.php

 /* 
  * class params 
 */
if( isset($gid) && $gid!=null ) {
  /* show project gallery images */
  $params['ticket'] = "gallery";
  $params['active'] = "Y";
  $params['gid'] = $gid;
} else {
  /* show lightbox thumbnails */
  $params['ticket'] = "lightbox";
  $params['active'] = "Y";
}
/* later in html body, instance object */
  $cObj = accesswrapper::factory($params);
  $cObj->jobrequest();
  unset($params);
  unset($cObj);

factory.php

 /**
 * @api
 * @return void
 * instantiates the sub class passed from viewer
 * 
 * @param array $params, [ticket] subclass name
 * pforeman, object interface
 */
 class accesswrapper {
    public static function factory($params) {

        $ticket = $params['ticket'];

        switch($ticket) {  //route to appropriate sub class
          case $ticket=="lightbox":
            $inst = new lightbox($params);
          break;
          case $ticket=="gallery";
            $inst = new gallery($params);
          break;        
        }

      if ($inst instanceof pforeman) {
        return $inst;
      } else {
        return void;
      }
     }
    }

问题: 这个过程需要令牌吗? 这足以阻止 CSRF 吗?

如果请求仅进行微不足道的更新(更多关于下面 "trivial updates" 的定义),则无需担心 CSRF。在典型的 CSRF 攻击中,您有:

  1. 用户使用网站 cookie 登录网站 A。
  2. 在同一个浏览器会话中,用户访问网站 B。
  3. 网站 B 导致浏览器访问网站 A 上的某些 URL。
  4. 网站 A 认为请求来自用户而响应。

由于同源策略,B站看不到访问的响应;它只能导致访问发生。因此,如果请求仅进行微不足道的更新,则用户的浏览器将在访问站点 B 时显示站点 A 的内容,但我们知道用户无论如何都有权查看该数据,否则站点 A 会拒绝该请求。

用户可能有点害怕,打电话给网站 A 的支持,无论如何,但没有数据泄露。

如果请求不仅仅是简单的更新,那么网站 B 已经导致用户在网站 A 上采取行动,而这并不是他们的意图。对用户和站点 A 非常不利。

所以在没有 CSRF 保护的情况下,只有琐碎的更新是安全的。其他一切都需要保护。

"Trivial updates" 对不同的网站意味着不同的东西。例如,更新某人的银行余额显然不是一件小事。但是,在数据库中记录获取余额请求是微不足道的更新吗?如何执行耗时的查询?您站点的技术和业务模型将决定您认为哪些更新是微不足道的,哪些可以不受 CSRF 保护,哪些是您认为必须保护的。

在您的应用程序身份验证而非用户身份验证模型中,您无需担心 CSRF,因为所有访问都是 public。

最后一点,在注销功能上不添加 CSRF 保护通常是个好主意。这有助于确保用户始终可以注销,即使在 CSRF 验证中出现错误也是如此。也就是说,这样做的风险是站点 B 可以强制用户从站点 A 注销。您必须选择最适合您的方式。