【问题标题】:Are JAXRS restful services prone to CSRF attack when content type negotiation is enabled?启用内容类型协商时,JAXRS RESTful 服务是否容易受到 CSRF 攻击?
【发布时间】:2012-05-30 04:05:54
【问题描述】:

我有一个 RESTful API,其中包含 @Consumes(MediaType.JSON) 之类的注释 - 在这种情况下,CSRF 攻击是否仍然可能对此类服务进行?我一直在修补在服务器端使用 CSRFGuard 保护我的服务或从客户端进行双重提交。但是,当我尝试使用带有 enctype="text/plain" 的 FORM 发布请求时,它不起作用。该技术已解释 here 如果我的消费注释中有 MediaType.APPLICATION_FORM_URLENCODED,则此方法有效。当我使用 POST/PUT/DELETE 动词时,内容协商很有用,但 GET 仍然可以访问,这可能需要研究。

任何建议或意见都会很棒,如果您需要更多信息,请告诉我。

干杯

【问题讨论】:

  • 很高兴知道没有人对此有意见......还是我的问题不太清楚?嗯

标签: web-services rest jax-rs csrf


【解决方案1】:

JAX-RS 旨在创建应该是无状态的 REST API。 跨站点请求伪造对于无状态应用程序来说不是问题。

跨站点请求伪造的工作方式是有人可能会诱骗您单击链接或在浏览器中打开链接,这会将您定向到您登录的站点,例如某些在线论坛。由于您已经在该论坛上登录,攻击者可以构造一个 url,这样说:someforum.com/deletethread?id=23454

该论坛程序设计不当,将根据会话 cookie 识别您,并确认您有能力删除该主题,实际上将删除该主题。

都是因为程序根据会话 cookie 对您进行了身份验证(甚至基于“记住我”cookie)

使用 RESTful API 没有 cookie,请求之间不维护任何状态,因此无需防止会话劫持。

您通常使用 RESTFul api 进行身份验证的方式是发送一些额外的标头。如果有人欺骗您点击指向 RESTful API 的 url,浏览器不会发送额外的标头,因此没有风险。

简而言之 - 如果 REST API 的设计方式应该是无状态的,那么就没有跨站点伪造的风险,也不需要 CSRF 保护。

【讨论】:

  • 您的 RESTful API 可能位于安全框架之后,例如 spring security,这意味着您需要通过框架进行身份验证。在这种情况下,它会写入一个 cookie 来将您识别为经过身份验证的用户。一旦用户被识别,那么对 GET/POST/DELETE/PUT 数据的常规服务调用将可用。因此,在这种情况下,服务本身不是无状态的,但服务位于具有状态的安全框架后面。无论如何,我的主要兴趣是检查是否有人能够在启用内容类型协商时执行 CSRF 攻击,因为我无法破解它。
  • 那将是一个糟糕的设计。 API 客户端可能是某个应用程序,而不是浏览器,并且根本不希望接收 cookie。在 REST API 中使用 cookie 是一种非常糟糕的做法。
  • 当然,现在我们的 API 使用基本身份验证和基于表单的身份验证来保护。因此,其他一些不是浏览器的应用程序通过基本身份验证,它通过 HTTPS 在每个请求上发送用户名和安全令牌。这些是系统生成的用户,他们可以访问部分 API。但是,在基于浏览器的应用程序中,我必须使用基于表单的身份验证来对用户进行身份验证。如果在第一次检查后在会话中保持,您可以避免通过用户来获取每个请求的主体。
【解决方案2】:

添加另一个答案,因为 Dmitri 的答案混合了服务器端状态和 cookie。

如果您的服务器通过多个请求将用户信息存储在内存中,则应用程序不是无状态的。这会降低水平可伸缩性,因为您需要为每个请求找到“正确”的服务器。

Cookie 只是一种特殊的 HTTP 标头。它们通常用于识别用户会话,但并非每个 cookie 都意味着服务器端状态。服务器也可以在不启动会话的情况下使用来自 cookie 的信息。另一方面,使用其他 HTTP 标头并不一定意味着您的应用程序自动是无状态的。如果您将用户数据存储在服务器的内存中,则不是。 cookie 和其他标头之间的区别在于浏览器处理它们的方式。对我们来说最重要的是浏览器会在每个后续请求中重新发送它们。如果有人欺骗用户提出他不想提出的请求,就会出现问题。

这对于使用 JSON 的 API 来说是个问题吗?是的,分两种情况:

  • 攻击者让用户提交带有enctype=text/plain的表单:Url编码的内容不是问题,因为结果不能是有效的JSON。 text/plain 如果您的服务器将内容解释为 JSON 而不是纯文本,则会出现问题。如果您的资源使用@Consumes(MediaType.JSON) 注释,您应该没有问题,因为它不会接受text/plain 并且应该返回状态415。 (请注意,JSON 可能有一天会成为有效的编码类型,而这将不再有效)。
  • 攻击者让用户提交 AJAX 请求:同源策略阻止向其他域发出 AJAX 请求,因此只要您不使用 CORS 标头禁用此保护,例如Access-Control-Allow-Origin: *

【讨论】:

    猜你喜欢
    • 2012-06-16
    • 1970-01-01
    • 2015-06-08
    • 2023-04-07
    • 1970-01-01
    • 2015-12-31
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多