我们发现Java Usage Tracker中存在设计缺陷(或者脆弱点),攻击者可以利用该缺陷创建任意文件、注入攻击者指定的参数以及提升本地权限。这些攻击手段也能组合使用实现权限提升,以便访问受影响系统中其他应用或者用户不能访问的某些保护资源。
我们通过 Zero Day Initiative 与Oracle合作修复了这个漏洞,厂商已经在 10月份补丁 中推出了安全更新。因此,用户以及企业应当尽快安装补丁,更新Java版本。
在本文中,我们将深入研究该缺陷在Windows上的利用过程,介绍Java Usage Tracker的工作原理,给出了利用该漏洞所需满足的条件。
Java中有一个Java Usage Tracker(JUT)的功能,可以用来跟踪已部署Java的系统对Java的使用情况。JUT具备如下功能:
1、记录关于Java虚拟机(JVM)启动配置参数的相关信息。
2、将输出导出到日志文件中,或者重定向到某个UDP服务。
3、可以记录在JUT配置数据中指定的自定义属性的值。
JUT使用的配置文件名为 usagetracker.properties
。该文件使用的是全局默认位置,具体值取决于操作系统(OS)。比如,Windows上的默认路径为 %ProgramData%/Oracle/Java/
。 usagetracker
文件可以用来跟踪系统中已启动的所有JVM的使用情况。
usagetracker.properties
示例文件内容如下图所示:
图1. usagetracker.properties
示例文件部分内容
如图1中第9行所示,JUT会将信息记录到 global_javatracker.log
文件中。以安装Apache Tomcat(一个开源的基于Java的工具)的过程为例,一旦该服务重启,就会创建 global_javatracker.log
文件,然后往文件中附加Java使用情况的跟踪数据。每次Tomcat服务启动时,新的跟踪信息都会附加到该文件结尾处。
跟踪数据示例如下图所示。注意其中的字段值会以逗号作为分隔符,分隔符由属性文件中的 separator
字段所决定。
图2. Tomcat的跟踪数据被附加到 global_javatracker.log
文件末尾
usagetracker.properties
文件中有两个有趣的属性,可以用来控制JUT的具体行为:
oracle.usagetracker.logToFile oracle.usagetracker.additionalProperties
logTofile
属性允许用户在系统中选择任意日志文件路径。需要注意的是,日志文件会由正在被监控的JVM所创建。如果JVM以高权限运行,那么就可以在系统任意位置创建该文件。此外,文件的扩展名也不受限制(比如,可以创建名为 global_javatracker.bat
的日志文件)。
即使可以任意设置 logToFile
的路径,我们也无法控制文件内容,因为JVM只会利用现有的、非可控的数据来写入文件内容。然而,JUT有一个特殊的功能,可以从自定义属性中提取值。 additionalProperties
支持包含待跟踪的任意属性和其他自定义属性。具体样例如下图所示:
图3. 通过 additionalProperties
添加自定义属性
图4. 重启Tomcat服务后将跟踪数据写入文件中
如图4所示,该行的末尾附加了一个我们配置的待跟踪属性,其值为 null
( com.anotherInterestingProperty=null
)。属性值为 null
,表明该属性并不存在。
我们有两种方法来控制JUT的行为:设置任意日志路径,以及设置任意自定义属性。这种组合貌似不大好用,但如果与其他安全漏洞或者缺陷结合起来,就能被充分利用。
举个例子说明如何利用自定义属性。如图5所示,之前配置文件的第9行会强制JUT创建一个 .bat
文件,然后添加自定义属性: ping 172.0.1.1 >
。生成的相应文件为 global_javatracker.bat
,如图5所示。
图5. global_javatracker.bat
中的自定义属性
图6. global_javatracker.bat
正在执行
请注意其中附加的属性 ping 172.0.1.1 >= null
。如果批处理文件 global_javatracker.bat
被执行,那么就会显示错误消息: “VM start” is not recognized
。之所以出现这个错误,是因为JUT的属性文件只生成一行数据,由分隔符切分各种字段(参考前面提到的 com.oracle.usagetracker.separator = ,
,表明这里的分隔符为逗号)。
如果我们将分隔符改为换行符,则会生成不同的跟踪日志(如图8所示)。
图7. JUT采用换行分隔符(高亮部分)
图8. 使用新的分隔符后生成的跟踪日志
图8中所有的值都会在新的一行中表示,最后一行包含 ping 172.0.1.1 >= null
语句。运行 global_javatracker.bat
会执行 ping 172.0.1.1 >= null
语句,但由于这里存在双引号,因此该命令无法被识别。然而,我们还是有机会执行该命令,因为封装每个属性值的双引号实际上可以被另一个配置文件所控制,具体配置语句为 com.oracle.usagetracker.quote = “
。
比如,我们可以创建一个值为空的 com.oracle.usagetracker.quote
配置,如图9所示:
图9. com.oracle.usagetracker.quote
设置为空值
图10. 利用空值 com.oracle.usagetracker.quote
所生成的跟踪日志
运行 global_javatracker.bat
则会执行 ping 172.0.1.1 >= null
命令,如图10中命令提示符(cmd)的最后一行语句,此时我们就可以创建一个 null
文件。
到目前为止,JUT可以用于如下操作:
1、在文件系统的任意位置创建文件;
2、创建文本脚本文件。前面例子中使用的是批处理文件,但我们可以利用它来创建其他类型的文件;
3、注入任意命令(或者与脚本文件相关的其他任意文本)。
我们可以在系统中的任意位置执行/创建如上操作或者脚本文件。然而,为了成功利用该漏洞,我们还需要满足一定条件:
1、应该在关键位置(比如自启动脚本)中创建恶意文件;
2、为了访问关键位置,应由高权限进程来创建恶意文件。
实际上这两个条件都可以满足。比如,非特权用户可以创建JUT配置文件( usagetracker.properties
),而高权限进程可以创建恶意日志文件(跟踪日志)。
由于使用的是全局配置路径(比如Windows系统中对应的是 %ProgramData%/Oracle/Java
),当JVM在系统中启动时就会读取JUT日志文件。我们以默认安装的Tomcat举例说明。一旦Tomcat安装完毕,全局的 usagetracker.properties
准备就绪,重启Tomcat后就会创建跟踪日志文件(如图11所示)。如图12中所示,该文件由Tomcat服务创建,而该服务默认情况下以 System
权限运行。
由于Tomcat服务以 System
权限运行,因此恶意文件 global_javatracker.bat
可以在任意位置创建。然而, usagetracker.properties
这个配置文件必须由非特权用户来创建。
图11. Tomcat安装后创建跟踪日志文件
图12. Tomcat以系统权限运行(高亮部分)
JUT的全局配置文件会在默认的 %ProgramData%/Oracle/Java/
路径中创建。该位置以及初始配置内容由Java在安装阶段创建及设置,但也可以在执行Java命令(比如 java -c
)时进行创建和设置。
默认权限下,系统中的用户可以在 %ProgramData%
位置创建文件。当Oracle/Java路径创建完毕后,也会继承默认权限。 %ProgramData%/Oracle/Java
的权限如图13所示。
这会影响Java的许多版本,可能会影响自引入JUT功能后的所有Java版本。
图13. %ProgramData%/Oracle/Java/
目录权限
举个例子来说明利用场景:低权限用户可以创建恶意配置文件 usagetracker.properties
,由于Tomcat服务器以 System
权限运行,因此会在系统的任意位置中创建批处理文件。批处理文件中可以包含各种例程,比如往启动脚本位置写入数据等。
我们可以通过各种方法,滥用Java Usage Tracker的功能来提升权限。我们的研究仅测试了Microsoft Windows环境,但其他系统可能同样存在漏洞。
攻击者可以使用一系列设计缺陷来实现权限提升,这些缺陷可以当成不同类型的漏洞:
1、任意文件类型创建:可以通过 oracle.usagetracker.logToFile
路径来实现。比如,我们可以创建类似批处理文件之类的脚本文件。
2、参数注入:可以通过 oracle.usagetracker.additionalProperties
属性来实现。
3、本地权限提升:可以利用低权限的 %ProgramData%/Oracle/Java
来实现。