ABAP和Java里的单例模式攻击

面向对象编程世界里的单例模式(Singleton)多是设计模式里最简单的一种,大多数开发人员都以为能够很容易掌握它的用法。单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。java

然而在某些场景下,这种设计模式的单例特性会被破坏,看下面这个例子:编程

clipboard1,1

代码的第三行,这个ABAP类实现了接口if_serializable_object,这意味着它能够被关键字CALL TRANSFORMATION进行序列化和反序列化操做。设计模式

使用下面的ABAP代码:this

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.

clipboard2,2

执行以后,在调试器里发现lo_instance和lo_instance2指向了两个不一样的对象实例,说明此时这个ABAP单例模式已经被破坏了。设计

clipboard3,3

再看看Java,下面是一个最简单的Java单例模式:3d

clipboard4,4

然而咱们仍然能够经过Java的反射机制来破坏这个单例:调试

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);

clipboard5,5

在Java里,咱们能够经过枚举类来防护这种反射攻击:code

public enum JerrySingletonAnotherApproach {
  INSTANCE ;  
  
  private String name = "Jerry" ;
   
  public String getName() {  
      return this.name;  
  }  
}

clipboard6,6

这种单例模式的消费代码:对象

System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());

此时别有用心的攻击者若是想使用反射机制建立新的实例,会收到下面的报错信息:blog

Exception in thread "main" java.lang.NoSuchMethodException: singleton.JerrySingletonAnotherApproach.<init>() 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)

要获取更多Jerry的原创文章,请关注公众号"汪子熙": 公众号截图

相关文章
相关标签/搜索