游客发表

java rmi 服务远程方法调用漏洞修复

发帖时间:2026-10-17 05:13:19

Java RMI 服务远程方法调用漏洞修复

上周五晚上十一点,服法调复某电商平台的程方库存系统突然返回大量“服务器内部错误”。运维查了半天,用漏发现是洞修RMI注册端口被扫到了,攻击者通过反序列化漏洞直接往JVM里塞了一个反弹Shell。服法调复这事不算新鲜,程方但每次发生都让人后背发凉——Java RMI这玩意儿,用漏天生就是洞修攻击者的甜点。

RMI的服法调复设计初衷是让分布式对象调用像本地调用一样简单。可它有个致命伤:默认信任所有来自网络的程方反序列化数据。你调用一个远程方法,用漏参数对象会被序列化成字节流传输,洞修接收方直接ObjectInputStream.readObject()还原。服法调复攻击者只要构造一个恶意对象,程方比如CommonCollections gadget,用漏就能在目标机器上执行任意命令。更麻烦的是,RMI的注册表(Registry)和远程对象通常绑定在1099端口,这个端口暴露在公网上,等于给黑客留了扇后门。

修复方案其实不复杂,但很多人懒得做。第一件事,升级JDK到最新版本。Oracle在Java 8u121之后加了反序列化过滤器(JEP 290),能限制反序列化类的白名单。如果你还在用Java 7或更老的Java 8,赶紧换。第二件事,别把RMI端口直接暴露到公网。用防火墙只允许内网IP访问1099,或者干脆用SSH隧道转发。我在一个客户那儿见过,他们把RMI服务绑在0.0.0.0上,导致全球任意IP都能连,这等于把家门钥匙挂在了门把手上。

第三,如果业务允许,尽量用RMI over SSL。在JVM参数里加-Djavax.net.ssl.keyStore和trustStore,配合SSLServerSocketFactory,能把传输层加密,防止中间人嗅探或篡改。但注意,SSL只解决传输安全问题,反序列化漏洞依然存在,所以还得叠加代码层面的防护。

第四,自定义ObjectInputStream,重写resolveClass方法,做类名黑名单过滤。比如禁止java.lang.Runtime、org.apache.commons.collections.functors.InvokerTransformer这些危险类。网上有不少现成的黑名单库,比如marshalsec项目里收集的gadget类名,拿过来直接用就行。但黑名单总有遗漏,更稳妥的做法是用白名单——只允许你业务里真正需要的DTO类通过反序列化。虽然麻烦,但安全系数高一个数量级。

有个细节容易被忽略:RMI的注册表本身也可能被攻击。攻击者能往Registry里绑定恶意对象,诱导客户端去调用。所以Registry的端口(默认1099)和远程对象端口(动态分配)都要限制访问。最好把Registry单独跑在一个沙箱环境里,用SecurityManager限制权限,比如禁止写文件、禁止执行系统命令。

我见过最离谱的一个案例,某金融公司把RMI服务跑在Windows服务器上,用管理员账户启动。攻击者利用漏洞直接添加了系统用户,然后远程桌面登录。修复后他们问我,要不要把RMI改成HTTP调用?我说,如果非要用RMI,至少做到上面说的四点。如果只是内部系统,其实可以换成更安全的RESTful API,或者用gRPC——那玩意儿自带TLS和认证,省心得多。

最后说个现实问题:很多遗留系统改不动,代码老得跟化石一样。那也别硬撑着,至少加个代理层,把RMI服务藏在内网,外网只暴露一个经过加固的网关。网关做协议转换,把RMI请求转成内部HTTP调用,这样就算网关被攻破,攻击者也摸不到真正的RMI对象。

修复RMI漏洞不是一锤子买卖。你得定期扫描端口,看看有没有新的暴露面。用nmap扫一下,如果发现1099端口开着,就假设它已经被盯上了。别嫌麻烦,安全这活儿,就是跟攻击者比耐心。你多堵一个洞,他就多花一夜时间。

    热门排行

    友情链接