An example of least privilege implementation (part II)

This is the 2nd post of a 3 posts serie where I’ll now expose the heart of the solution.

To be able to gain administrative privilege from a standard user account, only 2 holes needs to be drilled.

  • Change NTFS permissions to a file so that standard user accounts can write data into.
  • # Create an empty txt file            
    $null | Out-File $env:systemroot\tmpadmin.txt -Force -Encoding ascii            
    # Let authenticated users modify this file            
    & (Get-Command icacls)  @("$env:systemroot\tmpadmin.txt","/grant",'"Authenticated users":M')            
    
  • Give standard user accounts the permission to execute a task running as a local system account.
  • # Grant read and execute to the Authenticated users group            
    & (Get-Command icacls)  @("$env:systemroot\system32\Tasks\Elevate","/grant",'"Authenticated users":RX')            
    

    Now, let’s examine more deeply what the Elevate tasks does and how it’s created:

    • It’s created from an XML template so that we make sure it’ll run even when the laptop is on batteries.
    • The task runs under the system account
    $elevateTNxmltemplate = @"
    <?xml version="1.0" encoding="UTF-16"?>
    <Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
      <RegistrationInfo>
        <Date>2011-05-10T19:33:03</Date>
        <Author>SYSTEM</Author>
      </RegistrationInfo>
      <Triggers>
        <TimeTrigger>
          <StartBoundary>2011-05-10T00:00:00</StartBoundary>
          <Enabled>true</Enabled>
        </TimeTrigger>
      </Triggers>
      <Principals>
        <Principal id="Author">
          <UserId>S-1-5-18</UserId>
          <RunLevel>HighestAvailable</RunLevel>
        </Principal>
      </Principals>
      <Settings>
        <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
        <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
        <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
        <AllowHardTerminate>true</AllowHardTerminate>
        <StartWhenAvailable>false</StartWhenAvailable>
        <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
        <IdleSettings>
          <StopOnIdleEnd>true</StopOnIdleEnd>
          <RestartOnIdle>false</RestartOnIdle>
        </IdleSettings>
        <AllowStartOnDemand>true</AllowStartOnDemand>
        <Enabled>true</Enabled>
        <Hidden>false</Hidden>
        <RunOnlyIfIdle>false</RunOnlyIfIdle>
        <WakeToRun>false</WakeToRun>
        <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
        <Priority>7</Priority>
      </Settings>
      <Actions Context="Author">
        <Exec>
          <Command>c:\Windows\tmpadmin.bat</Command>
        </Exec>
      </Actions>
    </Task>
    "@
    # Create the task
    Write-Output -InputObject $elevateTNxmltemplate | Out-File -FilePath ("$env:temp\tmp.xml") -Encoding Unicode -Force 
    Invoke-Expression -Command ("schtasks.exe /create /RU SYSTEM /TN Elevate /F /XML $env:temp\tmp.xml")
    
    • The tasks actually just launches C:\windows\tmpadmin.bat
    • C:\windows\tmpadmin.bat just takes what it’s written into tmpadmin.txt and add it to the local administrators group
    @echo off
    for /f %%i in (%systemroot%\tmpadmin.txt) do @ net localgroup administrators %%i /add
    
  • Now, the 3rd thing required is a script that the user launches:
  • :: <#;
    @echo off
    
    echo %userdomain%\%username% > %systemroot%\tmpadmin.txt
    
    schtasks /run /tn Elevate
    
    "%systemroot%\system32\WindowsPowershell\v1.0\powerShell.exe" -WindowStyle Hidden -ExecutionPolicy Unrestricted -NoProfile -Command "$ErrorActionPreference = 'Continue';([scriptblock]::Create(((gc '%0' -ReadCount 0 -Encoding ASCII) -replace ';$|^\:\:',\"`n\"))).Invoke()"
    
    goto eof
    :: #>
    
    $ErrorActionPreference = 'Continue';
    
    ((Get-Date).AddHours(+1).Ticks).ToString() + ";" + "$env:userdomain\$env:username"| Out-File -FilePath "$env:systemroot\UAC.Allowed.dat" -Encoding ASCII -Force -NoClobber -Append;
    $timeout = 20;
    # Get the display language;
    switch($host.CurrentUICulture.LCID)
    {
        1036 {
            $titlemsg = "Message d'information:";
            $txtboxlabel = "Votre compte a acquis les droits d'administration de cet ordinateur pour une heure."
        }
        default {
            $titlemsg = "Information message: ";
            $txtboxlabel = "Your account has been granted administrative privileges on this computer for an hour."
        }
    }
    
    # Display the popup to the user  ;
    $obj = new-object -comobject wscript.shell;
    $obj.popup($txtboxlabel,$timeout,$titlemsg,0);
    
    <#;
    :eof
    :: ;#>
    

    As you can see, whenever the user launches the above script:

    • his username is written into c:\windows\tmpadmin.txt (1rst hole)
    • the elevate tasks is triggered (2nd hole)
    • the system account executes the c:\windows\tmpadmin.bat that adds his username written in c:\windows\tmpadmin.txt to the local administrators group
    • he obtains a popup window informing him that he can perform administrative tasks with his own credential within the next hour
    • most important, the expiry date (when his temporary admin credential should be removed) is appended to the C:\Windows\UAC.Allowed.dat CSV file
    • Of course, the file C:\Windows\UAC.Allowed.dat should be created the same way the tmpadmin.txt is, like this
    # Create an empty txt file                        
    $null | Out-File $env:systemroot\UAC.Allowed.dat -Force -Encoding ascii                        
    # Let authenticated users modify this file                        
    & (Get-Command icacls)  @("$env:systemroot\UAC.Allowed.dat","/grant",'"Everyone":M')

    This concludes the 2nd part and we’ll see in the 3rd part how to use the content of UAC.allowed.dat and ensure that the user is removed automatically from the local administrators group after 1 hour.

    Advertisements

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s