CERT.PUTENV.AUTO_VARIABLE

自動変数へのポインターを引数として putenv() を呼び出さない

C / C++ では、POSIX putenv() 関数は文字列引数を使用して環境変数値を設定します。putenv() 関数は、文字列へのポインターを環境配列に挿入し、引数としてそれに指定された文字列のコピーを作成しません。自動ストレージ期間のバッファへのポインターが putenv() の引数として指定されている場合、含まれている関数が戻り、スタックメモリがリサイクルされると、そのバッファに割り当てられたメモリが上書きされる可能性があります。CERT.PUTENV.AUTO_VARIABLE チェッカーは、自動変数へのポインターを引数として使用している putenv() の呼び出しにフラグを立てます。

脆弱性とリスク

putenv() が自動変数にアクセスする場合、環境変数は意図しない値になる可能性があり、データがリークされる場合があります。

脆弱コード例 1

コピー
   int func(const char *var) {
     char env[1024];
     int retval = snprintf(env, sizeof(env),"TEST=%s", var);
     if (retval < 0 || (size_t)retval >= sizeof(env)) {
     /* Handle error */
     }
      
     return putenv(env);                  // CERT.PUTENV.AUTO_VARIABLE
  }

この非準拠の例では、自動ストレージ期間のバッファ 'env' へのポインターが、putenv() の引数として使用されています。このコードが実行された場合、func() が返され、'env' を含んでいるスタックフレームがリサイクルされた後に TEST 環境変数がアクセスされると、意図しない値になる可能性があります。

修正コード例 1

コピー
  int func(const char *var) {
     static char env[1024];               // Fixed here
  
     int retval = snprintf(env, sizeof(env),"TEST=%s", var);
     if (retval < 0 || (size_t)retval >= sizeof(env)) {
     /* Handle error */
     }
  
     return putenv(env);
 }

この問題は、静的変数を使用することで修正できます。たとえば、上記の修正例では、変数 'env' は静的変数です。このコードが実行された場合、func() が終了すると、putenv() は引き続き有効なメモリを指し、環境変数 'TEST' は正しい値を保持します。

修正コード例 2

コピー
   int func(const char *var) {
      const char *env_format = "TEST=%s";
      const size_t len = strlen(var) + strlen(env_format);
      char *env = (char *) malloc(len);               // Fixed here
      if (env == NULL) {
 ...     return -1;
 ...   }
      int retval = snprintf(env, len, env_format, var);
      if (retval < 0 || (size_t)retval >= len) {
     /* Handle error */
     }
     if (putenv(env) != 0) {
     free(env);
     return -1;
     }
     return 0;
  }

この修正例では、自動変数の代わりにヒープを割り当てたメモリを使用しています。