
CVE-2025-38352 LG webOS स्मार्ट टीवी (ARM64) के लिए कर्नेल शोषण। नवीन शोषण तकनीकों के साथ वास्तविक उपभोक्ता हार्डवेयर पर स्थायी रूट प्राप्त करता है। LG को जिम्मेदारी से खुलासा किया गया।
CVE-2025-38352 के लिए कर्नेल शोषण (POSIX CPU टाइमर रेस कंडीशन / उपयोग-के-बाद-मुक्त) जो LG webOS स्मार्ट टीवी पर ARM64 पर कर्नेल 5.4.268 चलाने वाले स्थायी रूट प्राप्त करता है। कई फर्मवेयर संस्करणों में 4 टीवी मॉडलों पर सत्यापित। LG के सुरक्षा शोधकर्ता कार्यक्रम (फरवरी 2026) को जिम्मेदारी से प्रकट किया गया।
farazsth98 द्वारा Chronomaly पर निर्मित। स्टेज 1 UAF रेस तर्क और क्रॉस-कैश बुनियादी ढांचा ARM64 के लिए पोर्ट और अनुकूलित किया गया; स्टेज 2–5 को नवीन शोषण तकनीकों और वास्तविक-हार्डवेयर बाधाओं के समाधानों के साथ पुन: डिज़ाइन किया गया जो अनुकरणित वातावरण में मौजूद नहीं हैं। क्लॉड ओपस 4.6 की सहायता से विकसित।
पूर्ण भेद्यता विश्लेषण, शोषण श्रृंखला वॉकथ्रू और अनुशंसित शमन उपायों के लिए VULNERABILITY_REPORT.md देखें।
prisoner उपयोगकर्ता (uid=5038) से स्थायी कर्नेल रूट (uid=0)यह शोषण जिम्मेदार सुरक्षा अनुसंधान के भाग के रूप में विकसित किया गया था और 7 फरवरी, 2026 को LG के सुरक्षा शोधकर्ता कार्यक्रम को रिपोर्ट किया गया। यह केवल शैक्षिक उद्देश्यों के लिए प्रकाशित किया गया है। जिम्मेदारी से उपयोग करें और केवल अपने स्वामित्व वाले उपकरणों पर। लेखक इस सॉफ्टवेयर के उपयोग से होने वाली किसी भी क्षति, ब्रिकिंग, डेटा हानि या वारंटी रद्द होने के लिए जिम्मेदार नहीं हैं। यह सॉफ्टवेयर बिना किसी वारंटी के "जैसा है" प्रदान किया गया है।
मूल का मनमाना घटाव धीमा और शोरगुल वाला है: यह फोर्क किए गए प्रक्रियाओं के माध्यम से 1,000 struct cred ऑब्जेक्ट स्प्रे करता है, फिर लक्ष्य cred के EUID फ़ील्ड को N बार घटाता है। प्रत्येक घटाव एक अलग ऑपरेशन है। यह QEMU में स्वीकार्य है जहाँ टाइमिंग क्षमाशील है, लेकिन वास्तविक हार्डवेयर पर अविश्वसनीय है जहाँ इंटरप्ट-चालित पृष्ठ पुनर्प्राप्ति ऑपरेशनों के बीच पाइप बफर पेज चुरा सकती है।
इसे list_del_init() के माध्यम से एकल मनमाना लेखन से बदल दिया गया। शोषण UAF'd sigqueue के list_head.next और list_head.prev पॉइंटर्स को पाइप बफर के माध्यम से ओवरराइट करता है। जब कर्नेल लंबित सिग्नल को डी-क्यू करता है (collect_signal() → list_del_init()), यह prev->next = next (नकली cred पता task_struct->cred में लिखता है) और next->prev = prev (नियंत्रित साइड-इफेक्ट लेखन) करता है। एक लेखन प्रक्रिया के cred पॉइंटर को एक नकली cred संरचना के पॉइंटर से बदल देता है जिसमें सभी-शून्य uid/gid फ़ील्ड होते हैं। कोई cred स्प्रे नहीं, कोई फोर्क की गई प्रक्रिया नहीं, नियतात्मक।
tee() के माध्यम से peek_pipe()मूल पूरे शोषण में पाइप बफर पर विनाशकारी read() कॉल का उपयोग करता है। QEMU में, यह ठीक काम करता है क्योंकि ऑपरेशनों के बीच पेज चोरी नहीं होते। 4 भौतिक कोर वाले वास्तविक हार्डवेयर पर, कर्नेल की प्रति-CPU पृष्ठ सूची (pcplist) आक्रामक रूप से मुक्त किए गए पृष्ठों को पुनः प्राप्त करती है। एक विनाशकारी रीड पाइप बफर के बैकिंग पृष्ठ को मुक्त कर देता है, जिसे शोषण के पुनः आवंटित करने से पहले एक हार्डवेयर इंटरप्ट द्वारा तुरंत चुराया जा सकता है।
समाधान tee() का उपयोग करके एक अविनाशी पाइप रीड प्रिमिटिव है। tee() syscall दो पाइपों के बीच पाइप डेटा को उपभोग किए बिना डुप्लिकेट करता है, मूल पाइप बफर के बैकिंग पृष्ठ को पिन किए रखता है। यह शोषण को क्रॉस-कैश किए गए पाइप बफर से कर्नेल डेटा को बार-बार पढ़ने की अनुमति देता है बिना पृष्ठ खोने के जोखिम के। यह वास्तविक हार्डवेयर पर विश्वसनीयता के लिए महत्वपूर्ण था।
मूल cred ऑब्जेक्ट स्प्रे करता है और एक अनुमानित स्थान पर उतरने की उम्मीद करता है। यह संस्करण ज्ञात पते पर नकली cred संरचना का निर्माण दूसरा क्रॉस-कैश करके करता है: एक नया sigqueue आवंटित करें (tkill(SIGRTMIN+1) के माध्यम से), इसका पता पहले पाइप बफर के हीप लीक से जानें, फिर उस sigqueue के स्लैब पृष्ठ को दूसरे पाइप बफर में क्रॉस-कैश करें। नकली cred दूसरे पाइप बफर में लीक किए गए sigqueue पते के सटीक पृष्ठ ऑफ़सेट पर लिखा जाता है। परिणाम एक नियतात्मक कर्नेल वर्चुअल पते पर एक नकली cred है जिसमें कोई अनुमान नहीं है।
मूल UAF sigqueue का पता लीक करने के लिए स्टेज 2 में जल्दी SIGUSR2 को डी-क्यू करता है। यह सिग्नल को उपभोग करता है, इसलिए मूल को अंतिम लेखन के लिए एक अलग तंत्र की आवश्यकता होती है। यह संस्करण कभी भी UAF sigqueue के अपने पते की आवश्यकता नहीं रखता (हीप लीक पाइप बफर में आसन्न sigqueue पॉइंटर्स से आता है)। SIGUSR2 को सभी पांच चरणों में लंबित रखा जाता है और इसके डी-क्यू को अंतिम मनमाना लेखन ट्रिगर के रूप में उपयोग किया जाता है। जिस सिग्नल ने UAF बनाया वही वह सिग्नल है जिसके डी-क्यू का इसका शोषण करता है।
modprobe_path + socket(44) एस्केलेशननकली cred संरचना में NULL user_ns, user, और group_info पॉइंटर्स हैं (क्योंकि पाइप बफर uid/gid फ़ील्ड से परे शून्य-आरंभिक है)। setresuid(), fork(), या exec() को कॉल करने से ये NULL पॉइंटर्स डीरेफ़रेंस हो जाएंगे और कर्नेल पैनिक हो जाएगा। मूल इससे बचता है क्योंकि इसका cred स्प्रे वास्तविक cred ऑब्जेक्ट्स का उपयोग करता है जिनमें मान्य पॉइंटर्स होते हैं।
समाधान: /proc/sys/kernel/modprobe को एक पेलोड स्क्रिप्ट (/tmp/pwn) को इंगित करने के लिए ओवरराइट करें, फिर socket(44, SOCK_STREAM, 0) के माध्यम से call_usermodehelper ट्रिगर करें (एक गैर-मौजूद प्रोटोकॉल परिवार का अनुरोध करते हुए)। कर्नेल modprobe हेल्पर को init_cred (कर्नेल के अपने रूट क्रेडेंशियल्स, पूरी तरह से मान्य) के साथ निष्पादित करता है, जो भ्रष्ट cred को पूरी तरह से बायपास करता है। पेलोड पूर्ण रूट के रूप में चलता है और मनमाना संचालन कर सकता है।
स्टेज 4 में महत्वपूर्ण विंडो (पाइप बफर में दुर्भावनापूर्ण पॉइंटर्स लिखना, फिर सिग्नल डी-क्यू ट्रिगर करना) हार्डवेयर इंटरप्ट के लिए पाइप बफर पृष्ठ को प्रति-CPU पृष्ठ सूची से चुराने के लिए कमजोर है। यह QEMU में नहीं होता है। वास्तविक हार्डवेयर पर, इस विंडो को SCHED_FIFO प्राथमिकता (जब उपलब्ध हो) और sched_yield() के साथ संरक्षित किया जाता है ताकि महत्वपूर्ण खंड में प्रवेश करने से पहले CPU पर लंबित कार्य पूरा हो सके, साथ ही लेखन और ट्रिगर के बीच के समय को कम करने के लिए पहले से तैयार बफर सामग्री। शोषण तब भी सुचारू रूप से विफल हो जाता है जब SCHED_FIFO अनुपलब्ध हो (जैसे webOS पर जहाँ prisoner उपयोगकर्ता के पास CAP_SYS_NICE नहीं है)।
task_struct ऑफ़सेट रिवर्स इंजीनियरिंगमनमाना लेखन task_struct->cred को लक्षित करता है, जिसके लिए task_struct->pending (जिसका पता पाइप बफर से लीक होता है) से task_struct->cred तक बाइट ऑफ़सेट जानना आवश्यक है। यह ऑफ़सेट कर्नेल-कॉन्फ़िगर-निर्भर है। 0x80 (128 बाइट) ऑफ़सेट की गणना LG webOS कर्नेल स्रोत से मैन्युअल रूप से की गई, जिसमें CONFIG_KEYS=y, CONFIG_SYSVIPC=y, और ARM64-विशिष्ट स्ट्रक्ट लेआउट और संरेखण को ध्यान में रखा गया। मूल में x86_64 ऑफ़सेट अलग है क्योंकि अलग स्ट्रक्ट पैकिंग और कॉन्फ़िगर विकल्प हैं।
सफलता पर, शोषण:
/proc/sys/kernel/modprobe को init के रूप में एक रूटिंग पेलोड चलाने के लिए ओवरराइट करता हैaarch64-linux-gnu-gcc)# macOS (थर्ड-पार्टी टैप आवश्यक)
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu
# Ubuntu/Debian
sudo apt-get install gcc-aarch64-linux-gnu