一、漏洞簡介
Jackson是一個廣泛使用的Java庫,用於將JSON數據與Java對象相互轉換。由於其高效且易於使用,Jackson已成為許多Java應用程序的首選序列化和反序列化庫。然而,Jackson在處理反序列化時存在安全漏洞,攻擊者可以通過精心構造的JSON數據利用這些漏洞進行注入攻擊,進而竊取機密信息或遠程執行惡意代碼。這類安全漏洞稱為Jackson反序列化漏洞。
二、漏洞分類
根據CVE漏洞分類標準,Jackson反序列化漏洞可以分為以下三類:
1.遠程代碼執行漏洞
攻擊者可以構造惡意JSON數據,通過反序列化觸發遠程代碼執行漏洞,從而在受害者計算機上執行任意惡意代碼。
2.路徑遍歷漏洞
攻擊者可以構造惡意JSON數據,通過反序列化觸發路徑遍歷漏洞,竊取應用程序的敏感信息或配置文件。
3.反射注入漏洞
在某些情況下,攻擊者可以構造惡意JSON數據,通過反序列化觸發反射注入漏洞,從而使得攻擊者可以在受害者計算機上執行惡意代碼。
三、漏洞成因
Jackson反序列化漏洞的根本原因是Java反序列化機制的缺陷。在Java中,對象可以在網路上或磁碟上進行序列化,將其轉換為位元組流。序列化使得我們可以將對象轉換為流,以便在不同的應用程序之間共享。反序列化是在收到位元組流時將其轉換回Java對象。Jackson庫使用Java中的反射機制實現對象的反序列化,反射機制通過訪問對象的內部信息使得對象可以動態地創建、修改和處理,但它的缺陷也非常突出,這些缺陷為Jackson反序列化漏洞的產生提供了基礎。
四、漏洞驗證與漏洞實例分析
1.漏洞驗證
下面是一個漏洞驗證用例,攻擊者通過惡意構造JSON數據觸發遠程代碼執行漏洞,在受害者計算機上執行命令:
import com.fasterxml.jackson.databind.ObjectMapper; public class Test { public static void main(String[] args) throws Exception { String json = "{\"@class\":\"com.test.Exploit\",\"name\":\"test\",\"command\":\"calc.exe\"}"; ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); mapper.readValue(json, Object.class); } }
在這個例子中,攻擊者構建了一個名為Exploit的Java類,並將命令calc.exe作為Exploit對象的屬性值,然後使用ObjectMapper將其轉換為JSON字元串。接著,攻擊者使用ObjectMapper反序列化JSON字元串,由於ObjectMapper啟用了默認類型序列化,攻擊者的Exploit類和calc.exe命令將在受害者計算機上執行。
2.漏洞實例分析
以下是一個實際情況下的漏洞案例分析,通過該案例我們可以深入了解漏洞產生的原因以及防禦該漏洞的方法。
在Springfox-swagger2庫中使用的Jackson-databind庫存在反序列化漏洞。具體來說,在Springfox-swagger2庫的2.7.0版本以及之前的版本中,假設攻擊者能夠成功向伺服器端注入惡意對象,將可導致RCE漏洞。該漏洞的觸發條件如下:
攻擊者可以構造一個JSON字元串,其中包含一個表示日期的屬性,值為相應類型的JSON。由於在轉換Java類型之前,Jackson-databind庫沒有正確驗證輸入的類型,攻擊者可以通過構造適當的JSON類型來利用反序列化漏洞。
public class Exploit { public Exploit() throws Exception { // run calc.exe final String[] calc = new String[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"}; Runtime.getRuntime().exec(calc); } }
在上面的代碼中,我們定義了一個名為Exploit的類,並在構造函數中執行了calc.exe命令。這個Exploit的類聲明一個惡意類的成員,在編寫Jackson反序列化漏洞利用代碼時,這個Exploit類將被用於向伺服器送入一個用於反序列化的有效JSON字元串,以實現執行計算器應用程序的目的。
{ "date": { "@class": "com.exploit.Exploit" } }
攻擊者可以通過使用下面的JSON字元串將有效Java對象注入受害者的伺服器端,從而觸發攻擊:
{ "date": { "@class": "com.exploit.Exploit" } }
在上面的JSON字元串中,我們定義了一個JSON對象date,其中包含一個@class屬性,值為Exploit類的名稱,這是 Jackson-databind庫的一個特殊屬性,能夠自動進行類型解析和反序列化操作,因此,對於指定的類名稱,Jackson-databind庫將創建一個對象並將其初始化為注入的值,這是漏洞利用的重點。這個對象的初始化將調用Exploit類的構造函數,從而執行命令執行calc.exe程序。
五、漏洞修復
可以通過以下方式防止此類漏洞的出現:
1.關閉Jackson的默認類型序列化功能
關閉Jackson的默認類型序列化功能可以消除反序列化漏洞,這樣可以忽略來自不信任源的數據。請注意,關閉默認類型序列化功能可能導致某些應用程序出現不可預測的行為。
ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); //關閉默認類型序列化功能 mapper.disableDefaultTyping();
2.限制反序列化的輸入
可以通過Java Security Manager限制反序列化操作的輸入,防止攻擊者構造惡意JSON數據來觸發序列化攻擊。
SecurityManager sm = new SecurityManager(); Policy.setPolicy(new Policy() { @Override public PermissionCollection getPermissions(CodeSource codesource) { return new Permissions(); } }); System.setSecurityManager(sm);
3.使用Jackson的註解
開發人員使用Jackson的註解可以使反序列化過程受到更多的控制,從而避免誤用對象反序列化從而導致安全漏洞。
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat")}) public abstract class Animal { //... }
六、總結
本文深入介紹了Jackson反序列化漏洞的原因、分類及成因,並通過漏洞實例分析詳細講解了漏洞利用方法。最後,介紹了三種防範和修復該漏洞的方法,開發人員應該充分了解這些方法,並在編寫代碼時遵守相應的安全規則,以避免安全問題。
原創文章,作者:TSQYQ,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/334904.html