ABAP和Java单例模式的攻防
2023-09-14 09:02:50 时间
ABAP
CLASS zcl_jerry_singleton DEFINITION
PUBLIC
FINAL
CREATE PRIVATE .
PUBLIC SECTION.
INTERFACES if_serializable_object .
CLASS-METHODS class_constructor .
CLASS-METHODS get_instance
RETURNING
VALUE(ro_instance) TYPE REF TO zcl_jerry_singleton .
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-DATA so_instance TYPE REF TO zcl_jerry_singleton .
DATA mv_name TYPE string .
DATA mv_initialized TYPE abap_bool .
METHODS constructor .
ENDCLASS.
CLASS ZCL_JERRY_SINGLETON IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JERRY_SINGLETON=>CLASS_CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD class_constructor.
so_instance = NEW zcl_jerry_singleton( ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_JERRY_SINGLETON->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
mv_name = 'Jerry'.
IF mv_initialized = abap_false.
mv_initialized = abap_true.
ELSE.
MESSAGE 'you are in trouble!' TYPE 'E' DISPLAY LIKE 'I'.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JERRY_SINGLETON=>GET_INSTANCE
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RO_INSTANCE TYPE REF TO ZCL_JERRY_SINGLETON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_instance.
ro_instance = so_instance.
ENDMETHOD.
ENDCLASS.
通过序列化/反序列化攻击单例模式:
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.
绕过了单例的限制,构造了第二个实例。
Java
除了用序列化/反序列化攻击外,还可以用反射攻击。
然而我只需要将这个单例类JerrySingleton的构造函数通过反射设置成可以访问Accessible,然后就能通过反射调用该构造函数,进而生成新的对象实例。这样就破坏了单例模式。
第6行代码会打印false。
针对这种攻击,一种可行的防御措施是在单例类的构造函数内定义一个布尔变量,初始化为false。当构造函数执行后,该变量被置为true。如果接下来构造函数再次被执行,则人为抛出异常,避免构造函数重复执行。
这种防御措施无法从根本上杜绝Singleton被攻击,因为攻击者仍旧可以通过反射来修改布尔变量flag的值,从而绕过这个检查。
最理想的不会受到攻击的单例模式实现是借助Java里枚举类Enumeration的特性:
这种实现类型的单例模式的消费代码:
System.out.println(“Name:” + JerrySingletonAnotherApproach.INSTANCE.getName());
如果攻击者通过前面介绍的反射代码对这种实现方式的单例进行攻击,JDK会抛出NoSuchMethodException异常:
究其原因,是因为现在我们是通过Java枚举方式实现的单例,枚举类没有传统意义上的构造函数,因此对这种反射攻击免疫。
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关文章
- Servlet使用适配器模式进行增删改查案例(DeptDaoImpl.java)
- JAVA Eclipse ActivityManager Warning Activity not started, its current task has been brought to the front怎么办
- Java实现 LeetCode 725 分隔链表(暴力)
- Java实现 LeetCode 646 最长数对链(暴力)
- java实现第四届蓝桥杯危险系数
- java实现第七届蓝桥杯骰子游戏
- java实现拉丁方块填数字
- Java多线程编程之单例模式
- Java实现单例模式的9种方法
- Java 缩放图片工具类,创建缩略图、伸缩图片比例
- Gradle在大型Java项目上的应用
- Java设计模式之享元flyweight模式代码示例
- ABAP和Java里的单例模式攻击
- 程序员面试系列之Java单例模式的攻击与防御
- Java桥接模式:打破继承束缚,优雅实现多维度变化
- 从源头开始学习 Java 单例模式:线程安全和性能的双重保障
- Java的二十三种设计模式(原型模式(Prototype))
- Java的二十三种设计模式(单例模式、工厂方法模式、抽象工厂模式)
- 详谈 Java工厂 --- 静态工厂 【简单工厂模式】
- 详谈 Java工厂 --- 抽象工厂模式
- Kotlin - Java 互操作指南
- 频繁模式挖掘apriori算法介绍及Java实现
- Java设计模式偷跑系列(十八)建模和责任链模式的实现
- Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」
- Java多线程面试题与答案