Managing administrative privileges securely is crucial in any IT environment. One common scenario involves temporarily granting administrative rights to a user, often for specific tasks, then revoking them automatically to reduce security risks. To simplify this process, I've crafted a powerful PowerShell script that streamlines this entire workflow. What Does This Script Do? This PowerShell script safely grants a user temporary admin privileges on a remote Windows machine. It automates privilege escalation and schedules automatic revocation after a user-defined duration. Core Features and Functionality Administrator Privileges Check The script starts by verifying it's running with administrative rights. If not, it automatically re-launches itself with the necessary privileges. User-Friendly Inputs It prompts clearly for essential inputs: • Hostname or IP of the remote system. • Username to grant temporary admin privileges. • Duration (in hours or fractions thereof, like 0.5 for half an hour). Automated WinRM Management The script intelligently checks if Windows Remote Management (WinRM) is running on the target machine. If it’s off, the script starts it temporarily and ensures it stops afterward to maintain security: Temporary Admin Assignment The selected user is automatically added to the local administrators group on the remote system Automatic Privilege Revocation The script automatically creates a cleanup script (RevokeAdmin.ps1) on the remote system to revoke admin privileges Administrator Privileges Check The script starts by verifying it's running with administrative rights. If not, it automatically re-launches itself with the necessary privileges. Administrator Privileges Check Administrator Privileges Check The script starts by verifying it's running with administrative rights. If not, it automatically re-launches itself with the necessary privileges. User-Friendly Inputs It prompts clearly for essential inputs: • Hostname or IP of the remote system. • Username to grant temporary admin privileges. • Duration (in hours or fractions thereof, like 0.5 for half an hour). User-Friendly Inputs User-Friendly Inputs It prompts clearly for essential inputs: • Hostname or IP of the remote system. • Username to grant temporary admin privileges. • Duration (in hours or fractions thereof, like 0.5 for half an hour). Automated WinRM Management The script intelligently checks if Windows Remote Management (WinRM) is running on the target machine. If it’s off, the script starts it temporarily and ensures it stops afterward to maintain security: Automated WinRM Management Automated WinRM Management The script intelligently checks if Windows Remote Management (WinRM) is running on the target machine. If it’s off, the script starts it temporarily and ensures it stops afterward to maintain security: Temporary Admin Assignment The selected user is automatically added to the local administrators group on the remote system Temporary Admin Assignment Temporary Admin Assignment The selected user is automatically added to the local administrators group on the remote system Automatic Privilege Revocation The script automatically creates a cleanup script (RevokeAdmin.ps1) on the remote system to revoke admin privileges Automatic Privilege Revocation Automatic Privilege Revocation The script automatically creates a cleanup script (RevokeAdmin.ps1) on the remote system to revoke admin privileges Why use this script? • Enhanced Security: Reduces risks associated with permanent admin privileges. Enhanced Security • Automated and Foolproof: Minimizes human error by automating the entire grant-and-revoke process. Automated and Foolproof • Flexible: Supports fractional hours for precision privilege management. Flexible • Auditability: Each step provides clear, color-coded logging for easy tracking and auditing. Auditability How to Execute Simply run the script with administrative privileges, and follow the intuitive prompts. Use Case Scenarios • Temporary elevated permissions for helpdesk tasks. • Short-term admin rights for software installations. • Troubleshooting administrative issues remotely. Wrapping Up Implementing this automated solution enhances your organization's operational efficiency and security posture significantly. By granting administrative privileges only when absolutely necessary—and revoking them automatically—you minimize potential security breaches and enforce better compliance standards. Remember, "Now you know, and knowing is half the battle!" #Another /\_[]_/\ # fine |] _||_ [| # ___ \/ || \/ # /___\ || # (|0 0|) || # __/{\U/}\_ ___/vvv # / \ {~} / _|_P| # | /\ ~ /_/ [] # |_| (____) # \_]/______\ Barberion # _\_||_/_ Production # (_,_||_,_) # # Run with admin privileges if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Start-Process PowerShell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($myInvocation.MyCommand.Definition)`"" -Verb RunAs exit } # Define cleanup function to disable WinRM if it was started by the script function Cleanup { if ($winrmStartedByScript -eq $true) { Write-Host "WinRM was started by this script. Disabling WinRM on $remoteSystem..." -ForegroundColor Cyan $stopResult = $service.InvokeMethod('StopService', $null) Start-Sleep -Seconds 2 $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $false) { Write-Host "WinRM service on $remoteSystem stopped successfully." -ForegroundColor Green } else { Write-Host "Failed to stop WinRM service on $remoteSystem." -ForegroundColor Red } } } # Use a try block to ensure cleanup always ocurs try { # Prompt for rem sys and user $remoteSystem = Read-Host "Enter the hostname or IP of the remote system" $username = Read-Host "Enter the username to grant temporary admin access" # Prompt for duration in hrs do { $durationHours = Read-Host "Enter the duration in hours (e.g., 1 for 1 hour, 0.5 for half hour)" if (-not [double]::TryParse($durationHours, [ref]$null)) { Write-Host "Invalid input. Please enter a valid numeric value for the duration." -ForegroundColor Red } } while (-not [double]::TryParse($durationHours, [ref]$null)) # Convert duration from hrs to mins $durationMinutes = [math]::Round([double]$durationHours * 60) # Check WinRM status and start necesary $serviceName = "winrm" Write-Host "Checking WinRM status on $remoteSystem..." -ForegroundColor Cyan $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $false) { Write-Host "WinRM is not running. Starting WinRM service on $remoteSystem..." -ForegroundColor Cyan $startResult = $service.InvokeMethod('StartService', $null) Start-Sleep -Seconds 2 $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $true) { Write-Host "WinRM service on $remoteSystem started successfully." -ForegroundColor Green $winrmStartedByScript = $true } else { Write-Host "Failed to start WinRM service on $remoteSystem. Return code: $($startResult.ReturnValue)" -ForegroundColor Red exit } } else { Write-Host "WinRM is already running on $remoteSystem." -ForegroundColor Green } # Add user to Admin grp Write-Host "Adding $username to Administrators group on $remoteSystem..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($user) Add-LocalGroupMember -Group "Administrators" -Member $user Write-Host "User $user added to Administrators group." } -ArgumentList $username -ErrorAction Stop # Create the RevokeAdmin.ps1 file in C:\Temp on the remsys Write-Host "Creating RevokeAdmin.ps1 on $remoteSystem in C:\Temp..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($user) $revokeScriptPath = "C:\Temp\RevokeAdmin.ps1" $revokeScriptContent = @" $user = '$user' Remove-LocalGroupMember -Group "Administrators" -Member $user "@ if (-not (Test-Path -Path (Split-Path -Path $revokeScriptPath))) { New-Item -ItemType Directory -Path (Split-Path -Path $revokeScriptPath) -Force | Out-Null } Set-Content -Path $revokeScriptPath -Value $revokeScriptContent Write-Host "RevokeAdmin.ps1 created successfully." } -ArgumentList $username -ErrorAction Stop # Schedule revocation Write-Host "Scheduling revocation of admin privileges in $durationMinutes minutes..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($duration) $revokeScriptPath = "C:\Temp\RevokeAdmin.ps1" $taskName = "RevokeAdminAccess" # Check if the scheduled task exists and delete it if necessary if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $taskName -Confirm:$false Write-Host "Existing scheduled task '$taskName' found and deleted." -ForegroundColor Yellow } # Schedule the new task $time = (Get-Date).AddMinutes($duration).ToString("yyyy-MM-ddTHH:mm:ss") $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -NoProfile -File `"$revokeScriptPath`"" $trigger = New-ScheduledTaskTrigger -Once -At $time $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName $taskName Write-Host "Revocation task scheduled successfully." -ForegroundColor Green } -ArgumentList $durationMinutes -ErrorAction Stop Write-Host "Admin privileges granted for $durationMinutes minutes on $remoteSystem." -ForegroundColor Green } finally { # Cleanup to disable WinRM if it was started by the script Cleanup } # Remember kids: "Now you know, and knowing is half the battle" Write-Host "Process completed successfully." -ForegroundColor Green #Another /\_[]_/\ # fine |] _||_ [| # ___ \/ || \/ # /___\ || # (|0 0|) || # __/{\U/}\_ ___/vvv # / \ {~} / _|_P| # | /\ ~ /_/ [] # |_| (____) # \_]/______\ Barberion # _\_||_/_ Production # (_,_||_,_) # # Run with admin privileges if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Start-Process PowerShell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($myInvocation.MyCommand.Definition)`"" -Verb RunAs exit } # Define cleanup function to disable WinRM if it was started by the script function Cleanup { if ($winrmStartedByScript -eq $true) { Write-Host "WinRM was started by this script. Disabling WinRM on $remoteSystem..." -ForegroundColor Cyan $stopResult = $service.InvokeMethod('StopService', $null) Start-Sleep -Seconds 2 $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $false) { Write-Host "WinRM service on $remoteSystem stopped successfully." -ForegroundColor Green } else { Write-Host "Failed to stop WinRM service on $remoteSystem." -ForegroundColor Red } } } # Use a try block to ensure cleanup always ocurs try { # Prompt for rem sys and user $remoteSystem = Read-Host "Enter the hostname or IP of the remote system" $username = Read-Host "Enter the username to grant temporary admin access" # Prompt for duration in hrs do { $durationHours = Read-Host "Enter the duration in hours (e.g., 1 for 1 hour, 0.5 for half hour)" if (-not [double]::TryParse($durationHours, [ref]$null)) { Write-Host "Invalid input. Please enter a valid numeric value for the duration." -ForegroundColor Red } } while (-not [double]::TryParse($durationHours, [ref]$null)) # Convert duration from hrs to mins $durationMinutes = [math]::Round([double]$durationHours * 60) # Check WinRM status and start necesary $serviceName = "winrm" Write-Host "Checking WinRM status on $remoteSystem..." -ForegroundColor Cyan $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $false) { Write-Host "WinRM is not running. Starting WinRM service on $remoteSystem..." -ForegroundColor Cyan $startResult = $service.InvokeMethod('StartService', $null) Start-Sleep -Seconds 2 $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" -ComputerName $remoteSystem if ($service.Started -eq $true) { Write-Host "WinRM service on $remoteSystem started successfully." -ForegroundColor Green $winrmStartedByScript = $true } else { Write-Host "Failed to start WinRM service on $remoteSystem. Return code: $($startResult.ReturnValue)" -ForegroundColor Red exit } } else { Write-Host "WinRM is already running on $remoteSystem." -ForegroundColor Green } # Add user to Admin grp Write-Host "Adding $username to Administrators group on $remoteSystem..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($user) Add-LocalGroupMember -Group "Administrators" -Member $user Write-Host "User $user added to Administrators group." } -ArgumentList $username -ErrorAction Stop # Create the RevokeAdmin.ps1 file in C:\Temp on the remsys Write-Host "Creating RevokeAdmin.ps1 on $remoteSystem in C:\Temp..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($user) $revokeScriptPath = "C:\Temp\RevokeAdmin.ps1" $revokeScriptContent = @" $user = '$user' Remove-LocalGroupMember -Group "Administrators" -Member $user "@ if (-not (Test-Path -Path (Split-Path -Path $revokeScriptPath))) { New-Item -ItemType Directory -Path (Split-Path -Path $revokeScriptPath) -Force | Out-Null } Set-Content -Path $revokeScriptPath -Value $revokeScriptContent Write-Host "RevokeAdmin.ps1 created successfully." } -ArgumentList $username -ErrorAction Stop # Schedule revocation Write-Host "Scheduling revocation of admin privileges in $durationMinutes minutes..." -ForegroundColor Cyan Invoke-Command -ComputerName $remoteSystem -ScriptBlock { param ($duration) $revokeScriptPath = "C:\Temp\RevokeAdmin.ps1" $taskName = "RevokeAdminAccess" # Check if the scheduled task exists and delete it if necessary if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $taskName -Confirm:$false Write-Host "Existing scheduled task '$taskName' found and deleted." -ForegroundColor Yellow } # Schedule the new task $time = (Get-Date).AddMinutes($duration).ToString("yyyy-MM-ddTHH:mm:ss") $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -NoProfile -File `"$revokeScriptPath`"" $trigger = New-ScheduledTaskTrigger -Once -At $time $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName $taskName Write-Host "Revocation task scheduled successfully." -ForegroundColor Green } -ArgumentList $durationMinutes -ErrorAction Stop Write-Host "Admin privileges granted for $durationMinutes minutes on $remoteSystem." -ForegroundColor Green } finally { # Cleanup to disable WinRM if it was started by the script Cleanup } # Remember kids: "Now you know, and knowing is half the battle" Write-Host "Process completed successfully." -ForegroundColor Green