NextJS का खेल खत्म... 13 नई कमियाँ (vulnerabilities)

BBetter Stack
Computing/SoftwareBusiness NewsInternet Technology

Transcript

00:00:00यह फिर से हो गया। इस साल सर्वर कंपोनेंट CVEs पर यह मेरा लगभग तीसरा वीडियो है और मुझे
00:00:05नहीं लगता कि मैंने उन सभी को कवर किया है। इस बार 13 CVEs हैं, हाँ पूरे 13, React
00:00:11और Next.js में, जिनमें से 6 'हाई' गंभीरता के हैं और इनमें 'डिनायल ऑफ सर्विस', मिडलवेयर
00:00:15बायपास, क्रॉस-साइट स्क्रिप्टिंग और बहुत कुछ शामिल है। शायद सर्वर कंपोनेंट्स एक गलती थी।
00:00:20तो यह रहा Next.js सिक्योरिटी रिलीज़, यहाँ बस कुछ मामूली समस्याओं को ठीक किया गया है
00:00:28जो इस महीने आई थीं और नीचे स्पष्ट रूप से समाधान यही है कि आप
00:00:32अपने सभी Next.js वर्ज़न्स को अपग्रेड करें और ये प्रभावित वर्ज़न्स हैं। यह ध्यान देने योग्य है कि
00:00:36TanStack इससे प्रभावित नहीं है, जिसमें मैं पक्षपाती हो सकता हूँ लेकिन मेरे लिए
00:00:41TanStack का उपयोग करने का यह एक और कारण है। अब मैं इन सब पर विस्तार से नहीं जाऊँगा वरना हमें काफी समय लग जाएगा
00:00:44और मुझे इन सभी के लिए काम करने वाले 'एक्सप्लॉइट्स' भी नहीं मिले हैं, लेकिन मैं आपको
00:00:48हर श्रेणी से एक दिखाना चाहता हूँ और हम मिडलवेयर और प्रॉक्सी बायपास से शुरुआत करेंगे और जिसे मैं
00:00:52दोबारा बनाने में सफल रहा हूँ वह यह 'पेज राउटर' वाला है। तो हमारे पास पेज राउटर में एक मिडलवेयर प्रॉक्सी बायपास है
00:00:56यदि आप i18n का उपयोग कर रहे हैं और आप देख सकते हैं कि यह 10 में से 7.5 की गंभीरता वाला CVE है।
00:01:02यह एक कमज़ोर एप्लिकेशन का उदाहरण है, तो Next.js कॉन्फिग में मैंने i18n को चालू कर दिया है
00:01:06और दो लोकेल भी सेट किए हैं, अंग्रेजी और फ्रेंच, फिर मेरे पास एक मिडलवेयर फ़ाइल भी है
00:01:12जिसे Next.js के बाद के वर्ज़न्स में 'प्रॉक्सी' नाम दे दिया गया है ताकि उस भ्रम से बचा जा सके
00:01:16जो मैं आपको दिखाने वाला हूँ, लेकिन अनिवार्य रूप से मिडलवेयर हमें
00:01:19आने वाले रिक्वेस्ट को संशोधित करने की अनुमति देता है, चाहे वह रीडायरेक्ट करना हो, रीराइट करना हो या
00:01:24कुछ हेडर्स जोड़ना हो। मेरे मामले में मैं इसका उपयोग कर रहा हूँ ताकि जब हम
00:01:28/secret पेज पर जाने की कोशिश करें, तो यह जांचता है कि क्या उनके पास सेशन कुकी है यानी वे लॉग इन हैं
00:01:32और यदि नहीं, तो इसे उन्हें लॉगिन पेज पर रीडायरेक्ट करना चाहिए ताकि उम्मीद है कि केवल अधिकृत यूज़र्स ही
00:01:37मेरा सीक्रेट पेज देख सकें। नीचे हमारे पास एक 'मैचर' भी है ताकि हम उस सीक्रेट पेज पर जो भी मिडलवेयर
00:01:41लगा रहे हैं, वह उनके लोकेल वेरिएंट्स से भी मेल खाए क्योंकि तकनीकी रूप से
00:01:45अब हमारे पास दो लोकेल हैं, तो इस URL के तीन वर्ज़न हैं। खुद सीक्रेट पेज में
00:01:50मेरे पास कुछ 'सर्वर-साइड प्रॉप्स' भी हैं, इन्हें रेंडर समय पर सर्वर से लिया जाना चाहिए
00:01:54और फिर से, चूंकि हमने वह मिडलवेयर सेट किया है, सैद्धांतिक रूप से केवल एक लॉग-इन यूज़र ही देख पाना चाहिए
00:01:58कि ये वैल्यूज़ क्या हैं, जिन्हें मैं बाद में पेज पर उपयोग करता हूँ जैसे एक ईमेल, एक फ्लैग और
00:02:03एक हेडलाइन भी। फिर से, केवल एक अधिकृत यूज़र ही इन्हें देख पाना चाहिए। आइए इसकी
00:02:07परीक्षा लेते हैं और सबसे पहले मैं उस सीक्रेट पेज तक पहुँचने की कोशिश करूँगा और आप
00:02:11देख सकते हैं कि मुझे लॉगिन पर रीडायरेक्ट कर दिया गया है क्योंकि मैं लॉग इन नहीं हूँ जिसका मतलब है कि हमारा मिडलवेयर काम कर रहा है
00:02:16लेकिन क्या होगा अगर हम मास्टर हैकर बन जाएं? खैर, हम ऐसा सबसे पहले एलीमेंट का 'इंस्पेक्ट' करके
00:02:20कर सकते हैं, बिल्कुल क्रेजी हैकर वाली चीज़ें और फिर यहाँ नीचे 'नेक्स्ट डेटा स्क्रिप्ट' में हमें
00:02:24अपनी 'बिल्ड आईडी' देखनी होगी, तो मेरे मामले में वह यहाँ है और हम इसे कॉपी कर सकते हैं
00:02:28फिर हमें एक URL टाइप करना होगा जो है: underscore next slash data slash वह बिल्ड आईडी जिसे हमने
00:02:32अभी कॉपी किया है, और फिर वह पेज जिसे हम एक्सेस करना चाहते हैं dot JSON। एक बार जब आप यह कर लेते हैं, तो
00:02:37आप देख सकते हैं कि हमें वे प्रॉप्स वापस मिल जाते हैं जिन्हें उस मिडलवेयर के पीछे सुरक्षित होना चाहिए था
00:02:40जो मेरे मामले में एक फ्लैग, ईमेल, हेडलाइन और कुछ ऐसा था जो आपको अधिक डेवलपर न्यूज़,
00:02:44ट्यूटोरियल और टिप्स के लिए सब्सक्राइब करने के लिए कह रहा था। तो आगे बढ़ें और सब्सक्राइब करें, मुझे आशा है कि मैंने
00:02:48आपको अपने क्रेजी हैकर कौशल से प्रभावित किया होगा, लेकिन यह वास्तव में होता क्यों है? खैर, इसे
00:02:52समझाना उतना ही आसान है जितना इसे करना था, क्योंकि हमारे पास हमारा सीक्रेट पेज और कुछ सर्वर साइड प्रॉप्स थे
00:02:56Next.js में सर्वर साइड प्रॉप्स ऐसे URL से सर्व किए जाते हैं, लेकिन हमारे मिडलवेयर
00:03:00को इस रूट की रक्षा करनी चाहिए थी। समस्या यह है कि चूंकि हम i18n का उपयोग कर रहे थे, हमारे पास
00:03:05दो अन्य URL भी थे जो अंग्रेजी और फ्रेंच वेरिएंट थे, आप देख सकते हैं कि सर्वर साइड
00:03:09प्रॉप्स को अंग्रेजी और फ्रेंच वेरिएंट्स भी मिलते हैं और Next.js में बस कुछ दोषपूर्ण
00:03:13कोड था जिसका मतलब था कि अगर हमारे पास i18n सक्षम था, तो यह बेस केस की रक्षा नहीं कर रहा था,
00:03:18इसलिए यह मैचर में शामिल नहीं था लेकिन अन्य दो थे, तो अंग्रेजी और फ्रेंच वर्ज़न्स
00:03:22सुरक्षित थे लेकिन slash secret का बेस केस नहीं। हम इसे बहुत जल्दी देख सकते हैं अगर मैं बस
00:03:26इस URL को अंग्रेजी वर्ज़न में बदल दूँ, तो मुझे लॉगिन पेज पर रीडायरेक्ट कर दिया जाता है। एक अविश्वसनीय रूप से सरल भेद्यता
00:03:31है, लेकिन मैं आपके साथ ईमानदार रहूँगा, ये मिडलवेयर बायपास अक्सर सुनने में उससे कहीं अधिक खराब लगते हैं जितने वे वास्तव में
00:03:35हैं; वे अच्छे नहीं हैं लेकिन आपको वैसे भी सिर्फ मिडलवेयर से बहुत कुछ सुरक्षित नहीं करना चाहिए
00:03:40और Next.js भी इसकी सिफारिश नहीं करता है। यदि आपके पास उन सर्वर साइड प्रॉप्स में
00:03:44कुछ संवेदनशील डेटा था और आपके पास किसी प्रकार का सर्वर ऑथ लॉजिक नहीं था, तो मुझे लगता है कि
00:03:48समस्या का हिस्सा आप भी हैं, तो चलिए एक अधिक हानिकारक समस्या की ओर बढ़ते हैं जो है 'डिनायल ऑफ
00:03:53सर्विस', इनमें से तीन थे लेकिन केवल एक ही था जिसे मैं विश्वसनीय रूप से दोबारा बना सका और
00:03:56वह यहाँ यह वाला था जो सर्वर कंपोनेंट्स के साथ डिनायल ऑफ सर्विस है और यह Next.js
00:04:01के साथ-साथ 'react server DOM' पैकेज का उपयोग करने वाली किसी भी चीज़ को प्रभावित करता है जो कि लगभग केवल Next.js
00:04:05और अन्य फ्रेमवर्क्स हैं जिन्होंने इसकी नकल की है जैसे vinxt और कुछ अन्य फ़ोर्क्स। TanStack
00:04:10Start इसका उपयोग नहीं करता है इसलिए यह इसके प्रति संवेदनशील नहीं है। आप देख सकते हैं कि इसकी भी गंभीरता
00:04:1410 में से 7.5 है। इसके साथ, आपको बस एक बहुत ही सरल Next.js एप्लिकेशन की आवश्यकता है और
00:04:18इसमें आपको एक 'सर्वर एक्शन' का उपयोग करना होगा, लेकिन फिर से, यह एक बहुत ही सरल हो सकता है। यह
00:04:22वह साइट चल रही है और आप देख सकते हैं कि जब मैं पेज को रिफ्रेश करता हूँ तो लगभग कोई
00:04:25लोडिंग नहीं होती है, यह लगभग तत्काल है और इसके पीछे कुछ वास्तविक नंबर रखने के लिए अगर मैं यह रिक्वेस्ट भेजता हूँ
00:04:29तो आप देख सकते हैं कि यह 0.02 सेकंड में हल हो जाता है लेकिन अगर मैं अब जाकर अपना एक्सप्लॉइट चलाता हूँ और फिर
00:04:34वह रिक्वेस्ट फिर से भेजता हूँ, तो इस बार इसमें छह सेकंड लगे और वह भी मेरे सिर्फ एक बार एक्सप्लॉइट चलाने से,
00:04:39तो सोचिए क्या होगा अगर मैं इसे एक के बाद एक जोड़ दूँ। अब इस एक्सप्लॉइट को समझने के लिए हमें
00:04:42'React Flight' प्रोटोकॉल के बारे में थोड़ा जानना होगा, जो वह फॉर्मेट है जिसे React कंपोनेंट
00:04:46ट्रीज़ और सर्वर और क्लाइंट के बीच डेटा को सीरियलाइज़ करने के लिए उपयोग करता है। आपने शायद
00:04:50इसे पहले वास्तव में देखा होगा, तो इस पेज पर हमारे पास एक फॉर्म था जिसमें सर्वर एक्शन था। अगर मैं
00:04:54यहाँ नेटवर्क टैब पर जाऊं और सेंड पर क्लिक करूं, तो आप देख सकते हैं कि पेलोड वास्तव में
00:04:58ऐसे डेटा के रूप में भेजा जाता है जो किसी बकवास जैसा दिखता है और यहाँ रिस्पांस के लिए भी वैसा ही है।
00:05:02अगर हम इस पेलोड को कॉपी करें, तो मैं समझा सकता हूँ कि जब इसे सर्वर पर भेजा जाता है तो क्या होता है।
00:05:05पहला कदम 'डी-सीरियलाइज़ेशन' है और यह चंक 0 पर शुरू होगा जहाँ हमारे पास
00:05:10यह $k1 है। यह $k1 वास्तव में सिर्फ एक पॉइंटर है जो कह रहा है कि यहाँ कुछ फॉर्म डेटा होने वाला है
00:05:16जो एक अंडरस्कोर से शुरू होता है, तो यह उन सभी अन्य कीज़ (keys) को ले लेगा जिन्हें हमने पेलोड के
00:05:20हिस्से के रूप में भेजा है, यह उन सभी को पार करेगा और एक ऐसी स्ट्रिंग की तलाश करेगा जो
00:05:24एक अंडरस्कोर से शुरू होती है और उसे पता चल जाएगा कि यह की (key) होगी और यह वैल्यू होगी। तो एक बार
00:05:28जब यह हो जाता है, तो यह कह सकता है कि हमारे पास नाम, ईमेल, संदेश है और यह बस इस डेटा को
00:05:32उस ऑब्जेक्ट में बदल देगा जो हमारे पास यहाँ नीचे है। अच्छा और सरल। हालांकि इस दृष्टिकोण के साथ समस्या
00:05:36यह है कि जब हम इसे बड़े पैमाने पर करते हैं तो क्या होता है। मान लीजिए कि मैं एक और पॉइंटर जोड़ता हूँ, इस बार $k2 की तलाश में,
00:05:41यह उन सभी कीज़ की तलाश करने वाला है जो दो अंडरस्कोर से शुरू होती हैं। समस्या
00:05:44यह है कि अब जब हम $k1 पर हैं, तो यह उन की तलाश में इन सभी छह कीज़ को पार करेगा
00:05:48जो एक अंडरस्कोर से शुरू होती हैं और जब यह $k2 पर जाता है तो यह बिल्कुल वही
00:05:52चीज़ करेगा लेकिन दो अंडरस्कोर से शुरू होने वाली की तलाश में। तो अब हम कुल 12
00:05:56कीज़ को पार कर रहे हैं। अब यह इतना बुरा नहीं है, लेकिन आइए इसे चरम पर ले जाएं। अगर हम 199,999
00:06:03रैंडम कीज़ को उस पेलोड में जोड़ते हैं जिसे हम भेज रहे हैं और फिर हम यहाँ ज़ीरो पर अपनी एरे को
00:06:07$k1 $k2 से लेकर $k1000 तक बदल देते हैं, तो इसका मतलब है कि इसे एक अंडरस्कोर,
00:06:12दो अंडरस्कोर, तीन अंडरस्कोर, एक हज़ार अंडरस्कोर तक हमारी सभी 200,000 कीज़ में तलाशना
00:06:17पड़ेगा जो हमारे पेलोड में हैं और इसका मतलब है कि कुल मिलाकर यह 20 करोड़ स्ट्रिंग
00:06:21कंपेरिजन (तुलना) करेगा। जैसा कि आप कल्पना कर सकते हैं, यह कुछ सेकंड के लिए थ्रेड को ब्लॉक करने वाला है।
00:06:25यह वह कमिट (commit) है जिसके बारे में मेरा मानना है कि इसने उस समस्या को ठीक कर दिया जो हमारे सामने थी। आप देख सकते हैं कि
00:06:28इस कमिट में बहुत कुछ हो रहा है और ईमानदारी से कहूँ तो यह थोड़ा जटिल है लेकिन
00:06:33जितना हो सके इसे समझाने की कोशिश करूँगा। अनिवार्य रूप से अब वे कीज़ के लिए कर्सर-बेस्ड सिस्टम का उपयोग करते हैं
00:06:36इसलिए वे इन सभी 200,000 कीज़ को जिन्हें हमने अपने पेलोड में भेजा था, एक लिस्ट में लोड करते हैं और फिर
00:06:41हम यहाँ ज़ीरो पर शुरू करते हैं जहाँ यह $k1 रेफरेंस की तलाश में है और यह उस लिस्ट में
00:06:45एक कर्सर के साथ नीचे जाने लगता है जो पीछे नहीं जा सकता। तो यह यहाँ $j1 पर जाता है, यह देखता है कि वह
00:06:50उस अंडरस्कोर से मेल नहीं खाता जिसकी हमें आवश्यकता है, इसलिए यह $j2 पर जाता है, वह भी अंडरस्कोर से मेल नहीं खाता
00:06:54इसलिए यह इस की-लिस्ट में नीचे $j199,999 तक जारी रहता है। एक बार जब यह
00:07:01यहाँ पहुँच जाता है, तो उसे अहसास होता है कि $k1 के लिए कोई मैच नहीं है, इसलिए वह $k2 पर चला जाता है। अब $k2 दो
00:07:06अंडरस्कोर की तलाश शुरू करता है लेकिन समस्या यह है कि चूंकि यह कर्सर-बेस्ड सिस्टम है और यह कर्सर
00:07:09पीछे नहीं जा सकता, यह तुरंत लिस्ट के अंत में पहुँच जाता है, इसलिए वह भी अनडिफाइंड होने वाला है और
00:07:14यह $k1000 तक जारी रहता है। तो अब इस बार हम केवल 200,000 कीज़ से होकर गुज़रे हैं।
00:07:18अनिवार्य रूप से इस सुधार ने ऑपरेशन्स की संख्या को $k*n से कम कर दिया है, जहाँ $k
00:07:23हमारे पास मौजूद $k रेफरेंस की संख्या है और $n कीज़ की संख्या है, इसे घटाकर $n+k
00:07:27तक ले आया है। तो हमारे मामले में, हम 20 करोड़ ऑपरेशन्स से घटकर 201,000 पर आ गए क्योंकि
00:07:33इसे अभी भी सभी कीज़ और उन $k रेफरेंस से होकर गुजरना पड़ता है। मुझे लगता है कि
00:07:37Prime का यह ट्वीट वास्तव में उस स्थिति को संक्षेप में बताता है जिसमें हम हैं। सीरियलाइज़ेशन के साथ अपना खुद का
00:07:41प्रोटोकॉल बनाना अविश्वसनीय रूप से कठिन है, इसलिए यह आश्चर्यजनक नहीं है कि हम इतने सारे मुद्दे देख रहे हैं।
00:07:46मेरी राय में उन्हें React और Next.js कोडबेस पर Claude Mythos से एक बार जांच करवानी चाहिए।
00:07:50आगे हमारे पास सबसे अधिक गंभीरता वाला CV है जो Next.js
00:07:54एप्लिकेशन्स में सर्वर-साइड रिक्वेस्ट फोर्जरी (SSRF) है। आप देख सकते हैं कि इसे 10 में से 8.6 स्थान दिया गया है
00:07:59लेकिन यह भी ध्यान देने योग्य है कि इसने Vercel-होस्टेड डिप्लॉयमेंट को प्रभावित नहीं किया, केवल सेल्फ-होस्टेड या अन्य प्रोवाइडर्स को किया।
00:08:04इस एक्सप्लॉइट का लाभ उठाना भी बहुत सरल है। सबसे पहले हमें अपना Next.js सर्वर लॉन्च करना होगा
00:08:09और फिर से, यह एक स्टॉक Next.js एप्लिकेशन हो सकता है। आपको कोई बदलाव करने की ज़रूरत नहीं है।
00:08:14इसके बाद हमें एक इंटरनल सर्वर भी चाहिए होगा। मान लीजिए कि इस सर्वर को केवल Next.js
00:08:18सर्वर द्वारा ही एक्सेस किया जा सकता है और बाहरी दुनिया द्वारा नहीं। मान लीजिए कि यह हमारे क्लाउड डिप्लॉयमेंट पर था।
00:08:23फिर हम बस एक बहुत ही साधारण curl रिक्वेस्ट भेजेंगे जहाँ हम अपने
00:08:26Next.js एप्लिकेशन को curl रिक्वेस्ट भेजते हैं। तो वह पोर्ट 3002 पर था और हम कहते हैं कि हम चाहते हैं कि हमारा
00:08:31रिक्वेस्ट टारगेट वह सर्वर हो जिसे हम उस लोकलहोस्ट URL पर एक्सेस करना चाहते हैं। अगर मैं अब इस पर
00:08:36एंटर दबाता हूँ तो आप देख सकते हैं कि क्या वापस आता है। यह वास्तव में पायथन सर्वर का HTML पेज है
00:08:40जहाँ इसमें बस बेसिक डायरेक्टरी लिस्टिंग है और अगर मैं खुद पायथन सर्वर पर वापस जाऊं
00:08:45तो आप देख सकते हैं कि उसमें एक रिक्वेस्ट आई थी जो वास्तव में Next.js एप्लिकेशन से आई थी।
00:08:49हमने जो किया उसे बेहतर ढंग से समझने के लिए मान लीजिए कि इस डॉटेड लाइन में हमारा Next.js डिप्लॉयमेंट है
00:08:53तो हमारे पास हमारा Next.js सर्वर है और फिर कुछ इंटरनल सर्विसेज भी हैं जैसे कि Redis,
00:08:57एक डेटाबेस या कोई अन्य सर्विस और आप नहीं चाहते कि पब्लिक की इस तक पहुँच हो,
00:09:02ताकि कोई भी इस पर curl रिक्वेस्ट न भेज सके, यह फायरवॉल द्वारा ब्लॉक और लॉक होगा
00:09:06और इसे केवल Next.js सर्वर द्वारा ही एक्सेस किया जा सकता है। हमने क्या किया है कि हमने बस
00:09:10Next.js सर्वर को एक curl रिक्वेस्ट भेजी है और हमने कहा है कि क्या आप हमारी ओर से इंटरनल सर्विस को
00:09:15रिक्वेस्ट भेज सकते हैं और हमें वह जानकारी वापस मिल गई है, इसलिए हमने उस फायरवॉल को Next.js के माध्यम से
00:09:19बायपास कर दिया है, जिसके पास इंटरनल सर्विस तक पहुँच है। इसका मूल कारण
00:09:23भी बहुत सरल है, मूल रूप से हम अपनी curl रिक्वेस्ट में एक upgrade websocket
00:09:28हेडर भेजते हैं और जब हम ये हेडर भेजते हैं तो Next.js में क्या होता है कि हम कोड के इस हिस्से
00:09:32पर पहुँचते हैं और यह हमारे URL पर रूट्स (routes) को रिसॉल्व करता है लेकिन यहाँ हमें जो पास्ड (parsed) URL मिलता है वह
00:09:37वास्तव में वही रिक्वेस्ट टारगेट है जिसे हम अपनी curl रिक्वेस्ट में भेजते हैं, इसलिए यह वह
00:09:40टारगेट होने वाला है जिसे हम उस इंटरनल सर्वर पर पहुँचने की कोशिश कर रहे हैं न कि वास्तव में Next.js एप्लिकेशन।
00:09:45इस पास्ड URL के साथ क्या होता है कि यह यह देखने के लिए नीचे एक चेक से गुज़रता है कि क्या
00:09:49पास्ड URL में कोई प्रोटोकॉल है लेकिन इस मामले में यह हाँ है क्योंकि हम HTTP का उपयोग कर रहे हैं और वह एक प्रोटोकॉल है
00:09:55इसलिए यह आगे बढ़ता है और हमारे लिए उस रिक्वेस्ट को प्रॉक्सी कर देता है। इसके समाधान में हमारे
00:09:58'रिसॉल्व रूट्स' फंक्शन पर दो नए गार्ड्स जोड़े गए हैं जो हमें पहले थे, अब हमें एक फिनिश्ड (finished)
00:10:02बुलियन और साथ ही एक स्टेटस कोड मिल रहा है। यह रिसॉल्व रूट्स फंक्शन वास्तव में क्या करता है कि यह
00:10:06हमारे URL को लेता है और प्रोसेस करता है कि क्या यह हमारे Next.js रीराइट्स (rewrites),
00:10:11मिडलवेयर और इस तरह की चीजों के आधार पर एक वैध प्रॉक्सी रिक्वेस्ट है, यदि नहीं तो इसका मतलब है कि फिनिश्ड
00:10:15फॉल्स पर सेट हो जाएगा, तो यहाँ नीचे हमारे पास एक चेक है यदि फिनिश्ड ट्रू है तो हम अगले चरण पर जा सकते हैं, यदि
00:10:20नहीं तो यह फॉल्स पर सेट है इसलिए यह नहीं चलेगा जिसका मतलब है कि हम अपनी प्रॉक्सी रिक्वेस्ट नहीं चलाएंगे
00:10:24और हमारी curl रिक्वेस्ट के मामले में जो हमारे पास पहले थी, बिल्कुल वही होने
00:10:27वाला है कि 'फिनिश्ड' फॉल्स पर सेट हो जाएगा। अब अगर किसी तरह फिनिश्ड ट्रू पर सेट हो गया तो हमारा अगला
00:10:32चेक स्टेटस कोड है, जब रिसॉल्व रूट्स चलता है तो हमें वास्तव में एक स्टेटस कोड वापस मिलता है यदि
00:10:36रिक्वेस्ट एक HTTP वाली है, तो यह 200, 404 या ऐसा ही कुछ होने वाला है, इसलिए यदि कोई स्टेटस
00:10:41कोड है तो इसका मतलब है कि यह एक वैध वेब सॉकेट प्रॉक्सी रिक्वेस्ट नहीं है, इसलिए यह बस इस लाइन को
00:10:45अनदेखा कर देगा और इसे नहीं चलाएगा। मैंने वास्तव में इस वीडियो में इन मुद्दों की गहराई में जाने की कोशिश की है
00:10:49इसलिए मुझे बताएं कि क्या आप अभी भी कुछ रैंडम कमेंट करके देख रहे हैं, मुझे नहीं पता जैसे
00:10:53'bar' या ऐसा ही कुछ और अगर आप कंटेंट को पसंद करते हैं तो सब्सक्राइब भी करें। हमारे पास दो
00:10:58और श्रेणियां हैं जिन्हें पार करना है लेकिन ये थोड़ी तेज़ होनी चाहिए और मैं 'कैश पॉइज़निंग' (cache poisoning)
00:11:01से शुरुआत करूँगा जहाँ मैं इस 'मॉडरेट' मुद्दे को दोबारा बनाने में कामयाब रहा और आप देख सकते हैं कि यह
00:11:04रिएक्ट सर्वर कंपोनेंट में कैश पॉइज़निंग है और इसे 10 में से 5.4 स्थान दिया गया है। इसे दोबारा
00:11:09बनाने के लिए मेरे पास एक Next.js एप्लिकेशन है लेकिन फिर मेरे पास एक नकली CDN भी है ताकि ऐसा लगे जैसे यह
00:11:14एक वास्तविक डिप्लॉय किए गए वातावरण में था। इसका मतलब है कि अगर मैं पहली बार इसके CDN URL पर
00:11:18अपनी साइट पर जाता हूँ और फिर 'ब्राउज़ प्रोडक्ट्स' पर क्लिक करता हूँ और वापस जाकर फिर से क्लिक करता हूँ, तो पहली बार
00:11:23यह 'कैश मिस' होना चाहिए और फिर अगली बार 'कैश हिट'। हम उसे यहाँ लॉग्स में
00:11:27होते हुए देख सकते हैं, हमारे पास पहले एक क्वेरी स्ट्रिंग के साथ miss slash products था और फिर अगली बार यह
00:11:31एक 'हिट' था। हालाँकि मैंने इसके बाद कैश को साफ़ कर दिया है ताकि यह सिमुलेट किया जा सके कि शायद कैश एक्सपायर हो गया है
00:11:35या कुछ और और अब मैं यह curl रिक्वेस्ट भेज सकता हूँ। मेरे एप्लिकेशन पर वापस जाने पर
00:11:39अगर मैं अब 'ब्राउज़ प्रोडक्ट्स' पर क्लिक करता हूँ तो आप देख सकते हैं कि हमें बहुत सारा कचरा (gibberish) वापस मिलता है इसलिए हमने सफलतापूर्वक
00:11:44एक कैश पॉइज़निंग हमला किया है। मुझे विश्वास है कि यहाँ जो हो रहा है वह यह है कि जब हम अपनी curl
00:11:47रिक्वेस्ट भेजते हैं जिसमें रिएक्ट सर्वर कंपोनेंट का हेडर एक है, तो यह URL HTML के बजाय
00:11:52अपना सर्वर कंपोनेंट डेटा वापस करने वाला है। फिर जब इसे कैश करने की आवश्यकता होगी, तो अगला चरण
00:11:58एक फंक्शन से गुज़रना है जो चेक करता है कि यह सर्वर कंपोनेंट डेटा है या नहीं। यदि यह सर्वर कंपोनेंट डेटा
00:12:02है तो यह इसे कैश में वैसे ही स्टोर करेगा और यदि नहीं तो यह इसे HTML के रूप में स्टोर करेगा। इसका मतलब है कि
00:12:07सैद्धांतिक रूप से जब यूज़र पेज का HTML वर्ज़न प्राप्त करने की कोशिश करता है यानी बस
00:12:11बटन पर क्लिक करके, तो उसे कभी भी सर्वर कंपोनेंट डेटा वापस नहीं मिलना चाहिए। समस्या यह है कि
00:12:16हमारे मामले में चूंकि हमारी सर्वर कंपोनेंट curl रिक्वेस्ट के अंत में यह क्वेरी स्ट्रिंग थी, इसलिए
00:12:20इसने यह जांचने की आवश्यकताओं को पूरा नहीं किया कि यह सर्वर कंपोनेंट है या नहीं क्योंकि
00:12:24वह केवल यह जांचता है कि यह .rsc पर समाप्त होता है या नहीं, लेकिन हमारा वर्ज़न क्वेरी स्ट्रिंग पर समाप्त होता है, इसलिए
00:12:29अब इसे लगता है कि यह HTML है, यह इसे कैश में HTML के रूप में स्टोर करता है इसलिए अगली बार जब कोई यूज़र बटन पर
00:12:33क्लिक करता है तो उन्हें वास्तव में सर्वर कंपोनेंट डेटा वापस मिल जाता है क्योंकि इसे लगा कि
00:12:37वह HTML था। इसके लिए सुधार अविश्वसनीय रूप से सरल था जब वे यह चेक कर रहे हैं कि क्या
00:12:41यह .rsc पर समाप्त होता है, तो वे अब बस क्वेरी स्ट्रिंग्स को अनदेखा कर देते हैं। अब CVE की हमारी अंतिम
00:12:46श्रेणी की ओर बढ़ते हुए हमारे पास कुछ क्रॉस साइट स्क्रिप्टिंग (XSS) वाली समस्याएं हैं, यह वह है जिसे मैं दोबारा बनाने
00:12:50में कामयाब रहा, आप देख सकते हैं कि यह 6.1 है और इसमें अनट्रस्टेड इनपुट के साथ
00:12:55बिफोर इंटरेक्टिव (before interactive) स्क्रिप्ट्स में क्रॉस साइट स्क्रिप्टिंग है। मूल रूप से इसका मतलब यह है कि Next.js में अगर मेरे पास कोई
00:12:59स्क्रिप्ट टैग है जिसकी 'स्ट्रेटेजी' बिफोर इंटरेक्टिव है, तो यदि मेरे पास इस पर कोई अन्य एट्रिब्यूट है
00:13:03जिसे किसी प्रकार के अनट्रस्टेड कंटेंट की आवश्यकता है, उदाहरण के लिए यह सर्च पैराम्स (search params) से
00:13:08आ रहा है, तो मैं क्रॉस साइट स्क्रिप्टिंग कर सकता हूँ। मैं यूज़र से ऐसे लिंक पर क्लिक करवाकर ऐसा कर सकता हूँ
00:13:12जहाँ मैंने उस सर्च पैराम में बहुत सारा कंटेंट एम्बेड किया है। अगर कोई
00:13:16उस लिंक पर क्लिक करता है तो उन्हें यह दिखाई देगा, इसलिए उन्हें लग सकता है कि उन्हें फिर से साइट पर
00:13:19लॉग इन करना होगा और जब वे साइन इन पर क्लिक करते हैं तो आप यहाँ देख सकते हैं कि वह पूरी तरह से एक
00:13:22फर्जी लॉगिन फॉर्म था जिसे उस सर्च पैराम के माध्यम से इंजेक्ट किया गया था। यह अनिवार्य रूप से हमलावर को
00:13:26विक्टिम की मशीन पर कुछ जावास्क्रिप्ट चलाने की अनुमति देता है, इसलिए मुझे लगता है कि एक अधिक यथार्थवादी उदाहरण
00:13:31क्रोम की सेशन कुकीज़ चुराना होगा ताकि उन सभी चीजों में लॉग इन किया जा सके जिन तक आपकी पहुँच थी।
00:13:34यह गलत एस्केपिंग का एक बहुत ही सरल उदाहरण है और हम इसे इस अधिक सरल वर्ज़न के साथ
00:13:39थोड़ा आसानी से देख सकते हैं लेकिन मैं उस सर्च पैराम में बस इतना कर रहा हूँ कि मैं पहले एक
00:13:43स्क्रिप्ट टैग को बंद कर रहा हूँ फिर एक नया स्क्रिप्ट टैग खोल रहा हूँ जो कुछ भी मैं उसमें चलाना चाहता हूँ। जब हम
00:13:47उस पर एंटर दबाते हैं तो आप देख सकते हैं कि मुझे वह अलर्ट मिलता है जो कहता है “pwned” जैसा कि मैंने आपको अपने ऐप के साथ दिखाया था।
00:13:51यह जिस तरह से काम करता है वह यह है कि हमें एक Next.js स्क्रिप्ट टैग चाहिए जिसकी स्ट्रेटेजी बिफोर इंटरेक्टिव हो
00:13:55और आप उस स्क्रिप्ट टैग पर कुछ एट्रिब्यूट भी चाहते हैं जो किसी अनट्रस्टेड
00:13:59सोर्स से अपना डेटा लेता हो, मेरे मामले में वह क्वेरी पैराम्स से आ रहा है। Next.js में यह जो करता है वह यह है कि यह
00:14:04स्क्रिप्ट टैग कुछ इस तरह में बदल जाता है जहाँ हमारे पास एक dangerouslySetInnerHTML है।
00:14:08मेरा मतलब है, इसके नाम में ही है कि यह खतरनाक होने वाला है और हमारे पास एक JSON.stringify भी है।
00:14:12JSON stringify के बारे में जानने वाली महत्वपूर्ण बात यह है कि यह क्लोजिंग ब्रैकेट जैसे HTML कैरेक्टर्स को एस्केप नहीं करता है
00:14:17इसलिए वास्तव में यहाँ जो हो रहा है वह यह है कि हम उन सभी स्क्रिप्ट टैग्स को ले रहे हैं
00:14:21जिन्हें हमने Next.js में सेटअप किया है, यह सोर्स की तलाश कर रहा है जो यहाँ सेट होने वाला है और
00:14:24फिर बाकी के प्रॉप्स में डेटा ट्रैकिंग आईडी और साथ ही वह वैल्यू होगी जो
00:14:29हमने अपने क्वेरी पैरामीटर में सेट की थी, तो वह इस JSON stringify में चली जाती है। खैर, यह वास्तव में
00:14:33पेज पर रेंडर होता है, कुछ इस तरह से, तो हमारे पास हमारी डेटा ट्रैकिंग आईडी है जो
00:14:37बाकी प्रॉप्स थे लेकिन फिर हमारे पास वह स्ट्रिंग भी है जिसे हमने क्वेरी
00:14:41पैराम्स के माध्यम से डाला था। तो अगर हम विस्तार से देखें कि यह पेज पर वास्तव में कैसा दिखता है, तो यह कुछ
00:14:45इस तरह दिखता है, हमारे पास हमारा स्क्रिप्ट टैग है, हमारे पास एक डेटा ट्रैकिंग आईडी है लेकिन फिर इसके बाद हमारे पास वास्तव में
00:14:49एक क्लोजिंग स्क्रिप्ट टैग है, इसलिए यह उस स्क्रिप्ट टैग को समाप्त कर देता है जिसे Next.js करने की कोशिश कर रहा था और इसके बाद
00:14:53हम उस पेज पर जो भी स्क्रिप्ट चाहें चला सकते हैं। फिर हमारे पास अंत में यह एक्स्ट्रा हिस्सा भी है
00:14:58क्योंकि अगर हमारे पास यह नहीं होता तो एनालिटिक्स वास्तव में पेज पर
00:15:01टेक्स्ट के रूप में रेंडर होता क्योंकि HTML इसे टेक्स्ट के रूप में देखता, इसलिए यह अनिवार्य रूप से बस उसे
00:15:05निगल लेता है ताकि कोई स्पष्ट संकेत न मिले कि उस पेज पर कुछ बुरा हो रहा है और इस तरह
00:15:09इस हफ्ते Next.js और React के लिए 13 CVEs और उनमें से कुछ ने कैसे काम किया, और ईमानदारी से
00:15:14मुझे नहीं पता कि इस बारे में क्या सोचना है। मुझे यह नापसंद है और यह उस जगह से आ रहा है जहाँ दो
00:15:18साल पहले तक मेरा हर प्रोजेक्ट Next.js में था और मुझे लगा था कि यह सबसे अच्छा और भविष्य है,
00:15:22लेकिन ऐसा लगता है कि इसमें एक के बाद एक मुश्किलें आ रही हैं। ऐसा लगता है कि उन्होंने कुछ चीज़ों में
00:15:26जल्दबाजी की और फिर उन्हें बाद में ठीक करना पड़ा। व्यक्तिगत रूप से अब मैं पूरी तरह से TanStack और
00:15:31Astro की ओर झुक गया हूँ जब मुझे कंटेंट आधारित साइट की ज़रूरत होती है, वे मुझे बहुत सरल लगते हैं और ईमानदारी से
00:15:35Cloudflare हाल ही में जो कर रहा है वह भी मुझे बहुत पसंद आ रहा है इसलिए मैं धीरे-धीरे
00:15:39अपने प्रोजेक्ट्स को वहाँ माइग्रेट कर रहा हूँ लेकिन मेरे लगभग 20 प्रोजेक्ट अभी भी Vercel पर हैं और मुझे जाकर
00:15:43उन्हें अपडेट करना होगा। आप क्या सोचते हैं, क्या सर्वर कंपोनेंट्स कभी उपयोगी होंगे या हमने उन्हें आज़माया और विफल रहे?
00:15:48मुझे नीचे कमेंट्स में बताएं, सब्सक्राइब करें और हमेशा की तरह
00:15:51अगले वीडियो में मिलते हैं।

