Executing Code On Behalf Of Someone Else

In almost all of my trainings I get this question: "Can I launch a program remotely so another user can actually see it?" To answer that question, I'd like to take you on a quick security tour and provide you with a test tool that may or may not produce surprising results in your environment.

Why Launching Things For Other Users Can Be Bad

Back in the old days, you were able to use WMI to launch a process visibly in another users context. So if you were working at some help desk, and a user called in, you could simply help them and launch things for them. However, anything you launched continued to run under your account, so if you launched a notepad.exe for someone else, that person was able to use notepad with your credentials. Of course, Microsoft disabled that for security reasons.

Today, when the target is Windows Vista/Server 2008 or better, you can again launch processes visibly in another users context. This time, however, the task scheduler is used. It can be instructed to launch whatever you want in the interactive session of someone else. All you need is this:

  • Local Administrator privileges on the target machine
  • Windows Vista/W7 or Server 2008/R2 on all machines

Because the task scheduler runs the task on behalf of the target person, you are not jeopardizing your own identity anymore. The user can use whatever you launched, but he will be using it with his own privileges, not yours.

That sounds great until you start thinking backwards. What if the person I am launching the program for has actually more privileges that I do? Huh?

Houston - We (Might) Have A Problem!

Which brings us to the second objective of this post: Security. In not so few companies, local admin accounts are below security radar. Sometimes, the password for the local "Administrator" account is even common knowledge because it is used whenever someone needs to install something special or change settings. That's convenient until people start to realize that a local administrator is potentially just as powerful as the most powerful domain account that exists in your entire company. Let's check out why.

With the task scheduler, any local admin can launch programs on behalf of the logged on user. So if that user happens to be Enterprise Admin, and you wouldn't launch something as cute as notepad.exe but instead a PowerShell script that adds your account (or all accounts in your company) to the Domain Admin group, you probably can imagine what this means to corporate security. Since the script runs on behalf of the other person, if someone analyzes the change to find out the bad guy, logs won't show the true script initiator but instead the person that it was scheduled for.

So is this an exploit? Something to get really excited about? No - except if you did not realize the importance of local admin accounts in overall corporate security. A local admin owns a local machine. So a local admin could have installed a key logger, replaced explorer.exe with some malicious clone, or simply put script code into the logon script of someone else. The script I am going to present is special only in that it is (a) pretty easy to use and (b) a great security intrusion detector because if you really can do something bad with it, then it's time to seriously review your security settings.

Word Of Caution

Use the script to test-drive your security only.

If you are a domain admin, then you know you have plentyful privileges but still might find the script useful to launch software visibly for other people. Since you are domain admin, you are authorized to do this. If you abuse your privileges, then that's like stealing pencils or selling company secrets, and you get into trouble.

If you are however a regular user and you still can launch things on behalf of others, or if you know local admin credentials because they are not kept secret, and you can use them to launch things in other users sessions, then you know something is wrong. Don't continue to use this script to launch "special" websites on behalf of your boss just to see what happens next, or fire up 1000 instances of excel on behalf of that buddy of yours down the isle. Instead, report it to your security department to help create more awareness.

Launching Commands On Behalf of Someone Else

The following script provides a function called Start-ProcessInteractive. You can specify a target computer, a path to an executable on that computer and also some arguments. If you do not specify a path and arguments, then the defaults will run a powershell command and write a file into the target windows folder. That's a proof-of-concept, because if that command works it illustrates that the PowerShell command was launched with full privileges.

The function schedules the task for the currently logged on user. If no currently logged on user could be identified, then either no user was physically logged on, or the target machine is running virtual machines in which case you can manually submit the user account you want to schedule the command for.

Note that this type of task scheduling requires Windows Vista/Server 2008 or higher. It will not work on XP.

You can download the script here.

function Start-ProcessInteractive {
param(
$filepath = 'powershell.exe',
$arguments = '-noprofile -command Get-Date | Out-File $env:windir\testfile.txt',
[Parameter(Mandatory=$true)]
$computername
)


function Execute-Tool($path) {
$r = (Invoke-Expression $path) 2>&1
if ($LASTEXITCODE -ne 0) { Throw $r[0].Exception.Message }
}

$computername | ForEach-Object {
try {
$username = Get-WmiObject Win32_ComputerSystem -ComputerName $_ |
Select-Object -ExpandProperty UserName
} catch {}
$computer = $_

if ($username -eq $null) {
Write-Warning "On $computername no user is currently physically logged on."
$username = Read-Host "Enter username of logged on user at the remote system"
}
if ($username -ne '') {


$xml = @"
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo />
<Triggers />
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings />
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>$filepath</Command>
<Arguments>$arguments</Arguments>
</Exec>
</Actions>
<Principals>
<Principal id="Author">
<UserId>$username</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
</Task>
"@



$jobname = 'remotejob{0}' -f (Get-Random)

try {
$xml | Out-File "$env:temp\tj1.xml"
Execute-Tool "schtasks /CREATE /TN $jobname /XML $env:temp\tj1.xml /S $computer"
Start-Sleep -Seconds 1
Execute-Tool "schtasks /RUN /TN $jobname /S $computer"
Execute-Tool "schtasks /DELETE /TN $jobname /s $computer /F"
}
catch {
Write-Warning "$_ (trying to access user '$username' on system '$computer')"
}
}
}
}

I have used this script successfully in a number of environments but I cannot guarantee anything. It is just a proof-of-concept. I am looking forward to get your feedback.

Security is important, and I sincerely hope I was able to illustrate why protecting even local admin accounts is important in any good security concept. If you feel that this script could do harm in your environment, then don't blame the script for it. Instead, make sure it can't do harm by reviewing your corporate security settings. This script is just one example of a multitude of other approaches that take advantage of the power of local admins. So if this script can do something it shouldn't, then a heck of a number of other techniques could, too. Close that security hole.

If security is not important to you (or your security is in great shape), then you still might find that script useful. It demonstrates how to schedule tasks using XML. The problem with the regular command line switches is that they are (a) localized (different for every language/culture) and (b) incomplete. You cannot control all the things you can set up when scheduling a task using the UI. With XML, you can define the task culture-neutral and you have access to all settings.

Hope to see you next week,

Tobias

Microsoft MVP PowerShell Germany

P.S.
If you live in Germany or other parts of Europe and your company would like to set up a truly great PowerShell training, just contact me! I regularly train mid- to large-size companies. Trainings are always a blast with tons of real-world-examples and solutions. Here's how to get in touch with me: tobias.weltner@scriptinternals.de  

 

 


Posted Mar 13 2011, 06:19 PM by Tobias
Copyright 2012 PowerShell.com. All rights reserved.