从代码层面理解java的00截断漏洞深入篇

admin 2021年4月2日20:39:08gv7.me评论52 views3405字阅读11分21秒阅读模式

4个月前写了一篇文章叫《从代码层面理解java的00截断漏洞》,由于当时出差新疆没时间深入,便在文末立了个有空继续深入的flag。今天我们通过跟踪jdk代码, 彻底搞清楚java中00截断的原理,以及它之后版本是如何修复的?

一、漏洞测试代码改进

看了一些java web系统文件上传代码,基本都是使用FileOutputStream来实现对上传内容的保存。于是将上篇文章的测试代码修改如下,简单模拟java的文件上传。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.*;

public class T2 {
public static void main(String[] args) {
String filepath = "c://shell.jsp" + (char)0 + ".txt";
String content = "Test by c0ny1";
System.out.println(filepath);

try {
FileOutputStream fos = new FileOutputStream(filepath);
fos.write(content.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}

通过在漏洞版本和非漏洞版本运行以上代码,可知如果00截断成功,则会在系统的c盘根目录新建一个内容为Test by c0ny1shell.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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags)
{
......
if (onNT) { //如果在Windows NT/Windows 2000操作系统下
WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
if (pathbuf == NULL) {
/* Exception already pending */
return -1;
}
h = CreateFileW(
pathbuf, /* Wide char path name */
access, /* Read and/or write permission */
sharing, /* File sharing flags */
NULL, /* Security attributes */
disposition, /* creation disposition */
flagsAndAttributes, /* flags and attributes */
NULL);
free(pathbuf);//创建文件
} else {
WITH_PLATFORM_STRING(env, path, _ps) {
h = CreateFile(_ps, access, sharing, NULL, disposition,flagsAndAttributes, NULL);//创建文件
}
END_PLATFORM_STRING(env, _ps);
}
......
return (jlong)h;
}

通过阅读以上代码,可知如果在Windows NT/Windows 2000平台下会调用pathToNTPath函数将原始文件路径转化为Windows NT系统合法路径。然而通过阅读该方法源码,发现它并没有对0字符串进行过滤。如果在其他Window操作系统版本下,则直接使用原始文件路径。

按照winFileHandleOpen方法的逻辑,无论如何最终都是调用了CreateFileW这个Windows API函数来创建文件。由于这个过程中均未对0字符串进行过滤,如果传入的文件路径带有0字符,则CreateFileW函数在创建文件时,路径会被截断。这没什么好说的。

这里我们没法继续跟进CreateFileW函数,毕竟Windows不开源。为了文章的严谨性,这里我用C语言写一个demo,来证明该函数可以截断。

1
2
3
4
5
6
7
8
9
10
11
12
//test.c
#include "windows.h"
int main()
{
HANDLE fileHandle = CreateFileW(L"C:shell.jsptest.txt", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
char *data = "Test by c0ny1";
DWORD a = strlen(data);
unsigned long b;
WriteFile(fileHandle, data, a, &b, NULL);
CloseHandle(fileHandle);
return 0;
}

代码运行演示如下:

三、漏洞是如何修复的?

这里选择使用jdk1.7.0_80(JDK1.7最新版本),来观察漏洞如果被修复的。

我们继续按照原来漏洞触发的调用链重新跟踪一遍,跟踪到第二构造函数时,发现多了一个针对文件路径的检查,若检查结果为非法,则抛出异常Invalid file path.

继续跟进,来到java.io.File类的isInvalid方法,发现该检查函数判断了路径中是否包含00字符串。(注意:java默认编码为Unicode,00字符串的Unicode编码为u0000)。

四、漏洞影响的版本范围

我们知道jdk1.7版本是部分版本存在漏洞的。但这里我们需要确定是哪个版本修复了这个漏洞。翻阅了JDK1.7多个版本代码,发现在JDK1.7.0_40(7u40)开始加上了对文件名是否存在0字符的检查。也就是说 JDK1.7.0_40之前java是存在00截断的,而之后的版本就不存在了!

后面在官网的JDK 7u40的更新日志中也找到了关于00截断问题Bug ID,分别为JDK-8003992JDK-8011539,具体链接放在了文末的参考文章里了。其实这两个是同一个Bug,官网也说明了它们重复了。

五、参考文章

文章来源于gv7.me:从代码层面理解java的00截断漏洞深入篇

相关推荐: 构造优质上传漏洞fuzz字典

上传漏洞的利用姿势很多,同时也会因为语言,中间件,操作系统的不同,利用也不同。比如有:大小写混合,.htaccess,解析漏洞,00截断,.绕过,空格绕过,::$DATA绕过,以及多种姿势的组合等等。当遇到一个上传点,如何全面的利用以上姿势测试一遍,并快速发现…

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月2日20:39:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  从代码层面理解java的00截断漏洞深入篇 http://cn-sec.com/archives/318087.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: