字体对话框java实验_Java Web安全 || Java基础 sun.misc.Unsafe
點擊上方“凌天實驗室”,“星標或置頂公眾號”
漏洞、技術還是其他,我都想第一時間和你分享
“【歷史】已連載更新全部內容:【菜單欄】-【JAVA SEC】
sun.misc.Unsafe是Java底層API(僅限Java內部使用,反射可調用)提供的一個神奇的Java類,Unsafe提供了非常底層的內存、CAS、線程調度、類、對象等操作、Unsafe正如它的名字一樣它提供的幾乎所有的方法都是不安全的,本節只講解如何使用Unsafe定義Java類、創建類實例。
如何獲取Unsafe對象
Unsafe是Java內部API,外部是禁止調用的,在編譯Java類時如果檢測到引用了Unsafe類也會有禁止使用的警告:Unsafe是內部專用 API, 可能會在未來發行版中刪除。
sun.misc.Unsafe代碼片段:
import sun.reflect.CallerSensitive;import sun.reflect.Reflection;
public final class Unsafe {
private static final Unsafe theUnsafe;
static {
theUnsafe = new Unsafe();
省去其他代碼......
}
private Unsafe() {
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (var0.getClassLoader() != null) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
省去其他代碼......
}
由上代碼片段可以看到,Unsafe類是一個不能被繼承的類且不能直接通過new的方式創建Unsafe類實例,如果通過getUnsafe方法獲取Unsafe實例還會檢查類加載器,默認只允許Bootstrap Classloader調用。
既然無法直接通過Unsafe.getUnsafe()的方式調用,那么可以使用反射的方式去獲取Unsafe類實例。
反射獲取Unsafe類實例代碼片段:
// 反射獲取Unsafe的theUnsafe成員變量當然我們也可以用反射創建Unsafe類實例的方式去獲取Unsafe對象:
// 獲取Unsafe無參構造方法Constructor constructor = Unsafe.class.getDeclaredConstructor();
// 修改構造方法訪問權限
constructor.setAccessible(true);
// 反射創建Unsafe類實例,等價于 Unsafe unsafe1 = new Unsafe();
Unsafe unsafe1 = (Unsafe) constructor.newInstance();
獲取到了Unsafe對象我們就可以調用內部的方法了。
allocateInstance無視構造方法創建類實例
假設我們有一個叫com.anbai.sec.unsafe.UnSafeTest的類,因為某種原因我們不能直接通過反射的方式去創建UnSafeTest類實例,那么這個時候使用Unsafe的allocateInstance方法就可以繞過這個限制了。
UnSafeTest代碼片段:
public class UnSafeTest {private UnSafeTest() {
// 假設RASP在這個構造方法中插入了Hook代碼,我們可以利用Unsafe來創建類實例
System.out.println("init...");
}
}
使用Unsafe創建UnSafeTest對象:
// 使用Unsafe創建UnSafeTest類實例UnSafeTest test = (UnSafeTest) unsafe1.allocateInstance(UnSafeTest.class);
Google的GSON庫在JSON反序列化的時候就使用這個方式來創建類實例,在滲透測試中也會經常遇到這樣的限制,比如RASP限制了java.io.FileInputStream類的構造方法導致我們無法讀文件或者限制了UNIXProcess/ProcessImpl類的構造方法導致我們無法執行本地命令等。
defineClass直接調用JVM創建類對象
ClassLoader章節我們講了通過ClassLoader類的defineClass0/1/2方法我們可以直接向JVM中注冊一個類,如果ClassLoader被限制的情況下我們還可以使用Unsafe的defineClass方法來實現同樣的功能。
Unsafe提供了一個通過傳入類名、類字節碼的方式就可以定義類的defineClass方法:
public native Class defineClass(String var1, byte[] var2, int var3, int var4);
public native Class> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);
使用Unsafe創建TestHelloWorld對象:
// 使用Unsafe向JVM中注冊com.anbai.sec.classloader.TestHelloWorld類Class helloWorldClass = unsafe1.defineClass(TEST_CLASS_NAME, TEST_CLASS_BYTES, 0, TEST_CLASS_BYTES.length);
或調用需要傳入類加載器和保護域的方法:
// 獲取系統的類加載器ClassLoader classLoader = ClassLoader.getSystemClassLoader();
// 創建默認的保護域
ProtectionDomain domain = new ProtectionDomain(
new CodeSource(null, (Certificate[]) null), null, classLoader, null
);
// 使用Unsafe向JVM中注冊com.anbai.sec.classloader.TestHelloWorld類
Class helloWorldClass = unsafe1.defineClass(
TEST_CLASS_NAME, TEST_CLASS_BYTES, 0, TEST_CLASS_BYTES.length, classLoader, domain
);
Unsafe還可以通過defineAnonymousClass方法創建內部類,這里不再多做測試。
注意:
這個實例僅適用于Java 8以前的版本如果在Java 8中應該使用應該調用需要傳類加載器和保護域的那個方法。Java 11開始Unsafe類已經把defineClass方法移除了(defineAnonymousClass方法還在),雖然可以使用java.lang.invoke.MethodHandles.Lookup.defineClass來代替,但是MethodHandles只是間接的調用了ClassLoader的defineClass,所以一切也就回到了ClassLoader。
**如果您在閱讀文章的時候發現任何問題都可以通過Vchat與我們聯系,也歡迎大家加入javasec微信群一起交流。
Vchat獲取方式:對話框發送“javasec”
凌天實驗室凌天實驗室,是安百科技旗下針對應用安全領域進行攻防研究的專業技術團隊,其核心成員來自原烏云創始團隊及社區知名白帽子,團隊專業性強、技術層次高且富有實戰經驗。實驗室成立于2016年,發展至今團隊成員已達35人,在應用安全領域深耕不輟,向網絡安全行業頂尖水平攻防技術團隊的方向夯實邁進。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的字体对话框java实验_Java Web安全 || Java基础 sun.misc.Unsafe的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows svn
- 下一篇: oracle中scn(系统改变号)