2 पॉइंट द्वारा GN⁺ 2024-10-27 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Linux 6.10 का mseal exploit mitigation के लिए एक syscall है, जो running virtual memory areas को seal करता है, ताकि code execution अधिकार पा चुके attacker के लिए बाद में VMA permissions या layout बदलना मुश्किल हो जाए
  • mseal(start, len, flags) page-aligned VMA range पर VM_SEALED लगाता है, और kernel mprotect, munmap, mmap(MAP_FIXED), mremap और कुछ destructive madvise paths में बदलावों को reject करता है
  • मौजूदा memfd_create या memfd_secret जहां RAM-based anonymous files और secret memory access control के करीब हैं, वहीं mseal remote attacker द्वारा code execution के बाद permission changes, unmapping और remapping रोकने पर केंद्रित है
  • इसके प्रमुख defense targets हैं mprotect(PROT_EXEC) से NX bypass कर shellcode execute करने वाले attacks, और munmap/remapping से memory में holes बनाकर उन्हें attacker data से भरने वाले data-only exploits
  • glibc 2.41 के बाद integration संभव है, लेकिन stack और heap runtime में expand/shrink होते हैं, इसलिए वे automatic sealing के target नहीं हैं; developers को application का समय और scope सावधानी से तय करना होगा

mseal क्या protection देता है

  • memory sealing एक ऐसी capability है जो running VMA range को बाद में होने वाले खतरनाक modifications से लगभग immutable बना देती है
  • attacker code execution primitive हासिल कर भी ले, तो sealed VMA में virtual memory operations से permissions बदलना या layout को अपने पक्ष में manipulate करना मुश्किल होता है
  • Chrome Security team ने Linux-based ChromeOS में V8 CFI strategy को support करने के लिए यह syscall introduce किया
  • कई rounds की discussion और rewrites के बाद यह Linux kernel में शामिल हुआ, और glibc integration के जरिए इसका use browser के बाहर भी फैल सकता है

memfd family से अंतर

  • memfd_create और memfd_secret file sealing family के करीब हैं
    • RAM-based anonymous file बनाई जा सकती है
    • memfd_secret केवल file descriptor रखने वाली process को उस memory area तक access देता है
    • sensitive in-memory data को protect करने वाले “secure enclave” style user-space mappings में इसका उपयोग हो सकता है
  • mseal sensitive information leak करने वाले local attacker के बजाय, code execution के लक्ष्य वाले remote attacker के खिलाफ exploit mitigation के लिए tuned syscall है

Kernel के अंदर कैसे काम करता है

  • syscall signature int mseal(unsigned long start, size_t len, unsigned long flags) है
    • start और len seal की जाने वाली valid VMA की शुरुआत और length बताते हैं
    • len सही तरह से page-aligned होना चाहिए
    • अभी flags उपयोग में नहीं है और 0 होना चाहिए
  • Linux 6.12 के अनुसार implementation do_mseal को call करता है
    • current->mm calling process के पूरे virtual memory address space, यानी mm_struct, की ओर point करता है
    • mm_struct का mmap, mmap से बने contiguous memory regions यानी vm_area_struct की list रखता है
    • stack या VDSO जैसे areas भी एक VMA के रूप में represent हो सकते हैं
  • do_mseal range का end address calculate करने के बाद mmap_write_lock_killable से memory area lock करता है
  • check_mm_seal target range के हर VMA पर iterate करते हुए पहले boundary validity check करता है
    • range के बीच में unallocated memory हो तो -ENOMEM return करता है
    • यह first pass error आने पर केवल कुछ VMAs seal हो जाने वाली स्थिति से बचने के लिए है
  • apply_mm_seal उसी range पर दोबारा iterate करता है और mseal_fixup के जरिए target VMA में VM_SEALED flag जोड़ता है