Key Takeaway

Next.js और React में 13 नई सुरक्षा कमियों के कारण संवेदनशील डेटा लीक और सर्वर शटडाउन का गंभीर जोखिम है, जिसे केवल नवीनतम वर्ज़न पर अपडेट करके ही ठीक किया जा सकता है।

Highlights

  • React और Next.js में कुल 13 नई कमियां (CVEs) पाई गई हैं, जिनमें से 6 'हाई' गंभीरता की श्रेणी में आती हैं।

  • i18n सक्षम होने पर Next.js का मिडलवेयर 'slash secret' जैसे बेस रूट्स की रक्षा करने में विफल रहता है, जिससे अनधिकृत यूज़र्स को डेटा मिल सकता है।

  • रिएक्ट सर्वर कंपोनेंट्स में एक खामी हमलावर को 20 करोड़ स्ट्रिंग तुलनाएं कराकर सर्वर थ्रेड को ब्लॉक करने और 'डिनायल ऑफ सर्विस' की अनुमति देती है।

  • एक SSRF भेद्यता (CVE-2024-34351) के कारण हमलावर Next.js सर्वर के माध्यम से इंटरनल नेटवर्क सर्विसेज और डेटाबेस तक पहुँच प्राप्त कर सकते हैं।

  • Next.js स्क्रिप्ट टैग में 'beforeInteractive' रणनीति और JSON.stringify के उपयोग से हमलावर दुर्भावनापूर्ण जावास्क्रिप्ट इंजेक्ट कर सकते हैं।

