CS.SV.TAINTED.CALL.LOOP_BOUND.RESOURCE

循环(退出条件由已污染数据控制)中的资源分配

每当从用户或外部环境接受输入的时候,都应该在使用前验证类型、长度、格式和范围。在得到妥善验证之前,数据将被视为已被污染。CS.SV.TAINTED 系列检查器会查找代码中使用已污染数据的情况。

CS.SV.TAINTED.CALL.LOOP_BOUND.RESOURCE 检查器会标记代码,其中将未验证的整数数据作为调用参数传递给函数,在该函数中用作循环边界,同时已在循环内分配任何资源(托管或非托管)。

如果在循环体的末尾没有对其的引用,则可能会用垃圾回收器快速处置一些资源,但无法保证这种处置的时机。此外,某些已分配资源的使用寿命可能会延长,这可能导致过多的资源消耗,从而导致资源耗尽或程序失败。当此类循环的退出条件由外部输入控制时,潜在的攻击者可能会利用此行为。

漏洞与风险

当代码输入未经妥善验证时,攻击者可以精心地将输入编制为并非应用程序所预期的格式。接收意外的输入可能导致控制流被改变、任意的资源控制以及任意的代码执行。通过此类机会,攻击者可以

  • 提供无法预料的值并导致程序崩溃
  • 导致过度的资源消耗
  • 读取机密数据
  • 使用恶意输入来修改数据或改变控制流
  • 执行任意命令

漏洞代码示例

复制
  using System;
  using System.IO;
  namespace TaintedResource {
    class TestTaintedResource {
      const string fileName = "File.dat";
  
      public static void TaintedResourceExample1() {
              int num = getTaintedData();
              sinkMethod(num);               // CS.SV.TAINTED.CALL.LOOP_BOUND.RESOURCE
     }
  
     public static void sinkMethod(int value) {
       for(int i = 0; i < value; i++)
       {
          Test obj = new Test();
       }
     }
  
      public static int getTaintedData()
      {
        try
        {
          using (BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open)))
          {
            return(br.ReadInt32());
          }
        }
        catch (Exception e)
        {
          Console.WriteLine(e);
        }
      }
    }
    class Test
    {
      ---
      ---
    }
  }

Klocwork 针对第 14 行生成问题报告,这表示“在循环体内分配了一个或多个对象,而该循环体的退出条件是在第 9 行通过调用 sinkMethod 由未验证的整数值 taintedIntValue 控制”。在这种情况下,可能被污染的数据被用作循环边界,这可能被恶意用户利用。

修正代码示例

复制
   using System;
   using System.IO;
   namespace TaintedResource
   {
     class TestTaintedResource
     {
       const string fileName = "File.dat";
   
       public static void TaintedResourceExample1()
      {
        int num = getTaintedData();
        if (num > MAX_ALLOCATION_QUOTA_IN_ONE_GO)
        {
           return;
        }
        sinkMethod(num);
      }
  
      public static void sinkMethod(int value) {
        for(int i = 0; i < value; i++)
        {
           Test obj = new Test();
        }
      }
  
  
      public static int getTaintedData()
      {
        try
        {
          using (BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open)))
          {
            return(br.ReadInt32());
          }
        }
        catch (Exception e)
        {
          Console.WriteLine(e);
        }
      }
    }
    class Test
    {
      ---
      ---
    }
  }

在此示例中,Klocwork 不再报告缺陷,因为整数 num 在用作循环条件之前,已在第 12 行进行了检查。