1 पॉइंट द्वारा GN⁺ 2024-01-27 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • rhboot/shim के commit 0226b56 ने CVE-2023-40547 को fix किया, जो file receive करने की प्रक्रिया में HTTP header के size value पर सीधे भरोसा करने से पैदा हुआ था
  • अगर manipulated header असल received data से छोटा size specify करता है, तो shim ज़रूरी buffer से कम space allocate कर सकता है
  • पुराने code में allocation के लिए header value और copy के लिए protocol metadata इस्तेमाल किया जाता था, जिससे out-of-bounds write हो सकता था
  • patch ने httpboot.c के receive_http_response() में *buf_size < rx_message.BodyLength check जोड़ा, और fail होने पर इसे EFI_BAD_BUFFER_SIZE और Invalid Content-Length के रूप में handle किया
  • बदलाव का scope httpboot.c की 1 file में 7 lines added और 1 line deleted है, और Content-Lenght typo को भी Content-Length में सुधारा गया

Vulnerability होने का flow

  • CVE-2023-40547 एक issue है जो तब होता है जब shim HTTP या related protocols से file fetch करता है
  • received data store करने के लिए buffer allocate करते समय HTTP header का size value इस्तेमाल किया जाता है
  • HTTP header manipulate किया जा सकता है, और वह असल received data से छोटा size specify कर सकता है
  • पुराने flow में buffer allocation के लिए header value इस्तेमाल होती थी, और rx buffer से data copy करते समय basis protocol metadata होता था
  • इस difference के कारण allocated buffer से बड़ा data copy हो सकता था, और परिणामस्वरूप out-of-bounds write हो सकता था

Patch details

  • patch ने httpboot.c के receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) में defensive check जोड़ा
  • जब *buf_size == 0 हो, तो existing error message का typo ठीक करता है और goto error पर जाता है
    • Failed to get Content-LenghtFailed to get Content-Length
  • नया check *buf_size < rx_message.BodyLength condition verify करता है
    • अगर condition true है, तो efi_status = EFI_BAD_BUFFER_SIZE set करता है
    • Invalid Content-Length error output करता है
    • इसके बाद goto error पर जाता है

Change scope

  • बदली गई file सिर्फ httpboot.c है
  • बदलाव की मात्रा 7 lines added, 1 line deleted है
  • core logic यह check करना है कि received body length rx_message.BodyLength, allocation size *buf_size से बड़ा है या नहीं

Related records

  • यह commit CVE-2023-40547 को resolve करने वाला change बताया गया है
  • commit message साफ बताता है कि issue HTTP header पर गलत भरोसे से आया था
  • vulnerability reporter Microsoft Security Response Center के Bill Demirkapi दर्ज हैं