Timeline

सुरक्षा संकट और प्रभावित फ्रेमवर्क्स

  • React और Next.js के मौजूदा इकोसिस्टम में 13 अलग-अलग सुरक्षा भेद्यताएं मौजूद हैं।
  • इन समस्याओं में मिडलवेयर बायपास, क्रॉस-साइट स्क्रिप्टिंग और डिनायल ऑफ सर्विस शामिल हैं।
  • TanStack जैसे कुछ वैकल्पिक फ्रेमवर्क्स इन विशिष्ट सुरक्षा मुद्दों से प्रभावित नहीं हैं।

सर्वर कंपोनेंट्स के कार्यान्वयन में आई जटिलताओं ने सुरक्षा के नए जोखिम पैदा किए हैं। प्रभावित वर्ज़न का उपयोग करने वाले सभी एप्लिकेशन्स को तुरंत अपडेट करने की सलाह दी गई है। यह इस साल का तीसरा बड़ा सुरक्षा अलर्ट है जो रिएक्ट सर्वर कंपोनेंट्स से संबंधित है।

मिडलवेयर और i18n प्रॉक्सी बायपास

  • i18n (अंतर्राष्ट्रीयकरण) कॉन्फ़िगरेशन वाले एप्लिकेशन्स में मिडलवेयर सुरक्षा को बायपास किया जा सकता है।
  • एक साधारण URL बदलाव के माध्यम से सर्वर-साइड प्रॉप्स जैसे संवेदनशील डेटा को बिना लॉगिन के एक्सेस करना संभव है।
  • Next.js का मैचर कोड बेस केस रूट्स की सुरक्षा करने में विफल रहता है जब लोकेल वेरिएंट्स सक्रिय होते हैं।

