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 对输入的校验使用白名单是目前已知最好的编码方式

浙公网安备 33010602011771号