メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

ISO/IEC TS 17961 [taintsink]

Tainted, potentially mutilated, or out-of-domain integer values are used in a restricted sink

説明

ルール定義

汚染されている、切断されている可能性がある、または領域外にある整数値を制限のあるシンクで使用。1

Polyspace 実装

このチェッカーは以下の問題をチェックします。

  • 可変長配列の汚染されたサイズ

  • 汚染されたオフセットによるポインターのデリファレンス

  • 汚染されたインデックスによる配列へのアクセス

チェッカーの拡張

既定の Bug Finder 解析では、現在の解析境界の外部からの特定の入力に関する "可変長配列の汚染されたサイズ""汚染されたオフセットによるポインターのデリファレンス"、または "汚染されたインデックスによる配列へのアクセス" 問題にフラグを設定しない場合があります。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary] を使用します。

すべて展開する

問題

可変長配列の汚染されたサイズでは、セキュリティで保護されないソースに由来するサイズの可変長配列 (VLA) を検出します。

リスク

攻撃者が VLA のサイズを予期しない値に変更した場合、プログラムのクラッシュや予期しない動作の原因となることがあります。

サイズが正でない場合、VLA の動作は未定義となります。プログラムは想定どおりには実行されません。

サイズが無制限の場合、VLA はメモリ枯渇やスタック オーバーフローを引き起こすことがあります。

修正方法

VLA のサイズを検証して、正であり最大値より小さいことを確認します。

例 - VLA のサイズとして使用される入力引数
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size];
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

この例では、可変長配列のサイズが入力引数に基づいています。この入力引数の値はチェックされていないため、サイズが負になるか大きすぎる可能性があります。

修正 — VLA のサイズをチェック

1 つの修正方法として、可変長配列を作成する前にサイズ変数をチェックします。この例では、VLA を作成する前に、サイズが 0 より大きく 40 より小さいかどうかをチェックしています。

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}
問題

汚染されたオフセットによるポインターのデリファレンスでは、不明なソースまたはセキュリティで保護されないソースに由来するオフセット変数を使用したポインターのデリファレンス (読み取りか書き込みのいずれか) を検出します。

このチェックでは、動的に割り当てられたバッファーに注目します。静的バッファーのオフセットについては、汚染されたインデックスによる配列へのアクセスを参照してください。

リスク

インデックスは有効な配列範囲を外れている可能性があります。汚染されたインデックスが配列範囲を外れていると、以下の原因となることがあります。

  • バッファー アンダーフローまたはアンダーライト、すなわち、バッファーの先頭より前でのメモリへの書き込み。

  • バッファー オーバーフロー、すなわち、バッファーの末尾より後でのメモリへの書き込み。

  • バッファー オーバーリード、すなわち、対象バッファーの末尾より後でのメモリへのアクセス。

  • バッファーのアンダーリード、すなわち、対象バッファーの先頭より前のメモリへのアクセス。

攻撃者は、無効な読み取りや書き込みを使用してプログラムを侵害できます。

修正方法

変数を使用してポインターにアクセスする前に、インデックスを検証します。変数が有効範囲内にありオーバーフローしないことを確認します。

例 - ポインター配列のデリファレンス
#include <stdio.h>
#include <stdlib.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if(pint) {
        /* Filling array */
        read_pint(pint);
        c = pint[offset];
        free(pint);
    }
    return c;
}

この例では、関数が整数ポインター pint を初期化しています。ポインターは、入力インデックス offset を使用してデリファレンスされています。offset の値はポインター範囲外である可能性があり、値域外エラーの原因となります。

修正 — デリファレンス前にインデックスをチェック

1 つの修正方法として、インデックスの値を検証します。インデックスが有効範囲内にあれば、ポインターのデリファレンスを続行します。

#include <stdlib.h>
#include <stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if (pint) {
        /* Filling array */
        read_pint(pint);
        if (offset>0 && offset<SIZE10) {
            c = pint[offset];
        }
        free(pint);
    }
    return c;
}
問題

汚染されたインデックスによる配列へのアクセスは、配列に対する読み取りや書き込みにおいて、検証されていない汚染されたインデックスが使用される場合を検出します。

リスク

インデックスは有効な配列範囲を外れている可能性があります。汚染されたインデックスが配列範囲を外れていると、以下の原因となることがあります。

  • バッファー アンダーフローまたはアンダーライト — バッファーの先頭より前のメモリへの書き込み。

  • バッファー オーバーフロー — バッファーの末尾より後のメモリへの書き込み。

  • バッファーのオーバーリード — 対象バッファーの末尾より後のメモリへのアクセス。

  • バッファーのアンダーリード、すなわち、対象バッファーの先頭より前のメモリへのアクセス。

攻撃者は無効な読み取りや書き込みの操作を利用して、プログラムに問題を生じさせることができます。

修正方法

インデックスを使用して配列にアクセスする前に、インデックス値を検証して、それが配列範囲内にあることを確認します。

例 - インデックスを使用してバッファーの値を返す
#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
  return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
    return tab[num];  
}

この例では、インデックス num により配列 tab にアクセスします。この関数は、numtab の範囲内にあるかどうかをチェックしません。

修正 — 使用前に範囲をチェック

1 つの修正方法として、num が範囲内にあることを使用前にチェックします。

#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
	return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
	if (num >= 0 && num < SIZE100) {
		return tab[num]; 
	} else {
		return -1;
	}
}

チェック情報

決定可能性:決定不可能

バージョン履歴

R2019a で導入


1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.