正则表达式注入
数据被传递至应用程序并作为正则表达式使用。可能导致线程过度使用 CPU 资源,从而导致拒绝服务攻击。
下述代码java中字符串的split, replaceAll均支持正则的方式, 导致CPU挂起.
1 final String input = "0000000000000000000000000000000000000000000000"; 2 long startTime = System.currentTimeMillis(); 3 System.out.println(input.split("(0*)*A")); 4 System.out.println("耗时:" + (System.currentTimeMillis() - startTime) + "ms");
-
该正则的意思是说匹配器在输入的末尾并没有检测到”A”。现在外侧的限定符后退一次,内存的则前进一次,如此重复,无法得到结果。
-
因此,匹配器逐步回退,并尝试所有的组合以找出匹配符号。它最终将返回(没有匹配的结果),但是该过程的复杂性是指数型的(输入中添加一个字符加倍了运行时间)
修复方式
使用线程池 + Future, 限定执行时间, 并捕获异常.
1 ExecutorService service = Executors.newFixedThreadPool(1); 2 Future result = service.submit(new Callable<Object>() { 3 @Override 4 public Object call() { 5 final String input = "0000000000000000000000000000000000000000000000"; 6 return input.split("(0*)*A"); 7 } 8 }); 9 service.shutdown(); 10 System.out.println(result.get(5, TimeUnit.SECONDS));
不安全的随机数
Java API中提供了java.util.Random类实现PRNG(),该PRNG是可移植和可重复的,如果两个java.util.Random类的实例使用相同的种子,会在所有Java实现中生成相同的数值序列。
1 // Random对象r和s设置了相同的种子,因此 i == j 以及数组b[]和c[]的相应值是相等的。 2 Random r = new Random(12345); 3 int i = r.nextInt(); 4 byte[] b = new byte[4]; 5 r.nextBytes(b); 6 7 Random s = new Random(12345); 8 int j = s.nextInt(); 9 byte[] c = new byte[4]; 10 s.nextBytes(c);
修复方式
使用更安全的随机数生成器,如java.security.SecureRandom类。
1 SecureRandom number = SecureRandom.getInstance("SHA1PRNG"); 2 System.out.println(number.nextInt() + " " + number.nextInt());