
HTTP/2 से HTTP/1.1 रूपांतरण के माध्यम से HTTP अनुरोध तस्करी की कमजोरियों का पता लगाता है और उनका शोषण करता है, बैकएंड पार्सिंग विसंगतियों की पहचान करने के लिए स्वचालित हेडर तस्करी तकनीकों का उपयोग करता है।
यह उपकरण HTTP अनुरोध तस्करी का पता लगाने और उसका शोषण करने में मदद करता है जब इसे फ्रंटएंड सर्वर द्वारा HTTP/2 -> HTTP/1.1 रूपांतरण के माध्यम से प्राप्त किया जा सकता है।
योजना इस प्रकार है:
हमलावर ऐसा अनुरोध ढूंढना चाहता है जो बैकएंड सर्वर को दो अलग-अलग अनुरोधों के रूप में दिखाई दे।
यदि फ्रंटएंड<->बैकएंड HTTP/1.1 कनेक्शन कीप-अलाइव का उपयोग करता है, तो फ्रंटएंड उसी कनेक्शन पर अन्य उपयोगकर्ताओं के अनुरोध भेज सकता है। यदि हम एक आंशिक अनुरोध के साथ कनेक्शन को "जहर" देने में सक्षम हैं जो एक वैध अनुरोध के बाद आता है, तो हम दूसरे उपयोगकर्ता से अनुरोध प्राप्त कर सकते हैं।
अन्य संभावित परिदृश्यों में फ्रंटएंड सर्वर सुरक्षा और पुनर्लेखन को दरकिनार करना, कैश पॉइज़निंग या कैश धोखाधड़ी शामिल है।
HTTP अनुरोध तस्करी पर अधिक जानकारी के लिए कृपया Portswigger Web Security Academy देखें।
HTTP/2 में, सभी HTTP हेडर के नाम और मान बाइनरी होते हैं। इसका मतलब है कि तकनीकी रूप से उनमें अतिरिक्त स्थान या नई पंक्तियाँ भी हो सकती हैं।
RFC7540#10.3 में कहा गया है कि जो कार्यान्वयन HTTP/2 अनुरोधों को HTTP/1 में अनुवाद करते हैं, उन्हें वर्ण सेट पर सीमाओं का ध्यान रखना चाहिए जो ऐसे रूपांतरण से उत्पन्न होती हैं; अधिकांश कार्यान्वयन वास्तव में उन्हें अस्वीकार करते हैं। इसके बावजूद, हम ऐसे कार्यान्वयन खोजने की उम्मीद करते हैं जो ऐसे हेडर की अनुमति देते हैं। वे बैकएंड के लिए परिवर्तित HTTP/1.1 अनुरोध को दूषित कर देंगे।
एक और बात यह है कि HTTP अनुरोध तस्करी से संबंधित कुछ हालिया सुधार केवल HTTP/1.1 पार्सर्स में लागू किए गए हो सकते हैं।
सामान्य तौर पर, हम उम्मीद करते हैं कि HTTP/2 के कुछ कार्यान्वयन हैं जो HTTP/1.1 में HTTP अनुरोध तस्करी पर हाल के शोध से बहुत अवगत नहीं हैं और संबंधित शमन उपायों को शामिल नहीं करते हैं।
आश्चर्यजनक रूप से, हाँ!
मुझे Cloudflare के माध्यम से एक स्पेस कैरेक्टर वाले हेडर की तस्करी करने की संभावना मिली, जिससे Cloudflare<->क्लाइंट तस्करी का दरवाजा खुल गया (यदि Cloudflare क्लाइंट का सॉफ्टवेयर हेडर नामों को स्वीकार करता है और ट्रिम करता है)। यहाँ ब्लॉग पोस्ट है।
एक और बग बाउंटी रिपोर्ट भी है जो अभी तक सार्वजनिक नहीं है। यह इस तथ्य का उपयोग करता है कि कस्टम सॉफ़्टवेयर HTTP2 हेडर में न्यूलाइन को फ़िल्टर नहीं करता है, और तस्करी 100% होती है (मैं अन्य उपयोगकर्ताओं के अनुरोध देख सकता हूँ)।
हालाँकि, मैं समझता हूँ कि इस प्रकार की कमजोरियाँ निराशाजनक रूप से दुर्लभ होनी चाहिए: HTTP/1.1 के विपरीत, HTTP/2 के इतने सारे कार्यान्वयन नहीं हैं, और उनमें से अधिकांश सुरक्षा को ध्यान में रखकर बनाए गए हैं, इस प्रकार संदिग्ध या अमान्य हेडर को अस्वीकार करते हैं।
टूल में एक उपकमांड है जो स्वचालित रूप से पता लगाने का प्रयास करता है कि कोई लक्ष्य HTTP अनुरोध तस्करी हमले के लिए संवेदनशील है या नहीं। इस सुविधा के पीछे एल्गोरिदम इस खंड में वर्णित है।
HTTP अनुरोध तस्करी हमला करने के लिए, हमें वास्तव में पहले एक हेडर (या तो Content-Length या Transfer-Encoding) की "तस्करी" करने की आवश्यकता है। इसका मतलब है कि हमें एक ऐसा हेडर भेजना होगा जो क) यह नियंत्रित करता है कि अनुरोध का मुख्य भाग कहाँ समाप्त होता है और ख) फ्रंटएंड द्वारा संसाधित नहीं किया जाता है लेकिन बैकएंड द्वारा संसाधित किया जाता है।
यह आमतौर पर एक हेडर को किसी तरह से संशोधित करके प्राप्त किया जाता है: इसके नाम के अंत में स्थान या टैब जोड़ना, मान को अर्ध-समतुल्य से बदलना आदि।
कमजोरी का पता लगाने वाले एल्गोरिदम का मूल विचार यह पता लगाना है कि क्या सर्वर वास्तव में एक तस्करी किए गए हेडर को संसाधित करता है जैसे कि वह Content-Length या Transfer-Encoding हो। हम एकाधिक अनुरोध भेजकर ऐसा करते हैं: कुछ हेडर के लिए मान्य और अन्य के लिए अमान्य मानों के साथ। फिर यह पता लगाने का प्रयास करते हैं कि क्या इन दोनों समूहों के प्रतिक्रियाओं को अलग करने का कोई तरीका है।
इसीलिए टूल आउटपुट में "संवेदनशील/असंवेदनशील" शब्द नहीं होते: यह केवल यह बताता है कि क्या वह इन दो समूहों के अनुरोधों पर आई प्रतिक्रियाओं को अलग कर सकता है।
टूल HTTP प्रतिक्रियाओं के दो सेटों को अलग-अलग मानता है यदि निम्नलिखित दो शर्तों में से कम से कम एक पूरी होती है:
टाइमआउट को एक अद्वितीय स्थिति कोड मान के रूप में माना जाता है जो किसी अन्य के बराबर नहीं है; इस प्रकार, टूल शास्त्रीय "समय द्वारा पता लगाने" योजना से बेहतर है।
आइए एक उदाहरण पर विचार करें। मान लीजिए कि हम डैश को अंडरस्कोर से बदलकर transfer-encoding हेडर की तस्करी करने का प्रयास कर रहे हैं।
यदि ऐसा प्रतीत होता है कि सर्वर हर बार जब हम transfer_encoding:zalupa भेजते हैं तो स्थिति 400 के साथ प्रतिक्रिया करता है और जब यह transfer_encoding:chunked होता है तो हैंग हो जाता है, तो हम कह सकते हैं कि सर्वर संभवतः हेडर को ट्रांसफर एन्कोडिंग के मान के रूप में संसाधित करता है। सैद्धांतिक रूप से, यह फ्रंटएंड या बैकएंड सर्वर हो सकता है।
पहला मामला दिलचस्प नहीं है क्योंकि हम वैसे भी हेडर का गैर-तस्करी संस्करण भेज सकते हैं, और दूसरा वह है जिसकी हम तलाश कर रहे हैं। चूंकि सब कुछ HTTP/2 पर होता है, पहला मामला अधिकांश समय टाला जा सकता है: HTTP/2 सर्वर अनुरोध के मुख्य भाग के अंत को दूसरे तरीके से निर्धारित करता है जो अनुरोध हेडर से असंबंधित है और कभी भी HTTP/1.1 चंक्ड प्रारूप (हेक्साडेसिमल चंक लंबाई वाला) में मुख्य भाग की अपेक्षा नहीं करता है।
पता लगाने की तकनीकों के ठोस रूपांतर हैं:
हम Transfer-Encoding: chunked का तस्करी किया गया संस्करण (जैसे transfer_encoding:chunked) और अलग-अलग मुख्य भाग भेजते हैं: मान्य है 0\r\n\r\n और अमान्य है 999\r\n।
यदि प्रतिक्रियाएँ अलग हैं, तो हम निश्चित हो सकते हैं कि बैकएंड सर्वर तस्करी किए गए हेडर को प्राप्त करता है और संसाधित करता है। फ्रंटएंड के ऐसा करने का कोई कारण नहीं है: HTTP/2 हमारे द्वारा भेजे गए चंक्ड प्रारूप का उपयोग नहीं करता है, इसलिए यह अमान्य होगा।
हम उम्मीद करते हैं कि बैकएंड अमान्य अनुरोधों के लिए हैंग हो जाता है (अर्थात, अनुरोध टाइमआउट हो जाता है) क्योंकि यह अधिक डेटा आने की प्रतीक्षा करता है।
यह सबसे विश्वसनीय पता लगाने का रूपांतर है: यदि मुख्य भाग पढ़ते समय सर्वर हैंग हो जाता है, तो संभवतः कुछ गलत हो गया है क्योंकि HTTP/2 अनुरोध में HTTP/1.1 ट्रांसफर एन्कोडिंग का कोई उपयोग नहीं है।
हम Transfer-Encoding का तस्करी किया गया संस्करण और फिर से अलग-अलग मुख्य भाग भेजते हैं: 0\r\n\r\n मान्य मुख्य भाग के रूप में और X\r\n\r\n अमान्य मुख्य भाग के रूप में।
मामला ऊपर जैसा ही है, लेकिन मुख्य भाग पढ़ने के बजाय, हम उम्मीद करते हैं कि बैकएंड कम से कम इसे मान्य करेगा।
हम Content-Length हेडर का तस्करी किया गया संस्करण मान 1 और -1 के साथ भेजते हैं।
दोनों मान फ्रंटएंड के दृष्टिकोण से अमान्य हैं: HTTP/2 में मुख्य भाग की लंबाई निर्धारित करने का एक और तंत्र है, और दोनों मामलों में वास्तव में कोई अनुरोध मुख्य भाग नहीं भेजा जाता है। यदि प्रतिक्रियाएँ अलग हैं, तो हम मानते हैं कि यह बैकएंड सर्वर था जिसने हेडर को पार्स किया।
यह विधि सबसे कम विश्वसनीय है: हो सकता है कि फ्रंटएंड अलग-अलग त्रुटियाँ जारी करे जब Content-Length का मान अमान्य हो, और जब यह वास्तविक लंबाई से मेल नहीं खाता हो।
कई जोड़े मान्य/अमान्य अनुरोध भेजकर, हम यादृच्छिक गलत सकारात्मकता की संभावना को कम कर सकते हैं। दूसरी ओर, हम जल्दी रुक सकते हैं यदि हम देखते हैं कि "मान्य" अनुरोधों पर प्रतिक्रियाओं को "अमान्य" अनुरोधों पर प्रतिक्रियाओं से अलग करने का कोई तरीका नहीं है।
टूल एक हेडर को विभिन्न तरीकों से संशोधित करके कई तस्करी तकनीकों का उपयोग करने का प्रयास करता है। उनमें से कोई भी नई या एक ही समय में स्पष्ट नहीं है।
एक हेडर की तस्करी करने के लिए, हम इसमें एक स्थान जोड़ते हैं। यह सबसे सामान्य और क्लासिक विधि है। हम उम्मीद करते हैं कि हेडर फ्रंटएंड द्वारा संसाधित नहीं किया जाता है बल्कि ज्यों का त्यों बैकएंड को भेजा जाता है, जो स्थान को हटा देता है।
टूल स्थान के रूप में विभिन्न प्रकार के वर्णों का प्रयास करता है: इसमें , \t, \v, \x00 और यूनिकोड शामिल हैं।