SV.FIU.PROCESS_VARIANTS

特権昇格への露呈

一部のプロセス作成システム呼び出しにより、ローカル権限昇格の危険にさらされています。これらの呼び出しは、ホストプロセスの特権で悪意のあるコードの実行を許可する攻撃に脆弱です。SV.FIU.PROCESS_VARIANTS チェッカーは、次のシステム呼び出しにフラグを立てます。

  • CreateProcess
  • CreateProcessAsUser
  • CreateProcessWithLogon
  • ShellExecute
  • ShellExecuteEx
  • WinExec
  • システム
  • _wsystem
  • _*exec*
  • _*spawn*

脆弱性とリスク

プロセス作成システム呼び出しに、プロセス作成 API を呼び出す前の位置に .exe 実行可能ファイルのフルパスが含まれていない場合、プロセス作成システム呼び出しが攻撃の機会の要因となります。検索パスの脆弱性により、ローカルユーザーは悪意のある .exe ファイルを使用して特権を取得できます。

軽減と防止

攻撃にさらされることを回避するには、次の操作を実行します。

  • fork、execve、および pipe を使用して、プロセスの実行を完全に制御します。
  • Win32 CreateProcess 関数、CreateProcessAsUser 関数、または CreateProcessWithLogonW 関数では、実行している任意コマンドを回避するために null を最初のパラメーター lpApplicationName に渡さないでください。lpApplicationName が null でなければならない場合は、2 番目のパラメーター lpCommandLine のパスの前後に二重引用符を使用します。
CreateProcess(NULL, "\"C:\Program Files\foo.exe\" -L -S", ...)

脆弱コード例 1

コピー
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  
  int main(int argc, char *argv[]) {
    int fd;
  
    if ((fd = open(argv[1], 0)) == -1) {
      error("can't open %s", argv[1]);
     return -1;
   }
   if (argc == 2) {/* execute command */
     if (execlp ("/bin/sh/", "sh", "-c", argv[1], (char*) 0)) {
 
         /* some code */
       } else {
         error("can't execute %s", argv[1]);
       }
   }
 }

Klocwork は 13 行目で、関数 execlp の使用にフラグを立てます。このシステム呼び出しにより、悪意のある .exe ファイルを通じてローカル権限昇格の危険にさらされる可能性があります。

修正コード例 1

コピー
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  
  int main(int argc, char *argv[]) {
    int fd;
  
    if ((fd = open(argv[1], 0)) == -1) {
      error("can't open %s", argv[1]);
     return -1;
   }
   if (argc == 2) {/* execute command */
     if (execve ("/bin/sh/", "sh", "-c", argv[1], (char*) 0)) { 
 
         /* some code */
       } else {
         error("can't execute %s", argv[1]);
       }
   }
 }

修正されたコードでは、関数 execlp は execve に置換されました。これにより、プロセス実行が制御され、特権昇格の可能性が排除されます。

脆弱なコード例 #2

コピー
  #include <stdlib.h>
  /* Execute a program passed as a command-line argument */
  int main(char *argv[])
  {
      system(argv[1]); /* NON-COMPLIANT */

      return 0;
  }

修正コード例 #2

コピー
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>

  int    main(int argc, char *argv[])
  {
      char *newargv[] = { NULL, "hello", "world", NULL };
      char *newenviron[] = { NULL };
  
     if (argc != 2) {
  
           fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
  
           exit(EXIT_FAILURE); 
 
     }
     
     newargv[0] = argv[1];
 
     execve(argv[1], newargv, newenviron); /* COMPLIANT */
     perror("execve");                     /* execve() only returns on error */
     exit(EXIT_FAILURE);
 }

セキュリティトレーニング

Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。