CS.SV.TAINTED.DESERIALIZATION

オブジェクト作成におけるシリアル化解除中の未検証整数の使用

入力がユーザーまたは外部環境から受け入れられるときは常に、入力のタイプ、長さ、書式、および範囲を検証してから使用する必要があります。適切に検証されるまでは、そのデータは汚染していると言われます。CS.SV.TAINTED ファミリーのチェッカーは、コードでの汚染データの使用箇所を探します。

CS.SV.TAINTED.DESERIALIZATION チェッカーは、未検証データがオブジェクトコンストラクター呼び出しに引数として渡され、その中で内部メンバーの割り当てに使用されるコードにフラグを立てます。そうした使用により、汚染されたデータの逆シリアル化を構成することになり、チェッカーによって潜在的に危険であると報告されます。

脆弱性とリスク

コードへの入力が適切に検証されないと、攻撃者は入力をアプリケーションが予期しない形で作成することができます。意図しない入力を受け取ると、制御フローの改変、任意リソースの制御、および任意のコードの実行につながる可能性があります。この種のチャンスがある場合、攻撃者は次のことを行えます。

  • 予期しない値を提供し、プログラムクラッシュを引き起こします。
  • 過剰なリソース消費を引き起こします。
  • 機密データを読み取ります。
  • 悪意のある入力を使用して、データを変更したり制御フローを改めたりします。
  • 任意のコマンドを実行します。

汚染されたデータで構成されたオブジェクトは、予期しない動作を引き起こす可能性があり、サードパーティのコードで定義されたクラスをインスタンス化する場合に特に危険です。そのようなオブジェクトを構成すると、弱点を悪用する可能性が生じます。開発者は、そうしたオブジェクトはどれも有効であり、潜在的に危険なコンテキストで安全に使用できると思い込んでしまうことがあるため、ソースコードが使用できる場合でも、信頼できないデータでオブジェクトを構成することは危険です。

脆弱コード例

コピー
  using System;
  using System.IO;
  namespace TaintedResource {
    class TestTaintedResource {
      const string fileName = "File.dat";
  
      public static void TaintedResourceExample1() {
              int taintedIntValue = Console.Read();
              SimpleVariableTest test1 = new SimpleVariableTest(taintedIntValue);  // CS.SV.TAINTED.DESERIALIZATION
     }
   }
   class SimpleVariableTest
   {
     public SimpleVariableTest(int value) {
       setIntValue = value;
     }
     private int setIntValue;
   }
 }

Klocwork は 9 行目で指摘レポートを生成し、「8 行目で 'Read' から受け取った未検証の整数値 'taintedIntValue' は、9 行目で 'constructor' の呼び出しによりデータの逆シリアル化中に使用される」ことを示します。この場合、汚染されている可能性のあるデータが、constructor を呼び出してオブジェクトを作成するときに、引数として渡されており、これは constructor クラスのフィールドメンバーに引数の値を実際に割り当てることになり、悪意のあるユーザーによって悪用される可能性があります。

修正コード例

コピー
  using System;
  using System.IO;
  namespace TaintedResource {
    class TestTaintedResource {
      const string fileName = "File.dat";
  
      public static void TaintedResourceExample1() {
              int taintedIntValue = Console.Read();
        if (taintedIntValue > MAX_VALUE || taintedIntValue < MIN_VALUE)
       {
          return;
       }
             SimpleVariableTest test1 = new SimpleVariableTest(taintedIntValue); 
     }
   }
   class SimpleVariableTest
   {
     public SimpleVariableTest(int value) {
       setIntValue = value;
     }
     private int setIntValue;
   }
 }

この例では、整数 'num' は constructor の呼び出しで使用される前に 9 行目でチェックされるので、Klocwork はもはや欠陥を報告しません。