?
Java反射机制指的是程序在运行时能够获取自身的信息;它能动态截获或改写程序的行为。
?
1. 单例模式漏洞
class="java">/** * 懒汉式单例模式 */ public class Singleton { private static Singleton instance = null; private Singleton() { } public static synchronized Singleton getInstance() { if( instance == null ){ instance = new Singleton(); } return instance; } }
?
常规情况下,只能通过 getInstance() 创建实例;但是通过反射可以直接调用private方法创建实例。
/** * 单例反射攻击 */ public static void singletonTest() throws Exception { Class<Singleton> clazz = (Class<Singleton>)Class.forName( "com.sun.Singleton" ); Constructor<Singleton> constructor = clazz.getDeclaredContructor( null ); constructor.setAccessible( true ); // 允许访问私有属性,跳过权限检查 // 成功创建多个实例 Singleton s1 = constructor.newInstance(); Singleton s2 = constructor.newInstance(); }
?解决方案:在无参构造函数中再次检测instance是否存在。
?
2. 泛型漏洞
面试题:
给一个ArrayList<Integer>的一个对象,要在这个集合中添加一个字符串数据,如何实现呢?
大家都知道,泛型约束了集合的数据类型,添加非Integer数据会引起编译错误。
?
/** * 反射突破泛型检测 */ public static void addString() throws Exception { List<Integer> list = new ArrayList<Integer>(); list.add( 1 ); // Get class Class<? extends List> clazz = list.getClass(); // Get add method Method method = clazz.getMethod( "add", Object.class ); // invoke Object obj = method.invoke( list, "str1" ); obj = method.invoke( list, "str1" ); obj = method.invoke( list, "str2" ); // print for( Object i : list ){ System.out.println( "Val: " + i ); } }
?
上述代码成功绕开泛型检测,执行结果如下:
Val: 1
Val: str1
Val: str2
?
?
?
?
?