- Linux kernel
nf_tablesमें CVE-2024-1086 Netfilter verdict input validation की विफलता के कारणsk_buffdouble-free बनाता है, और सही conditions में local privilege escalation तक ले जा सकता है - attack flow में
NF_DROPprocessing के दौरान freed skb कोNF_ACCEPTकी तरह processing जारी रखने के लिए मजबूर किया जाता है, जिससे वही object बाद के path में फिर से free हो जाता है - PoC को KernelCTF mitigation, Debian, Ubuntu और vanilla kernels पर verify किया गया है; कम से कम v5.14.21~v6.6.14 range kconfig के हिसाब से प्रभावित हो सकती है, और February 2024 में stable branches में fix rollout हुआ
- core technique Dirty Pagedirectory है: PTE और PMD pages को एक ही physical page पर overlapping allocate करके user-space read/write से ही arbitrary physical addresses तक access करने वाली data-only KSMA method
- physical KASLR discovery,
modprobe_pathbypass, fileless execution, और namespace escape के लिए file descriptor bridging—इन सबको जोड़कर यह kernel memory management और network subsystem दोनों को target करने वाला practical LPE case बनता है
vulnerability conditions और impact range
nf_tablesbug CVE-2024-1086 के रूप में registered है; Linux kernel Netfilter के verdict handling में positive drop error allow करने वाली input validation failure इसकी core issue है- exploit के लिए ये conditions चाहिए
nf_tablesenabled होना चाहिए- unprivileged user namespace enabled होना चाहिए
- Debian और Ubuntu जैसे major distributions में यह setting default enabled होने पर attack संभव माना जाता है
- testing के आधार पर stable branches
linux-5.15.y,linux-6.1.y,linux-6.6.yप्रभावित range में हैं, औरlinux-6.7.1की भी संभावना है - February 2024 में stable branches में bug fix rollout हुआ
- PoC source code CVE-2024-1086 PoC repository में public है
double-free बनने का code flow
- Netfilter verdict वह value है जो तय करती है कि packet drop करना है, accept करना है, queue में भेजना है आदि
- vulnerable flow इस बात से शुरू होता है कि
nft_verdict_init()user input verdict value को पर्याप्त रूप से restrict नहीं करता था, इसलिए ऐसी value set की जा सकती थी जोNF_DROPजैसी दिखे लेकिन जिसका drop error positive हो nf_hook_slow()verdict के lower bits देखकर अगर उसेNF_DROPमानता है, तोkfree_skb_reason()से skb को पहले free कर देता है- इसके बाद अगर
NF_DROP_GETERR()का resultNF_ACCEPTके बराबर value के रूप में return होता है, तो caller side packet को accepted मानकर processing जारी रखती है - नतीजतन already freed skb बाद के path में फिर free होता है और double-free primitive बनता है
corrupted objects और packet processing method
- double-free
skbuff_head_cacheकेstruct sk_buffऔरsk_buff->headobjects को affect करता है sk_buff->headactual packet contents रखता है, और IPv4 packet size के हिसाब सेkmalloc-256से लेकर buddy allocator के order 4 page तक allocate हो सकता है- PoC बड़े IP packets का इस्तेमाल करके slab allocator के बजाय buddy allocator path में जाने के लिए design किया गया है
- IPv4 fragmentation queue skb की दूसरी free को delay करने या desired moment पर trigger करने के लिए इस्तेमाल होती है
- packet path में corrupted skb fields इस्तेमाल हों तो kernel panic हो सकता है, इसलिए TCP/UDP stack से बचकर specific IP fragment error path का उपयोग किया जाता है
test range और success rate
- vanilla kernel, KernelCTF, Debian, Ubuntu environments में कई kernel versions और settings test किए गए
- successful cases में ये environments शामिल हैं
- Linux v5.14.21, v5.15.148, v5.16.20, v5.17.15, v5.18.19, v5.19.17, v6.0.19
- KernelCTF Mitigation v3 का Linux v6.1.55
- Debian Bookworm 6.1.0-17 का Linux v6.1.69
- KernelCTF LTS का Linux v6.1.72
- Ubuntu Jammy v6.2.0-37
- Linux v6.2.16, v6.3.13
- failed cases में v5.4.270, v5.10.209, v6.4.16, Ubuntu Jammy v6.5.0-15, v6.5.13, v6.6.14, v6.7.1 आदि शामिल हैं
- v6.4.0 के बाद कुछ failures
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=yके कारण bad_page() detection से जुड़े हैं - v6.4.16 environment में success rate 99.4% था, और कुछ cases में 93.0% तक गिरा; sample size दोनों में n=1000 था
fix method
- initially proposed fix Netfilter stack के बीच में breaking change बना सकता था
- Netfilter maintainer के fix ने user input से आने वाले verdict को API stage पर अधिक strictly restrict किया
- patch userland input के लिए DROP/QUEUE verdict parameter reject करने की approach अपनाता है
- CVE description के अनुसार
nft_verdict_init()hook verdict के अंदर drop error के रूप में positive values allow करता था, औरnf_hook_slow()ऐसी situation में double free बना सकता था जहाँNF_DROPऔरNF_ACCEPToverlap करते हैं - fix patch [PATCH nf] netfilter: nf_tables: reject QUEUE/DROP verdict parameters. में देखा जा सकता है
Dirty Pagedirectory और arbitrary physical memory access
- PoC की central technique Dirty Pagedirectory है, जो existing Dirty Pagetable technique का variant है
- core idea PTE page और PMD page को same physical page पर duplicate allocate करना है
- जब एक virtual address region में PTE value जैसी दिखने वाली value लिखी जाती है, तो दूसरा virtual address region इसे page table entry के रूप में interpret करके specified physical page को map करता है
- यह method user-space address read/write से ही arbitrary physical addresses और permission flags set करके access करने वाले kernel-space mirroring attack की तरह काम करता है
- इसका उपयोग virtual KASLR, KPTI, SMAP, SMEP,
CONFIG_STATIC_USERMODEHELPERजैसी mitigations bypass करने में होता है
page allocator manipulation
- kernel page allocation में slab allocator, buddy allocator, और PCP allocator शामिल होते हैं
- बड़े size में skb head buddy allocator के order 4 page का इस्तेमाल करता है, लेकिन PTE/PMD pages order 0 pages होते हैं, इसलिए सीधे match नहीं होते
- इसे solve करने के लिए दो page conversion methods इस्तेमाल होती हैं
- PCP list draining: order 4 page को buddy freelist में डालना, और PCP order 0 freelist को खाली करना ताकि buddy allocator से order 0 pages refill हों
- race condition: second free के दौरान race का उपयोग करके order 4 page को order 0 freelist में डालने की method
- PCP list draining ज्यादा simple, stable और fast तरीका है
- race condition method KernelCTF के initial exploit में इस्तेमाल हुआ था, लेकिन QEMU VM जैसे serial TTY delay ज्यादा वाले environments पर depend करने के कारण obsolete माना गया
KernelCTF mitigation bypass
- KernelCTF mitigation environment में जिसे actively bypass करना पड़ा वह mitigation
sk_bufffreelist corruption check था skbuff_head_cache->offset == 0x70होने से freelist next pointerskb->lenके साथ overlap करता है- पहले skb free के बाद
skb->lenfreelist pointer के हिस्से से overwritten हो जाता है, और बाद में packet parsing के दौरान यह value बदलने से corruption check trigger हो सकता है - corrupted skb के ऊपर एक normal skb को अतिरिक्त free करके freelist head overwrite करने के तरीके से detection bypass किया जाता है
- KernelCTF developer के अनुसार free के समय भी freelist head next pointer check किया जाए तो इस bypass को mitigate किया जा सकता है
TLB flush और physical KASLR discovery
- Dirty Pagedirectory से page table को unexpected तरीके से बदलने पर CPU के TLB cache में stale translation information बची रह सकती है
- user space में
fork()के बाद child द्वाराmunmap()चलाकर और sleep में जाने की method से TLB flush किया जाता है - यह method AMD CPUs और QEMU VMs पर 100% काम करती हुई verify की गई
- physical KASLR में kernel physical base address
CONFIG_PHYSICAL_STARTयाCONFIG_PHYSICAL_ALIGNपर aligned होता है—इस fact का उपयोग search range घटाने में किया जाता है - 8GiB physical memory और 16MiB alignment मानने पर 512 candidates बनते हैं, और get-sig script से kernel base signature generate करके identify किया जाता है
modprobe_path और root shell हासिल करना
- arbitrary physical memory read/write मिलने के बाद, PoC kernel base के बाद करीब 80MiB range scan करके
modprobe_pathढूंढता है - normal configuration में
"/sbin/modprobe"और null padding pattern ढूंढा जाता है, और/proc/sys/kernel/modprobeमें reflection से actual variable verify किया जाता है CONFIG_STATIC_USERMODEHELPERenabled होने पर"/sbin/usermode-helper"string को target बनाया जाता है- root shell हासिल करने के लिए
modprobe_pathया static usermode helper string को/proc/<pid>/fd/<fd>format वाले memfd path से overwrite किया जाता है - privilege escalation script exploit के file descriptor को shell के stdin/stdout से connect करती है ताकि यह local terminal और reverse shell दोनों में काम करे
fileless execution और PoC structure
- PoC disk पर file लिखे बिना fileless execution support करता है
- target पर Perl हो तो
memfd_create()का उपयोग करके exploit binary को memory में load कर/proc/$$/fd/<fd>से execute किया जा सकता है - compilation dependencies
libnftnl-devऔरlibmnl-devहैं - KernelCTF के लिए static build में
musl-gccइस्तेमाल हुआ; यह glibc static linking और QEMU AVX512 opcode problem से बचने के लिए चुना गया था - exploit source कई files में divided है, और standalone binary उद्देश्य होने के कारण error आने पर error code return करने के बजाय crash/exit approach चुनता है
stability और limitations
- exploit process की pagetable state unstable हो सकती है, इसलिए success या failure के बाद child process को terminate किए बिना sleep state में छोड़ा जाता है ताकि kernel instability कम हो
- network activity होने पर skb freelist में noise बनता है, जिससे stability affect हो सकती है
- SSH या reverse shell environments में double-free timing के आसपास stdout output घटाया जाता है, ताकि network की वजह से skb allocation/free कम से कम हों
- कुछ hardware tests में system कुछ seconds बाद crash हो गया, और WiFi frames भी skb use करते हैं—इसलिए WiFi activity का असर पड़ा हो सकता है
- BIOS में WiFi adapter disable करने पर उस environment में exploit ने सही काम किया
research process से निकले conclusions
- PoC को broad compatibility, high stability, और stealth execution के लक्ष्य से refine किया गया
- development में 2 months लगे, और stability तथा compatibility improvements पर अतिरिक्त 2 months लगाए गए
- exploit खुद slab allocator behavior पर बहुत अधिक depend नहीं करता और IPv4 subsystem तथा virtual memory जैसी widely enabled features के इर्द-गिर्द बना है
- initial bug के लिए unprivileged user namespace और nftables चाहिए, लेकिन Dirty Pagedirectory और PCP draining जैसी techniques दूसरे real-world exploits में भी इस्तेमाल हो सकती हैं
- यह काम Linux kernel के networking subsystem और memory management subsystem दोनों को गहराई से analyze करने वाले case के रूप में रहेगा
1 टिप्पणियां
Hacker News की रायें
आज CVE-2024-1086 का proof-of-concept exploit जारी किया गया, और यह Debian व Ubuntu आदि पर काम करता है
प्रभावित versions Linux kernel v5.14~v6.6 हैं, और v6.4~v6.6 का support
CONFIG_INIT_ON_ALLOC_DEFAULT_ONkernel setting पर निर्भर करता हैयह bug फरवरी 2024 में patch हो चुका है, इसलिए Linux machines को update करना चाहिए
https://github.com/Notselwyn/CVE-2024-1086/blob/main/src/mai...
modprobe_pathतरीका क्यों इस्तेमाल किया गया और fileless तरीके की वजह से pid brute force तक क्यों जोड़ा गयाउदाहरण के लिए, kernel
.textको छोटे shellcode से patch करके root बनने और namespace से बाहर निकलने का तरीका क्यों नहीं चुना गया—यह पूछना चाहूंगाहालांकि उसमें लिखा है कि patched branches
v5.15.149>,v6.1.76>,v6.6.15>इससे बाहर हैंpatch में यह वाक्य है: “This reverts commit e0abdadcc6e1. [...] Its not clear to me why this commit was made.”
क्या किसी ने इस commit का background history ढूंढा है, यह जानना चाहूंगा
[1] https://lore.kernel.org/all/20240120215012.129529-1-fw@strle...
पुराने netdev list में खोजा, लेकिन कुछ नहीं मिला, और यह संभव है कि यह सीधे committer Pablo Neira Ayuso को भेजा गया patch रहा हो
original author Patrick McHardy थे, जो अब persona non grata बन चुके हैं, और जब तक Pablo को याद न हो या वे mail में न ढूंढ लें, basic investigation से सही use case सामने आना मुश्किल लगता है
netfilter: nf_tables: accept QUEUE/DROP verdict parameters, जिसमें user space कोQUEUEऔरDROPverdicts के लिए queue number या errno code specify करने की अनुमति दी गई थीयह लेख security writing के नजरिए से भी बहुत प्रभावशाली है
security blog लिखते समय हमेशा दुविधा रहती है कि “कितना background knowledge और prior knowledge मानकर चलें”; accessible और लिख पाने योग्य balance बनाना कठिन है
इसमें target readers को पहले तय करके पर्याप्त background explanation दिया गया है, जो बेहतरीन है, इसलिए मैंने इसे bookmark किया है ताकि हर साल मिलने वाले aspiring researchers को guide material के रूप में दे सकूं
यह exploit unprivileged user namespace access पर निर्भर है:
sysctl kernel.unprivileged_userns_clone = 1यह Debian/Ubuntu और Arch Linux kernels का default है, और अगर sudo के बिना Docker commands चलाने जैसी जरूरत नहीं है तो इसे बंद रखना बेहतर है
Electron apps या 1Password जैसी जगहों में इस्तेमाल होने वाला Chrome sandbox भी इससे जुड़ा है, और sandbox helper binary setuid program के रूप में भी काम कर सकती है
अगर Proton भी आगे चलकर user namespaces इस्तेमाल करना शुरू करे तो हैरानी नहीं होगी, इसलिए सामान्य desktop Linux में इसे बंद न रखना बेहतर हो सकता है
servers या खास तौर पर hardened Linux में इसे बंद रखना अक्सर बुरा विकल्प नहीं होता
समस्या यह है कि containers को “बस चलाने” के लिए networking side पर ढेर सारे hacks चाहिए होते हैं, और Docker का core selling point भी लगभग यही है कि वह आपके लिए वे खतरनाक hacks कर देता है
अंततः कोई भी container solution ऐसे hacks को स्वीकार करता है, और भले ही normal namespace features access घटाते हों, kernel networking hacks की वजह से दरवाजा खोल देता है
समझ नहीं आता कि unprivileged user namespaces default रूप से on क्यों हैं
भले ही वे “unprivileged” namespace के अंदर चलते हों, मूल रूप से user को iptables या mount जैसी चीजें चलाने की क्षमता देने की वजह क्या है, यह सवाल है
उदाहरण के लिए Chrome process sandbox implement करने के लिए namespaces इस्तेमाल करता है, लेकिन unprivileged namespaces के बिना भी काम हो सके इसलिए setuid-root binary install करता है
setuid-root binary खुद security risk है, इसलिए long term में बेहतर यही है कि Chrome को ऐसी binary install न करनी पड़े
हालांकि इसके लिए unprivileged user namespaces का व्यापक रूप से उपलब्ध होना जरूरी है, और ऐसे bugs उस भविष्य को धीमा कर देते हैं
साथ ही Chrome जैसे programs, जो namespace-based sandbox बनाते हैं, अक्सर seccomp भी साथ में इस्तेमाल करते हैं, ताकि sandbox के अंदर का code namespaces जैसे असामान्य kernel features इस्तेमाल न कर सके
single-user desktop पर user और root के बीच separation को सख्ती से लागू करने का फायदा बहुत बड़ा नहीं होता, और ज्यादातर दिलचस्प चीजें user account से भी accessible होती हैं
दूसरी ओर Chrome जैसे sandboxes desktop security के लिए जरूरी हैं, इसलिए single-user desktop पर unprivileged user namespaces on रखना overall security बढ़ाता है—ऐसा मानना बेहतर है
multi-user systems की बात जाहिर है अलग है
अगर ऐसे bugs लगातार न आते, तो unprivileged user namespaces एक शानदार security feature होते
उदाहरण के लिए, अच्छा होता अगर Flatpak चलाने के लिए app isolation हेतु host के setuid binaries की ज़रूरत न पड़ती
ज़्यादातर defaults सुरक्षित नहीं होते, और technical knowledge व hardening work की ज़रूरत पड़ती है
समस्या लाने वाला commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
nested
switch/caseमें default path परreturnहै, जबकि उसके बाद fall-through की उम्मीद रखने वाली संरचना अजीब लगती हैhttps://lwn.net/Articles/882397/
https://bugs.launchpad.net/bugs/cve/2024-1086
Linux kernel के
netfilter: nf_tablescomponent में मौजूद use-after-free vulnerability से local privilege escalation संभव हैnft_verdict_init()function hook verdict के भीतर drop error के रूप में positive values की अनुमति देता है, और इसके परिणामस्वरूपnf_hook_slow()NF_ACCEPTजैसा दिखने वाले drop error के साथNF_DROPको process करते समय double-free vulnerability पैदा कर सकता हैf342de4e2f33e0e39165d8639387aa6c19dff660के बाद के version पर upgrade करने की सलाह दी जाती हैASLR जैसी modern mitigations होने के बावजूद ऐसे exploits कैसे संभव होते हैं, यह सोचने वाली बात है
university class में एक assignment किया था, जिसमें एक खास Ubuntu version पर चलने वाले कई binaries मिले थे, और use-after-free या buffer overflow जैसे bugs ढूंढकर exploit करना था; यह सचमुच कठिन था
flaw ढूंढना भी मुश्किल था, और उस flaw से कोई उपयोगी काम कराने वाला सटीक shellcode लिखना उससे भी कठिन था
ज्यादा कठिन चरणों में ASLR, stack canary जैसी mitigations भी enable थीं, और controlled student environment में भी यह लगभग असंभव जैसा लगा
आखिरकार 1) exploit करने योग्य flaw ढूंढना और 2) program को बस crash किए बिना कोई उपयोगी काम करने वाला सटीक binary payload खोजना पड़ता है; real world में तो यह और कठिन होगा, फिर यह कैसे संभव है, यह सवाल है
[0] https://web.stanford.edu/class/archive/cs/cs107/cs107.1194/a...
दूसरी classes के साथ-साथ, एक bug पर खर्च कर सकने वाला समय शायद कुछ घंटों से कुछ दिनों तक रहा होगा
Zerodium सामान्य Linux local privilege escalation के लिए 50,000 डॉलर देता है, जो skilled exploit developer की लागत के हिसाब से लगभग 200 person-hours खरीद सकता है
यानी experts beginner students की तुलना में 10–100 गुना अधिक समय लगा रहे होते हैं
इसे ऐसे समझें जैसे पहली बार woodworking shop में जाने वाले व्यक्ति और carpenter, pottery beginner और master craftsman, या नए painter और professional artist के बीच का फर्क
ऊपर से समय भी 10–100 गुना अधिक लग रहा होता है
[1] https://zerodium.com/program.html
ज़्यादातर latest protection mechanisms को bypass करने की “classic” techniques हैं, और अगर नहीं हैं तो नए attacks या bypass methods निकल आते हैं
उदाहरण के लिए heap protection bypass के लिए how2heap देख सकते हैं[0], KASLR bypass exploit के उदाहरण भी रहे हैं[1], और यह exploit dirty pagetable technique इस्तेमाल करता दिखता है[2]
mitigations जुड़ती रहती हैं और researchers उन्हें bypass करते रहते हैं—यह लगातार चलने वाला cat-and-mouse game है
[0] https://github.com/shellphish/how2heap
[1] https://www.willsroot.io/2022/12/entrybleed.html
[2] https://pwning.tech/nftables/#452-the-technique
ऐसी चीज़ खोजने के लिए आखिरी वाली श्रेणी का एक व्यक्ति ही काफी है
आजकल यह सचमुच कठिन है, और mitigations बंद कर दें तब भी vulnerability ढूंढना और exploit लिखना आसान नहीं है
लेकिन ऐसी vulnerabilities खोजने वाले कई लोग teams में काम करते हैं, fuzzing को parallelize करते हैं, और knowledge व दूसरे exploits को combine या chain कर सकते हैं
कुछ researchers की expertise और talent हैरान करने लायक होती है, और इस field में वर्षों से लेकर दशकों तक का experience बहुत बड़ी value रखता है
लेकिन अगर मानें कि आजकल मिल रहे major bugs अच्छी funding वाली teams या state actors द्वारा खोजे जाते हैं, तो यह ज्यादा समझ में आता है कि वे बड़ी मात्रा में manpower और resources लगाकर existing mitigations को bypass कर सकते हैं
Ubuntu के अनुसार सभी LTS releases प्रभावित हैं, और currently patched kernels में fix हो चुके हैं: https://ubuntu.com/security/CVE-2024-1086
Focal में
5.4.0-174.193, Jammy में5.15.0-101.111, Mantic में6.5.0-26.26पर fix हुआअगर extended support इस्तेमाल कर रहे हैं, तो Xenial और Bionic भी शामिल हैं
एक vulnerable Debian सिस्टम पर इसे चलाकर देखा; privilege escalation तो नहीं हुआ, लेकिन दूसरे run में पूरा सिस्टम hang हो गया
पहला run बस fail हुआ था, इसलिए फिर भी patch करने में समय लगाना पूरी तरह worthwhile है
मौजूदा kernel settings को
/boot/configया/proc/config.gzजैसी files में देखा जा सकता है