【问题标题】:Why is my request working without requesting a new XSRF token?为什么我的请求没有请求新的 XSRF 令牌就可以工作?
【发布时间】:2016-09-18 17:26:03
【问题描述】:

从服务器请求一个 XSRF 令牌并在整个会话中重复使用它是否足够我应该请求每个值得保护的操作,例如保存、编辑或先删除 new XSRF 令牌,然后然后执行实际请求?

出现这个问题是因为我不明白为什么我的受 XSRF 保护的请求有效,即使我没有请求新的请求:

public void saveName(Long shopId, Long languageId, String name, OnSuccessCallback<String> success, OnFailureCallback failure) {

    Request.<String> doRequest(this.shopService,

            asyncCallback -> {
                this.shopService.saveName(shopId, languageId, name, asyncCallback);
            }, 

            (String result) -> {
                // ..
                success.onSuccess(result);
            }, failure);
}

这里Request#doRequest() 将简单地执行请求,但不会首先请求新的 XSRF 令牌。我必须将其更改为 XsrfRequest#doRequest(),它基本上做同样的事情,但会请求 XSRF 令牌first

问题是saveName() 应该受到保护:

@XsrfProtect
@RemoteServiceRelativePath("shop")
public interface ShopServlet extends RemoteService {
    // ..
    String saveName(Long shopId, Long languageId, String name);
}

请注意:在调用saveName() 之前,还有其他几个请求,其中一些已经获得了XSRF 令牌。但是由于我可以保存一个新名称而无需请求一个新名称,所以我感觉之前请求的令牌在这里被重用了。这样可以吗?

我注意到的另一件事是,如果我将 @NoXsrfProtect 添加到 saveName()

@NoXsrfProtect
String saveName(Long restaurantId, Long languageId, String name);

该请求仍将包含 XSRF 令牌信息:

7|2|9|http://localhost:8080/app/|424F33664CAA93E2F8A4A94C57DA5827|com.google.gwt.user.client.rpc.XsrfToken/4254043109|..ShopServlet|saveName|java.lang..

为什么在方法声明为@NoXsrfProtect 的情况下仍将令牌发送到此处?

有人可以向我澄清一下吗?我不想犯任何错误——尤其是在安全相关的问题上..

【问题讨论】:

    标签: java gwt csrf


    【解决方案1】:

    从服务器请求一个 XSRF 令牌并在整个会话中重用它是否足够,或者我应该先请求每个值得保护的操作,例如保存、编辑或删除一个新的 XSRF 令牌,然后再执行实际请求?

    让我们暂时忽略 GWT RPC 的内置 XSRF 保护,看看标题问题和这句话:什么是 XSRF,我们如何防范它?

    什么是 XSRF

    XSRF 代表 Cross Site Request Forgery - 其想法是恶意网站可能会以某种方式伪造请求,并迫使我们的用户正确地将其发送到我们的应用程序,就好像他们打算自己做一样。例如,如果将钱从一个银行账户转移到另一个银行账户所需要的只是

    GET /transfer?from=me&to=attacker&amount=10000USD
    

    然后,攻击者可以非常简单地从他们自己的站点向我们的服务器发出图像、css 或 js 文件的请求:

    <img src="https://securebank.com/transfer?from=me&to=attacker&amount=10000USD" />
    

    抛开其他细节(“好吧,这适用于 GET,他们是如何设法将 POST 发送到我的 GWT RPC 服务的?”),让我们看看 XSRF“令牌”防止这种攻击的想法:什么是友好的客户知道或可以做到,而攻击者却无法知道或做到吗?

    缓解

    这个想法是客户端应该有一种方法向服务器表明它是受信任的——它知道只有有效客户端才能知道的东西,这表明用户愿意做出指定的操作。一种选择是要求用户执行验证码,以使攻击站点无法编写该操作的脚本,并且用户必须有意识地执行。另一种选择是让一些数据可供真实/受信任的客户端使用,例如 cookie(只能从加载在同一域上的页面中读取),或者作为 HTML 页面加载时的一部分或其他请求(可能可以通过其他方式发送,但无法读取结果)。

    OWASP 将后一条数据称为"Synchronizer Token"

    同步器令牌模式需要生成与用户当前会话关联的随机“挑战”令牌。 [...] 当用户希望调用这些敏感操作时,HTTP 请求应包含此质询令牌。然后由服务器应用程序负责验证此令牌的存在和正确性。

    因此,在这种情况下,我们可以将一些值写入 cookie,以便只有客户端可以看到它,然后客户端可以使用它来生成令牌。然后,该令牌应在必须验证的每个请求上传递给服务器。但从这个描述中,我们看到一次只有一个有效令牌并不一定重要。

    但是如果攻击者能够获得 XSS,他们就可以读取令牌并再次强制请求!或 MitM!

    确实如此,但如果他们有 XSS,那么任何您自己的 JS 可以发出的请求,攻击也可以发出。你迷路了,收拾行装,该回家了。同样,如果他们拥有用户和应用程序之间的连接并且可以随意读写。 XSRF 保护不是解决所有问题的魔杖,它是一种特定的攻击,只需要自行解决:如果窗户可以被打破,则不会认为您家中的锁有问题。

    好的,回到 GWT

    那么 GWT 是如何做到这一点的呢?正如您所注意到的,@XsrfProtect 注释将服务类型标记为需要在服务器上检查。然后客户端必须请求一个令牌,然后确保客户端的服务知道该令牌以供将来的请求。

    那么服务器是如何生成令牌的呢?服务器上的XsrfTokenServiceServlet RPC 服务生成令牌,作为对服务器的每次调用的一部分,正如您所观察到的,XsrfProtectedServiceServlet.validateXsrfToken 然后验证这是正确的。如果您想要自定义行为,则必须修改该系统的每一侧,并且您可以构建它以使每个令牌在使用后失效,但这不是默认设置(也不是,根据OWASP,是否鼓励)。

    我注意到的另一件事是,如果我将 @NoXsrfProtect 添加到 saveName()...

    请注意,validateXsrfToken 仅在 GWT 中的一处被调用,来自 AbstractXsrfProtectedServiceServlet

    @Override
    protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
      if (shouldValidateXsrfToken(rpcRequest.getMethod())) {
        validateXsrfToken(rpcRequest.getRpcToken(), rpcRequest.getMethod());
      }
    }
    

    方法shouldValidateXsrfToken 然后检查该方法是否明确禁用了保护。如果是这样,它将返回 false,并且不会执行任何检查。但是在构建 RPCRequest 对象时,RPC.decodeRequest 总是附加令牌,即使该令牌恰好为空:

      RpcToken rpcToken = null;
      if (streamReader.hasFlags(AbstractSerializationStream.FLAG_RPC_TOKEN_INCLUDED)) {
        // Read the RPC token
        rpcToken = (RpcToken) streamReader.deserializeValue(RpcToken.class);
      }
    

    因此,如果客户端被配置为发送令牌,它将始终被发送,尽管服务器可能会忽略它。

    更多阅读:

    【讨论】:

      猜你喜欢
      • 2020-04-14
      • 2019-09-12
      • 1970-01-01
      • 2019-07-06
      • 2023-03-16
      • 2020-02-23
      • 2020-01-25
      • 2016-10-06
      • 2016-10-15
      相关资源
      最近更新 更多