- Chromium की WebUI privilege boundary, enterprise policy testing feature, और DevTools extension API की खामियां आपस में जुड़ गईं, जिससे एक malicious Chrome extension बहुत कम user interaction के साथ shell command execution तक पहुंच सकती थी
- attack path में
chrome://policyपर undocumented policy testing API को कॉल करके user policy बदली जाती थी, और Browser Switcher के alternative browser path व arguments को shell command के रूप में abuse किया जाता था chrome.devtools.inspectedWindow.reload()injectedScriptexecution की अनुमति देता था, और WebUI navigation के समय access blocking में देरी या crash के बाद बचेPage.reloadrequest की वजह से privileged WebUI में code चलाया जा सकता था- Google ने इस vulnerability को P1/S1 के रूप में classify किया और
Page.reloadकेloaderIdvalidation,inspectedWindow.reload()URL check, और WebUI handler में policy testing enablement check जोड़ा - संबंधित vulnerabilities को CVE-2024-5836 और CVE-2024-6778 सौंपे गए, दोनों को CVSS 8.8 High मिला, और अंतिम bounty $20,000 थी
Chromium WebUI और sandbox boundary
- Chromium untrusted code को sandbox के अंदर चलाता है, और Chrome extension का JavaScript भी केवल दिए गए permissions और accessible APIs के भीतर ही काम करना चाहिए
- extension permissions के दम पर login info या browser history चुराई जा सकती है, लेकिन सिद्धांततः उसका असर browser के अंदर ही सीमित रहना चाहिए
- Chromium के GUI का कुछ हिस्सा
chrome://settings,chrome://historyजैसे WebUI के रूप में implement किया गया है- WebUI HTML, CSS, JavaScript में लिखा होता है, लेकिन browser की internal information दिखाने और बदलने की जरूरत के कारण इसे सामान्य web page से ज्यादा privileges मिलते हैं
- WebUI frontend का JavaScript private APIs के जरिए browser के native C++ code से communicate कर सकता है
- अगर WebUI में code execution संभव हो जाए, तो यह Chromium sandbox bypass तक पहुंच सकता है, इसलिए attackers को
chrome://page पर untrusted JavaScript चलाने से रोकना जरूरी है - उदाहरण के लिए,
chrome://downloadsमें.exedownload item par click करने से executable खुल सकता है, इसलिए Chromium जांचता है कि file open action वास्तव में user input से आया है या नहीं
enterprise policy testing feature का bypass
- vulnerability research की शुरुआत Chromium के enterprise policy system से हुई
- यह system कंपनी या स्कूल के device पर admin द्वारा कुछ settings force करने के लिए होता है
- policies आम तौर पर Google account से जुड़ी होती हैं और Google management server से डाउनलोड की जाती हैं
- policies को device policies और user policies में बांटा जाता है
- device policies Chrome OS device की पूरी settings manage करती हैं
- user policies किसी खास user या browser instance पर लागू होती हैं और सभी platforms पर उपलब्ध हैं
- Linux में
/etc/opt/chrome/policiesमें JSON file रखकर Google Chrome instance पर user policies लागू की जा सकती हैं, लेकिन इस directory में लिखने के लिए root privileges चाहिए
- वर्तमान device पर लागू policies को
chrome://policyWebUI में देखा जा सकता है- यह page applied policy list, policy service logs, और JSON export feature देता है
- सामान्यतः इस page पर policies edit करने का कोई तरीका नहीं होता
- Chrome v117 के Chrome Enterprise release notes में
chrome://policy/testpage का उल्लेख था, जो Beta, Dev, Canary channels में policy testing की अनुमति देता है- Chromium documentation में release notes के अलावा इस feature का कहीं और जिक्र नहीं था
- इसे सामान्य रूप से enable करने के लिए undocumented
PolicyTestPageEnabledpolicy चाहिए - यह policy न होने पर
chrome://policy/testchrome://policyपर redirect हो जाता है
setLocalTestPolicies validation failure
chrome://policy/testका JavaScript code test policies सेट करने के लिएsendWithPromise('setLocalTestPolicies', ...)का उपयोग करता हैsendWithPromise()WebUI private APIchrome.send()का wrapper है- यह call C++ handler function को request भेजती है, और handler browser के अंदर के काम कर सकता है
chrome://policyconsole सेsetLocalTestPoliciesको सीधे कॉल करने पर शुरुआत में browser crash हुआ, और log में policy array की जरूरत का message दिखा- policy array का format सही करके
AllowDinosaurEasterEggजैसी user policy भेजी गई, तो feature को explicitly enable किए बिना भी arbitrary policy सेट हो गई - C++ side के
HandleSetLocalTestPolicieshandler ने सिर्फlocal_test_providerकी मौजूदगी जांची, यह नहीं देखा कि policy testing वास्तव में allowed है या नहीं LocalTestPolicyProvider::CreateIfAllowed()IsPolicyTestingEnabled(nullptr, channel)को कॉल करता था- पहला argument
pref_servicenullहोने सेPolicyTestPageEnabledcheck skip हो गया - बची हुई जांच सिर्फ यह थी कि release channel
CANARYयाDEFAULTहै या नहीं
- पहला argument
- unbranded Chromium build में
GOOGLE_CHROME_BRANDINGcode compile नहीं होता, इसलिए channelUNKNOWNरहता है- enum में
UNKNOWN = 0,DEFAULT = UNKNOWNहोने से Chromium और derived builds में channel check pass हो जाता है - branded Google Chrome stable build में release channel सही तरह set होता है, इसलिए यह bug stable Google Chrome में काम नहीं करता
- enum में
Browser Switcher से shell command execution
- arbitrary user policy सेट की जा सकने पर Chrome enterprise policies का Legacy Browser Support module sandbox escape path बन गया
- Legacy Browser Support को Browser Switcher भी कहा जाता है, और इसे इस तरह design किया गया है कि जब user Chromium में किसी खास URL पर जाए तो alternative browser launch हो
- यह Internet Explorer users को support करने के लिए बनाया गया feature था
- इसका behavior policies से controlled होता है
AlternativeBrowserPathऔरAlternativeBrowserParameterspolicies को मिलाकर Chromium “alternative browser” के रूप में arbitrary shell command चला सकता था- ये Browser Switcher policies केवल Linux, macOS, और Windows पर मौजूद हैं
- उदाहरण flow इस प्रकार है
BrowserSwitcherEnabledकोtrueपर सेट करेंBrowserSwitcherUrlListमेंexample.comडालें- Linux पर
AlternativeBrowserPathको/bin/bashपर सेट करें AlternativeBrowserParametersको["-c", "xcalc # ${url}"]जैसा सेट करें
- browser जब
example.comपर जाता है, तो Browser Switcher सक्रिय हो जाता है और/bin/bash -c 'xcalc # https://example.com'जैसे command चलती है${url}replacement value को#के बाद रखकर shell comment बना दिया जाता है
chrome://policyमें policies सेट करने के बादwindow.open("https://example.com")कॉल करने से केवल JavaScript के जरिए arbitrary shell command execution तक पहुंचा जा सकता था
DevTools extension API का bypass path
- सिर्फ पिछले चरणों से victim को
chrome://policyमें malicious code browser console में paste करना पड़ता, इसलिए यह व्यावहारिक नहीं था - auto-execution path malicious Chrome extension के जरिए मिला
- extension page में JavaScript inject कर सकती है, लेकिन privileged WebUI pages में JavaScript नहीं चल पाना चाहिए
- page में JavaScript चलाने के लिए extension की चार मुख्य APIs थीं
chrome.scripting- Manifest v2 की
chrome.tabs chrome.debuggerchrome.devtools.inspectedWindow
- जांच के लिए
chrome.devtools.inspectedWindowचुना गया, क्योंकि यह अपेक्षाकृत कम hardened लग रहा थाchrome.devtoolsAPI इस्तेमाल करने वाली extension के manifest मेंdevtools_pagefield होनी चाहिए- जब user DevTools खोलता है, तो वह page iframe में load होता है, और उसके भीतर
chrome.devtoolsAPI इस्तेमाल की जा सकती है
- David Erceg की पुरानी bug report में
chrome.devtools.inspectedWindow.eval()के जरिए WebUI में code execution तक पहुंचने का मामला पहले से था- सामान्य रूप से inspected page के WebUI पर जाने पर DevTools API access disable हो जाना चाहिए
- bypass का सार यह था कि Chrome API disable करने से पहले eval request भेज दी जाए, ताकि वह request WebUI page तक पहुंच जाए
inspectedWindow.reload() और about:blank की विशेषता
chrome.devtools.inspectedWindow.reload()भीinjectedScriptargument मिलने पर inspected page में JavaScript चला सकता है- WebUI द्वारा खोले गए
about:blankpage मेंinspectedWindow.reload()कॉल करने पर privileged page में JavaScript execution संभव थाabout:blankURL खुद में खास नहीं है, लेकिन यह उसे खोलने वाले page के privileges और origin inherit करता हैchrome://settingsद्वारा खोला गयाabout:blankpage,chrome://settingsorigin वाला privileged page था
- DevTools API disable करने वाला code inspected target का सिर्फ URL जांचता था, origin नहीं
- URL सामान्य दिखे तब भी origin privileged हो सकता है
- केवल
about:blankpath को सीधे exploit chain में इस्तेमाल करना कठिन था, क्योंकिchrome://policyabout:blankpopup नहीं खोलता - फिर भी कुछ स्थितियों में जहां
inspectedWindow.eval()fail होता था, वहींinspectedWindow.reload()chrome://settingsमें JavaScript चला देता था- इससे पता चलता है कि
eval()में origin check जैसा अतिरिक्त guard था, जबकिreload()में वैसी सुरक्षा नहीं थी
- इससे पता चलता है कि
race condition से crash-based method तक stabilization
- पहली exploit chain में
inspectedWindow.reload()कॉल को बार-बार दोहराया गया, ताकि inspected page के WebUI में जाने के तुरंत बाद और DevTools page द्वारा API disable करने से पहले की छोटी window को hit किया जा सके- यह इस धारणा पर आधारित था कि inspected page और DevTools page अलग processes में हैं
- अगर
chrome://policynavigation के क्षण और DevTools API disable होने के बीचreload()request पहुंच जाए, तो WebUI में code चल सकता था
- यह तरीका काम करता था, लेकिन reliable नहीं था
- tuning के बाद लगभग 70% success rate मिली
- vulnerability गंभीर थी, लेकिन instability severity कम कर सकती थी
- इसके बाद David Erceg के पुराने approach की तरह यह परखा गया कि tab crash के बाद pending debugger requests वाला behavior
inspectedWindow.reload()पर भी लागू ho sakta hai ya nahin debuggerstatement को लगातार दो बार trigger करने पर tab crash हो गया, और queue में बचाPage.reloadrequest WebUI पर जाने के बाद execute हो सकता था- इससे race condition की जरूरत खत्म हो गई और यह 100% reliable हो गया
- पहले के bug patch में Google ने crash के बाद pending debugger requests साफ करने का बदलाव किया था, लेकिन
Page.reloadrequest को exception के रूप में छोड़ दिया गया थाinspectedWindow.reload()internallyPage.reloadrequest भेजता है, इसलिए यह उसी exception से प्रभावित था- उस समय का patch यह नहीं रोक पाया कि
Page.reloadscript execute कर सकता है
- tab crash सिर्फ
debuggermethod से ही नहीं, out-of-memory condition बनाकर भी संभव था, लेकिन अंतिम PoC में तेजdebuggercrash इस्तेमाल किया गया
अंतिम exploit chain और user interaction
- अंतिम PoC इस क्रम में काम करता था
chrome.devtools.inspectedWindow.reload()vulnerability का उपयोग करकेchrome://policyमें JavaScript payload चलाया जाता था- payload
sendWithPromise("setLocalTestPolicies", policy)कॉल करके user policies सेट करता था BrowserSwitcherEnabled,BrowserSwitcherUrlList,AlternativeBrowserPath,AlternativeBrowserParametersसेट किए जाते थेwindow.open()या page navigation से Browser Switcher trigger करके shell command चलाया जाता था
- PoC में OS के अनुसार calculator launch command इस्तेमाल की गई
- Windows:
C:\Windows\System32\cmd.exeऔरcalc.exe - Linux:
/bin/bashऔरxcalc - macOS:
/bin/bashऔरopen -na Calculator
- Windows:
- user interaction बस इतना था कि user DevTools खोल दे
- example screen का “extension install error” user को DevTools खोलने के लिए trick करने का एक तरीका था
- DevTools खुलते ही sandbox escape chain शुरू हो जाती थी
Google के fixes और CVE assignment
- report के बाद Google ने vulnerability को जल्दी verify किया और इसे P1/S1 classify किया
- P1/S1 का मतलब high priority और high severity है
- अगले कुछ हफ्तों में तीन मुख्य fixes लागू किए गए
Page.reloadcommand मेंloaderIdargument जोड़ा गया और renderer side परloaderIDcheck जोड़ा गया- इससे command सिर्फ एक single origin तक वैध रहे और गलती से privileged page तक पहुंचने पर भी काम न करे
inspectedWindow.reload()function में URL check जोड़ा गया- अब यह सिर्फ extension API access revoke होने पर निर्भर नहीं रहा
- WebUI handler में test policy enablement check जोड़ा गया
- इससे test policies पूरी तरह block हो गईं
- race condition से जुड़ी vulnerability को CVE-2024-5836 दिया गया
- इसका CVSS severity score 8.8 High है
- inspected page crash से जुड़ी vulnerability को CVE-2024-6778 दिया गया
- इसे भी CVSS severity score 8.8 मिला
- fixes release branch में merge होने के बाद Chrome VRP panel ने reward तय किया, और अंतिम bounty $20,000 रही
सार्वजनिक समयरेखा और सामग्री
- timeline इस प्रकार है
- 16 अप्रैल: test policies bug मिला
- 29 अप्रैल:
inspectedWindow.reload()race condition bug मिला - 1 मई: Google को bug report किया गया
- 4 मई: Google ने इसे P1/S1 classify किया
- 5 मई: inspected page crash से जुड़ा bug मिलने के बाद report update की गई
- 6 मई: Google ने chain के हर हिस्से के लिए अलग bug report मांगी
- 8 जुलाई: bug report को fixed के रूप में mark किया गया
- 13 जुलाई: reward decision के लिए Chrome VRP panel को भेजा गया
- 17 जुलाई: VRP panel ने $20,000 reward तय किया
- 15 अक्टूबर: पूरी bug report public हुई
- संबंधित मूल bug report crbug.com/338248595 पर देखी जा सकती है
- vulnerability के हर हिस्से के PoC GitHub repository में public हैं
inspectedWindow.reloadbug Chrome v45 तक पीछे जाकर काम करता था- जब undocumented, अधपके और unsafe features सभी users तक पहुंचा दिए जाते हैं, तो कई साधारण गलतियां मिलकर high severity vulnerability बन सकती हैं
1 टिप्पणियां
Hacker News की राय
कहा गया था कि पेज URL को
${url}से बदला जाता है, और कमांड को खराब होने से बचाने के लिए उसे#के बाद रखने पर वह comment बन जाता है — क्या इस policy में ऐसा कोई validation logic है कि URL कोAlternativeBrowserParametersमें कहीं पास होना चाहिए?प्रोग्रामिंग, वेब डेवलपमेंट और साइबरसिक्योरिटी में रुचि रखने वाला एक हाई स्कूल छात्र — यह सच में प्रभावशाली है
responsible disclosure process तक का पालन करने वाली पेशेवर नैतिकता भी कमाल की है; आगे चलकर यह व्यक्ति बहुत बड़ा करेगा
यह शानदार लेख और काम था, और खोज पर खोज जुड़ने के साथ उत्साह बढ़ता गया — ऐसा लगा मानो मैं भी उस प्रक्रिया के साथ चल रहा हूँ
इनाम भी पूरी तरह deserve करता है
vulnerability chaining की प्रक्रिया भी साफ-सुथरी थी और लेखन भी बेहतरीन। vulnerable code कैसे काम करता है, इसे तोड़कर दिखाना भी बहुत अच्छा लगा
“फिर से कोशिश करने के लिए F12 दबाएँ” जैसी साधारण ट्रिक्स हर बार प्रभावित करती हैं — सच में शरारती अंदाज़ है
इससे मुझे वह पुराना मामला याद आ गया जब इसी API से Chrome OS के
croshshell को debug करके OS protections को bypass किया गया था, और developer device पर root access तक मिल गया था। वह CVE-2014-3172 थालेकिन इस लेख के लेखक को इससे कहीं कठिन बाधाओं को bypass करना पड़ा, और यह सच में शानदार काम है
रात बहुत हो चुकी है, इसलिए WebUI validation में क्या टूटा, उसमें गहराई से जाना मुश्किल है, लेकिन यह अच्छा लगा कि लेखक ने अंत तक जाकर इसे समझा
जिन चीज़ों को हम ship करते हैं, उनकी toolchain पर शक करना और उस पर भरोसा न करना काफ़ी standard mindset है, लेकिन साथ ही हम Google या Microsoft जैसी बड़ी कंपनियों के जादुई रूप से सुविधाजनक development tools पर बहुत ज़्यादा भरोसा करते हैं। आखिरकार Chromium या VSCode के अंदर क्या छिपा है, इसकी चिंता करने के बजाय मैं अपना code लिखना और test करना चाहता हूँ
यह उन बेहतरीन लेखों में से एक है जो मैंने पढ़े हैं
सच में बहुत ही चतुर tracking work था
browser code खंगालकर यहाँ तक पहुँचने की मेहनत कमाल की है, और लेख भी बहुत दिलचस्प और विस्तारपूर्ण है
हाई स्कूल छात्र? वाह, सच में कमाल है
Chromium project ने
chrome://net-internalsको यह कहकर हटा दिया कि वह बहुत जटिल था, और उसकी जगह आधा-अधूरा JSON editing support वालाchrome://policyजोड़ दिया