Fix issue 5790

Leaving around plaintext username and passwords in a script on a box isn't the best from a security standpoint. This change ensures the scheduled task wrapper script for WinRM doesn't leave these around on the box, and instead passes them to the script as arguments.
This commit is contained in:
Shawn Neal 2015-06-10 12:47:26 -07:00
parent 28a42122b8
commit 1152b4e1df
2 changed files with 21 additions and 26 deletions

View File

@ -134,12 +134,7 @@ module VagrantPlugins
}.merge(opts || {})
opts[:good_exit] = Array(opts[:good_exit])
if opts[:elevated]
guest_script_path = create_elevated_shell_script(command)
command = "powershell -executionpolicy bypass -file #{guest_script_path}"
end
command = wrap_in_scheduled_task(command) if opts[:elevated]
output = shell.send(opts[:shell], command, &block)
execution_output(output, opts)
end
@ -187,19 +182,15 @@ module VagrantPlugins
)
end
# Creates and uploads a PowerShell script which wraps the specified
# command in a scheduled task. The scheduled task allows commands to
# run on the guest as a true local admin without any of the restrictions
# that WinRM puts in place.
# Creates and uploads a PowerShell script which wraps a command in a
# scheduled task. The scheduled task allows commands to run on the guest
# as a true local admin without any of the restrictions that WinRM puts
# in place.
#
# @return The path to elevated_shell.ps1 on the guest
def create_elevated_shell_script(command)
# @return The wrapper command to execute
def wrap_in_scheduled_task(command)
path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
script = Vagrant::Util::TemplateRenderer.render(path, options: {
username: shell.username,
password: shell.password,
command: command.gsub("\"", "`\""),
})
script = Vagrant::Util::TemplateRenderer.render(path)
guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
begin
@ -211,7 +202,15 @@ module VagrantPlugins
file.close
file.unlink
end
guest_script_path
# convert to double byte unicode string then base64 encode
# just like PowerShell -EncodedCommand expects
wrapped_encoded_command = Base64.strict_encode64(
"#{command}; exit $LASTEXITCODE".encode('UTF-16LE', 'UTF-8'))
"powershell -executionpolicy bypass -file \"#{guest_script_path}\" " +
"-username \"#{shell.username}\" -password \"#{shell.password}\" " +
"-encoded_command \"#{wrapped_encoded_command}\""
end
# Handles the raw WinRM shell result and converts it to a

View File

@ -1,6 +1,4 @@
$command = "<%= options[:command] %>" + '; exit $LASTEXITCODE'
$user = '<%= options[:username] %>'
$password = '<%= options[:password] %>'
param([String]$username, [String]$password, [String]$encoded_command)
$task_name = "WinRM_Elevated_Shell"
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
@ -14,7 +12,7 @@ $task_xml = @'
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Principals>
<Principal id="Author">
<UserId>{user}</UserId>
<UserId>{username}</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
@ -47,19 +45,17 @@ $task_xml = @'
</Task>
'@
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encoded_command = [Convert]::ToBase64String($bytes)
$arguments = "/c powershell.exe -EncodedCommand $encoded_command &gt; $out_file 2&gt;&amp;1"
$task_xml = $task_xml.Replace("{arguments}", $arguments)
$task_xml = $task_xml.Replace("{user}", $user)
$task_xml = $task_xml.Replace("{username}", $username)
$schedule = New-Object -ComObject "Schedule.Service"
$schedule.Connect()
$task = $schedule.NewTask($null)
$task.XmlText = $task_xml
$folder = $schedule.GetFolder("\")
$folder.RegisterTaskDefinition($task_name, $task, 6, $user, $password, 1, $null) | Out-Null
$folder.RegisterTaskDefinition($task_name, $task, 6, $username, $password, 1, $null) | Out-Null
$registered_task = $folder.GetTask("\$task_name")
$registered_task.Run($null) | Out-Null