メインコンテンツ

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

ISO/IEC TS 17961 [usrfmt]

Including tainted or out-of-domain input in a format string

説明

ルール定義

書式文字列に汚染された入力または領域外の入力が含まれる。1

Polyspace 実装

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

  • 書式文字列指定子と引数の不一致

  • 汚染された文字列形式

.

チェッカーの拡張

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

すべて展開する

問題

書式文字列指定子と引数の不一致は、printf などの書式設定付き出力関数の書式指定子が、それに対応する引数と一致しない場合に発生します。たとえば、unsigned long 型の引数の書式指定は %lu でなければなりません。

リスク

書式指定子と対応する引数の間の不一致により、未定義の動作が発生します。

修正方法

書式指定子が対応する引数と一致することを確認します。たとえば、次の例では、%d 指定子は文字列引数 message に一致せず、%s 指定子は整数引数 err_number に一致しません。

  const char *message = "License not available";
  int err_number = ;-4
  printf("Error: %d (error type %s)\n", message, err_number);
2 つの書式指定子を入れ替えると、問題が修正されます。書式指定子の詳細は、関数 printf の仕様を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - 浮動小数点の出力
#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%d\n", fst);
}

printf ステートメントで、書式指定子 %dfst のデータ型と一致していません。

修正 — 符号なしの long 書式指定子を使用

1 つの修正方法として、%lu 書式指定子を使用することができます。この指定子は fstunsigned 整数型および long サイズに合致します。

#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%lu\n", fst);
}
修正 — 整数引数を使用

1 つの修正方法として、書式指定子と一致するように引数を変更することができます。fst を書式指定子と一致するよう整数に変換し、値 1 を出力します。

#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%d\n", (int)fst);
}
問題

"汚染された文字列形式" が発生するのは、printf 形式の関数が、セキュリティで保護されていないソースから構築された書式指定子を使用する場合です。

リスク

外部で制御される要素を使用して文字列を形式化すると、バッファー オーバーフローやデータ表現の問題の原因となることがあります。攻撃者はこうした文字列形式の設定要素を利用して、%x でスタックの内容を表示し、あるいは %n でスタックへの書き込みを行うことができます。

修正方法

静的文字列を渡して文字列関数を形式化します。この修正により、外部アクターは文字列を制御できなくなります。

別の修正方法として、必要な数の引数のみを許可します。可能な場合は、脆弱性のある %n 演算子をサポートしない関数を、文字列形式で使用します。

例 — ユーザー入力からの要素の取得
#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf(userstr);//Noncompliant   
}

この例では、入力引数 userstr を出力しています。この文字列は不明です。そこに % などの要素が含まれている場合、printf では userstr が文字列でなく文字列形式と解釈され、プログラムがクラッシュする原因となります。

修正 — 文字列として出力

1 つの修正方法として、userstr を明示的に文字列として出力し、あいまいさをなくします。

#include "stdio.h"
#include <unistd.h>
#define MAX 40

void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf("%.20s", userstr); 
}

チェック情報

決定可能性:決定不可能

バージョン履歴

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.