Local Administrator Temporary Elevation Request (LATER)

This is my realization of the Local Administrator Temporary Elevation Request (LATER) concept Mathias R. Jessen (@IISResetMe) talked about in the session “Attack Surface Reductions – for the Adventurous Admin” at PowerShell Conference Europe 2019, Hannover.
If you couldn’t attend the session in person the great people of #PSConfEU have uploaded the recording on Youtube. I highly recommend that you stop reading and go watch it now!

YouTube - LATER

As you saw in the presentation there are no actual code-snippets or demos just pure awesomeness from Mathias philosophies around Security Engineering. So what I’ve tried to do is convert all L.A.T.E.R topics mentioned in the session to actual PowerShell code and let the session from Mathias speak for it self regarding on how it works.

So basically the picture, down below, is what I’ve got to work with to realize the concept.
The first thing I did was create a rough to do list.

  • WinForms or WPF application/GUI-script for the end user.
  • A service account with R/W permissions to the SQL database and Read+Reset permissions for target LAPS clients.
  • LAPS installed and configured for target clients.
  • Windows Server to host the JEA endpoint.
  • SQL database for logging and throttling.
  • PowerShell code to run in the JEA endpoint.
  • PowerShell code to run client side when the end user clicks “Request Administrator”.

The Later module, the JEA endpoint settings and the SQL database with all tables is published at GitHub and licensed under the MIT license.

YouTube - LATER-Concept

 

LATER.exe

I began at the top of the to-do list and created a Windows Forms GUI using PowerShell Studio*. The GUI itself is very simple, a company logo, some description or disclaimer and the request button.
*PowerShell Studio doesn’t support Windows Presentation Framework (WPF) hence the use of WinForms.

Then I created a service account (CONTOSO\svc-admpwd) and set the appropriate permissions to request and reset LAPS passwords.
Notice:  If utlilizing auditing for LAPS, Set-AdmPwdAuditing, will only show the service account as the requester not the actual end user.

 

After LAPS was configured I created a database named Later and set the appropriate service account permissions.

And of course the database needed some tables and columns which took some trial and error to figure out, how many tables was needed, which columns in each table, what data to log in each column etc. But in the end this is what I came up with.

  • FailedRequests – Contains all requests that failed because of policy throttling or just general exceptions.
  • PasswordResets – Contains all successful LAPS reset that was initiated.
  • Policy – Contains the Policy for throttling, how many requests per computer per day.
  • Requests – The actual requests for LAPS passwords.
LATER Database

All tables can be found on GitHub.

The next step was to configure a Windows Server to host the JEA endpoint. For this lab purpose I reused the SQL server.

Most up to date version found on GitHub.

The actual magic happens in the module that that runs under the context of svc-admpwd. The module, that I called LATER, includes two public and one private function.
LaterModuleCommandsLaterModuleCommandsPrivate

Inside the LATER module I created a JEA role capability file which simply grants the session configuration “LATER” the “Request” capability.

The source on GitHub already includes the Requester role capability file.

When the JEA endpoint and the LATER module was working I had to figure out the code behind the “Request Administrator” button event. Basically the button creates a PowerShell session targeting the JEA endpoint and runs Invoke-Command {Get-CurrentComputerLATER} to retrive the LAPS password and then starts another PowerShell process to Add-LocalGroupMember -Group Administrators -Member 'NT Authority\Interactive'.

