SV.FIU.PROCESS_VARIANTS

Exposure to privilege escalation

Some process-creation system calls provide exposure to local privilege escalation. These calls are prone to attacks that allow execution of malicious code with the privileges of the host process. The SV.FIU.PROCESS_VARIANTS checker flags the following system calls:

  • CreateProcess
  • CreateProcessAsUser
  • CreateProcessWithLogon
  • ShellExecute
  • ShellExecuteEx
  • WinExec
  • system
  • _wsystem
  • _*exec*
  • _*spawn*

Vulnerability and risk

If a process-creation system call doesn't contain the full path of the .exe executable before calling the process-creation API, it creates an opportunity for attack. A search path vulnerability can allow local users to gain privileges using a malicious .exe file.

Mitigation and prevention

To prevent exposure:

  • Use fork, execve, and pipes to control process execution completely.
  • In Win32 CreateProcess, CreateProcessAsUser, or CreateProcessWithLogonW functions, don't pass a null for the first parameter, lpApplicationName, to avoid running arbitrary command. If lpApplicationName must be null, use quotation marks around the path in the second parameter, lpCommandLine:
CreateProcess(NULL, "\"C:\Program Files\foo.exe\" -L -S", ...)

For more information, see Documenting Security Implications of C Runtime and Windows APIs.

Vulnerable code example #1

1  #include <stdio.h>
2  #include <sys/types.h>
3  #include <sys/stat.h>
4  
5  int main(int argc, char *argv[]) {
6    int fd;
7  
8    if ((fd = open(argv[1], 0)) == -1) {
9      error("can't open %s", argv[1]);
10     return -1;
11   }
12   if (argc == 2) {/* execute command */
13     if (execlp ("/bin/sh/", "sh", "-c", argv[1], (char*) 0)) {
14 
15         /* some code */
16       } else {
17         error("can't execute %s", argv[1]);
18       }
19   }
20 }

Klocwork flags the use of function execlp in line 13. This system call provides possible exposure to local privilege escalation through a malicious .exe file.

Fixed code example #1

1  #include <stdio.h>
2  #include <sys/types.h>
3  #include <sys/stat.h>
4  
5  int main(int argc, char *argv[]) {
6    int fd;
7  
8    if ((fd = open(argv[1], 0)) == -1) {
9      error("can't open %s", argv[1]);
10     return -1;
11   }
12   if (argc == 2) {/* execute command */
13     if (execve ("/bin/sh/", "sh", "-c", argv[1], (char*) 0)) { 
14 
15         /* some code */
16       } else {
17         error("can't execute %s", argv[1]);
18       }
19   }
20 }

In the fixed code, function execlp has been replaced by execve, which controls process execution, eliminating the possibility of privilege escalation.

Vulnerable code example #2

1  #include <stdlib.h>
2  /* Execute a program passed as a command-line argument */
3  int main(char *argv[])
4  {
5      system(argv[1]); /* NON-COMPLIANT */
6
7      return 0;
8  }

Fixed code example #2

1  #include <stdio.h>
2  #include <stdlib.h>
3  #include <unistd.h>
4
5  int	main(int argc, char *argv[])
6  {
7      char *newargv[] = { NULL, "hello", "world", NULL };
8      char *newenviron[] = { NULL };
9  
10     if (argc != 2) {
11  
12       	fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
13  
14       	exit(EXIT_FAILURE); 
15 
16     }
17     
18     newargv[0] = argv[1];
19 
20     execve(argv[1], newargv, newenviron); /* COMPLIANT */
21     perror("execve");                     /* execve() only returns on error */
22     exit(EXIT_FAILURE);
23 }

Security training

Application security training materials provided by Secure Code Warrior.