java17及以上版本如何抵御跨模块的TemplatesImpl注入

最近有2篇写的很好的关于java17反序列化绕过模块化的文章:

https://mp.weixin.qq.com/s/DrUUAJaLig_RtXZWaAm1IQ

https://mp.weixin.qq.com/s/xfmHjgx5jQRLKkIR7XUCcg

防守的方法也比较传统,直接jep290在java运行时增加命令行参数:

-Djdk.serialFilter=!com.sun.org.apache.xalan.internal.xsltc.**;!org.apache.commons.beanutils.**;

 

那有没有办法在源码级项目自己控制安全策略呢?可以使用如下java代码:

首先在main函数文件上引入相关包

//代码片段1
import jdk.internal.reflect.Reflection;
import javax.xml.transform.Templates;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

之后增加对TemplatesImpl和Templates的反射限制,如下

//代码片段2完整版
Reflection.registerMethodsToFilter(TemplatesImpl.class, Set.of("*"));
Reflection.registerMethodsToFilter(Templates.class, Set.of("*"));

如果业务冲突则精简为:

//代码片段2精简版
Reflection.registerMethodsToFilter(TemplatesImpl.class, 
    Set.of("readObject","getOutputProperties","newTransformer"));
//javax.xml.transform.Templates 只有2个方法,都需要防护
Reflection.registerMethodsToFilter(Templates.class, Set.of("*"));

增加完之后启动,发现系统提示:

Exception in thread "main" java.lang.IllegalAccessError: 
class SerializeJDK8 (in unnamed module @0x6d311334) cannot access class 
jdk.internal.reflect.Reflection (in module java.base) 
because module java.base does not export jdk.internal.reflect to unnamed module @0x6d311334
at SerializeJDK8.main(SerializeJDK8.java:20)

对应在java进程执行启动时增加vm参数:

--add-exports=java.base/jdk.internal.reflect=ALL-UNNAMED
--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED

备注:

#使用--add-exports导出包,意味着所有的public类型和成员都可以在编译和运行时访问。
#使用--add-opens  打开包,意味着其中的所有类型和成员(不仅是公共的!)随时可以访问。 

#对 代码片段2精简版 进行说明:
#1、因为对 TemplatesImpl 进行了--add-exports,但是默认java17模块之间是封闭的
#2、所以要对它的两个public函数newTransformer和getOutputProperties重新禁止反射,再次封闭
#3、getOutputProperties调用了newTransformer,所以这两个函数防护缺一不可
#4、TemplatesImpl 实现了 Templates 接口,所以两个类都要防护

 

可以把“代码片段2”增加2行:

//代码片段3
//保护Reflection的方法不被随意反射调用
Reflection.registerMethodsToFilter(Reflection.class, Set.of("*"));
//将调用sun.misc.Unsafe打破模块化限制的手段堵住,主要防御内存马
Reflection.registerMethodsToFilter(Unsafe.class, Set.of("theUnsafe"));

增加对Reflection和Unsafe进行反射的限制,以减少未知攻击的可能性

 

总结:

1)反序列化时对流进行安全校验增加对未知漏洞的防护

2)对跨模块行为进行限制,可以增加对未知反射的防护

3)参照:https://alibaba.github.io/fastjson2/autotype_cn.html  对输入的校验使用白名单是目前已知最好的编码方式

 

posted @ 2025-10-01 13:32  国产大熊猫~  阅读(91)  评论(0)    收藏  举报