Java漏洞原理與實戰

一、基本概念

1、序列化與反序列化

(1)序列化:將對象寫入IO流中,ObjectOutputStream類的writeobject()方法可以實現序列化

(2)反序列化:從IO流中恢復對象,ObjectinputStream類的readObject()方法用于反序列化

(3)意義:序列化機制允許將實現序列化的Java對象轉換為字節序列,這些字節序列可以保存到磁盤上,或通過網絡傳輸,以達到以后恢復成原來的對象。序列化機制使得對象可以脫離程序的運行而獨立存在

(4)序列化與反序列化是讓Java對象脫離Java運行環境的一種手段,可以有效的實現多平臺之間的通信、對象持久化儲存。主要應用在以下場景:

HTTP:多平臺之間的通信,管理等,也可以用于流量帶外

RMI:是Java的一組擁護開發分布式應用程序的API,實現了不同操作系統之間程序的方法調用。值得注意的是,RMI的傳輸100%基于反序列化,Java RMI的默認端口是1099端口

JMX:JMX是一套標準的代理和服務,用戶可以在任何Java應用程序中使用這些代理和服務實現管理,中間件weblogic的管理頁面就是基于JMX開發的,而JBoss則整個系統都基于JMX框架

(5)Java代碼審計思路

如果是Java原生類,則需要入口類readObject方法,同時實現了序列化接口,使其可以進行有效的反序列化,此時如果存在DNS解析,或者實現反序列化(利用Runtime對象進行類反射操作)

需要有最終的執行函數(可以執行代碼或者命令),比如Runtime.getRuntime().exec,ProcessBuilder().start,getHostAddress,文件讀寫...等等,這些函數需要自己平常去收集,這樣審計起來會更得心應手

2、Java類反射機制

(1) 反射機制的作用:通過Java語言中的反射機制可以操作字節碼文件(可以讀和修改字節碼文件),可以通過另外的方式調用到類的屬性和方法,甚至私有屬性和方法

(2)反射機制的相關類在java.lang.reflect.*包下面

(3)反射機制的相關類有哪些:Constructor、Field、Method、Class等類

(4)java.lang.Class代表字節碼文件,代表整個類

(5)java.lang.reflect.Method代表字節碼中的方法字節碼,代表類中的方法java.lang.reflect.Constructor代表字節碼中的構造方法字節碼,代表類中的構造方法java.lang.reflect.Field代表字節碼中的屬性字節碼,代表類中的屬性

(6)Java中為什么要使用反射機制,直接創建對象不是更方便?

如果有多個類,每個用戶所需求的對象不同,直接創建對象,就要不斷的去new一個對象,非常不靈活。而Java反射機制,在運行時確定類型,綁定對象,動態編譯最大限度發揮了java的靈活性

(7)獲取成員變量

(8)獲取并調用方法

(9)獲取構造方法

(10)訪問私有屬性

二、類反射機制實踐