1 टिप्पणियां

 
GN⁺ 2024-01-27
Hacker News की राय
  • shim एक EFI bootloader है, जिसे Secure Boot चालू करना चाहने वाले Linux distributions में आम तौर पर इस्तेमाल किया जाता है
    distribution के नज़रिए से वे चाहते हैं कि user खुद key register करने के बजाय, पहले से मौजूद Microsoft-signed key के साथ Secure Boot आसानी से चालू कर सके
    लेकिन Microsoft आम तौर पर GRUB जैसे GPL bootloaders को sign नहीं करता, इसलिए ऐसा shim बनाया गया जिसे Microsoft key से sign किया जा सके, और shim अपने boot target के signature को Machine Owner Key, यानी MOK, नाम की अलग key से verify करता है
    shim में boot करने के लिए EFI binary specify करते समय HTTP URL दिया जा सकता है, और इस स्थिति में अगर HTTP server malicious हो तो out-of-bounds write कराया जा सकता है
    हालांकि आम तौर पर इसका इस्तेमाल GRUB जैसे local second-stage bootloader को boot करने के लिए होता है, इसलिए ज़्यादातर installs में इसके समस्या बनने की संभावना कम लगती है
    Secure Boot को शुरू से ही ऐसा design किया गया था कि पहले से signed binaries को भी DBX list के जरिए revoke किया जा सके, और इस list को UEFI में डालने पर valid signature होने के बावजूद वह binary reject कर दी जाती है
    अगर इस bug वाले पुराने shim binaries के signatures list में जोड़ दिए जाते हैं, तो लोग अपने-अपने devices पर list update कर सकते हैं; यह LVFS जैसे capsule updates के रूप में distribute भी हो सकती है, और अगर आप Secure Boot keys और variables सीधे manage करते हैं, तो https://uefi.org/revocationlistfile से list download करके register भी कर सकते हैं

    • मैं original post में bug खोजने वाला व्यक्ति हूं, और यह एक आम गलतफहमी है कि यह issue सिर्फ HTTP booting इस्तेमाल करने पर ही exploit किया जा सकता है
      अगर ऐसा होता तो इसे Critical rating नहीं मिली होती
      इस bug को local privileged malware द्वारा EFI partition overwrite किए जाने पर, PXE booting enabled वाले adjacent network में man-in-the-middle attack के दौरान, और HTTP booting इस्तेमाल करते समय remote man-in-the-middle attack से exploit किया जा सकता है
      अगर कोई unprivileged remote attacker man-in-the-middle position में है और victim machine HTTP booting इस्तेमाल करती है, तो direct access के बिना भी इसे exploit किया जा सकता है
      अगर remote attacker ने victim machine पर privileges और code execution हासिल कर लिया है, तो victim HTTP booting न भी इस्तेमाल करे, लेकिन firmware HTTP support करता हो, तब भी वह Secure Boot bypass कर सकता है
      उदाहरण के लिए, boot order variable बदलकर attacker-controlled server specify किया जा सकता है, या EFI partition के bootloader को valid shim और GRUB2 image से overwrite करने के बाद grub.cfg में HTTP के जरिए नया shim chainload कराया जा सकता है
      क्योंकि GRUB2 का device syntax HTTP समेत supported devices specify कर सकता है
      साथ ही, अगर कोई unprivileged adjacent attacker man-in-the-middle position में है और victim machine PXE booting इस्तेमाल करती है, तो PXE के shim → PXE के GRUB2 → HTTP के shim की तरह chain बनाकर exploit किया जा सकता है
    • Microsoft के legal team का मानना है कि अगर Microsoft GRUB, जो GPLv3-licensed bootloader है, को sign करता है, तो GPLv3 की वजह से developers को signing keys उपलब्ध कराने का अधिकार जबरन लागू हो सकता है
      स्रोत: https://techcommunity.microsoft.com/t5/hardware-dev-center/u...
    • मुझे हैरानी थी कि bootloader network communication क्यों करता है, लेकिन यह समझाने से बात समझ आई कि EFI binary को HTTP URL के रूप में specify किया जा सकता है
    • मुझे यह जानना है कि shim Microsoft की चिंता वाले issue से कैसे बचता है
      अगर GPLv3 का anti-Tivoization clause Secure Boot signing key उपलब्ध कराने की मांग कर सकता है, तो क्या MOK signing key भी request करने पर उपलब्ध नहीं करानी चाहिए?
      अगर ऐसा है, तो इसका मतलब है कि कोई भी ऐसी key हासिल कर सकता है जिससे वह arbitrary code sign कर सके जो Secure Boot के जरिए indirectly boot होगा; मुझे नहीं पता कि यह Microsoft द्वारा GRUB जैसे GPLv3 projects को सीधे signing key जारी करने के नतीजे से meaningful तौर पर अलग कैसे है
    • अगर मकसद local second-stage bootloader को boot करना है, तो लगता है Windows Boot Manager भी वही भूमिका निभा सकता है
      पुराने BIOS machines पर मैंने WBM से GRUB chainload कराया था, लेकिन UEFI machines पर अभी तक नहीं किया, इसलिए नहीं जानता कि कोई blocking point है या नहीं
  • अगर आप सोच रहे हों, “अविश्वसनीय या compromised server से boot क्यों करना?”, या “अगर server compromised है तो वह सीधे malicious binary भेज देगा, फिर इसका क्या मतलब?”, तो संक्षेप में: shim जिस binary को अंत में boot करता है, उसे MOK से signed होना चाहिए
    इसलिए चाहे compromised network के अंदर boot किया जाए, HTTP से boot किया जाए, या compromised server से boot किया जाए, HTTPS हो या न हो, वही security guarantee बनी रहनी चाहिए
    Secure Boot downgrade को नहीं रोकता, इसलिए compromised server का downgrade attack में इस्तेमाल हो सकना इस vulnerability से अलग बात है
    downgrade attack prevention को वैसे भी अलग से, अधिक मजबूत तरीके से implement करना होगा
    हालांकि मुझे नहीं पता कि shim को सीधे HTTP booting support करने की जरूरत क्यों है
    इसे MOK-signed second local EFI binary में handle किया जा सकता था, लेकिन शायद इसे implement करने में अपेक्षाकृत आसान feature माना गया होगा

  • समझ नहीं आता कि यह code body length को दो अलग-अलग आधारों पर क्यों संभालता है
    RFC के हिसाब से HTTP/1.1 में Content-Length HTTP request/response body की length के लिए authoritative जानकारी है
    उस length से आगे wire पर मौजूद data, परिभाषा के अनुसार किसी दूसरे message का हिस्सा है
    उल्टा, अगर Content-Length rx_message.BodyLength से बड़ा है, तो इसका मतलब है कि अभी पूरा message नहीं मिला है, इसलिए और इंतज़ार करना चाहिए या timeout error देना चाहिए
    किसी भी स्थिति में, अगर यह guarantee नहीं है कि rx_message.BodyLength Content-Length के बराबर है, तो वह गलत value है
    अगर इसे ज़्यादा lenient तरीके से handle करना है, तो Content-Length header देखने की कोई वजह नहीं है; बस rx_message.BodyLength को buffer size मानकर wire पर मौजूद सारे data को received message के रूप में interpret कर लें
    मौजूदा code बेवजह complex है, और इसी तरह bug घुसता है

    • सिर्फ उस commit को अलग से देखने पर गलतफहमी होना आसान है
      आसपास का code https://github.com/rhboot/shim/blob/0226b56513b2b8bd5fd281bc... देखें तो loop के अंदर data chunks receive करते हुए हर बार check करता है कि नया data Content-Length से तय buffer capacity से ज़्यादा तो नहीं हो रहा
      लेकिन पहले loop के बाहर की पहली read के लिए वह check नहीं था, और वही bug था
      हालांकि downloaded size *buf_size, यानी Content-Length के बराबर है या नहीं, इसकी final check करने वाला code नहीं दिखता
      अगर यह condition टूटती है तो यह connection के बहुत जल्दी बंद हो जाने का संकेत हो सकता है
  • यह साफ तौर पर bug है और अच्छा है कि fix हो गया, लेकिन सोचता हूँ कि अविश्वसनीय host से अपनी machine boot कौन करता है
    अगर attacker ने malicious header भेजने लायक HTTP service पर control पा लिया है, तो इस overflow से बचना सबसे छोटी समस्या है; certificate भी compromise हो चुका होगा और वह spec-compliant payload में malware डालकर भेज सकता है
    bug तो है, लेकिन यह Critical है या नहीं, इस पर यकीन नहीं

    • Secure Boot को जोर देकर आगे बढ़ाने वाले लोग भी कुछ इसी तरह के हैं
      वे सचमुच ऐसी security strategy पर भरोसा करते हैं जिसमें संभावित रूप से compromise हो सकने वाली हर चीज Secure Boot से signed नहीं होनी चाहिए
      अगर कोई एक भी vulnerable signed चीज मौजूद है, तो उसका इस्तेमाल करके सबके Secure Boot+TPM encrypted disks को decrypt किया जा सकता है
      यह approach valid security model क्यों मानी गई, समझना मुश्किल है, और ऐसी vulnerabilities पहले से बहुत सारी हैं
      ऊपर से कमरे में मौजूद हाथी यानी Windows को पूरी तरह ignore कर देते हैं
      ऐसी सोच का उदाहरण: https://lkml.org/lkml/2018/4/3/767
      Linus की चिंताओं के बावजूद, कई distros में Secure Boot से boot करने पर सच में integrity mode चालू हो जाता है
      शायद इसकी वजह Microsoft policy और यह स्थिति हो सकती है कि distros को Microsoft UEFI signature पाने के लिए उस thread में बताए गए procedure का पालन करने के लिए मजबूर किया जाता है
      नतीजा यह है कि Secure Boot चालू करने पर आमतौर पर distro functionality सीमित हो जाती है, जैसे hibernation इस्तेमाल नहीं कर पाते
    • अच्छी defense सिर्फ defense in depth की तरह कई defense layers बनाने से होती है, और यह bug उन्हीं में से एक layer में छेद करता है
    • इसका इस्तेमाल कुछ locked devices में घुसने के लिए भी हो सकता है
    • दूसरे thread की बेहतरीन explanation देखें https://news.ycombinator.com/item?id=39135275 तो attack vector सिर्फ HTTP तक सीमित नहीं है, इसलिए इसे Critical माना जा सकता है
  • जब कोई अहम काम हो, तो HTTP का S इस्तेमाल करना चाहिए
    device booting भी इसमें शामिल है, और HTTPS headers हमेशा encrypted रहे हैं
    फिर भी bug अच्छी तरह खोजा गया है

    • यहाँ HTTPS relevant नहीं है
      गलत header दोनों में भेजा जा सकता है
    • पक्का नहीं कि इस use case में HTTPS संभव है या नहीं
      क्योंकि encryption के लिए सही time और date चाहिए होते हैं
      RTC valid हो सकता है, लेकिन time zones ठीक से handle होते हैं या नहीं पता नहीं, और वैसे भी समय गलत हो सकता है
    • यह S होने या न होने से जुड़ी समस्या नहीं है
      लगता है आपने problem सही से समझी नहीं
  • Content-length असली body length नहीं, बल्कि Content-encoding के बाद की length है

    • “HTTP/1.1 अगर उसका ज्यादातर हिस्सा ignore कर दें, तो यह वाकई मज़ेदार रूप से simple protocol है”
  • क्या इन shim builds में httpboot शामिल है?
    मेरी जानकारी में shim तो सिर्फ disk पर मौजूद दूसरे EFI binaries चलाने के लिए होता है, और shim की network boot functionality सच में इस्तेमाल होते मैंने शायद नहीं देखी

  • शायद मुझे ठीक से पता न हो, लेकिन मुझे लगा था कि ज्यादातर HTTP clients सिर्फ specified Content-Length तक ही पढ़ते हैं, और अगर पढ़े गए bytes Content-Length से कम हों तो उसे error मानते हैं

    • HTTP client UEFI द्वारा EFI driver के रूप में provide किया जाता है
      मेरी नज़र में UEFI spec यह साफ-साफ define नहीं करती कि Content-Length header और response body length match न होने पर behavior क्या होना चाहिए
      इसलिए कुछ implementations बस connection:close request बनाती हों और Content-Length check न करती हों, इसकी पूरी संभावना है
      यह vulnerability MSRC ने report की थी और CVE description में actual exploitation के बारे में कुछ नहीं है
      बाद में public हो सकता है, या यह theoretical issue भी हो सकता है
  • क्या बता सकते हैं कि actual body length से कम पढ़ना खतरनाक क्यों है?
    मुझे तो उम्मीद थी कि उल्टा case खतरनाक होगा

    • HTTP या related protocol से file fetch करते समय shim received data store करने के लिए buffer allocate करना चाहता है
      लेकिन size manipulable HTTP header से लिया जाता है, और attacker received data से छोटा size specify कर सकता है
      इस case में code allocation के लिए header value इस्तेमाल करता है, और receive buffer से copy करते समय protocol metadata का size इस्तेमाल करता है, जिससे out-of-bounds write हो जाती है
    • explanation के हिसाब से buffer Content-Length के आधार पर allocate होता है, लेकिन असल में मिले buffer के size जितना copy करता है, जिससे allocated range से बाहर write हो जाता है