So what happens in depth when the User clicks on the “Request Administrator” button?

  1. First, whoami /groups runs and checks against hard coded strings (regex) if the user is eligible (Member of) the necessary LATER request groups, otherwise hard fail.
    LATERFailWhoami

  2. A PowerShell session is created using the ConfigurationName, LATER. If the session creation fails for some reason, the user is presented with an error.
    LATERFailPSSession

  3. If the session was successfully created, the next step is to run Invoke-Command with a scriptblock that runs the Get-CurrentComputerLATER function with the current computer name ($using:env:COMPUTERNAME) as value to the parameter ComputerName.
  4. Now we jump inside the Get-CurrentComputerLATER.
    The first thing that happens is that the function Get-LaterRequesterInfo runs to retrieve information about the session from the automatic variable $PSSenderInfo. The information returned contains the requesting user’s username, the IP-address of the PSSession source, the resolved name from the IP-address and all Claims (groups) which is evaluated against the same regex as used in step 1.
  5. When the session information is retrieved we query the Policy table in the database with all Claims (group SIDs) that the user has. This will determine how many requests the user is eligible for. If the user has more than one policy group assigned, the effective policy will be the policy that contains the least number of requests.

  6. Now we query the Requests table to determine if the user has done Later requests in the past.
    Based on past requests and the effective policy, the “throttling” begins. Example of one throttling policy reached.
    LATERThrottlePolicy
    If no past requests was found the script continues to the next part, request the LAPS password.

  7. If the user was not throttled, the Cmdlet Get-AdmPwdPassword tries to retrieve the current LAPS password and outputs it to the pipeline. After a successful retrieval the request gets logged to the Requests table.

  8. Now back in the end user context. We have retrieved the current LAPS password using Invoke-Command and will now issue a gpupdate /force.  This is so the user actually have at least 60 minutes of admin privileges before the Group Policy automatically refreshes and the Restricted Groups policy kicks in. The automatic refresh interval is fully configurable.

  9. The GUI/script will now start another PowerShell process which will run as the local administrator account using the retrieved LAPS password.
    The local Administrator account adds the NT Authority\Interactive to the local group Administrators and resets it’s own password to a random string.

  10. After the NT Authority\Interactive was added, we connect again to the JEA endpoint using Invoke-Command. But instead of running Get-CurrentComputerLATER we run Reset-CurrentComputerLATER to update the LAPS password for the current computer.

  11. We close the PSSession and start to validate if NT Authority\Interactive actually was added to the local Administrators group. And if everything went smoothly we receive a success.
    LATERSuccess
  12. Now the user can actually install the print driver or missing application that required local administrator privileges in the first place.
    One caveat to this is is that the user must provide credentials at the UAC prompt. If the user logoff and login again, then there is just a prompt to consent. This is because of how the Local Security Authority (LSA) hands out it’s access tokens which only happens at login. More info about this can be found here.

 

One last thing, you can start the Later.exe as another user and the end result will still be the same. The current logged on user will be local administrator since the user already got the NT Authority\Interactive in their ticket.
A use case for this is when you don’t trust all endusers but you trust certain “Local IT Persons” in each branch office. Those “Local IT Persons” will have a more broader throttling policy assigned so they can actually help the enduser if necessary.
“Shift + Right click” will retrieve the option “Run as diffrent user”.
Later.exe Another User

 

If you have any question, please free to drop a comment down below or post an issue at the repository.

Leave a Comment

Your email address will not be published. Required fields are marked *


Fatal error: Uncaught RuntimeException: Error saving action: Error saving action: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Unclosed quotation mark after the character string 'O:30:"ActionScheduler_SimpleSchedule":2:{s:22:"'. in D:\home\site\wwwroot\wp-content\plugins\wpforms-lite\vendor\woocommerce\action-scheduler\classes\migration\ActionScheduler_DBStoreMigrator.php:44 Stack trace: #0 D:\home\site\wwwroot\wp-content\plugins\wpforms-lite\vendor\woocommerce\action-scheduler\classes\data-stores\ActionScheduler_HybridStore.php(225): ActionScheduler_DBStoreMigrator->save_action(Object(ActionScheduler_Action), NULL) #1 D:\home\site\wwwroot\wp-content\plugins\wpforms-lite\vendor\woocommerce\action-scheduler\classes\ActionScheduler_ActionFactory.php(177): ActionScheduler_HybridStore->save_action(Object(ActionScheduler_Action)) #2 D:\home\site\wwwroot\wp-content\plugins\wpforms-lite\vendor\woocommerce\action-scheduler\classes\ActionScheduler_ActionFactory.php(84): ActionScheduler_ActionFactory->store(Object(ActionSc in D:\home\site\wwwroot\wp-content\plugins\wpforms-lite\vendor\woocommerce\action-scheduler\classes\migration\ActionScheduler_DBStoreMigrator.php on line 44