You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

The principle of least privilege states that every program and every user of the system should operate using the least set of privileges necessary to complete the job [Saltzer 1974, Saltzer 1975]. The Build Security In website [DHS 2006] provides additional definitions of this principle. Executing with minimal privileges mitigates against exploitation in case a vulnerability is discovered in the code.

Noncompliant Code Example

An application may spawn another process as part of its normal course of action.  On Windows, the newly-spawned process automatically receives the same privileges as the parent process [MSDN].  By allowing the child process to run in the same security context as the parent process, the attack surface for the application is extended to the child process.

#include <Windows.h>
 
void launch_notepad(void) {
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
 
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof( si );
  if (CreateProcess(TEXT("C:\\Windows\\Notepad.exe"), NULL, NULL, NULL, TRUE,
                    0, NULL, NULL, &si, &pi )) {
    /* Process has been created; work with the process and wait for it to
       terminate. */
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
  }
}

It is possible that the act of calling launch_notepad() will give the user an elevated Notepad application (from which the user could execute Explorer.exe), allowing them access to all user's files, change system settings, etc.

Compliant Solution

By using the Windows Integrity Mechanism [MSDN] when creating the process, you can assign an integrity level to the launched child process.  This allows you to execute the child process with a specific set of privileges instead of defaulting to the parent process' security level.

static void launch_notepad_as_user(HANDLE token) {
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
 
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof( si );
  if (CreateProcessAsUser(token, TEXT("C:\\Windows\\Notepad.exe"), NULL, NULL,
                          NULL, FALSE, 0, NULL, NULL, &si, &pi )) {
    /* Process has been created; work with the process and wait for it to
       terminate. */
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
  }
}
 
static BOOL adjust_token_integrity_level(HANDLE token, const char *sid) {
  /* Convert the string SID to a SID *, then adjust the token's
     privileges. */
  BOOL ret;
  PSID psd = NULL;
  if (ConvertStringSidToSidA(sid, &psd)) {
    TOKEN_MANDATORY_LABEL tml;
    
    ZeroMemory(&tml, sizeof(tml));
    tml.Label.Attributes = SE_GROUP_INTEGRITY;
    tml.Label.Sid = psd;
 
    ret = SetTokenInformation(token, TokenIntegrityLevel, &tml,
                              sizeof(tml) + GetLengthSid(psd));
    
    LocalFree(psd);
  }
  return ret;
}
 
void launch_notepad(void) {
  const char *requested_sid = "S-1-16-4096";  /* Low level */
  HANDLE token_cur, token_dup;
  /* Get the current process' security token as a starting point, then modify
     a duplicate so that it runs with a fixed integrity level. */
  if (OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE |
                                            TOKEN_ADJUST_DEFAULT |
                                            TOKEN_QUERY |
                                            TOKEN_ASSIGN_PRIMARY,
                                            &token_cur)) {
    if (DuplicateTokenEx(token_cur, 0, NULL, SecurityImpersonation,
                         TokenPrimary, &token_dup)) {
      if (adjust_token_integrity_level(token_dup, requested_sid))
        launch_notepad_as_user(token_dup);
      CloseHandle(token_dup);
    }
    CloseHandle(token_cur);
  }
}

 The compliant example demonstrates how to launch Notepad.exe using a low integrity level, regardless of what privilege level the parent process is running from.

Risk Assessment

Failure to follow the principle of least privilege may allow exploits to execute with elevated privileges.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

WIN01-C

high

likely

high

P9

L2

Related Guidelines

ISO/IEC TR 24772Adherence to Least Privilege [XYN]
MITRE CWECWE-250, Execution with unnecessary privileges CWE-272, Least privilege violation

Bibliography

  • No labels