CWE Rule 547
説明
ルールの説明
The program uses hard-coded constants instead of symbolic names for security-critical values, which increases the likelihood of mistakes during code maintenance or security policy change.
Polyspace 実装
ルール チェッカーは以下の問題をチェックします。
バッファー サイズがハードコードされています
ループ境界がハード コードされています
メモリの操作に使用するオブジェクトのサイズがハードコードされています
ハードコードされた機密データ
例
この問題は、配列などのメモリ バッファーを宣言する際に、シンボリック定数ではなく数値を使用した場合に発生します。
バッファー サイズがハード コードされていると、次の問題の原因となります。
バッファー サイズがハード コードされていると、誤りが生じる可能性が大きくなり、そのため保守コストも高くなる。ポリシーの変更によりバッファー サイズの変更が必要になった場合、開発者はコードにバッファー サイズが出現するたびに変更しなければならない。
ハード コードされている定数は、コードが開示された場合に攻撃にさらされることがある。
バッファー サイズには、ハード コードされている定数ではなくシンボリック名を使用します。シンボリック名には、const
修飾子付き変数、enum
定数またはマクロを含めます。
enum
定数の使用を推奨します。
マクロは前処理後に、その定数値によって置き換えられます。したがって、ループ境界が外部にさらされる場合があります。
enum
定数はコンパイルの時点で既知となっています。したがって、コンパイラではループをより効率的に最適化できます。const
修飾子付き変数は、多くの場合、実行時に既知となります。
int table[100]; //Noncompliant
void read(int);
void func(void) {
for (int i=0; i<100; i++) //Noncompliant
read(table[i]);
}
この例では、配列 table
のサイズがハード コードされています。この例では、for
ループのループ境界もハードコードされているため、2 つ目のルール違反があります。
考えられる 1 つの修正方法として、ハード コードされているサイズをシンボリック名に置き換えます。
const int MAX_1 = 100;
#define MAX_2 100
enum { MAX_3 = 100 };
int table_1[MAX_1];
int table_2[MAX_2];
int table_3[MAX_3];
void read(int);
void func(void) {
for (int i=0; i < MAX_1; i++)
read(table_1[i]);
for (int i=0; i < MAX_2; i++)
read(table_2[i]);
for (int i=0; i < MAX_3; i++)
read(table_3[i]);
}
この問題は、for
、while
、または do-while
ループの境界にシンボリック定数ではなく数値を使用した場合に発生します。
ループ境界がハード コードされていると、次の問題の原因となります。
ループ境界がハード コードされていると、時間のかかる計算やリソース割り当てがループに含まれている場合に、サービス拒否攻撃に対する脆弱性が生じる。
ループ境界がハード コードされていると、誤りが生じる可能性が大きくなり、保守コストが高くなる。ポリシーの変更によりループ境界の変更が必要になった場合、開発者はコードに境界が出現するたびに変更しなければならない。
たとえば、ループ境界が 10000 であり、ネットワーク サーバー アプリケーションでサポートされているクライアント接続数の最大値を表現しているとします。サーバーでサポートしているクライアント数がこれより多い場合、コード内のループ境界のインスタンスをすべて変更しなければなりません。ループ境界が 1 回しか発生しない場合でも、コード内の
10000
の数値に対して検索しなければなりません。この数値は、ループ境界以外の場所にも現れる可能性があります。こうした場所は、ループ境界を検索する前に参照しておかなければなりません。
ループ境界に、ハード コードされている定数ではなくシンボリック名を使用します。シンボリック名には、const
修飾子付き変数、enum
定数またはマクロが含まれます。以下の理由により、enum
定数の使用が推奨されます。
マクロは前処理後に、その定数値によって置き換えられます。したがって、バッファー サイズが外部にさらされる場合があります。
enum
定数はコンパイルの時点で既知となっています。したがって、コンパイラではストレージをより効率的に割り当てられます。const
修飾子付き変数は、多くの場合、実行時に既知となります。
void performOperation(int);
void func(void) {
for (int i=0; i<100; i++) //Noncompliant
performOperation(i);
}
この例では、for
ループの境界がハード コードされています。
考えられる 1 つの修正方法として、ハード コードされているループ境界をシンボリック名に置き換えます。
const int MAX_1 = 100;
#define MAX_2 100
enum { MAX_3 = 100 };
void performOperation_1(int);
void performOperation_2(int);
void performOperation_3(int);
void func(void) {
for (int i=0; i<MAX_1; i++)
performOperation_1(i);
for (int i=0; i<MAX_2; i++)
performOperation_2(i);
for (int i=0; i<MAX_3; i++)
performOperation_3(i);
}
この問題は、ハードコードされている定数を次のメモリ関数のメモリ サイズ引数として使用する場合に発生します。
malloc
やcalloc
などの動的メモリ割り当て関数。memcpy
、memmove
、memcmp
、memset
などのメモリ操作関数。
メモリ サイズをハードコードしている場合、文字列リテラルを使用してメモリ操作を実行すると、Polyspace® は欠陥を報告しません。
オブジェクトのサイズをハードコードすると、コードが、型のサイズが異なるアーキテクチャに移植できません。定数値がオブジェクトのサイズと同じでない場合、バッファーがオーバーフローしたり、しなかったりする可能性があります。
メモリ関数のサイズ引数には、sizeof(
を使用します。object
)
#include <stddef.h>
#include <stdlib.h>
enum {
SIZE3 = 3,
SIZE20 = 20
};
extern void fill_ints(int **matrix, size_t nb, size_t s);
void bug_hardcodedmemsize()
{
size_t i, s;
s = 4;
int **matrix = (int **)calloc(SIZE20, s); //Noncompliant
if (matrix == NULL) {
return; /* Indicate calloc() failure */
}
fill_ints(matrix, SIZE20, s);
free(matrix);
}
この例では、メモリ割り当て関数 calloc
が 4 バイトのメモリ サイズで呼び出されています。このメモリは整数ポインターに対して割り当てられています。整数ポインターは、ターゲットによって 4 バイトよりも大きい場合も小さい場合もあります。整数型ポインターが 4 バイトでない場合、プログラムは失敗する可能性があります。
sizeof(int *)
を使用calloc
を呼び出す際、ハード コードしているサイズを sizeof
の呼び出しに置き換えます。この変更によりコードの移植性が高くなります。
#include <stddef.h>
#include <stdlib.h>
enum {
SIZE3 = 3,
SIZE20 = 20
};
extern void fill_ints(int **matrix, size_t nb, size_t s);
void corrected_hardcodedmemsize()
{
size_t i, s;
s = sizeof(int *);
int **matrix = (int **)calloc(SIZE20, s);
if (matrix == NULL) {
return; /* Indicate calloc() failure */
}
fill_ints(matrix, SIZE20, s);
free(matrix);
}
この問題は、機密性の高いデータが文字列リテラルなどとしてコード内で直接露出された場合に発生します。チェッカーは、特定のデータを機密性が高いとして識別し、パスワード暗号化関数などの特定の関数で使用されないようにします。
以下のデータは機密性が高い可能性があります。
データの型 | 情報の機密性を示唆する関数 |
---|---|
ホスト名 |
|
パスワード |
|
データベース |
|
ユーザー名 |
|
ソルト | crypt 、crypt_r (第 2 引数) |
暗号化キーと初期化ベクトル | OpenSSL:
|
シード |
|
ハードコードされた情報は、コードから生成されたバイナリから問い合わせることができます。
機密情報のハードコーディングを回避します。
// Typically, you include the header "mysql.h" with function and type declarations.
// In this example, only the required lines from the header are quoted.
typedef struct _MYSQL MYSQL;
MYSQL *mysql_real_connect(MYSQL *mysql,
const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket,
unsigned long client_flag);
typedef void * DbHandle;
extern MYSQL *sql;
// File that uses functions from "mysql.h"
const char *host = "localhost";
char *user = "guest";
char *passwd;
DbHandle connect_to_database_server(const char *db)
{
passwd = (char*)"guest";
return (DbHandle)
mysql_real_connect (sql, host, user, passwd, db, 0, 0x0, 0); //Noncompliant
}
この例では、引数の host
(ホスト名)、user
(ユーザー名)、および passwd
(パスワード) が文字列リテラルで、コードで直接露出されます。
ASCII 文字列の生成されたバイナリを問い合わせると、この情報が公開されます。
1 つの修正方法として、構成ファイルからデータを読み取ります。次の修正例では、関数 connect_to_database_server_init
を呼び出すことによって、保護された構成ファイルからホスト名、ユーザー名、およびパスワードがその引数に読み取られる可能性があります。
// Typically, you include the header "mysql.h" with function and type declarations.
// In this example, only the required lines from the header are quoted.
typedef struct _MYSQL MYSQL;
MYSQL *mysql_real_connect(MYSQL *mysql,
const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket,
unsigned long client_flag);
typedef void * DbHandle;
extern MYSQL *sql;
// File that uses functions from "mysql.h"
int connect_to_database_server_init(const char **host,
const char **user,
const char **passwd,
const char **db);
DbHandle connect_to_database_server(const char *db)
{
const char *host_from_cfg;
const char *user_from_cfg;
const char *passwd_from_cfg;
const char *db_from_cfg;
if (connect_to_database_server_init(&host_from_cfg,
&user_from_cfg,
&passwd_from_cfg,
&db_from_cfg))
{
return (DbHandle)
mysql_real_connect (sql, host_from_cfg, user_from_cfg,
passwd_from_cfg, db_from_cfg, 0, 0x0, 0);
}
else
return (DbHandle)0x0;
}
チェック情報
カテゴリ: Bad Coding Practices |
バージョン履歴
R2023a で導入
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)