SV.TAINTED.CALL.BINOP

関数呼び出しによるバイナリ演算での未検証整数値の使用

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

SV.TAINTED.BINOP チェッカーが、加算、減算、または乗算など、関数呼び出しを使って、バイナリ演算により、汚染データを使用するコードにフラグを立てます。

脆弱性とリスク

コードへの入力された整数データが適切に検証されず、バイナリ演算のオペランドとして使用されると、結果は整数オーバーフローまたはラップアラウンドを起こす可能性があります。これが起きると、攻撃者が通常の制御フローを変更し、予期せぬプログラム行動を引き起こす可能性があります。最悪の場合攻撃者は次のことを行えます。
  • 予期しない値を提供し、プログラムクラッシュを引き起こします。
  • 過剰なリソース消費を引き起こします。
  • 機密データを読み取る
  • 悪意のある入力を使用して、データを変更したり制御フローを改めたりします。
  • 任意のコマンドを実行します。

軽減と防止

汚染入力エラーを回避するには:
  • パラメーターや引数、クッキー、ネットワークから読み取られる入力、環境変数、逆 DNS ルックアップ、クエリ結果、ファイル名、データベース、および外部システムという、信頼されていない入力がソフトウェア内に入り込む可能性がある領域すべてを把握します。
  • ブラックリスト、つまり 既知の不良な 戦略だけを信頼するのではなく、入力のホワイトリスト、つまり 既知の良好な ポリシーを使用します。
  • 入力の該当するプロパティがすべて検証済みであることを確認します。 これには、長さ、タイプ、範囲、欠落しているか余計な入力、構文、および一貫性が含まれます。
  • アプリケーションのクライアント側でセキュリティチェックが実行される場合、サーバー側で複製されることを確認します。
  • アプリケーションで複数ソースからの入力が組み合わされる場合、ソースの組み合わせが完了したら検証を行います。

脆弱コード例

コピー
 int get_altitude();
 void set_altitude(int);

 int get_untrusted() {
     int i;
     scanf("%d", &i);
     return i;
 }
 
 extern const int max_altitude;

 int get_new_altitude(int shift) {
     int current_altitude = get_altitude();
     return current_altitude + shift;
 }

 void increase_altitude() {
    int shift = get_untrusted();
     if (shift > 0) {
         int new_altitude = get_new_altitude(shift);
         if (new_altitude < max_altitude) {
             set_altitude(new_altitude);
         }
     }
 }

上の例では、攻撃者が変数 'new_altitude' に対して任意に大きな値を提供することができます。14行目のバイナリ演算がオーバフローする場合、20行目の変数 'new_altitude' が負の値となり、予期せぬプログラム行動を起こす可能性があります。

Klocworkが、20 行目に SV.TAINTED.BINOP の欠陥を報告。18行目の 'get_untrusted' から受け取られた未検証整数値 'shift' が、20行目で 'get_new_altitude' への呼び出しを介してバイナリ演算子へのオペランドとして使用されます。

修正コード例

コピー
 int get_altitude();
 void set_altitude(int);

 int get_untrusted() {
     int i;
     scanf("%d", &i);
     return i;
 }

 extern const int max_altitude;
 extern const int max_trusted_shift;

 int get_new_altitude(int shift) {
     int current_altitude = get_altitude();
     return current_altitude + shift;
 }

 void increase_altitude() {
     int shift = get_untrusted();
     if (shift > 0 && shift < max_trusted_shift) {
         int new_altitude = get_new_altitude(shift);
         if (new_altitude < max_altitude) {
             set_altitude(new_altitude);
         }
     }
 }

Klocwork チェッカーは指摘レポートを生成しなくなります。これは、整数値 'shift' がバイナリ演算で使用される前に 20 行目で検証されるためです。

セキュリティトレーニング

Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。