Seal होने के बाद forbidden memory operations

  • kernel patchset ने VM_SEALED checks को mm/madvise.c, mm/mmap.c, mm/mprotect.c, mm/mremap.c, mm/mseal.c में add किया
  • mprotect और pkey_mprotect internally mprotect_fixup में can_modify_vma call करते हैं, और VMA sealed होने पर -EPERM return करते हैं
  • sealed VMA में ये operations allow नहीं होते
    • mprotect, pkey_mprotect के जरिए permission bits बदलना
    • munmap के जरिए unmapping
    • mmap(MAP_FIXED) के जरिए sealed mapping को mutable/unsealed mapping से replace करना
    • mremap के जरिए size expand या shrink करना
    • mremap(MREMAP_MAYMOVE | MREMAP_FIXED) के जरिए नए destination पर move करना
    • कुछ destructive flags के साथ madvise
  • mremap move में source और destination दोनों VMAs पर sealing check लागू होता है
  • MREMAP_DONTUNMAP न हो तो source VMA unmap होता है, और इस समय भी munmap sealing check pass करना जरूरी है
  • Linux 6.10 या बाद के versions में direct syscall call से mseal use किया जा सकता है, और example wrapper syscall number 462 और flags=0 का उपयोग करता है

NX hardening से shellcode execution रोकना

  • ROP जैसी code reuse techniques होने पर भी attacker shellcode execution पसंद कर सकता है
    • non-executable stack या heap में shellcode फैलाता है
    • vulnerability से initial ROP chain execute करता है
    • mprotect(PROT_EXEC) से shellcode वाले area का NX bit बंद करता है
    • उस area पर jump कर shellcode execute करता है
  • CVE-2018-7445 का इस्तेमाल करने वाला MikroTik RouterOS SMB daemon attack इस flow का example है
    • socket-based shellcode को non-executable heap में फैलाया गया
    • stack overflow से बनी ROP chain ने heap memory permissions बदलीं
    • इसके बाद shellcode execute किया गया
  • mseal से संबंधित VMA को seal करने पर mprotect call के समय can_modify_vma check permission change रोकता है
  • example code में, stack के shellcode page को seal नहीं करने पर mprotect(PROT_READ|PROT_WRITE|PROT_EXEC) के बाद execution संभव है
  • उसी page को mseal से seal करने पर mprotect वास्तविक permissions बदल नहीं पाता, और shellcode execution के समय segmentation fault होता है

Stack और heap पर लागू करने की सीमाएं

  • glibc 2.41 के बाद mseal introduce होने पर dynamic loader पहले से तय VMA set पर sealing apply करेगा
  • मौजूदा plan में stack और heap automatic रूप से seal नहीं होंगे
  • stack और heap runtime में expand हो सकते हैं, इसलिए automatic sealing application behavior तोड़ सकती है
    • heap allocator space reclaim करने के लिए brk syscall call कर सकता है
    • इस path में arch_unmap और do_vmi_unmap के जरिए shrink हो सकता है
    • sealed state में ऐसी unmapping allow नहीं होगी, जिससे dynamic memory allocation टूट सकता है
  • developers को application context के अनुसार तय करना चाहिए कि किस समय और किन areas पर sealing apply की जा सकती है
  • example macro selected stack frames के pages को बार-बार seal करता है, जिनमें untrusted data हो सकता है
  • पहले से sealed VMA पर फिर से mseal call करने पर उसे no-op की तरह handle किया जाता है और error नहीं आता
  • automatic stack expansion या stack splitting जैसी capabilities पर अलग से ध्यान देने की जरूरत है
  • attacker अगर shellcode पर अड़ा रहे तो नया executable area mmap कर सकता है और readable area से payload copy कर सकता है, लेकिन procedure ज्यादा cumbersome हो जाती है

Unmapping-based data-only exploit mitigation

  • mprotect block करना sealed area को writable state में बदलने से भी रोकता है, जिससे ऐसे data variables protect करने में मदद मिलती है जो modify होने पर exploit primitives को मजबूत कर सकते हैं
  • Chrome maintainers ने उस technique पर विचार किया जिसमें corrupted pointer को unmapping/remapping syscall में pass कर memory में hole punch किया जाता है और फिर attacker-controlled data से भरा जाता है
  • यह method stack return address या function pointer जैसे control-flow transfer को सीधे नहीं बदलता, इसलिए forward-edge और backward-edge CFI guarantees को bypass कर सकता है
  • JIT compiler implement करने वाले browsers में यह technique खास तौर पर useful हो सकती है
    • V8 का Turbofan RW और RX के बीच switch करने वाला area बना सकता है
    • attacker JIT compilation process में hot-path JavaScript से executable code generate करवा सकता है
    • unmapped area को भरकर important data overwrite कर सकता है और ऐसे changes बना सकता है जो code execution तक ले जाएं
  • यह data-only exploit है, जो direct control flow hijack या pointer leak की जरूरत के बिना memory के specific data को manipulate कर control flow पर असर डालता है
  • mseal unmapping और remapping को block कर ऐसे hole-punching scenarios रोक सकता है

