1.Java 文件名空字节截断漏洞(%00 Null Bytes)
受空字节截断影响的JDK版本范围:JDK<1.7.40
实际上修复就是检查文件名中是否包含u0000,包含则为非法路径
find usages看一下可以看到跟文件名相关的函数基本上都调用了此函数来进行校验,比如这里用java1.6进行测试,用u0000就进行了成功的截断
用大于1.7.40的肯定会报错,这里修复的话如果考虑到jdk兼容问题,最好的方法就是添加fileName.indexOf('u0000')的判断
如下面的代码所示,如果filename是从url中获取的并且用户可控就可能造成任意文件读取
import java.io.File; import java.io.FileInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; public class file_read { public static void main(String[] args){ try { String filename = "c:\install.ini"; File file = new File(filename); FileInputStream fin = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int a= -1; while ((a=fin.read(b))!=-1){ //System.out.println(a); baos.write(b,0,a); } System.out.println(new String(baos.toByteArray())); fin.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.类加载机制
Java程序在运行前需要先编译成class文件
,Java类初始化的时候会调用java.lang.ClassLoader
加载类字节码,ClassLoader
会调用JVM的native方法(defineClass0/1/2
)来定义一个java.lang.Class
实例。
所有的类都必须要让JVM加载以后才能够运行,classloader主要完成的就是类文件的加载
jvm的类加载器包括:
引导加载器Bootstrap ClassLoader
扩展类加载器 Extension ClassLoader
系统类加载器 App ClassLoader,默认情况下使用的类加载器就是App Classloader,使用ClassLoader.getSystemClassLoader()返回的也是App ClassLoader加载器。
ClassLoader 类有如下核心方法:
1.loadClass (加载指定的Java类)
2.findClass(查找指定的Java类)
感觉上面两个最常用
3.findLoadedClass
(查找JVM已经加载过的类)
4.defineClass
(定义一个Java类)
5.resolveClass
(链接指定的Java类)
Java类动态加载方式:
分为显式和隐式加载,显式加载即通过java反射机制或者ClassLoader机制来动态加载一个类对象,隐式一般就是通过类名.方法名或者new 类实例来加载。感觉很多开源库用反射加载类用的挺多,在调试fastjson中调用链实际上还用到了ClassLoader来动态加载类。
例子:
反射:
Class.forname("java.lang.Runtime");
类加载器:
this.getClass().getClassLoader().loadClass('java.lang.Runtime');
其中用Class.forName("java.lang.Runtime")默认会初始化被加载类的静态属性和方法
可以使用Class.forName('java.lang.Runtime',是否初始化,类加载器)来不让类进行初始化,防止去加载可能恶意类中静态方法的代码