ABAP和Java裡的單例模式攻擊

面向對象編程世界裡的單例模式(Singleton)可能是設計模式裡最簡單的一種,大多數開發人員都覺得可以很容易掌握它的用法。單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

然而在某些場景下,這種設計模式的單例特性會被破壞,看下面這個例子

ABAP和Java裡的單例模式攻擊

代碼的第三行,這個ABAP類實現了接口if_serializable_object,這意味著它可以被關鍵字CALL TRANSFORMATION進行序列化和反序列化操作。

使用下面的ABAP代碼:

<code>DATA(lo_instance) = zcl_jerry_singleton=>get_instance( ).
DATA: s TYPE string.

CALL TRANSFORMATION id SOURCE model = lo_instance RESULT XML s.

DATA: lo_instance2 TYPE REF TO zcl_jerry_singleton.

CALL TRANSFORMATION id SOURCE XML s RESULT model = lo_instance2./<code>

執行之後,在調試器裡發現lo_instance和lo_instance2指向了兩個不同的對象實例,說明此時這個ABAP單例模式已經被破壞了。

ABAP和Java裡的單例模式攻擊

再看看Java,下面是一個最簡單的Java單例模式:

ABAP和Java裡的單例模式攻擊

然而我們仍然可以通過Java的反射機制來破壞這個單例:

<code>Class> classType = JerrySingleton.class;  
Constructor> c = classType.getDeclaredConstructor(null);
c.setAccessible(true);
JerrySingleton e1 = (JerrySingleton)c.newInstance();
JerrySingleton e2 = JerrySingleton.getInstance();
System.out.println(e1 == e2); /<code>

在Java裡,我們可以通過枚舉類來防禦這種反射攻擊:

<code>public enum JerrySingletonAnotherApproach {
INSTANCE ;

private String name = "Jerry" ;

public String getName() {
return this.name;
}
}/<code>

這種單例模式的消費代碼:

<code>System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());/<code>

此時別有用心的攻擊者如果想使用反射機制創建新的實例,會收到下面的報錯信息:

Exception in thread "main" java.lang.NoSuchMethodException: singleton.JerrySingletonAnotherApproach.(

<code>at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at singleton.SingletonAttack.test3(SingletonAttack.java:31)
at singleton.SingletonAttack.main(SingletonAttack.java:43)/<code>


分享到:


相關文章: