分析
补丁原理
当补丁打完之后,我们传入文件的时候,程序做了这样的处理1
2
3
4protected File file(String name, boolean mustExist) {
File file = new File(base, name);
return validate(file, mustExist, absoluteBase);
}
调用了validate函数
1 | protected File validate(File file, boolean mustExist, String absoluteBase) { |
也就是,如果我们传入jsp[空格] 这样的文件,就会使用file.getCanonicalPath()来进行格式规整,下面的条件就无法通过,所以无法创建文件。
突破
我们进入file.getCanonicalPath()函数
1 | public String getCanonicalPath() throws IOException { |
这里调用了fs的canonicalize函数,fs是对WinNTFileSystem对象的实例,我们进WinNTFileSystem看看,发现是Win32FileSystem的子类。我们主要看canonicalize函数,进入Win32FileSystem
1 | public String canonicalize(String path) throws IOException { |
我们主要看核心代码,我进行简单梳理:
首先,两个变量useCanonCaches和useCanonPrefixCache默认是等于ture的,这是Caches和PrefixCache两个hashmap是否使用的配置变量,首先我们如果传入jsp[空格],那么cache的hashmap里是不存在这个key对应的键值的。我们就进入了if里,那么parentOrNull函数在取得文件的路径之后,我们进入这一句resDir = prefixCache.get(dir);明显,prefixCache这个hashmap里是不存在我们的路径的,所以直接向下跳转调用res = canonicalize0(path);这个函数功能就是规范res,去掉了res中的空格。所以就回到上节说的为什么通不过了
那么突破从何入手呢?
首先我们传入正常的123.txt文件,这里都是十分正常通过,和上面一样,到了这里
1 | if (res == null) { |
程序将res作为path的键值存入了cache(重要),程序判断了文件是否存在,以及文件是否是路径格式,这里我们不满足文件存在的条件,也就没有任何动作
第二遍我们传入123.txt[空格],这里为什么要加空格呢,因为要过
1 | String res = cache.get(path); |
如果path相同,cache中已经存在了这个path对应的键值,就不会进入if了。我们使用123.txt[空格]便过了这一点,之后,就正常进入程序运行,但是在后面,因为canonicalize0处理掉了res的空格,所以当实例化file时,file.exists()的返回值变为ture了,那么进入了prefixCache.put(dir, resDir);,那么prefixCache里便存在了dir。
第三次再次传入123.jsp[空格]时,正常走程序,当到了resDir = prefixCache.get(dir);的时候,这里由于第二次我们在prefixCache里传入了值,resDir就有值了,就会进入
1 | if (resDir != null) { |
这里是不会对文件整理的,就这样,我们绕过了之前的absoluteBase.length() < canPath.length(),文件就可以创建成功了