
कॉपी फेल: हर प्रमुख लिनक्स वितरण पर रूट तक 732 बाइट्स।
732 बाइट्स। कोई भी डिस्ट्रो। रूट।
Linux कर्नेल के
authencesnक्रिप्टोग्राफिक टेम्पलेट में एक सीधी-रेखा लॉजिक त्रुटि एक अनप्रिविलेज्ड स्थानीय उपयोगकर्ता को किसी भी पठनीय फ़ाइल — जिसमें setuid बाइनरी भी शामिल हैं — के पेज कैश में एक सटीक, नियंत्रित 4-बाइट राइट करने में सक्षम बनाती है। कोई रेस नहीं। कोई रीट्राई नहीं। कोई रीकंपाइलेशन नहीं। 2017 से शिप किए गए हर प्रमुख Linux डिस्ट्रीब्यूशन पर रूट।
📄 तकनीकी विवरण · 🔗 कर्नेल पैच · 🛡️ CVSS: क्रिटिकल
| डिस्ट्रो | कर्नेल संस्करण |
|---|---|
| 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 |
सभी चारों को बिना किसी संशोधन के समान 732-बाइट Python स्क्रिप्ट का उपयोग करके रूट किया गया।
AF_ALG कर्नेल के क्रिप्टो सबसिस्टम को अनप्रिविलेज्ड यूज़रस्पेस के लिए उजागर करता है। splice() फ़ाइल डेटा को पाइप में संदर्भ द्वारा स्थानांतरित करता है — पेज कैश पेजों को सीधे, बिना कॉपी किए पास करता है। जब कोई उपयोगकर्ता किसी फ़ाइल को AF_ALG AEAD सॉकेट में स्प्लाइस करता है, तो सॉकेट का इनपुट स्कैटरलिस्ट उस फ़ाइल के कर्नेल के कैश्ड पेजों के लाइव संदर्भ रखता है।
algif_aead.c में, 2017 का इन-प्लेस ऑप्टिमाइज़ेशन TX स्कैटरलिस्ट से AAD और सिफरटेक्स्ट को RX बफर में कॉपी करता था, लेकिन प्रमाणीकरण टैग पेजों को sg_chain() का उपयोग करके संदर्भ द्वारा जोड़ता था, फिर req->src = req->dst सेट करता था:
इनपुट SGL: [ AAD | CT | Tag ]
^
└─ sg_chain() → अभी भी पेज कैश पेजों की ओर इशारा करता है
आउटपुट SGL: [ AAD | CT ] ──→ [ Tag (पेज कैश पेज) ]
(RX बफर) (TX SGL से जुड़ा हुआ)
req->src ──┐
├──→ समान संयुक्त स्कैटरलिस्ट
req->dst ──┘
splice() से पेज कैश पेज अब एक राइटेबल डेस्टिनेशन स्कैटरलिस्ट के अंदर बैठे थे, जो वैध राइट क्षेत्र से केवल एक ऑफसेट सीमा द्वारा अलग किए गए थे। API में कुछ भी यह लागू नहीं करता था कि एल्गोरिदम को सीमाओं के भीतर रहना चाहिए।
authencesn का आउट-ऑफ-बाउंड स्क्रैच राइटauthencesn एक AEAD रैपर है जिसका उपयोग IPsec 64-बिट एक्सटेंडेड सीक्वेंस नंबर (ESN) समर्थन के लिए करता है। HMAC गणना के लिए ESN बाइट्स को पुनर्व्यवस्थित करने के लिए, यह कॉलर के डेस्टिनेशन बफर को स्क्रैच स्पेस के रूप में उपयोग करता है — जिसमें ऑफसेट assoclen + cryptlen पर एक राइट शामिल है, जो प्रमाणीकरण टैग सीमा से परे स्थित है:
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); // AAD[0..7] पढ़ें
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); // dst[4..7] ओवरराइट करें
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1); // ← टैग से परे लिखता है
तीसरा कॉल dst[assoclen + cryptlen] पर 4 बाइट्स (seqno_lo) लिखता है। इन-प्लेस AF_ALG पथ में, स्कैटरवॉक RX बफर से जुड़े पेज कैश टैग पेजों में पार करता है। कर्नेल kmap_local_page के माध्यम से पेज कैश पेज को मैप करता है और सीधे लक्ष्य फ़ाइल की कैश्ड कॉपी में लिखता है।
फिर HMAC विफल हो जाता है (सिफरटेक्स्ट नकली है), recvmsg() एक त्रुटि लौटाता है — लेकिन 4-बाइट राइट स्थायी रूप से बनी रहती है।
कोई भी एकल परिवर्तन व्यक्तिगत रूप से गलत नहीं था। भेद्यता तीनों के प्रतिच्छेदन पर रहती है।
डिफ़ॉल्ट लक्ष्य /usr/bin/su है, एक setuid-root बाइनरी जो सभी परीक्षण किए गए डिस्ट्रीब्यूशन पर मौजूद है।
चरण 1 — सॉकेट सेटअप
AF_ALG सॉकेट खोलें, authencesn(hmac(sha256),cbc(aes)) से बाइंड करें
कुंजी सेट करें। रिक्वेस्ट सॉकेट स्वीकार करें। (कोई विशेषाधिकार आवश्यक नहीं।)
चरण 2 — राइट लूप (प्रति 4-बाइट शेलकोड चंक एक बार)
sendmsg() → AAD बाइट्स [4:8] लिखने के लिए 4 बाइट्स ले जाते हैं (seqno_lo)
splice() → लक्ष्य फ़ाइल के पेज कैश पेज AF_ALG सॉकेट में
recv() → डिक्रिप्ट ट्रिगर करता है → authencesn seqno_lo को पेज कैश में लिखता है
(recvmsg त्रुटि लौटाता है; राइट बनी रहती है)
चरण 3 — निष्पादन
execve("/usr/bin/su")
कर्नेल बाइनरी को (अब-दूषित) पेज कैश से लोड करता है
Setuid-root बाइनरी इंजेक्टेड शेलकोड निष्पादित करती है → UID 0
a = socket.socket(38, 5, 0) # AF_ALG, SOCK_SEQPACKET
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# ... कुंजी सेट करें, रिक्वेस्ट सॉकेट u स्वीकार करें ...
u.sendmsg([b"A"*4 + payload_chunk], [cmsg_headers], MSG_MORE)
os.splice(target_fd, pipe_wr, offset)
os.splice(pipe_rd, alg_fd, offset)
u.recv(...) # पेज कैश राइट ट्रिगर करता है
पैच a664bf3d603d युक्त कर्नेल में अपडेट करें। फिक्स algif_aead.c को आउट-ऑफ-प्लेस ऑपरेशन में वापस लाता है: req->src TX SGL की ओर इशारा करता है; req->dst RX बफर की ओर इशारा करता है। splice() से पेज कैश पेज रीड-ओनली रहते हैं। sg_chain() तंत्र जो उन्हें राइटेबल डेस्टिनेशन से जोड़ता था, हटा दिया गया है।
// पहले (भेद्य): src और dst समान स्कैटरलिस्ट साझा करते हैं
aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, rsgl_src, used, ctx->iv);
// बाद में (ठीक): src TX SGL है, dst RX बफर है — पूरी तरह से अलग
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src, rsgl_dst, used, ctx->iv);
algif_aead कर्नेल मॉड्यूल अक्षम करें:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
या अपने वर्कलोड प्रोफाइल में seccomp नीति के माध्यम से AF_ALG सॉकेट निर्माण को ब्लॉक करें।
कंटेनर वातावरण के लिए नोट: क्योंकि पेज कैश होस्ट में साझा होता है, यह भेद्यता कंटेनर सीमाओं को पार करती है। शमन को नोड स्तर पर लागू करें, न कि केवल प्रति-पॉड। पूर्ण Kubernetes एस्केप विवरण के लिए भाग 2 देखें।
Theori शोधकर्ता Taeyang Lee ने पिछले kernelCTF कार्य के माध्यम से पहचाना कि AF_ALG + splice() एक ऐसा पथ बनाता है जहां अनप्रिविलेज्ड यूज़रस्पेस पेज कैश पेजों को सीधे क्रिप्टो सबसिस्टम में फीड कर सकता है — और स्कैटरलिस्ट पेज उत्पत्ति एक कम खोजी गई भेद्यता श्रेणी थी।
शोध टीम ने निम्नलिखित ऑपरेटर प्रॉम्प्ट के साथ इस अंतर्दृष्टि को पूरे crypto/ सबसिस्टम में विस्तारित करने के लिए Xint Code का उपयोग किया:
"यह Linux crypto/ सबसिस्टम है। कृपया यूज़रस्पेस सिस्कॉल से पहुंच योग्य सभी कोडपाथ की जांच करें। एक प्रमुख अवलोकन नोट करें: splice() रीड-ओनली फ़ाइलों (setuid बाइनरी सहित) के पेज-कैश संदर्भ क्रिप्टो TX स्कैटरलिस्ट्स तक पहुंचा सकता है।"
लगभग एक घंटे के स्वचालित विश्लेषण के बाद, कॉपी फेल उच्चतम-गंभीरता वाला आउटपुट था। उसी स्कैन के दौरान खोजी गई अतिरिक्त भेद्यताएं समन्वित प्रकटीकरण के अधीन हैं।
भाग 2: पॉड से होस्ट तक — कॉपी फेल हर प्रमुख क्लाउड Kubernetes प्लेटफॉर्म से कैसे बच निकलता है। जल्द आ रहा है।
| गुण | विवरण |
|---|
| निर्धारक | सीधी-रेखा लॉजिक त्रुटि — कोई रेस कंडीशन नहीं, कोई टाइमिंग विंडो नहीं, कोई रीट्राई नहीं |
| पोर्टेबल | समान स्क्रिप्ट, समान बाइट्स, सभी परीक्षण किए गए डिस्ट्रो और आर्किटेक्चर पर काम करती है |
| छोटा | केवल मानक लाइब्रेरी (os, socket, zlib) का उपयोग करने वाली 732-बाइट Python स्क्रिप्ट। os.splice के लिए Python 3.10+ आवश्यक है |
| गुप्त | दूषित पेज कभी डर्टी चिह्नित नहीं होता। डिस्क पर चेकसम अपरिवर्तित रहते हैं; केवल इन-मेमोरी पेज कैश संशोधित होता है |
| क्रॉस-कंटेनर | पेज कैश कंटेनर सीमाओं के पार सिस्टम-व्यापी रूप से साझा होता है — यह एक Kubernetes नोड एस्केप प्रिमिटिव भी है (भाग 2 देखें) |
| चर | नियंत्रण के माध्यम से |
|---|
| लक्ष्य फ़ाइल | वर्तमान उपयोगकर्ता द्वारा पठनीय कोई भी फ़ाइल |
| राइट ऑफसेट | assoclen, splice ऑफसेट, और splice लंबाई |
| राइट मान | sendmsg() में आपूर्ति किए गए AAD के बाइट 4–7 (seqno_lo) |
| वर्ष | घटना |
|---|
| 2011 | IPsec ESN समर्थन के लिए authencesn कर्नेल में जोड़ा गया (a5079d084f8b)। स्क्रैच राइट मौजूद था लेकिन हानिरहित था — केवल आंतरिक xfrm परत इसे कॉल करती थी, और AAD एक अलग स्कैटरलिस्ट में रहता था। |
| 2015 | AF_ALG AEAD समर्थन प्राप्त करता है। authencesn नए AEAD इंटरफ़ेस में परिवर्तित (104880a6b470), जिससे assoclen + cryptlen राइट ऑफसेट पेश हुआ। फिर भी आउट-ऑफ-प्लेस: पेज कैश पेज src (रीड-ओनली) में थे। अभी तक शोषण योग्य नहीं। |
| 2017 | algif_aead.c में इन-प्लेस ऑप्टिमाइज़ेशन जोड़ा गया (72548b093ee3)। req->src = req->dst। पेज कैश टैग पेज राइटेबल डेस्टिनेशन में जुड़े। भेद्यता का निर्माण हुआ। |
| 2026-03-23 | Linux कर्नेल सुरक्षा टीम को रिपोर्ट किया गया। |
| 2026-04-01 | पैच मेनलाइन में मर्ज किया गया। |
| 2026-04-22 | CVE-2026-31431 असाइन किया गया। |
| 2026-04-29 | सार्वजनिक प्रकटीकरण। |
| तिथि | घटना |
|---|
| 2026-03-23 | भेद्यता Linux कर्नेल सुरक्षा टीम को रिपोर्ट की गई |
| 2026-03-24 | प्रारंभिक स्वीकृति प्राप्त हुई |
| 2026-03-25 | पैच प्रस्तावित और समीक्षित किए गए |
| 2026-04-01 | पैच मेनलाइन कर्नेल में कमिट किए गए |
| 2026-04-22 | CVE-2026-31431 असाइन किया गया |
| 2026-04-29 | सार्वजनिक प्रकटीकरण |