<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>

    Dubbo Kryo & FST RCE

    VSole2022-11-25 15:31:47


    漏洞簡介

    漏洞原理

    Dubbo Provider即服務提供方默認使用dubbo協議來進行RPC通信,而dubbo協議默認是使用Hessian2序列化格式進行對象傳輸的,但是針對Hessian2序列化格式的對象傳輸可能會有黑白名單設置的限制,參考:https://github.com/apache/dubbo/pull/6378

    針對這種場景,攻擊者可以通過更改dubbo協議的第三個flag位字節來更改為使用Kryo或FST序列化格式來進行Dubbo Provider反序列化攻擊從而繞過針對Hessian2反序列化相關的限制來達到RCE。

    影響版本

    • Dubbo 2.7.0 to 2.7.8
    • Dubbo 2.6.0 to 2.6.9
    • Dubbo all 2.5.x versions (not supported by official team any longer)

    環境復現

    安裝zookeeper和dubbo-samples,用idea打開dubbo-samples-api,然后修改其中的pom.xml如下:

    注意,dubbo-common必須 ≤2.7.3版本。

    在Dubbo<=2.7.3中fastjson的版本≤1.2.46 ,這也是我們這個洞的利用點,不過這里復現使用的更高版本所以需要添加依賴,

    <dependency>    <groupId>com.alibabagroupId>    <artifactId>fastjsonartifactId>    <version>1.2.46version>dependency>
    

    使用POC進行測試:

    Dubbo的協議設計

    由于Dubbo可以支持很多類型的反序列化協議,以滿足不同系統對RPC的需求,比如:

    ?跨語言的序列化協議:Protostuff、ProtoBuf、Thrift、Avro、MsgPack

    ? 針對Java語言的序列化方式:Kryo、FST

    ? 基于Json文本形式的反序列化方式:Json、Gson

    Dubbo中對支持的協議做了一個編號,每個序列化協議都有一個對應的編號,以便在獲取TCP流量后,根據編號選擇相應的反序列化方法,因此這就是Dubbo支持這么多序列化協議的秘密,但同時也是危險所在。

    org.apache.dubbo.common.serialize.Constants中可見每種序列化協議的編號:

    而在Dubbo的RPC通信時,對流量的規定最前方為header,而header中通過指定SerializationID,確定客戶端和服務提供端通信過程使用的序列化協議。

    Dubbo通信的具體數據包規定如下圖所示:

    雖然Dubbo的provider默認使用hessian2協議,但我們可以自由的修改SerializationID,選定危險的(反)序列化協議,例如kryo和fst。

    Dubbo RPC數據包格式

    ?Magic(魔術) - Magic High & Magic Low (16 bits)用值標識dubbo協議:0xdabb?Req/Res (1 bit)標識這是一個請求或響應。請求 : 1;響應 : 0。?2 Way (1 bit)Only useful when Req/Res is 1 (Request), expect for a return value from server or not. Set to 1 if need a return value from server.?Event (1 bit)Identifies an event message or not, for example, heartbeat event. Set to 1 if this is an event.?Serialization ID (5 bit)標識序列化類型:fastjson 的值為 6。?Status (8 bits)Only useful when Req/Res is 0 (Response), identifies the status of response?20 - OK–30 - CLIENT_TIMEOUT–31 - SERVER_TIMEOUT–40 - BAD_REQUEST–50 - BAD_RESPONSE–60 - SERVICE_NOT_FOUND–70 - SERVICE_ERROR–80 - SERVER_ERROR–90 - CLIENT_ERROR–100 - SERVER_THREADPOOL_EXHAUSTED_ERROR?Request ID (64 bits)Identifies an unique request. Numeric (long).?Data Length (32)序列化后內容(可變部分)的長度,以字節為單位。數字(整數)。?Variable PartEach part is a byte[] after serialization with specific serialization type, identifies by Serialization ID.Every part is a byte[] after serialization with specific serialization type, identifies by Serialization ID1.If the content is a Request (Req/Res = 1), each part consists of the content, in turn is:?Dubbo version–Service name–Service version–Method name–Method parameter types–Method arguments–Attachments1.If the content is a Response (Req/Res = 0), each part consists of the content, in turn is:?Return value type, identifies what kind of value returns from server side: RESPONSE_NULL_VALUE - 2, RESPONSE_VALUE - 1, RESPONSE_WITH_EXCEPTION - 0.–Return value, the real value returns from server.
    

    注意:對于(Variable Part)變長部分,當前版本的dubbo框架使用json序列化時,在每部分內容間額外增加了換行符作為分隔,請選手在Variable Part的每個part后額外增加換行符,如:

    Dubbo version bytes (換行符)Service name bytes  (換行符)...
    

    案例

    漏洞分析

    FTS反序列化

    FTS反序列化發生在RPC協議反序列化。

    org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation#decode(org.apache.dubbo.remoting.Channel, java.io.InputStream)
    

    在上述方法中首先通過serializationType索引序列化器,當TypeId為8時使用Kryo,TypeId為9時使用Fst。

    kryo和fst的調用鏈都比較類似,使用map序列化器反序列化時觸發,

    instantiate:79, FSTMapSerializer (org.nustaq.serialization.serializers)instantiateAndReadWithSer:497, FSTObjectInput (org.nustaq.serialization)readObjectWithHeader:366, FSTObjectInput (org.nustaq.serialization)readObjectFields:708, FSTObjectInput (org.nustaq.serialization)instantiateAndReadNoSer:562, FSTObjectInput (org.nustaq.serialization)readObjectWithHeader:370, FSTObjectInput (org.nustaq.serialization)readObjectFields:708, FSTObjectInput (org.nustaq.serialization)instantiateAndReadNoSer:562, FSTObjectInput (org.nustaq.serialization)readObjectWithHeader:370, FSTObjectInput (org.nustaq.serialization)readObjectInternal:327, FSTObjectInput (org.nustaq.serialization)instantiate:77, FSTMapSerializer (org.nustaq.serialization.serializers)instantiateAndReadWithSer:497, FSTObjectInput (org.nustaq.serialization)readObjectWithHeader:366, FSTObjectInput (org.nustaq.serialization)readObjectInternal:327, FSTObjectInput (org.nustaq.serialization)readObject:307, FSTObjectInput (org.nustaq.serialization)readObject:102, FstObjectInput (org.apache.dubbo.common.serialize.fst)decode:116, DecodeableRpcInvocation (org.apache.dubbo.rpc.protocol.dubbo)decode:73, DecodeableRpcInvocation (org.apache.dubbo.rpc.protocol.dubbo)decodeBody:132, DubboCodec (org.apache.dubbo.rpc.protocol.dubbo)
    

    核心部分調用堆棧入手,根據調用堆棧可知獲取了FstSerialization解析器進行反序列化,在反序列化的過程中必然涉及到還原對象以及相關字段,而在還原HashMap 的時候對其成員進行還原時候會調用HashMap#put方法將鍵值對進行放入,而這個放入的過程就是觸發漏洞的關鍵點,在放入的過程中存在兩個口子,一個是hashCode,另一個是 equals。

    這里調用equals口子進入toString方法,由此可知這里使用的:


    org.springframework.aop.target.HotSwappableTargetSource#equals -> com.sun.org.apache.xpath.internal.objects.XString#equals(java.lang.Object) -> xxxx.toString()
    

    這里再次觸發equals方法,參數是我們構造的惡意JSONObject對象,

    com.sun.org.apache.xpath.internal.objects.XString#equals(java.lang.Object)
    

    在上述方法 中觸發了傳入的惡意JSONObject對象的toString方法:

    fastjson中JSONObject是可以被序列化的,當其顯式或隱式被調用toString方法時,會觸發綁定對象的getter方法:

    這里將會觸發這個JSONObject中成員的值,也就是觸發了這個TemplatesImpl對象的get系列方法,而我們的Payload入口就是getOutProperties方法,至于后面就是常規的TemplatesImpl利用手法。

    下圖是POC中對應的鏈的構造:

    完整漏洞調用棧

    exec:-1, Runtime (java.lang):-1, Pwner8957425893700 (ysoserial)newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:-1, DelegatingConstructorAccessorImpl (sun.reflect)newInstance:-1, Constructor (java.lang.reflect)newInstance:-1, Class (java.lang)getTransletInstance:-1, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)newTransformer:-1, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)getOutputProperties:-1, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)write:-1, ASMSerializer_1_TemplatesImpl (com.alibaba.fastjson.serializer)write:270, MapSerializer (com.alibaba.fastjson.serializer)write:44, MapSerializer (com.alibaba.fastjson.serializer)write:280, JSONSerializer (com.alibaba.fastjson.serializer)toJSONString:863, JSON (com.alibaba.fastjson)toString:857, JSON (com.alibaba.fastjson)equals:-1, XString (com.sun.org.apache.xpath.internal.objects)equals:104, HotSwappableTargetSource (org.springframework.aop.target)putVal:-1, HashMap (java.util)put:-1, HashMap (java.util)instantiate:79, FSTMapSerializer (org.nustaq.serialization.serializers)instantiateAndReadWithSer:497, FSTObjectInput (org.nustaq.serialization)readObjectWithHeader:366, FSTObjectInput (org.nustaq.serialization)readObjectInternal:327, FSTObjectInput (org.nustaq.serialization)readObject:307, FSTObjectInput (org.nustaq.serialization)readObject:102, FstObjectInput (org.apache.dubbo.common.serialize.fst)decode:116, DecodeableRpcInvocation (org.apache.dubbo.rpc.protocol.dubbo)decode:73, DecodeableRpcInvocation (org.apache.dubbo.rpc.protocol.dubbo)decodeBody:132, DubboCodec (org.apache.dubbo.rpc.protocol.dubbo)decode:122, ExchangeCodec (org.apache.dubbo.remoting.exchange.codec)decode:82, ExchangeCodec (org.apache.dubbo.remoting.exchange.codec)decode:48, DubboCountCodec (org.apache.dubbo.rpc.protocol.dubbo)decode:90, NettyCodecAdapter$InternalDecoder (org.apache.dubbo.remoting.transport.netty4)decodeRemovalReentryProtection:508, ByteToMessageDecoder (io.netty.handler.codec)callDecode:447, ByteToMessageDecoder (io.netty.handler.codec)channelRead:276, ByteToMessageDecoder (io.netty.handler.codec)invokeChannelRead:379, AbstractChannelHandlerContext (io.netty.channel)invokeChannelRead:365, AbstractChannelHandlerContext (io.netty.channel)fireChannelRead:357, AbstractChannelHandlerContext (io.netty.channel)channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)invokeChannelRead:379, AbstractChannelHandlerContext (io.netty.channel)invokeChannelRead:365, AbstractChannelHandlerContext (io.netty.channel)fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)processSelectedKey:719, NioEventLoop (io.netty.channel.nio)processSelectedKeysOptimized:655, NioEventLoop (io.netty.channel.nio)processSelectedKeys:581, NioEventLoop (io.netty.channel.nio)run:493, NioEventLoop (io.netty.channel.nio)run:989, SingleThreadEventExecutor$4 (io.netty.util.concurrent)run:74, ThreadExecutorMap$2 (io.netty.util.internal)run:30, FastThreadLocalRunnable (io.netty.util.concurrent)run:-1, Thread (java.lang)
    

    Kryo反序列化

    在DecodeableRpcInvocation類的decode()方法(該方法會在處理RPC請求時候調用)中,通過serializationType為8、獲取到反序列化器Kryo,然后調用readUTF()函數來讀取dubbo協議對應的字段信息如dubbo協議版本、服務名稱、服務版本、方法名、方法參數類型等:

    提取方法參數類型為類數組后,再循環對參數進行Kryo反序列化。

    從input中讀取解析到type為HashMap,因此會調用Kryo的MapSerializer序列化器來讀取input中的信息:

    其中會將解析到的key和value都通過調用map.put()來放入HashMap對象中,發生在com.esotericsoftware.kryo.serializers.MapSerializer#read方法調用中,這里是有兩對鍵值對放進去了:

    往下putVal()函數中會調用key即XString類的equals()函數來判斷兩個key值是否相等:

    到這和前面FST反序列化基本上一樣了。

    修復

    dubbo-common 2.7.3的版本中存在kryo和fst的序列化需要的類,而在dubbo-common 2.7.4.1中,這三個包并不存在,需要自行導入。

    在高版本中已將com.esotericsoftware:kryo依賴去掉了,在使用Kryo序列化器進行反序列化獲取KryoObjectInput對象時會報找不到KryoException類的錯誤,自帶的Fastjson版本為1.2.70,AutoType會自動攔截掉TemplatesImpl類。

    dubbodecode
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Dubbo Kryo & FST RCE
    2022-11-25 15:31:47
    影響版本Dubbo 2.7.0 to 2.7.8Dubbo 2.6.0 to 2.6.9Dubbo all 2.5.x versions 環境復現 安裝zookeeper和dubbo-samples,用idea打開dubbo-samples-api,然后修改其中的pom.xml如下: 注意,dubbo-common必須 ≤2.7.3版本。在Dubbo<=2.7.3中fastjson的版本≤1.2.46 ,這也是我們這個洞的利用點,不過這里復現使用的更高版本所以需要添加依賴, com.alibabagroupId> fastjsonartifactId> 1.2.46version>dependency>. 案例漏洞分析 FTS反序列化FTS反序列化發生在RPC協議反序列化。
    攻擊者可能利用此漏洞獲取敏感信息或執行惡意代碼。漏洞概述  漏洞名稱Apache Dubbo多個反序列化漏洞漏洞編號CVE-2023-29234、CVE-2023-46279公開時間2023-12-15影響對象數量級十萬級奇安信評級高危CVSS 評分7.7、8.1威脅類型信息泄露、代碼執行利用可能性中POC狀態未公開在野利用狀態未發現EXP狀態未公開技術細節狀態未公開危害描述:
    近日,安識科技A-Team團隊監測到Apache發布安全公告,修復了一個Apache Dubbo中的遠程代碼執行漏洞。漏洞威脅等級:嚴重。該漏洞是由于在Dubbo的hessian-lite中存在反序列化漏洞,未經身份驗證的攻擊者可利用該漏洞在目標系統上遠程執行任意代碼。 對此,安識科技建議廣大用戶及時升級到安全版本,并做好資產自查以及預防工作,以免遭受黑客攻擊。
    近日,奇安信CERT監測到國外安全研究人員披露Apache Dubbo多個高危漏洞詳情,其中包括Apache Dubbo YAML反序列化漏洞(CVE-2021-36162):解析攻擊者構造的惡意YAML規則時,使用SnakeYAML進行反序列化從而造成遠程代碼執行;Apache Dubbo Hessian協議反序列化漏洞(CVE-2021-36163):當Apache Dubbo服務提...
    2022年1月13日,360漏洞云團隊監測到Apache發布安全公告,修復了一個Apache Dubbo中的遠程代碼執行漏洞。漏洞編號: CVE-2021-43297,漏洞威脅等級:高危。
    在2022RSA大會上,來自Techstrong Research[1]的Mitch Ashley發表了一個名為“The Rise of API Security:It’s 10 pm – Do You Know Where Your APIs Are?”的演講。該議題主要針對目前不斷增長的API安全進行了調查和探討。
    Apache Log4j2是一款Java開源日志組件,該工具重寫了Log4j框架,該日志框架被大量用于業務系統開發,用來記錄日志信息。多數情況之下,開發者可能會將用戶輸入導致的錯誤信息寫入日志中。此漏洞的嚴重性、影響面,堪稱史上之最。若程序使用gradle打包,可查看編譯配置文件,若在dependencies部分存在相關字段,且版本號為小于,則存在該漏洞。
    這篇文章主要收集一些常見的未授權訪問漏洞。未授權訪問漏洞可以理解為需要安全配置或權限認證的地址、授權頁面存在缺陷導致其他用戶可以直接訪問從而引發重要權限可被操作、數據庫或網站目錄等敏感信息泄露。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类