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

          Fastjson < 1.2.68版本反序列化漏洞分析篇

          共 7173字,需瀏覽 15分鐘

           ·

          2020-10-25 04:39

          點(diǎn)擊上方藍(lán)色“程序猿DD”,選擇“設(shè)為星標(biāo)”

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!

          作者 |?ale_wong@云影實(shí)驗(yàn)室
          來(lái)源 |?https://www.anquanke.com/post/id/219731

          前言

          遲到的Fastjson反序列化漏洞分析,按照國(guó)際慣例這次依舊沒(méi)有放poc。道理還是那個(gè)道理,但利用方式多種多樣。除了之前放出來(lái)用于文件讀寫(xiě)的利用方式以外其實(shí)還可以用于SSRF。

          ?

          一、漏洞概述

          在之前其他大佬文章中,我們可以看到的利用方式為通過(guò)清空指定文件向指定文件寫(xiě)入指定內(nèi)容(用到第三方庫(kù))。當(dāng)gadget是繼承的第一個(gè)類(lèi)的子類(lèi)的時(shí)候,滿足攻擊fastjson的條件。此時(shí)尋找到的需要gadget滿足能利用期望類(lèi)繞過(guò)checkAutoType。

          本文分析了一種利用反序列化指向fastjson自帶類(lèi)進(jìn)行攻擊利用,可實(shí)現(xiàn)文件讀取、SSRF攻擊等。

          ?

          二、調(diào)試分析

          1. 漏洞調(diào)試

          從更新的補(bǔ)丁中可以看到expectClass類(lèi)新增了三個(gè)方法分別為:

          java.lang.Runnable、java.lang.Readable、java.lang.AutoCloseable

          首先,parseObject方法對(duì)傳入的數(shù)據(jù)進(jìn)行處理。通過(guò)詞法解析得到類(lèi)型名稱,如果不是數(shù)字則開(kāi)始checkAutoType檢查。

          if (!allDigits) {
          clazz = config.checkAutoType(typeName, null, lexer.getFeatures());
          }

          當(dāng)傳入的數(shù)據(jù)不是數(shù)字的時(shí)候,默認(rèn)設(shè)置期望類(lèi)為空,進(jìn)入checkAutoType進(jìn)行檢查傳入的類(lèi)。

          final boolean expectClassFlag;
          if (expectClass == null) {
          expectClassFlag = false;
          } else {
          if (expectClass == Object.class
          || expectClass == Serializable.class
          || expectClass == Cloneable.class
          || expectClass == Closeable.class
          || expectClass == EventListener.class
          || expectClass == Iterable.class
          || expectClass == Collection.class
          ) {
          expectClassFlag = false;
          } else {
          expectClassFlag = true;
          }
          }

          判斷期望類(lèi),此時(shí)期望類(lèi)為null。往下走的代碼中,autoCloseable 滿足不在白名單內(nèi),不在黑名單內(nèi),autoTypeSupport沒(méi)有開(kāi)啟,expectClassFlag為false。

          其中:

          A.計(jì)算哈希值進(jìn)行內(nèi)部白名單匹配

          B.計(jì)算哈希值進(jìn)行內(nèi)部黑名單匹配

          C.非內(nèi)部白名單且開(kāi)啟autoTypeSupport或者是期望類(lèi)的,進(jìn)行hash校驗(yàn)白名單acceptHashCodes、黑名單denyHashCodes。如果在acceptHashCodes內(nèi)則進(jìn)行加載( defaultClassLoader),在黑名單內(nèi)則拋出 autoType is not support。

          clazz = TypeUtils.getClassFromMapping(typeName);

          滿足條件C后來(lái)到clazz的賦值,解析來(lái)的代碼中對(duì)clazz進(jìn)行了各種判斷

          clazz = TypeUtils.getClassFromMapping(typeName);

          從明文緩存中取出autoCloseable賦值給 clazz

          clazz = TypeUtils.getClassFromMapping(typeName);

          if (clazz == null) {
          clazz = deserializers.findClass(typeName);
          }

          if (clazz == null) {
          clazz = typeMapping.get(typeName);
          }

          if (internalWhite) {
          clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);
          }

          if (clazz != null) {
          if (expectClass != null
          && clazz != java.util.HashMap.class
          && !expectClass.isAssignableFrom(clazz)) {
          throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
          }

          return clazz;

          當(dāng)clazz不為空時(shí),expectClassFlag為空不滿足條件,返回clazz,至此,第一次的checkAutoType檢查完畢。

          ObjectDeserializer deserializer = config.getDeserializer(clazz);
          Class deserClass = deserializer.getClass();
          if (JavaBeanDeserializer.class.isAssignableFrom(deserClass)
          && deserClass != JavaBeanDeserializer.class
          && deserClass != ThrowableDeserializer.class) {
          this.setResolveStatus(NONE);
          } else if (deserializer instanceof MapDeserializer) {
          this.setResolveStatus(NONE);
          }
          Object obj = deserializer.deserialze(this, clazz, fieldName);
          return obj;

          將檢查完畢的autoCloseable進(jìn)行反序列化,該類(lèi)使用的是JavaBeanDeserializer反序列化器,從MapDeserializer中繼承

          public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
          return deserialze(parser, type, fieldName, 0);
          }

          public T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features) {
          return deserialze(parser, type, fieldName, null, features, null);
          }//進(jìn)入后代碼如下

          if ((typeKey != null && typeKey.equals(key))
          || JSON.DEFAULT_TYPE_KEY == key) {
          lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
          if (lexer.token() == JSONToken.LITERAL_STRING) {
          String typeName = lexer.stringVal();
          lexer.nextToken(JSONToken.COMMA);

          if (typeName.equals(beanInfo.typeName)|| parser.isEnabled(Feature.IgnoreAutoType)) {
          // beanInfo.typeName是autoCloseable ,但I(xiàn)gnoreAutoType沒(méi)有開(kāi)啟
          if (lexer.token() == JSONToken.RBRACE) {
          lexer.nextToken();
          break;
          }
          continue;
          }//不滿足條件所以這塊代碼被跳過(guò)了

          JSON.DEFAULT_TYPE_KEY 為@type?,并給它賦值傳入的key?@type?,將第二個(gè)類(lèi)也就是這次 的gadget傳入

          if (deserializer == null) {
          Class expectClass = TypeUtils.getClass(type);
          userType = config.checkAutoType(typeName, expectClass, lexer.getFeatures());
          deserializer = parser.getConfig().getDeserializer(userType);
          }

          期望類(lèi)在這里發(fā)生了變化,expectClass的值變?yōu)閖ava.lang.AutoCloseable,typeName為gadget,

          boolean jsonType = false;
          InputStream is = null;
          try {
          String resource = typeName.replace('.', '/') + ".class";
          if (defaultClassLoader != null) {
          is = defaultClassLoader.getResourceAsStream(resource);
          } else {
          is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
          //開(kāi)了一個(gè)class文件的輸入流
          }
          if (is != null) {
          ClassReader classReader = new ClassReader(is, true);//new reader工具
          TypeCollector visitor = new TypeCollector("", new Class[0]);
          classReader.accept(visitor);
          jsonType = visitor.hasJsonType();
          }
          } catch (Exception e) {
          // skip
          } finally {
          IOUtils.close(is);//關(guān)閉流 JarURLConnection$JarURLInputStream
          }

          來(lái)到JSONType注解,取typename gadget轉(zhuǎn)換變?yōu)槁窂剑瑀esource通過(guò)將 “.” 替換為”/“得到路徑 。其實(shí)已經(jīng)開(kāi)始讀取gadget了,它本意應(yīng)該是加載AutoCloseable。

          public ClassReader(InputStream is, boolean readAnnotations) throws IOException {
          this.readAnnotations = readAnnotations;

          {
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          byte[] buf = new byte[1024];
          for (; ; ) {
          int len = is.read(buf);
          if (len == -1) {
          break;
          }

          if (len > 0) {
          out.write(buf, 0, len);
          }
          }
          is.close();
          this.b = out.toByteArray();
          }

          可以看到這里有讀取文件的功能。所以之前網(wǎng)傳的POC可能是利用這里這個(gè)特性(?)留意一下以后研究…

          if (autoTypeSupport || jsonType || expectClassFlag) {
          boolean cacheClass = autoTypeSupport || jsonType;
          clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
          //開(kāi)始加載gadget
          }

          if (expectClass != null) {
          if (expectClass.isAssignableFrom(clazz)) {//判斷里面的類(lèi)是否為繼承類(lèi)
          TypeUtils.addMapping(typeName, clazz);
          return clazz;
          } else {
          throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
          }
          }

          isAssignableFrom()這個(gè)方法用于判斷里面的類(lèi)是否為繼承類(lèi),當(dāng)利用了java.lang.AutoCloseable這個(gè)方法去攻擊fastjson,那么后續(xù)反序列化的鏈路需要是繼承于該類(lèi)的子類(lèi)。

          TypeUtils.addMapping(typeName, clazz)這一步成功把gadget加入緩存中并返回被賦值gadget的clazz.

          checkAutoType正式檢查完畢,此時(shí)用deserializer = parser.getConfig().getDeserializer(userType); userType既gadget進(jìn)行反序列化。

          private void xxTryOnly(boolean isXXXXeconnect, Properties mergedProps) throws
          XXXException {
          Exception connectionNotEstablishedBecause = null;

          try {

          coreConnect(mergedProps);
          this.connectionId = this.io.getThreadId();
          this.isClosed = false;

          進(jìn)入coreConnect()

          在這里進(jìn)行連接。至此漏洞利用完結(jié)。

          ?

          2. 總結(jié)

          在本次反序列化漏洞中,筆者認(rèn)為關(guān)鍵點(diǎn)在于找到合適并且可利用的常用jar包中的gadget。gadget在被反序列化后即可執(zhí)行類(lèi)里的惡意的功能(不僅限于RCE還包括任意文件讀取/創(chuàng)建,SSRF等)。也可以使本漏洞得到最大化的利用。

          ?

          三、參考考鏈接

          • https://b1ue.cn/archives/348.html

          • https://daybr4ak.github.io/2020/07/20/fastjson%201.6.68%20autotype%20bypass/


          往期推薦

          音效摸魚(yú)還不夠爽?試試IDE里打幾盤(pán)魂斗羅?

          3折購(gòu)書(shū)優(yōu)惠碼限時(shí)搶?zhuān)诙〞?shū)單來(lái)了!

          面試:知道 CopyOnWriteArrayList 嗎?

          居然還有人在用 System.out.println打日志的嗎?

          不錯(cuò)的秒殺系統(tǒng)架構(gòu)分析與實(shí)戰(zhàn)!

          一個(gè)讓你敲代碼的同時(shí),找回童年樂(lè)趣的 IntelliJ 插件


          掃一掃,關(guān)注我

          一起學(xué)習(xí),一起進(jìn)步

          每周贈(zèng)書(shū),福利不斷


          深度內(nèi)容

          推薦加入


          最近熱門(mén)內(nèi)容回顧? ?#技術(shù)人系列

          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  www.黄网 | 麻豆成人电影九九 | 天干夜天干天天天爽色播 | 99久久久无码... | 草 榴一区二区三区 |