4个月前写了一篇文章叫《从代码层面理解java的00截断漏洞》,由于当时出差新疆没时间深入,便在文末立了个有空继续深入的flag。今天我们通过跟踪jdk代码, 彻底搞清楚java中00截断的原理,以及它之后版本是如何修复的?
一、漏洞测试代码改进
看了一些java web系统文件上传代码,基本都是使用FileOutputStream
来实现对上传内容的保存。于是将上篇文章的测试代码修改如下,简单模拟java的文件上传。
1 |
import java.io.*; |
通过在漏洞版本和非漏洞版本运行以上代码,可知如果00截断成功,则会在系统的c盘根目录新建一个内容为Test by c0ny1
的shell.jsp
,如果没有截断成功,则抛出Invalid file path
异常。
二、漏洞是如何产生的?
我选择使用JDK1.7.0
(JDK1.7第一个版本),来跟踪漏洞测试代码从运行到触发。
将传进来的name参数作为路径,新建了File对象,再次传入到FileOutputStream
对象新的构造函数。根据传入的两个参数的类型,我们可以确定会进入到以下这个构造函数。
FileOutputStream对象的构造方法又调用了open函数,打开了name参数传进来的文件路径,我们继续跟进open函数。
发现open函数是一个native method。它的实现体是由非java语言(c语言)实现的。只能去OpenJDK官网下载jdk源码来查看它的实现。无奈没有找到jdk7u1的源码,只找到了jdk7u75的源码。其实在小版本上源码应该区别不大。
在openjdkjdksrcwindowsnativejavaioFileOutputStream_md.c
中找到了FileOutputStream
类的open
方法的JNI实现。open方法又调用了fileOpen
方法,继续跟进fileOpen方法。
在io_util_md.c
中找到了fileOpen
方法的定义。
fileOpen方法调用了winFileHandleOpen
函数,继续跟进。由于winFileHandleOpen函数代码比较多,这里精简出了关键代码。
1 |
jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags) |
通过阅读以上代码,可知如果在Windows NT/Windows 2000平台下会调用pathToNTPath
函数将原始文件路径转化为Windows NT系统合法路径。然而通过阅读该方法源码,发现它并没有对 0字符串进行过滤。如果在其他Window操作系统版本下,则直接使用原始文件路径。
按照winFileHandleOpen
方法的逻辑,无论如何最终都是调用了CreateFileW
这个Windows API函数来创建文件。由于这个过程中均未对
评论