House of Muney case

  • House of Muney user-space heap exploits में similar unmapping-based technique use करता है
  • Qualys ने पुराने Qmail bug के लिए real exploit में इस technique का उपयोग किया
  • यह technique इस behavior पर निर्भर करती है कि बड़े allocation chunks M_MAP_THRESHOLD से बड़े होने पर malloc और free क्रमशः direct mmap और munmap call करते हैं
  • बड़े chunks में intermediate freelist cache नहीं होता, जिससे exploit procedure simpler हो जाती है
  • allocation chunk के top पर size metadata को किसी दूसरे page size में tamper करने के बाद free करने पर chunk-adjacent memory area पर munmap हो सकता है
  • Dulin का example arbitrary munmap से .gnu.hash और .dynsym areas को target करता है
    • फिर उन्हें बड़े mmap chunk से दोबारा भरता है
    • अभी resolve न हुई PLT entry को overwrite करना संभव बनाता है
    • GOT overwrite style attack को फिर से जिंदा करता है
  • संक्षिप्त PoC दो बड़े chunks allocate करता है, top[-1] के size field को manipulate करता है, फिर free(top) से adjacent area तक unmap करता है, और बड़े allocation से X data फिर से भरता है
  • यह technique CFI होने पर भी काम कर सकती है, और पहले से ASLR leak की जरूरत नहीं होती
  • glibc के mseal integration में planned VMA set sealing से mapped binary code और dynamic libraries को unmapping/remapping tricks से protect कर इस attack को automatically mitigate करने की उम्मीद है
  • अतिरिक्त hardening चाहने वाले developers program lifetime के दौरान expand या unmap न होने वाले mmap allocations को selectively seal कर सकते हैं

आगे इसका उपयोग कहां तक जाएगा

  • mseal Linux kernel की अपेक्षाकृत नई mitigation capability है, और अभी और use cases हो सकते हैं जिन पर चर्चा नहीं हुई है
  • glibc integration complete और mature होने पर syscall की requirements के अनुसार improvements जारी रह सकते हैं
  • अभी unused flags parameter का भी future में specific use तय हो सकता है
  • real software में apply करते समय seal की जाने वाली memory की lifetime और बदलाव की जरूरत, दोनों का मूल्यांकन करना चाहिए