package com.woniu.vul;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;class Test{public String name = "蝸牛學苑";public int age = 8;private String addr = "西安";private int price = 10000;public Test() {}public Test(int price){this.price = price;}public int setPrice(int price){System.out.println("新價格為:" + price);return price;}public int getPrice(){return this.price;}private void getAddr(){System.out.println("私有方法:" + addr);}}public class Reflect {public static void main(String[] args) throws Exception {/*Test t = new Test();System.out.println(t.getPrice());Test t1 = new Test(15000);System.out.println(t1.getPrice());System.out.println(t.name);*///使用反射機制實現屬性和方法的調用(包括構造方法)//使用Class.forName可以獲取到類本身,在JVM中動態加載Test類//Class clazz = Class.forName("com.woniu.vul.Test");//Class clazz = Test.class;//使用new Instance進行實例化//Test t = (Test) clazz.newInstance();//System.out.println(t.getPrice());//Object o = clazz.newInstance();  //實例化動態加載的類,類型必須是Object//        Method m1 = clazz.getMethod("getPrice");
//        int price1 = (int)m1.invoke(o,null);
//        System.out.println(price1);
//
//        Method m2 = clazz.getMethod("setPrice",int.class);
//        int price2 = (int)m2.invoke(o,15000);
//        System.out.println(price2);//調用price私有屬性和getAddr私有方法,getFiled只能調用公有屬性,getDeclareField才能調私有屬性//Field f1 = clazz.getDeclaredField("price");//f1.setAccessible(true);  //設置私有屬性可訪問//System.out.println(f1.get(o));//getMethod只能調用公有方法,而getDeclareMethod才能嗲用私有方法//Method m1 = clazz.getDeclaredMethod("getAddr");//m1.setAccessible(true);//m1.invoke(o,null);//構造方法如果有參數,怎么辦?Class clazz = Class.forName("com.woniu.vul.Test");Constructor c = clazz.getConstructor(int.class);  //獲取到一個帶參數的構造器Object o = c.newInstance(10); //用構造器去構造一個動態加載的類Method m1 = clazz.getDeclaredMethod("getPrice");int price = (int) m1.invoke(o,null);System.out.println(price);//遍歷所有方法或操作Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {System.out.println(method + "   " + method.getName() + "    " + method.getModifiers());}Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {System.out.println(field + "   " + field.getName() + "    " + field.getModifiers());}}
}

三、序列化與反序列化

序列化的實現代碼

package com.woniu.vul;import java.io.*;class Student implements Serializable {public String name = "";public int id = 0;public String phone = "";public Student(){System.out.println("構造方法運行");}public void study(){System.out.println("學生正在學習");}public void sleep(){System.out.println("學生正在休息");}
}public class Unserial {public void serial() throws Exception {Student s = new Student();s.name = "張三";s.id = 12345;s.phone = "188123456786";FileOutputStream fos = new FileOutputStream("./data/student.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(s);}public void unserial() throws Exception {FileInputStream fis = new FileInputStream("./data/student.ser");ObjectInputStream ois = new ObjectInputStream(fis);Student obj =(Student) ois.readObject();System.out.println(obj.name);obj.study();}public static void main(String[] args) throws Exception {Unserial us = new Unserial();//us.serial();us.unserial();}
}

序列化的內容如下:

?然后進行反序列化,切記不要去改我們的序列化內容,不然無法反序列化回去

?我們再補充兩個小問題

正常情況下,高亮部分是可以被序列化的,但是如果在這之前加上transient來修飾的話就無法序列化

高亮部分的意思就是定義一個序列化版本的編號,也就是唯一標識

?

這個標識是用來干嘛的

接下來我們看看

我們重新反序列化看看效果

報錯信息告訴我們是一個不可用的類

為什么不可用,讓我們繼續看報錯信息

序列化的時候類的ID是前面的那一個,但是反序列的時候類的ID是后面那一個,序列化和反序列化的時候標識號是不一樣的,意思就是這個類并不是我們需要反序列化的類

我們將代碼中的ID改為其序列化時候原本的ID,那我們就可以完成反序列化的操作了

也就是說這個類在序列化的時候會記錄下其類的標識UID

接下來我們看看反序列化產生的機制

首先這個序列化對象一旦有重寫的方法,那我們在反序列化的時候會優先調用重寫的readObject


?因為我們重寫了readObject,所以就會先調用readObject,這就是Java反序列化的起點,也是唯一的起點

也就是說Java反序列化漏洞能夠被利用,我們得有一個最基本的前提,就是目標類必須重寫readObject方法,只有這樣,代碼才會被自動調用,否則就沒有起點

如果不重寫readObject方法的話,就不會發生Java反序列化漏洞

而我們的代碼已經重寫了readObject方法,所以我們可以對其利用

我們可以直接在重寫方法的下面加上終點,也就是攻擊者想要達到的效果,有始有終,整個攻擊鏈才算完整

當然我們也可以使用類反射機制的手段去執行命令

因為getRuntime的實例不是純粹的new出來的,而是通過調用getRuntime這個方法來獲取其實例的,然后再通過這個實例去調用exec

加載java.lang.Runtime類

獲取Runtime類中的getRuntime方法

調用Runtime方法,獲取Runtime類的實例

獲取Runtime類中的exec(string)方法

調用exec(String)方法,運行外部命令ifconfig

?運行代碼,發現沒有報錯,說明應該是利用成功了,我不知道為啥不會顯示執行ifconfig命令的內容,如果是Windows的話,可以將ifconfig改為calc.exe,大概率會顯示出計算器

當然為了執行命令,不僅僅只有Runtime,還有ProcessBuilder

接下來我們看看其反射的調用

根據正常的調用來構造反射

先使用Class.forName這個方法來加載java.lang.ProcessBuilder這個類

然后使用Class對象的getConstructor來獲取Processbuilder類的構造函數

接著使用Constructor對象的newInstance方法來創建ProcessBuilder的實例

然后使用Class對象的getMethod方法去獲取ProcessBuilder中的start方法

最后使用Method對象的invoke方法去調用start方法

?然后運行,發現報錯,是類型出現了錯誤

?我們先去看看ProcessBuilder的構造方法,它不是嚴格意義上的String,是String...(可變長的字符串)如果是whoami /user這條命令的話,我們得寫到兩個字符串里面,在Java中,對于可變長的字符串是將其放入到數組當中去

?然后我們將其修改為String[].class

然后繼續運行,然后還是報錯說類型不匹配

就是因為我們上面定義的是數組,下面是字符串,所以會報錯

所以我們要將下面的類型轉換為數組類型就可以了,也就是將其放到數組中就可以了,如下

繼續運行,發現還是報錯,報錯信息還是類型不匹配

?我們去看看newInstace的構造方法,發現還是一個數組,它的類型是數組,數組里面的參數還是一個數組

所以這個cmd的類型要定義成二維數組,二維數組只需加兩個{}即可,如下

然后去運行,發現沒有報錯,但是也沒有回顯命令的內容,應該是電腦的問題,如果是Windows的話在命令那一塊改為calc.exe就可以打開計算器了

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79541.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79541.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79541.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每日算法【雙指針算法】(Day 1-移動零)

雙指針算法 1.算法題目(移動零)2.講解算法原理3.編寫代碼 1.算法題目(移動零) 2.講解算法原理 數組劃分,數組分塊(快排里面最核心的一步)只需把0改為tmp 雙指針算法:利用數組下標來…

SQL Server 的鎖機制

SQL Server 的鎖機制是為了確保數據的一致性和事務的隔離性而設計的。以下是針對讀寫操作的鎖定行為的詳細說明: 1. 鎖的基本類型 SQL Server 的鎖主要分為以下幾類: 共享鎖(Shared Lock, S Lock) 用於讀操作(如 S…

AIP目錄

專注于開發靈活API的設計文檔。 AIP是總結了谷歌API設計決策的設計文檔,它也為其他人提供了用文檔記錄API設計規則和實踐的框架和系統。 基礎1AIP目的和指南2AIP編號規則3AIP版本管理200先例8AIP風格與指導9術語表流程100API設計評審常見問題205Beta版本發布前置條…

CSS進度條帶斑馬紋動畫(有效果圖)

效果圖 .wxml <view class"tb"><view class"tb-line" style"transform:translateX({{w%}})" /> </view> <button bind:tap"updateLine">增加進度</button>.js Page({data: {w:0,},updateLine(){this.…

【工具-Krillin AI】視頻翻譯、配音、語音克隆于一體的一站式視頻多語言轉換工具~

Krillin AI 是全能型音視頻本地化與增強解決工具。這款簡約而強大的工具&#xff0c;集音視頻翻譯、配音、語音克隆于一身&#xff0c;支持橫豎屏格式輸出&#xff0c;確保在所有主流平臺&#xff08;嗶哩嗶哩&#xff0c;小紅書&#xff0c;抖音&#xff0c;視頻號&#xff0c…

zset.

zset 有序集合 zset 保留了 set 不能有重復元素的特點 zset 中的每個元素都有一個唯一的浮點類型的分數&#xff08;score&#xff09;與之關聯&#xff0c;使得 zset 內部的元素是可以維護有序性的。但是這個有序不是用下標作為排序依據的&#xff0c;而是根據分數&#xf…

Spring 數據庫編程

Spring JDBC 傳統的JDBC在操作數據庫時&#xff0c;需要先打開數據庫連接&#xff0c;執行SQL語句&#xff0c;然后封裝結果&#xff0c;最后關閉數據庫連接等資源。頻繁的數據庫操作會產生大量的重復代碼&#xff0c;造成代碼冗余&#xff0c;Spring的JDBC模塊負責數據庫資源…

492Q 型氣缸蓋雙端面銑削組合銑床總體設計

一、引言 492Q 型氣缸蓋是發動機的重要組成部分&#xff0c;其雙端面的加工精度對發動機的性能和可靠性有著重要影響。設計一款適用于 492Q 型氣缸蓋雙端面銑削的組合銑床&#xff0c;能夠提高加工效率和質量&#xff0c;滿足發動機生產的需求。 二、總體設計要求 加工精度&…

顎式破碎機的設計

一、引言 顎式破碎機作為礦山、建材等行業的重要破碎設備&#xff0c;其性能優劣直接影響物料破碎效率與質量。隨著工業生產規模的擴大和對破碎效率要求的提高&#xff0c;設計一款高效、穩定、節能的顎式破碎機具有重要意義。 二、設計需求分析 處理能力&#xff1a;根據目…

第三階段面試題

Nginx nginx常用模塊以及其功能 proxy模塊&#xff0c;進行代理功能 ssl模塊&#xff0c;進行HTTPS協議的使用 gzip模塊&#xff0c;進行傳輸數據的壓縮 upstream模塊&#xff0c;進行反向代理時使用 static模塊&#xff0c;靜態資源進行訪問的模塊 cache模塊&#xff0…

鴻蒙NEXT開發鍵盤工具類(ArkTs)

export declare type KeyboardCallBack (show: boolean, height: number) > void; import { AppUtil } from ./AppUtil; import { LogUtil } from ./LogUtil; import { ArrayUtil } from ./ArrayUtil;/*** 鍵盤工具類* author 鴻蒙布道師* since 2025/04/18*/ export class…

基于 LabVIEW 的電液伺服閥測試臺開發

開發了一種基于 LabVIEW 圖形編程語言的自動測試系統&#xff0c;能夠完成電液伺服閥的空載流量特性、壓力增益特性、內泄漏特性等靜態特性的自動測試。針對測試過程中干擾信號頻段與正常信號頻段接近&#xff0c;普通數字濾波器濾波效果不佳的問題&#xff0c;采用迭代濾波分解…

【uniapp】vue2 使用 Vuex 狀態管理

創建store文件夾&#xff1a;store/index.js // index.js import Vue from vue import Vuex from vuex import address from ./modules/address.jsVue.use(Vuex)const store new Vuex.Store({modules: {address} })export default store 創建modules文件夾&#xff1a;modul…

c# 簡單實現將Message的內容保存到txt中,超過100個則清理舊文件

using System; using System.IO; using System.Threading;public static class LogManager {private static readonly object _fileLock new object(); // 線程安全鎖private const int MaxFiles 100; // 最大文件數限制private const string LogDire…

阿里云鏡像加速僅支持阿里云產品了

最近在拉取docker鏡像時一直報超時的錯誤&#xff1a; docker pull hello-world Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exce…

從零實現Git安裝、使用

一、git安裝 Git官方下載 1.下載exe程序 2.雙擊安裝&#xff0c;一直點擊next&#xff0c;默認安裝 安裝完成后&#xff0c;在任意文件夾右鍵&#xff0c;出現下圖所示&#xff0c;即為安裝成功。 3.【Git Bash Here】調出命令窗口&#xff0c;設置用戶名和 email 地址。 gi…

生產環境中如何使用Caffeine+Redis實現二級緩存(詳細分析了遇到的各種情況)

生產環境中如何使用CaffeineRedis實現二級緩存&#xff08;詳細分析了各種情況&#xff09; 本篇主要講解的是實現CaffeineRedis實現一個現成的使用流程。下一篇講解什么是Caffeine以及caffeine的使用 00背景&#xff1a; 使用Caffeine和Redis的二級緩存方案源自于分布式系統…

RT-Thread開發文檔合集

瑞薩VisionBoard開發實踐指南 RT-Thread 文檔中心 RT-Thread-【RA8D1-Vision Board】 RA8D1 Vision Board上的USB實踐RT-Thread問答社區 - RT-Thread 【開發板】環境篇&#xff1a;05燒錄工具介紹_嗶哩嗶哩_bilibili 【RA8D1-Vision Board】基于OpenMV 實現圖像分類_嗶哩嗶哩_…

甘果桌面tv版下載-甘果桌面安卓電視版使用教程

甘果桌面 TV 版是一款備受關注的應用&#xff0c;它可以讓安卓電視的界面更加個性化、操作更加便捷。接下來&#xff0c;我們就詳細了解一下甘果桌面 TV 版的下載方法以及安卓電視版的使用教程。 甘果桌面 TV 版下載 打開你的安卓電視&#xff0c;找到并進入電視自帶的應用商店…

RAII資源管理理解

基礎介紹 RAII (Resource Acquisition Is Initialization) 是一種 C 編程范式&#xff0c;這不是一個語法特性&#xff0c;而是一種處理方式。RAII的思想&#xff1a; 資源獲取與對象初始化同時發生資源釋放與對象銷毀同時發生通過對象的生命周期來管理資源&#xff0c;確保資…