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:
parent
28a42122b8
commit
1152b4e1df
|
@ -134,12 +134,7 @@ module VagrantPlugins
|
||||||
}.merge(opts || {})
|
}.merge(opts || {})
|
||||||
|
|
||||||
opts[:good_exit] = Array(opts[:good_exit])
|
opts[:good_exit] = Array(opts[:good_exit])
|
||||||
|
command = wrap_in_scheduled_task(command) if opts[:elevated]
|
||||||
if opts[:elevated]
|
|
||||||
guest_script_path = create_elevated_shell_script(command)
|
|
||||||
command = "powershell -executionpolicy bypass -file #{guest_script_path}"
|
|
||||||
end
|
|
||||||
|
|
||||||
output = shell.send(opts[:shell], command, &block)
|
output = shell.send(opts[:shell], command, &block)
|
||||||
execution_output(output, opts)
|
execution_output(output, opts)
|
||||||
end
|
end
|
||||||
|
@ -187,19 +182,15 @@ module VagrantPlugins
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates and uploads a PowerShell script which wraps the specified
|
# Creates and uploads a PowerShell script which wraps a command in a
|
||||||
# command in a scheduled task. The scheduled task allows commands to
|
# scheduled task. The scheduled task allows commands to run on the guest
|
||||||
# run on the guest as a true local admin without any of the restrictions
|
# as a true local admin without any of the restrictions that WinRM puts
|
||||||
# that WinRM puts in place.
|
# in place.
|
||||||
#
|
#
|
||||||
# @return The path to elevated_shell.ps1 on the guest
|
# @return The wrapper command to execute
|
||||||
def create_elevated_shell_script(command)
|
def wrap_in_scheduled_task(command)
|
||||||
path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
|
path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
|
||||||
script = Vagrant::Util::TemplateRenderer.render(path, options: {
|
script = Vagrant::Util::TemplateRenderer.render(path)
|
||||||
username: shell.username,
|
|
||||||
password: shell.password,
|
|
||||||
command: command.gsub("\"", "`\""),
|
|
||||||
})
|
|
||||||
guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
|
guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
|
||||||
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
|
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
|
||||||
begin
|
begin
|
||||||
|
@ -211,7 +202,15 @@ module VagrantPlugins
|
||||||
file.close
|
file.close
|
||||||
file.unlink
|
file.unlink
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# Handles the raw WinRM shell result and converts it to a
|
# Handles the raw WinRM shell result and converts it to a
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
$command = "<%= options[:command] %>" + '; exit $LASTEXITCODE'
|
param([String]$username, [String]$password, [String]$encoded_command)
|
||||||
$user = '<%= options[:username] %>'
|
|
||||||
$password = '<%= options[:password] %>'
|
|
||||||
|
|
||||||
$task_name = "WinRM_Elevated_Shell"
|
$task_name = "WinRM_Elevated_Shell"
|
||||||
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
|
$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">
|
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
||||||
<Principals>
|
<Principals>
|
||||||
<Principal id="Author">
|
<Principal id="Author">
|
||||||
<UserId>{user}</UserId>
|
<UserId>{username}</UserId>
|
||||||
<LogonType>Password</LogonType>
|
<LogonType>Password</LogonType>
|
||||||
<RunLevel>HighestAvailable</RunLevel>
|
<RunLevel>HighestAvailable</RunLevel>
|
||||||
</Principal>
|
</Principal>
|
||||||
|
@ -47,19 +45,17 @@ $task_xml = @'
|
||||||
</Task>
|
</Task>
|
||||||
'@
|
'@
|
||||||
|
|
||||||
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
|
|
||||||
$encoded_command = [Convert]::ToBase64String($bytes)
|
|
||||||
$arguments = "/c powershell.exe -EncodedCommand $encoded_command > $out_file 2>&1"
|
$arguments = "/c powershell.exe -EncodedCommand $encoded_command > $out_file 2>&1"
|
||||||
|
|
||||||
$task_xml = $task_xml.Replace("{arguments}", $arguments)
|
$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 = New-Object -ComObject "Schedule.Service"
|
||||||
$schedule.Connect()
|
$schedule.Connect()
|
||||||
$task = $schedule.NewTask($null)
|
$task = $schedule.NewTask($null)
|
||||||
$task.XmlText = $task_xml
|
$task.XmlText = $task_xml
|
||||||
$folder = $schedule.GetFolder("\")
|
$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 = $folder.GetTask("\$task_name")
|
||||||
$registered_task.Run($null) | Out-Null
|
$registered_task.Run($null) | Out-Null
|
||||||
|
|
Loading…
Reference in New Issue