@CallerSensitive public static Lookup lookup() { return new Lookup(Reflection.getCallerClass()); } @CallerSensitive public static native Class<?> getCallerClass();
JEP 176: Mechanical Checking of Caller-Sensitive Methods中的說明:
Improve the security of the JDK's method-handle implementation by replacing the existing hand-maintained list of caller-sensitive methods with a mechanism that accurately identifies such methods and allows their callers to be discovered reliably.
使用能夠精確識別caller-sensitive方法並且保證這些方法的調用者可靠地被發現的一種機制 代替 現存的手動維護的caller-sensitive方法表,提高JDK method-handler實現的安全性。
A caller-sensitive method varies its behavior according to the class of its immediate caller.
It discovers its caller's class by invoking the sun.reflect.Reflection.getCallerClass method.
caller-sensitive方法會根據其直接調用者的類型改變其行為。通過調用sun.reflect.Reflection.getCallerClass方法可以獲得調用者class類型。
Most caller-sensitive methods act in some way as an agent for the caller. When invoked via reflection, these methods must be handled specially in order to ensure that the class of the actual caller, rather than some class of the reflection mechanism itself, is returned by the getCallerClass method.
大多數caller-sensitive方法某種程度上是作為調用者的代理。當通過反射調用時,這些方法必須經過特殊處理以確保getCallerClass返回的是實際調用者的class類型,而不是反射機制本身的某些類。
另外,據JVM注解@CallSensitive文章,有一個類似的解釋:
這個注解是為了堵住漏洞用的。曾經有黑客通過構造雙重反射來提升權限,
原理是當時反射只檢查固定深度的調用者的類,看它有沒有特權,
例如固定看兩層的調用者(getCallerClass(2))。如果我的類本來沒足夠 權限群訪問某些信息,那我就可以通過雙重反射去達到目的:反射相關 的類是有很高權限的,而在 我->反射1->反射2 這樣的調用鏈上,反射2 檢查權限時看到的是反射1的類,這就被欺騙了,導致安全漏洞。 使用CallerSensitive后,getCallerClass不再用固定深度去尋找 actual caller(“我”),而是把所有跟反射相關的接口方法都標注上 CallerSensitive,搜索時凡看到該注解都直接跳過,這樣就有效解決了 前面舉例的問題
作者:王偵
鏈接:https://www.jianshu.com/p/fe292d874e04
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
JVM注解@CallSensitive
HEL_WOR 2015-12-06 23:28:57 10819 收藏 3
展開
轉載請注明 http://blog.csdn.net/HEL_WOR/article/details/50199797
@CallSensitive是JVM中專用的注解,在類加載過過程中是可以常常看到這個注解的身影的。
這是在Sun.reflect中的定義:
@Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.METHOD })
public @interface CallerSensitive {
}
1
2
3
4
而對@CallSensitive的使用如下:
@CallerSensitive
public final ClassLoader getParent() {
if (this.parent == null)
return null;
SecurityManager localSecurityManager = System.getSecurityManager();
if (localSecurityManager != null)
checkClassLoaderPermission(this.parent, Reflection.getCallerClass());
return this.parent;
}
1
2
3
4
5
6
7
8
9
至少在剛剛看見這個注解時我是不明白@CallSensitive有什么用處,一來這是JVM里專用的一個注解,二來在JVM規范和一些書上也沒有看到對這個注解的解釋,第三是發現百度不出來對這個注解的解釋。
這里有兩個解釋:
What does the sun.reflect.CallerSensitive annotation mean?
JEP 176: Mechanical Checking of Caller-Sensitive Methods
StackOverFlow里的回答,答案只是提到了@CallSensitive用來找到真正發起反射請求的類的,但沒有提到具體怎么尋找的,而在OpenJDK文檔里,有下面這句話。
When invoked via reflection, these methods must be handled specially in order to ensure that the class of the actual caller, rather than some class of the reflection mechanism itself, is returned by the getCallerClass method. The logic for doing this involves pattern matching against a hand-maintained list of caller-sensitive methods,
我原本的理解是這個注解用來區分開反射和自省的,並且只有調用方有這個注解我才會回應它,但感覺總有地方說不過去。所以我去問了莫樞:
這個注解是為了堵住漏洞用的。曾經有黑客通過構造雙重反射來提升權限,原理是當時反射只檢查固定深度的調用者的類,看它有沒有特權,例如固定看兩層的調用者(getCallerClass(2))。如果我的類本來沒足夠權限群訪問某些信息,那我就可以通過雙重反射去達到目的:反射相關的類是有很高權限的,而在 我->反射1->反射2 這樣的調用鏈上,反射2檢查權限時看到的是反射1的類,這就被欺騙了,導致安全漏洞。使用CallerSensitive后,getCallerClass不再用固定深度去尋找actual caller(“我”),而是把所有跟反射相關的接口方法都標注上CallerSensitive,搜索時凡看到該注解都直接跳過,這樣就有效解決了前面舉例的問題
下面是我的理解:
當”我“->反射1->反射2->反射3->反射4->…反射->N,從”我“開始后的每個引用對象,當我引用下一個對象(對象1)時,首先會被裝載,驗證,這個時候把這個對象在這個過程中沒調用過的反射接口都標記上@callSentitive,然后對象1引用對象2后重復這個過程一直到N,那么在N調用GetCallCalss時跳過這中間所有已經被標記的對象,最后到達未被標記的“我”。
如果是這樣的話,我倒是比較好奇當初用固定深度檢查調用類有無權限時,從“我”->對象1 -> 對象2,如果對象1有很高的權限,那”我”是如何有權限調用對象1的?有點想讀和寫的權限控制,有點模糊,先復習下那部分再來補充吧。
————————————————
版權聲明:本文為CSDN博主「HEL_WOR」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/HEL_WOR/java/article/details/50199797