जब i18n सक्षम होता है, तो 'slash secret' जैसा रूट सुरक्षित नहीं रहता जबकि उसके लोकेल वर्ज़न (जैसे /en/secret) सुरक्षित हो सकते हैं। हमलावर '_next/data' URL और बिल्ड आईडी का उपयोग करके सीधे JSON डेटा प्राप्त कर सकते हैं। यह 10 में से 7.5 की गंभीरता रेटिंग वाली समस्या है।

सर्वर कंपोनेंट्स में डिनायल ऑफ सर्विस (DoS)

  • रिएक्ट फ्लाइट प्रोटोकॉल में डी-सीरियलाइजेशन की प्रक्रिया सर्वर को धीमा करने के लिए इस्तेमाल की जा सकती है।
  • लाखों कीज़ वाले पेलोड भेजने से सर्वर रिस्पांस समय 0.02 सेकंड से बढ़कर 6 सेकंड तक हो सकता है।
  • कर्सर-बेस्ड सिस्टम की कमी के कारण सर्वर को बार-बार पूरी की-लिस्ट को पार करना पड़ता है।

हमलावर पेलोड में हजारों पॉइंटर्स और रैंडम कीज़ जोड़कर CPU पर अत्यधिक बोझ डाल सकते हैं। सुधार के बाद, ऑपरेशन्स की संख्या $k*n$ से घटकर $n+k$ हो गई है, जिससे थ्रेड ब्लॉकिंग का जोखिम कम हुआ है। यह समस्या मुख्य रूप से Next.js और रिएक्ट सर्वर DOM पैकेज का उपयोग करने वाले फ्रेमवर्क्स को प्रभावित करती है।

