
शून्य लंबाई वाला एक IPv6 ND विकल्प। एक लापता जाँच। डेमॉन पीछे की ओर चलता है और लूप में रहता है। OpenBSD को रिपोर्ट किया गया, ठीक किया गया, CVE निर्दिष्ट किया गया।
लोकल नेटवर्क से एक क्राफ्टेड ICMPv6 पैकेट slaacd और/या rad को स्थायी रूप से हैंग कर देता है। IPv6 SLAAC पता स्वतः-कॉन्फ़िगरेशन तब तक मृत रहता है जब तक कोई डेमॉन को मैन्युअल रूप से पुनः आरंभ नहीं करता। कोई प्रमाणीकरण नहीं, कोई विशेषाधिकार नहीं, ICMPv6 पेलोड के 18 बाइट्स।
| CVE | CVE-2026-41285 |
| बग वर्ग | पूर्णांक अंडरफ़्लो के माध्यम से अनंत लूप |
| मूल कारण | ND विकल्प पार्सर nd_opt_len * 8 - 2 करता है बिना len==0 की जाँच किए |
| घटक | sbin/slaacd/engine.c, usr.sbin/rad/engine.c |
| प्रभाव | IPv6 SLAAC (slaacd) या RA सेवा (rad) का स्थायी DoS |
| आवश्यकता | उसी L2 नेटवर्क सेगमेंट पर कोई भी डिवाइस |
| परीक्षित | OpenBSD 7.8 GENERIC amd64 |
RFC 4861 §4.6 के अनुसार शून्य लंबाई वाले ND विकल्प अमान्य हैं और उन्हें चुपचाप छोड़ दिया जाना चाहिए। कर्नेल का अपना nd6_options() sys/netinet6/nd6.c में यह सही ढंग से करता है। लेकिन उस जाँच के प्रभावी होने से पहले ही कच्चा ICMPv6 पैकेट userland सॉकेट्स को पहुँचा दिया जाता है।
slaacd और rad दोनों स्वयं ND विकल्प पार्स करते हैं। लूप कुछ इस प्रकार है:
while (len > 0) {
// ...
optlen = nd_opt->nd_opt_len * 8 - 2; // nd_opt_len is uint8_t
if (optlen > len)
break;
len += 2;
// advance pointer by optlen... which is (uint32_t)-2 promoted from int
}
जब nd_opt_len == 0 होता है: व्यंजक 0 * 8 - 2 int में प्रमोट होकर → -2 बनता है। गार्ड (-2 > len) हमेशा गलत (false) होता है (साइन्ड तुलना, len धनात्मक है)। फिर len += 2 होता है और पॉइंटर 2 बाइट्स पीछे चला जाता है। लूप कभी आगे नहीं बढ़ता। CPU 100% पर अटक जाता है। हमेशा के लिए।
कर्नेल ने अपनी प्रति की जाँच कर ली। userland डेमॉन को कच्चा मूल पैकेट मिला। किसी ने slaacd को नहीं बताया।
rcctl restart slaacd या रिबूट आवश्यक हैpython3 poc/kill_slaacd.py <interface>
इसके लिए scapy आवश्यक है। एक ही ND विकल्प के साथ एक Router Advertisement भेजता है जहाँ nd_opt_len = 0 होता है। बस इतना ही। विकल्प प्रकार मायने नहीं रखता (PoC टाइप 200 / अज्ञात का उपयोग करता है)।
पूर्ण एंड-टू-एंड प्रमाण के लिए (SLAAC कार्यशील -> एक्सप्लॉइट -> SLAAC मृत दिखाता है):
python3 poc/prove_dos.py
── Before exploit ──
SLAAC addresses: 2001:db8:1:0:df6f:edeb:6e3a:2640, ...
Engine CPU: 0.0%
── After one packet ──
Engine CPU: 23.1% → 43.3% (climbing)
New RA with 2001:db8:2::/64 sent → no address configured
slaacd is dead. IPv6 autoconf: DEAD.
यह CVE-2022-27881 और CVE-2022-27882 (engine.c में पिछले slaacd अनंत लूप, जो ND विकल्प पार्सिंग से भी संबंधित थे) के समान आक्रमण सतह है। यह उसी श्रेणी के बग का एक नया उदाहरण है - पिछले फिक्स ने सभी पार्सिंग लूप को कवर नहीं किया था।
उस पर अंकगणितीय संक्रिया करने से पहले nd_opt_len == 0 की जाँच करें। लूप से बाहर निकलें। कर्नेल nd6_options() में यही करता है:
if (nd_opt->nd_opt_len == 0)
break; // or: goto bad;
slaacd के parse_ra(), debug_log_ra(), और rad के RS पार्सर के लिए सुझाया गया पैच - तीनों लूप को समान एक-पंक्ति गार्ड की आवश्यकता है।
यह एक लोकल-नेटवर्क DoS है। यदि आप slaacd चला रहे OpenBSD मशीन के समान L2 सेगमेंट पर हैं, तो एक पैकेट उसका IPv6 फ्रीज़ कर देता है। इसे उन नेटवर्कों पर न भेजें जिनके मालिक आप नहीं हैं। यदि आप OpenBSD चलाते हैं, तो पैच की जाँच करें या स्वयं len==0 गार्ड जोड़ें।
Daniel Wade - GitHub · Twitter/X · Bluesky · nadsec.online