Search code examples
asp.netasp.net-mvcveracodessrf

Unable to rectify VeraCode CWE ID 918 - (SSRF) in ASP.NET


Long story short, no matter what I try VeraCode continues to flag 8 lines of my code as flaws with CWE 918. This is old code so I'm not sure why it's suddenly being flagged.

Here's an example [offending] method with the flagged line in bold

  public virtual async Task<HttpResponseMessage> Put(string controller = "", Dictionary<string, object> parameters = null, object body = null)
        {
            if (string.IsNullOrWhiteSpace(ApiBaseUrl)) return null;
            HttpResponseMessage response = null;

            using (var client = GetHttpClient())
            {
                client.BaseAddress = new Uri(ApiBaseUrl);

                if (!string.IsNullOrEmpty(Token)) client.DefaultRequestHeaders.Add("Token-Key", Token);
                if (!string.IsNullOrEmpty(DeviceId)) client.DefaultRequestHeaders.Add("DeviceId", DeviceId);

                var url = GenerateUrl(controller, parameters);

                var requestBody = GeneratedHttpContent(body);
                if (requestBody == null) requestBody = new StringContent("");

                **response = await client.PutAsync(url, requestBody);**

                await LogError(response);
                return response;
            }
        }

Here's my proposed fix that utilized an extension method to validate the URL

var url = GenerateUrl(controller, parameters);

                var requestBody = GeneratedHttpContent(body);
                if (requestBody == null) requestBody = new StringContent("");

                **if (url.IsValidUrl())
                {
                    response = await client.PutAsync(url, requestBody);
                }
                else
                {
                    response = new HttpResponseMessage(HttpStatusCode.BadRequest);
                }**

                await LogError(response);
                return response;

Here is the extension method with a VeraCode attribute

        [RedirectUrlCleanser]
        public static bool IsValidUrl(this string source)
        {
            return Uri.TryCreate(source, UriKind.RelativeOrAbsolute, out Uri uriResult) && Uri.IsWellFormedUriString(source, UriKind.RelativeOrAbsolute);
        }

I can have VeraCode automatically mitigate based on the attribute, but our client will be performing their own scan and certainly won't have that setting enabled.

Any ideas on how I can resolve this would be appreciated.


Solution

  • The true source of the flaw is inside of your GenerateUrl method which is unfortunately not shown, but here is the general idea of what the Veracode is complaining about.

    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. Below is what I found at the Veracode site: https://community.veracode.com/s/question/0D52T00004i1UiSSAU/how-to-fix-cwe-918-veracode-flaw-on-webrequest-getresponce-method

    The complete solution existed only for the case where you have single or some small number of possible input values (white list):

    public WebResponse ProxyImage(string image_host, string image_path)
    {
        string validated_image_host = AllowedHosts.Host1;
        if (image_host.Equals(AllowedHosts.Host2))
            validated_image_host = AllowedHosts.Host2;
    
        string validated_image = AllowedImages.Image1;
        if (image_path.Equals(AllowedImages.Image2))
            validated_image = AllowedImages.Image2;
    
        string url = $"http://{validated_image_host}.example.com/{validated_image}";
    
        return WebRequest.Create(url).GetResponse();
    }
    

    If the set of possible valid values is too large for that kind of validation then you need to fix the flaw by implementing dynamic validation of inputs using regular expressions. Unfortunately, Veracode is not smart enough to recognize that kind of fix, so "mitigation by design" is still required.

    public WebResponse ProxyImage(string image_host, string image_path)
    {
        var image_host_regex = new System.Text.RegularExpressions.Regex("^[a-z]{1,10}$");
        if (!image_host_regex.Match(image_host).Success)
            throw new ArgumentException("Invalid image_host");
    
        var image_path_regex = new System.Text.RegularExpressions.Regex("^/[a-z]{1,10}/[a-z]{1,255}.png$");
        if (!image_path_regex.Match(image_path).Success)
            throw new ArgumentException("Invalid image_host");
    
        string url = $"http://{image_host}.example.com/{image_path}";
        return WebRequest.Create(url).GetResponse();
    }