在微服务架构中使用 API 网关模式时无法修复 veracode cwe id 918 缺陷 (SSRF)

Unable to fix veracode cwe id 918 flaw (SSRF) when using API gateway pattern in a Microservices architecture

我在 Micro services 架构中使用 API Gateway Pattern,其中 Front End Angular app 为我的 API Gateway 项目创建了一个 HTTP request,它只是一个 ASP.net Core 3.1 Web API 项目。目前我只有 2 个 micro services 和一个 API Gateway,它们都是 ASP.net Core 3.1 Web API 类型的项目。 API Gateway 项目拥有我 micro services 的所有控制器。 API Gateway 的目的只是接收来自 Front end 的请求并向适当的 Micro service.

发送 HTTP Request

现在在我的 API Gateway 项目的 AccountController.cs 中,我有以下代码

/// <summary>
/// Gets the detail of an account by its id
/// </summary>
/// <param name="organizationId">Id of the Organization of which the account belongs to</param>
/// <param name="accountId">Id of Account of which information is being requested</param>
/// <returns>Account's Details</returns>
[HttpGet("{organizationId}/{accountId}")]
public async Task<IActionResult> GetAccountAsync(Guid organizationId, Guid accountId)
{
    _uri = new Uri(uriString: $"{_configurationService.AccountAPI}GetAccount/{organizationId}/{accountId}");
    using var result = await _client.GetAsync(_uri);
    var content = await result.Content.ReadAsStringAsync();
    return Ok(content.AsObject<MessageResponse<AccountDetailVM>>());
}

在 Whosebug 上搜索 SSRF 问题后,我在 Veracode community 找到了以下建议。

Veracode Static Analysis will report a flaw with CWE 918 if it can detect that data from outside of the application (like an HTTP Request from a user, but also a file that may have been uploaded by a user, database data, webservice data, etc) is able to change the nature of a network request.

上,我找到了以下修复方法

For CWE ID 918 it is hard to make Veracode recognize your fix unless you have static URL. You need to validate all your inputs that become parts of your request URL.

这意味着我必须在将输入参数 OrganizationIdAccountId 附加到请求 URL.

之前清理它们

另外一个关于veracode community的问题建议

The only thing that Veracode Static Analysis will automatically detect as a remediation for this flaw category is to change the input to be hardcoded

他们提出了查询字符串的解决方案

The given example appears to take a model identifier and put it in the URL used in an internal request. We would recommend validating the ID per the rules you have for this datatype (typically this should only be alphanumeric and less than 255 characters) and URLencode it before appending it to a URL.

完成所有这些之后,我对我的代码进行了以下更改

  1. 确保 OrganizationId 和 AccountId Guid 不为空
  2. URL 编码字符串

修改后的代码如下

/// <summary>
/// Gets the detail of an account by its id
/// </summary>
/// <param name="organizationId">Id of the Organization of which the account belongs to</param>
/// <param name="accountId">Id of Account of which information is being requested</param>
/// <returns>Account's Details</returns>
[HttpGet("{organizationId}/{accountId}")]
public async Task<IActionResult> GetAccountAsync(Guid organizationId, Guid accountId)
{
    if (organizationId != Guid.Empty && accountId != Guid.Empty)
    {
        string url = HttpUtility.UrlEncode($"{_configurationService.AccountAPI}GetAccount/{organizationId}/{accountId}");
        using var result = await _client.GetAsync(url);
        var content = await result.Content.ReadAsStringAsync();
        return Ok(content.AsObject<MessageResponse<AccountDetailVM>>());
    }

    return BadRequest();
}

这就是我清理输入参数 OrganizationIdAccountId 所能做的所有事情,但在所有这些更改之后 veracode 仍然在 [=45] 行上识别出 SSRF 缺陷=]

using var result = await _client.GetAsync(url);

我找到了解决此问题的 hack,我只是将查询字符串参数附加到 httpClient 的基址,veracode 不再给我错误。

这是解决方案的样子

/// <summary>
/// Gets the detail of an account by its id
/// </summary>
/// <param name="organizationId">Id of the Organization of which the account belongs to</param>
/// <param name="accountId">Id of Account of which information is being requested</param>
/// <returns>Account's Details</returns>
[HttpGet("{organizationId}/{accountId}")]
public async Task<IActionResult> GetAccountAsync(Guid organizationId, Guid accountId)
{
    if (organizationId != Guid.Empty && accountId != Guid.Empty)
    {
        var httpClient = new HttpClient();

        //Appended the parameters in base address to
        //to fix veracode flaw issue
        httpClient.BaseAddress = new Uri($"{_configurationService.AccountAPI}GetAccount/{organizationId}/{accountId}");

        //passing empty string in GetStringAsync to make sure
        //veracode doesn't treat it like modifying url 
        var content = await httpClient.GetStringAsync("");

        return Ok(content.AsObject<MessageResponse<AccountDetailVM>>());
    }

    return BadRequest();
}