1 टिप्पणियां

 
GN⁺ 2024-10-27
Hacker News की राय
  • अच्छा होगा अगर कोई अंदरूनी व्यक्ति kernel mailing list की तीखी बहस में आई आपत्तियों और चिंताओं का सार बता दे
    mailing list खुद कभी-कभी बहुत तीखी हो जाती है, इसलिए मैं उससे बचता हूँ, और वैसे भी सिरदर्द पहले से काफी है
    mechanism खुद तो वाजिब लगता है, लेकिन यह हैरानी की बात है कि kernel में ऐसी functionality पहले से नहीं थी

    • लिंक किए गए thread के अलावा और कुछ था या नहीं, पता नहीं, लेकिन कुल मिलाकर यह Linus-स्टाइल सीधी बात थी
      प्रस्तावित flags में एक ऐसा था जिससे seal को ignore किया जा सकता था, और Linus ने कुछ इस तरह प्रतिक्रिया दी कि “एक जगह तो आप munmap रोकना चाहते हैं, लेकिन दूसरी जगह seal को ignore करना चाहते हैं?”
      इसके बाद उन्होंने और सख्ती से कहा कि “एक बार seal हो गया तो seal हो गया”, और ऐसा नहीं चलेगा कि “कुछ जगह seal माना जाए और मनमानी दूसरी जगहों पर न माना जाए”
      बाद में तो उन्होंने यहां तक कहा कि seal को ignore नहीं किया जा सकता और यह negotiation का विषय नहीं है; अगर flag से seal ignore करने के और प्रस्ताव आए तो उन्हें ignore list में डाल देंगे
    • https://lwn.net/ml/linux-kernel/7071.1697661373@cvs.openbsd....
      Theo de Raadt ने Jeff Xu को भेजे email में, इस बात पर कि mimmutable() और mseal() के approaches अलग हैं लेकिन दोनों का लक्ष्य attacker से memory को seal करके Linux applications को अधिक सुरक्षित बनाना है, जवाब दिया कि “लगता है आप सिर्फ Chrome के लिए mseal बना रहे हैं”
      उनका मानना था कि यह applications के व्यापक दायरे में ठीक नहीं बैठेगा; वजह के तौर पर उन्होंने कहा कि यह बहुत complex है और mimmutable() के अनुभव में applications इसे सीधे handle नहीं करतीं, बल्कि execve(), libc initialization और ld.so इसे संभालते हैं
    • Matthew Wilcox ने भी Jeff Xu को कड़े अंदाज में जवाब दिया, कुछ इस तरह कि “यह दिखाने के लिए धन्यवाद कि आपको पता नहीं कि क्या रोकना चाहिए”
      वे Theo और Linus से सहमत थे, और उनका मानना था कि mimmutable() का मूल idea अच्छा है, लेकिन इसे जिस तरह बांटा और implement किया गया है वह बेहद खराब है
    • यह लेख मदद कर सकता है: https://lwn.net/Articles/948129/
  • मुझे उत्सुकता है कि इस system call का इस्तेमाल कैसे किया जाता है
    Chrome इसे चाहता है, लेकिन attacker दूसरे flags के साथ फिर से map कर सकता है, इसलिए sealed page को unmap नहीं किया जा सकता
    तो क्या runtime पर allocate किए गए pages के लिए, अगर उन्हें process की पूरी lifetime तक रखने का इरादा न हो, तो यह practically usable नहीं है?
    अगर ऐसा है, तो JS sandbox memory जैसे बहुत आकर्षक target पर इसे लागू करना मुश्किल नहीं होगा?
    उत्सुकता है कि क्या इस तरह का काम अलग process में चलाकर, memory seal करके और काम खत्म होने पर process को kill करके solve किया जाता है
    मैं Chrome की memory और process management को अच्छी तरह नहीं जानता, इसलिए समझ नहीं पा रहा कि यह समस्या क्यों नहीं है; और क्या यही वजह है कि अक्सर कहा जाता है कि यह feature ज्यादातर programs के लिए उपयोगी नहीं है

    • यहाँ multi-process एक विकल्प हो सकता है
      मेरी जानकारी में Chrome इसका बड़े पैमाने पर इस्तेमाल करता है, और namespaces के जरिए isolation जैसी वजहों से अलग process वैसे भी जरूरी होता है, इसलिए दिशा वही हो सकती है
  • mseal() के बाद की चर्चा, 20 अक्टूबर 2023: https://lwn.net/Articles/948129/
    mseal() करीब आ रहा है, 19 जनवरी 2024: https://lwn.net/Articles/958438/
    GNU C Library के लिए memory sealing, 12 जून 2024: https://lwn.net/Articles/978010/

  • आधुनिक x86_64 architecture में secure programming और computing में मदद करने वाली इतनी सारी सुविधाएँ हैं, फिर भी operating system को ऐसी calls implement करनी पड़ें, यह अफसोस की बात है
    मेरा मानना है कि पुरानी legacy और सोच, तथा आज की दुनिया और ज्ञान से मेल न खाने वाले paradigms पर बने पुराने systems को patch करते रहने का रवैया computing की प्रगति को धीमा करता है और सचमुच अरबों लोगों को खतरे में डालता है
    बेशक मैं यह नहीं कह रहा कि यह बदलाव सही दिशा में कदम नहीं है, लेकिन अगर हम operating system को किस तरह काम करना चाहिए वाले पुराने आदर्श को छोड़कर मौजूदा systems, ज्ञान, और लोग systems से क्या चाहते हैं, इन सबको ध्यान में रखें, तो आज developers और users पर डाले गए बोझ और जोखिम से मुक्त systems की कल्पना कर सकते हैं
    architecture bugs मौजूद हैं, यह सही है, लेकिन software मौजूदा features का भी सही इस्तेमाल नहीं कर पा रहा, इसलिए architecture bugs का हवाला देकर विरोध करना असल मुद्दे से भटकना है
    अगर नींव ही डगमगाती हो, तो breach का सस्ता तरीका हमेशा मौजूद रहेगा

    • जिज्ञासा है: x86_64 में ऐसे कौन से unused या कम-used safety features हैं जिन्हें operating system के इन्हें इस्तेमाल या enable करने के तरीके के बिना इस्तेमाल किया जा सकता है, यह बता सकें तो अच्छा होगा
      यह भी जानना चाहूँगा कि आप mseal को justified क्यों नहीं मानते, और उसकी जगह क्या बेहतर होगा
  • LD_PRELOAD ट्रिक से क्या mseal system call को overwrite या disable किया जा सकता है?

    • mseal, Linux की मौजूदा memory protection विधियों से अलग, memory के अंदर मौजूद संवेदनशील secrets निकालने की कोशिश करने वाले local attacker के बजाय remote code execution attack mitigation पर केंद्रित system call है
      अगर remote attacker local environment बदल सकता है, तो मानना चाहिए कि वह पहले ही system में घुस चुका है
    • शायद LD_PRELOAD से यह संभव नहीं होगा
      असर होने के लिए वह imported function होना चाहिए, लेकिन raw system calls को इस तरह intercept नहीं किया जा सकता
      Linux system call interception पर चर्चा: https://stackoverflow.com/questions/69859/how-could-i-interc...
      ऐसा patched kernel खुद बनाना, जो mseal के काम करने का नाटक करे, इस feature को “disable” करने का सबसे आसान तरीका हो सकता है
      हालांकि mseal इस्तेमाल करने वाला program यह verify कर सकता है कि वह सच में काम कर रहा है या नहीं, इसलिए compromised kernel को deployment के बाद app की checks रोकने के लिए mseal को चुपचाप disable करने का तरीका भी चाहिए होगा
    • अगर process की शुरुआत में control हो, तो overwrite करने के काफी तरीके हैं
      उदाहरण के लिए executable को ptrace से trace करके system calls monitor किए जा सकते हैं और mseal(2) को skip कराया जा सकता है
      यह system call उस threat model के लिए नहीं है जिसमें “attacker के पास process initialization से पहले ही access था”
    • mseal call wrapper को overwrite किया जा सकता है, लेकिन system call itself को overwrite नहीं किया जा सकता
      देखने पर लगा कि preload-based system call overwrite के सभी तरीके wrapper बदलने वाले हैं, और direct system call करने पर शायद overwrite नहीं किया जा सकेगा
      technically, शायद syscall function itself को overwrite किया जा सके
    • https://lwn.net/Articles/978010/ के अनुसार glibc tunable आने वाला है
  • Meta: लेख में दिया गया mseal() prototype edit करने की जरूरत है
    पहला argument unsigned start addr के रूप में दिखाया गया है, शायद unsigned long start_addr सही होगा

    • अभी ठीक दिख रहा है: int mseal(unsigned long start, size_t len, unsigned long flags)
  • “Memory Sealing ‘Mseal’ System Call Merged for Linux 6.10” (2024) https://news.ycombinator.com/item?id=40474510#40474551 में CPython को mseal() system call कैसे support करना चाहिए इस पर पहले ही चर्चा हो चुकी है

  • OpenBSD में यह feature काफी पहले से था https://man.openbsd.org/mimmutable.2
    सोचने वाली बात है कि इतना obvious feature Linux में अब जाकर क्यों आ रहा है

    • OpenBSD का mimmutable, 10 अप्रैल 2023 को release हुए OpenBSD 7.3 में introduce हुआ था, इसलिए “काफी पहले से” कहना सही नहीं है
      दूसरी ओर Linux और FreeBSD में memfd_create काफी समय से था, और OpenBSD में anonymous files नहीं हैं, इसलिए वह shm_open पर निर्भर करता है