सर्वर-साइड रिक्वेस्ट फोर्जरी (SSRF) भेद्यता

  • सेल्फ-होस्टेड Next.js एप्लिकेशन्स में 10 में से 8.6 गंभीरता वाला SSRF जोखिम मौजूद है।
  • हमलावर 'upgrade websocket' हेडर का उपयोग करके Next.js सर्वर को इंटरनल सर्विसेज के लिए प्रॉक्सी के रूप में इस्तेमाल कर सकते हैं।
  • यह खामी बाहरी हमलावरों को फायरवॉल के पीछे छिपे डेटाबेस और Redis सर्वर तक पहुँच प्रदान करती है।

Next.js का रूट रिसॉल्वर 'request-target' को ठीक से गार्ड नहीं करता था, जिससे वह आंतरिक नेटवर्क के URL को भी प्रोसेस कर लेता था। नए सुधार में स्टेटस कोड और फिनिश्ड बुलियन जैसे नए चेक जोड़े गए हैं जो अवैध प्रॉक्सी रिक्वेस्ट को रोकते हैं। ध्यान देने योग्य है कि Vercel पर होस्ट किए गए एप्लिकेशन्स इस विशिष्ट हमले से सुरक्षित पाए गए थे।

कैश पॉइज़निंग और XSS हमले

  • क्वेरी स्ट्रिंग में हेरफेर करके सर्वर कंपोनेंट डेटा को HTML के रूप में कैश कराया जा सकता है।
  • स्क्रिप्ट टैग्स में गलत एस्केपिंग के कारण फर्जी लॉगिन फॉर्म इंजेक्ट किए जा सकते हैं।
  • JSON.stringify क्लोजिंग HTML ब्रैकेट्स को एस्केप नहीं करता, जिससे स्क्रिप्ट इंजेक्शन आसान हो जाता है।

कैश पॉइज़निंग हमलावरों को वैध यूज़र्स के लिए वेबसाइट का स्वरूप बदलने की अनुमति देता है। क्रॉस-साइट स्क्रिप्टिंग (XSS) के माध्यम से यूज़र की सेशन कुकीज़ चुराई जा सकती हैं। 'beforeInteractive' रणनीति का उपयोग करने वाले स्क्रिप्ट टैग विशेष रूप से असुरक्षित पाए गए हैं क्योंकि वे सीधे अनट्रस्टेड इनपुट को रेंडर करते हैं।

Community Posts

View all posts