テイント解析

フィールド 説明
source 追跡を開始する入力値や式を指定します。
sanitizer このルールでテイントの伝播を止めるものとして扱う処理を指定します。関数の実装が安全かどうかを、エンジンが自動で証明するわけではありません。
sink 追跡中の値が到達したときに、検出結果を報告する箇所を指定します。
method sanitizerやsinkで、メソッド名を使って呼び出しを指定します。引数の位置や呼び出し形式を区別する必要がある場合は、その条件もルールに指定してください。

次の例では、Javaコード内の特定の入力値の流れを検出します。

  • 対象言語はJavaです。
  • getInput()の戻り値がunsafeSinkの第1引数に渡され、第2引数が"unsafe_option"である場合に検出します。
  • この例では、sanitizerValueが用途に応じて入力値を適切に処理すると仮定し、その戻り値からテイントが除去されたものとして扱います。実際にルールを作成する際は、この仮定が関数の動作と一致することを確認してください。
yaml
rule:
  taint:
    source:
      pattern: getInput()
    sanitizer:
      method:
        - sanitizerValue
    sink:
      pattern: unsafeSink($IN, "unsafe_option")

以下のコードでこのルールの検出条件を満たすのは、unsafe()内の呼び出しだけです。ほかの呼び出しで結果が報告されないのは、このルールの条件を満たさないためであり、コード全体の安全性を保証するものではありません。例で使う関数の実装は省略しています。

java
public class TaintExample {
    public void unsafe() {
        String userInput = getInput();
        unsafeSink(userInput, "unsafe_option"); // 検出: 入力値とオプションが条件に一致
    }

    public void safe_1() {
        String userInput = getInput();
        unsafeSink(userInput, "safe_option"); // 検出なし: 第2引数が条件と異なる
    }

    public void safe_2() {
        String userInput = getInput();
        userInput = sanitizerValue(userInput);
        unsafeSink(userInput,"unsafe_option"); // 検出なし: サニタイザーの戻り値を使用
    }

    public void safe_3() {
        String userInput = getInput();
        unsafeSink("something", userInput); // 検出なし: 入力値が第1引数ではない
    }
}