
रस्ट एक्सप्लॉइट PoC लिनक्स कर्नेल LPE CVE-2026-31431 (AF_ALG पेज-कैश राइट) के लिए, साथ ही eBPF रनटाइम डिफेंस जो LSM या kprobe के माध्यम से बिना रीबूट के AF_ALG सॉकेट निर्माण को ब्लॉक करता है।
CVE-2026-31431 (कॉपी फेल) लिनक्स कर्नेल के algif_aead मॉड्यूल (AF_ALG सबसिस्टम) में एक लोकल प्रिविलेज एस्केलेशन कमजोरी है। अगस्त 2017 में पेश किया गया एक लॉजिक दोष किसी भी अनप्रिविलेज्ड लोकल यूज़र को AF_ALG + splice() के माध्यम से किसी भी पठनीय फ़ाइल के पेज कैश में 4 नियंत्रित बाइट्स लिखने की अनुमति देता है, फिर रूट प्राप्त करने के लिए एक दूषित setuid बाइनरी निष्पादित करता है। एक्सप्लॉइट नियतात्मक है — कोई रेस कंडीशन नहीं, कोई कर्नेल ऑफसेट नहीं, कोई सिस्टम क्रैश नहीं। यह 4.14 से 7.0-rc तक कर्नेल भेजने वाले सभी प्रमुख लिनक्स वितरणों को प्रभावित करता है।
CVSS: 7.8 | इसमें ठीक किया गया: कर्नेल 7.0, 6.19.12, 6.18.22 | मेनलाइन फिक्स: कमिट a664bf3d603d
स्रोत: copy.fail, द हैकर न्यूज़, CloudLinux सलाह
crates/
├── exp/ # एक्सप्लॉइट PoC (Rust पुनःकार्यान्वयन)
├── copy_fail_guard/ # यूज़रस्पेस eBPF लोडर — LSM मोड
├── copy_fail_guard-ebpf/ # eBPF LSM प्रोग्राम (वर्कस्पेस में नहीं)
├── copy_fail_guard_kprobe/ # यूज़रस्पेस eBPF लोडर — kprobe मोड
└── copy_fail_guard_kprobe-ebpf/ # eBPF kprobe प्रोग्राम (वर्कस्पेस में नहीं)
scripts/
└── build_guard.sh # वन-क्लिक बिल्ड → आउटपुट dist/ में
मूल कारण तीन स्वतंत्र कर्नेल सुविधाओं की एक श्रृंखला है जो असुरक्षित रूप से परस्पर क्रिया करती हैं:
AF_ALG सॉकेट — कर्नेल क्रिप्टो API को अनप्रिविलेज्ड यूज़रस्पेस के लिए उजागर करता हैsplice() — फ़ाइल डेटा को पेज कैश संदर्भों के रूप में (प्रतियों के रूप में नहीं) क्रिप्टो स्कैटरलिस्ट में स्थानांतरित करता हैauthencesn AEAD टेम्पलेट — कॉलर के आउटपुट बफर को स्क्रैच स्पेस के रूप में उपयोग करता है, dst[assoclen + cryptlen] पर 4 बाइट्स लिखता है2017 में, algif_aead.c (72548b093ee3) में एक इन-प्लेस अनुकूलन ने req->src == req->dst बना दिया, पेज कैश पेजों को लिखने योग्य गंतव्य स्कैटरलिस्ट में जोड़ दिया। जब authencesn अपने स्क्रैच बाइट्स लिखता है, तो यह आउटपुट बफर से आगे जुड़े पेज कैश पेजों में चला जाता है। हमलावर नियंत्रित करता है:
दूषित पेज कभी गंदा (dirty) चिह्नित नहीं होता — डिस्क पर फ़ाइल अछूती रहती है, लेकिन execve() पेज कैश से पढ़ता है। एक setuid बाइनरी को दूषित करें → रूट।
सार्वजनिक 732-बाइट Python PoC का Rust पुनःकार्यान्वयन। /usr/bin/su को लक्षित करता है, इसके पेज-कैश पेजों को AF_ALG AEAD सॉकेट में splice करता है, और उन्हें एक संपीड़ित शेल पेलोड के साथ अधिलेखित करता है।
Rust 1.85+ (edition 2024) की आवश्यकता है।
cargo build --release -p copy_fail
बाइनरी केवल Linux के लिए है। अन्य प्लेटफार्मों पर यह Unsupported त्रुटि के साथ बाहर निकलता है।
चेतावनी: यह एक वास्तविक कर्नेल दोष का शोषण करता है। केवल उन प्रणालियों पर चलाएं जिनके आप स्वामी हैं और नियंत्रित करते हैं, आदर्श रूप से एक डिस्पोजेबल VM।
एक कमजोर कर्नेल चलाने वाला VM बूट करें (कर्नेल < 7.0 / < 6.19.12 / < 6.18.22 वाला कोई भी मुख्यधारा डिस्ट्रो)।
निर्मित बाइनरी को VM में कॉपी करें और इसे गैर-रूट उपयोगकर्ता के रूप में चलाएं:
./target/release/copy_fail
कमजोर: एक रूट शेल (#) दिखाई देता है। पुष्टि करने के लिए whoami चलाएं कि यह root है।
कमजोर नहीं (पैच किया गया कर्नेल): AF_ALG ऑपरेशन विफल हो जाता है या su बाइनरी सामान्य रूप से व्यवहार करती है। आपको एक त्रुटि या एक नियमित su पासवर्ड प्रॉम्प्ट दिखाई देगा।
एक रनटाइम कर्नेल रक्षा जो CVE-2026-31431 को कर्नेल को अपग्रेड किए बिना या रीबूट किए बिना अवरुद्ध करती है। यह AF_ALG सॉकेट निर्माण को रोकने के लिए eBPF का उपयोग करता है, जिससे एक्सप्लॉइट का पहला चरण कट जाता है।
दो मोड प्रदान किए गए हैं। वन-क्लिक लोडर स्वचालित रूप से उपलब्ध सर्वोत्तम मोड का चयन करता है:
┌──────────────────────────────────────────────────┐
│ run_guard.sh │
│ • BPF LSM समर्थन का पता लगाता है │
│ • LSM उपलब्ध → copy_fail_guard (EPERM) │
│ • LSM अनुपलब्ध → copy_fail_guard_kprobe (KILL) │
└──────────────┬───────────────────────────────────┘
│
┌──────────────▼───────────────────────────────────┐
│ eBPF प्रोग्राम │
│ यदि socket family == 38 (AF_ALG) │
│ → अवरुद्ध करें (EPERM या SIGKILL) │
│ अन्यथा │
│ → अनुमति दें │
└──────────────────────────────────────────────────┘
AF_ALG को अवरुद्ध करने का विशिष्ट प्रणालियों पर लगभग शून्य प्रभाव होता है:
AF_ALG के माध्यम से नहीं, बल्कि सीधे इन-कर्नेल क्रिप्टो API का उपयोग करते हैंAF_ALG का उपयोग करने के लिए कॉन्फ़िगर किए गए एप्लिकेशन (जैसे afalg इंजन सक्षम के साथ OpenSSL, कुछ एम्बेडेड क्रिप्टो ऑफलोड पथ)socket(AF_ALG, ...) को कॉल न करने वाली किसी भी चीज़ के लिए शून्य ओवरहेडवन-क्लिक बिल्ड (अनुशंसित):
./scripts/build_guard.sh
यह स्वचालित रूप से लापता टूलचेन (nightly, bpf-linker) स्थापित करता है, सभी eBPF प्रोग्राम और यूज़रस्पेस लोडर संकलित करता है, और सब कुछ dist/ में आउटपुट करता है:
dist/
├── copy_fail_guard.bpf.o # eBPF LSM प्रोग्राम
├── copy_fail_guard_kprobe.bpf.o # eBPF kprobe प्रोग्राम
├── copy_fail_guard # यूज़रस्पेस लोडर (LSM)
├── copy_fail_guard_kprobe # यूज़रस्पेस लोडर (kprobe)
└── run_guard.sh # ऑटो-चयन: sudo ./run_guard.sh
dist/ निर्देशिका को किसी भी लक्ष्य मशीन पर कॉपी करें और सुरक्षा सक्रिय करने के लिए sudo ./run_guard.sh चलाएं।
मैनुअल बिल्ड (चरण दर चरण):
चरण 1: eBPF प्रोग्राम संकलित करें (Linux पर किया जाना चाहिए):
# LSM वैरिएंट
cd crates/copy_fail_guard-ebpf
cargo +nightly build --target bpfel-unknown-none -Z build-std=core --release
# kprobe वैरिएंट
cd crates/copy_fail_guard_kprobe-ebpf
cargo +nightly build --target bpfel-unknown-none -Z build-std=core --release
चरण 2: यूज़रस्पेस लोडर बनाएं:
cargo build --release -p copy_fail_guard -p copy_fail_guard_kprobe
अनुशंसित — सर्वोत्तम मोड का स्वचालित चयन:
sudo ./dist/run_guard.sh
मैनुअल — एक विशिष्ट मोड चलाएं:
# LSM मोड (lsm=bpf की आवश्यकता है)
sudo GUARD_BPF_OBJ=path/to/copy_fail_guard.bpf.o RUST_LOG=info ./copy_fail_guard
# kprobe मोड (हर जगह काम करता है)
sudo GUARD_BPF_OBJ=path/to/copy_fail_guard_kprobe.bpf.o RUST_LOG=info ./copy_fail_guard_kprobe
eBPF प्रोग्राम को अलग करने और सामान्य व्यवहार को बहाल करने के लिए Ctrl-C दबाएं।
एक टर्मिनल में गार्ड चलाने के साथ:
# दूसरे टर्मिनल में, एक्सप्लॉइट का प्रयास करें:
./target/release/copy_fail
# LSM मोड: "error: Operation not permitted"
# kprobe मोड: "已杀死" / "Killed"
# या Python के साथ सीधे परीक्षण करें:
python3 -c "import socket; socket.socket(38, 5, 0)"
# LSM मोड: PermissionError: [Errno 1] Operation not permitted
# kprobe मोड: Killed
AF_ALG सॉकेट निर्माण को अवरुद्ध करता है। PID, cgroup या कमांड नाम द्वारा विशिष्ट प्रक्रियाओं को छूट देने का कोई तंत्र नहीं है। यह भविष्य के संस्करण के लिए योजनाबद्ध है (eBPF HashMap मैप्स के माध्यम से)। अधिकांश प्रणालियों के लिए यह ठीक है क्योंकि लगभग कुछ भी AF_ALG का उपयोग नहीं करता है।bpf-linker के साथ अलग से संकलित किया जाना चाहिए (वे bpfel-unknown-none को लक्षित करते हैं और सामान्य वर्कस्पेस सदस्य नहीं हो सकते)।अधिकांश वितरण डिफ़ॉल्ट रूप से BPF LSM सक्षम नहीं करते हैं। यदि आप क्लीनर LSM मोड (SIGKILL के बजाय EPERM) चाहते हैं:
# वर्तमान LSM जांचें:
cat /sys/kernel/security/lsm
# यदि "bpf" गायब है, तो इसे जोड़ें:
sudo sed -i 's/^GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 lsm=lockdown,capability,yama,apparmor,bpf"/' /etc/default/grub
sudo update-grub && sudo reboot
kprobe मोड इस चरण के बिना काम करता है।
कर्नेल को ≥ 7.0 / ≥ 6.19.12 / ≥ 6.18.22 में पैच करने के बाद:
# कर्नेल संस्करण की पुष्टि करें
uname -r
# एक्सप्लॉइट को फिर से चलाएं — इसे अब रूट शेल उत्पन्न नहीं करना चाहिए
./target/release/copy_fail
वैकल्पिक रूप से, पुष्टि करें कि कमजोर मॉड्यूल निष्प्रभावी है:
modinfo algif_aead | grep filename
# यदि बिल्ट-इन है, तो initcall को ब्लैकलिस्ट करें (रीबूट की आवश्यकता है)
sudo grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init"
sudo reboot
| LSM मोड | kprobe मोड |
|---|
| कैसे अवरुद्ध करता है | -EPERM लौटाता है (सॉकेट निर्माण अस्वीकृत) | SIGKILL (प्रक्रिया मार दी गई) |
| कर्नेल आवश्यकता | ≥ 5.7 lsm=bpf बूट पैरामीटर के साथ | ≥ 5.3, कोई विशेष पैरामीटर नहीं |
| सक्षम करने के लिए रीबूट की आवश्यकता | शायद (यदि lsm=bpf पहले से सेट नहीं है) | नहीं |
| हुक बिंदु | socket_create LSM हुक | __sys_socket kprobe |