SV.TAINTED.CALL.DEREF
関数呼び出しによる未検証ポインターの逆参照
入力データがユーザーまたは外部環境から受け入れられるときは常に、入力のタイプ、長さ、書式、および範囲を検証してから使用する必要があります。このデータが適切に検証されるまでは、そのデータは汚染していると言われます。SV.TAINTED ファミリーチェッカーは、コードでの汚染データの使用箇所を探します。
SV.TAINTED.CALL.DEREF チェッカーが、関数呼び出しを介して、逆参照操作の汚染データを使用するコードにフラグを立てます。
脆弱性とリスク
コードへのポインター入力が適切に検証されておらず、逆参照操作で使用されると、結果として、禁止されているメモリ領域の読み書きを試行しようとします。その結果、プログラムクラッシュ、またはユーザーパスワードなど機密データを含む有効なメモリの場所を意図せず読み書きが行われます。これにより、潜在的なセキュリティホールに以下のような攻撃が行われる可能性があります:
- 予期しない値を提供し、プログラムクラッシュを引き起こします。
- 機密データを読み取る
- 悪意のある入力を使用して、データを変更したり制御フローを改めたりします。
- 過剰なリソース消費を引き起こします。
- 任意のコマンドを実行します。
軽減と防止
汚染入力エラーを回避するには:
- パラメーターや引数、クッキー、ネットワークから読み取られる入力、環境変数、逆 DNS ルックアップ、クエリ結果、ファイル名、データベース、および外部システムという、信頼されていない入力がソフトウェア内に入り込む可能性がある領域すべてを把握します。
- ブラックリスト、つまり 既知の不良な 戦略だけを信頼するのではなく、入力のホワイトリスト、つまり 既知の良好な ポリシーを使用します。
- 入力の該当するプロパティがすべて検証済みであることを確認します。 これには、長さ、タイプ、範囲、欠落しているか余計な入力、構文、および一貫性が含まれます。
- アプリケーションのクライアント側でセキュリティチェックが実行される場合、サーバー側で複製されることを確認します。
- アプリケーションで複数ソースからの入力が組み合わされる場合、ソースの組み合わせが完了したら検証を行います。
脆弱コード例 1
コピー
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define SHMEM_SIZE 1024
typedef struct S_ {
int transaction_id;
int* id;
char* str;
} S;
void use_shared_mem_example(key_t shmem_key, int id) {
int shmem_id = shmget(shmem_key, SHMEM_SIZE, IPC_CREAT);
S* s = (S*) shmat(shmem_id, NULL, 0);
if (s != (S*) (-1)) {
*(s->id) = id; // dereference of untrusted pointer, flagged as SV.TAINTED.DEREF
strcpy (s->str, "Sample signal string" ); // dereference of untrusted pointer via call, flagged as SV.TAINTED.CALL.DEREF
}
shmdt(( void *) s);
}
上記の例では、プロセス間で共有されるメモリへのポインターは直接、または関数呼び出しを介して逆参照されます。SV.TAINTED.DEREF と SV.TAINTED.CALL.DEREF の欠陥を昇格することにより、Klocwork はこれらの操作にフラグを立てます。
17 行目: [SV.TAINTED.DEREF] 15 行目で 'shmat' から受け取られた未検証ポインター 's->id' は、17 行目で逆参照されます。 18 行目: [SV.TAINTED.CALL.DEREF] 15 行目で 'shmat' から受け取られた未検証ポインター 's->str' は、18 行目で 'strcpy' への呼び出しを介して逆参照されます。
コードのデベロッパーは、逆参照操作の前に、信頼できるポインター衛生を使用するよう推奨され、またはポインターの逆参照を避けます。
脆弱コード例 2
コピー
#include <string.h>
typedef struct {
void *data;
} request_t;
#define MAGIC_ADDRESS ((void*)0xdeadbeef)
#define MAGIC_SIZE 1024
char* get_sensitive_data();
void* read_from_port() {
// a library function known to return pointer to untrusted data
// for example, read from a fixed memory location
return MAGIC_ADDRESS;
}
void unsafe_dereference() {
request_t* req = read_from_port();
char* data = get_sensitive_data();
memcpy(req->data, data, MAGIC_SIZE); // unsafe dereference inside the function, flagged by SV.TAINTED.CALL.DEREF
}
この例では、類似した汚染ポインターの逆参照 req->data がライン 20 で実行されます。Klocwork は SV.TAINTED.CALL.DEREF 警告を発し、潜在的なセキュリティ問題にフラグを立てます。
[SV.TAINTED.CALL.DEREF] 18 行目で 'read_from_port' から受け取られた未検証ポインター 'req->data' は、20 行目で 'memcpy' への呼び出しを介して逆参照されます。
関連チェッカー
拡張機能
このチェッカーは、Klocwork knowledge base (ナレッジベース) を利用して拡張できます。詳細については、C/C++ 解析のチューニングを参照してください。