【问题标题】:Impersonate Windows User with AntiForgery Tokens使用 AntiForgery 令牌模拟 Windows 用户
【发布时间】:2016-04-26 19:01:13
【问题描述】:

我有两个 Web API;一种是公开的,一种是内部的。我希望公共的与内部的沟通。但是,我想要内部一层的两层安全性:

  • Windows 身份验证(已完成)
  • AntiForgery 令牌(这是我遇到的问题)

现在我正在公共 API 中生成 AntiForgery 令牌:

string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;

然后,我在内部 API 的过滤器中将其删除:

var request = actionContext.Request;
if (!request.RequestUri.PathAndQuery.StartsWith("/api"))
{
    return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}

string cookieToken = "";
string formToken = "";

IEnumerable<string> tokenHeaders;
if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
{
    string[] tokens = tokenHeaders.First().Split(':');
    if (tokens.Length == 2)
    {
        cookieToken = tokens[0].Trim();
        formToken = tokens[1].Trim();
    }
}

try
{
    AntiForgery.Validate(cookieToken, formToken);
}
catch (HttpAntiForgeryException ex)
{
    return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}

return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));

这行得通,有点。我得到的错误是这样的:

提供的防伪令牌用于用户“”,但当前用户是“WINDOWS8VM\Michael”。

生成令牌时我需要以某种方式模拟 Windows 用户,以便用户的相同。

另一个问题是CredentialCache.DefaultNetworkCredentials 是空的。这几乎可以肯定是因为公共 API 没有打开 Windows 身份验证。但是,应用程序池有一个身份,这就是我要寻找的身份。

【问题讨论】:

  • 如果你从另一个 api(公共)调用一个 api(内部),你为什么需要防伪令牌?
  • 主要原因是确保其他内部应用程序无法利用此 API。数据异常敏感。如果我们只有 Windows 身份验证,那么我们觉得这还不够。这可能是我们必须解决的问题,但我们想添加某种类型的承载,我们想从尝试使用AntiForgery 令牌开始。当然还有其他方式,但就架构而言,它们的参与度更高。
  • 你确定你真的明白你想在这里用 AF 令牌实现什么吗?这些令牌是为了防止 CSRF 攻击,而不是保护服务之间的请求。您想要使用它们的方式完全违背了它们的设计目的。您基本上将一堆加密数据从服务 A 传递到服务 B 并检查 B 是否知道解密密钥,但是不需要 AF 来做这些事情。
  • @Evk,我想简单地在服务之间传递一个密钥是正确的。我只是希望我能够利用 AF 代币来做到这一点,而不是构建那个架构。
  • 好吧,您只能使用 AF 的加密部分,跳过其他所有内容(无论如何这与您的任务无关)。只需使用 MachineKey.Protect (msdn.microsoft.com/en-us/library/…) 使用与 AF 令牌相同的密钥加密任意数据,然后使用 MachineKey.Unprotect 进行解密。请注意,AF 令牌还包含您案例的“任意数据”。如果不确定要加密什么 - 加密请求数据本身,那么您也可以确定请求不是在中间伪造的。

标签: c# .net security asp.net-web-api csrf


【解决方案1】:

由于您只想验证您的内部 api 是否由受信任的调用者(即公共 api)调用 - 您不需要使用防伪令牌。相反,您可以使用 AF 令牌在公共 api 上加密\签名您自己的数据的相同机制,然后解密和验证这些数据是您在内部 api 上所期望的。为此,您可以使用 MachineKey.ProtectMachineKey.Unprotect 方法。

如果您这样做,请注意用于加密的密钥可能因应用程序而异。查看machineKey元素的描述,注意IsolateApps设置的效果。如果您的机器密钥配置为 IsolateApps - 一个 IIS 应用程序将无法解密受另一个保护的数据(与 AF 令牌相同),即使它们都位于同一台机器上。

另外请注意,如果应用程序在这方面没有被隔离,同一台机器上的任何 IIS 应用程序都将能够使用相同的密钥加密数据并调用您的内部 api。但是,如果您只想保护您的 api 免受网络中其他机器的影响 - 那应该足够了。

如果您不确定要加密哪些数据 - 合并来自请求本身的所有敏感数据,对其进行散列并保护该散列。然后在内部 api 合并相同的数据,对其进行哈希处理,取消保护从调用方接收到的数据,并确保未保护的数据与目标哈希匹配。

【讨论】:

  • 这两个 Web 应用程序将在不同的机器上。如果机器密钥相同,它们将能够成功加密和解密吗?
  • 是的,作为一个选项,您可以在两台机器上将这些键显式设置为相同的值(请参阅答案中的 machineKey 链接)。
  • 好的,我认为这会很好,因为只有这两台机器会同步。这实际上正是我们想要的!
  • 我已在两个Web.config 文件中将machineKey 属性添加到system.web。对于validationvalidationKeydecryptionKey,它们具有相同的值。但是,我在解密过程中不断收到错误Error occurred during a cryptographic operation.。我错过了什么吗?
  • 如果您在同一台机器上保护和取消保护,您的完全相同的代码是否有效?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多