JDK 8u161中Apache FTPS客户端中的SSL会话重用

使用Apache Commons-Net的FTPSClient连接到现代FTP / S服务器不起作用。 原因是它们需要重用SSL会话,即需要重新使用来自控制连接的SSL会话进行数据连接。

这通常可以在服务器中停用,但也就是说

  • 不安全
  • 并不总是一个选项(因为服务器可能不在您的控制之下)

正确的解决方案是让客户端实际重用会话。 Commons-Net存在一个漏洞 ,但看起来不会很快得到解决。

此外,还有一个由Cyber​​duck(一个FTP客户端应用程序)的作者创建的“reflection黑客”,它在他们的bugtracker中进行了描述,并且在博客文章中更深入地描述。 StackOverflow上还有一篇相关文章描述了这个解决方案。 他们使用reflection来访问JDK的SSLSessionContext的内部缓存并注入一个新条目。

这个hack工作正常,直到JDK 8u161和9.0.4(?),其中引入了对更改日志中描述的SSL的一些更改。 显然,一些实现细节已经改变,导致黑客不再工作。

据我所知,现在有以下选项:

  • 继续使用JDK 8u152,直到有人找到解决方案/ apache-commons-net得到修补/ JDK更改被回滚(不是真正的选项,因为这会切断生产系统的安全更新)
  • 使用不同的FTPS客户端(我能找到的唯一替代方案是专有且非常昂贵)
  • 尝试对SSLSessionContext实现的更改进行反向工程以查找新的解决方法。 这看起来不仅仅是一项非常重要的任务 – 解决方案可能会再次成为黑客,因此可能随时再次破裂。
  • 不要再使用FTP / S.

谁能建议如何在这里继续?


相关链接:

  • http://mail.openjdk.java.net/pipermail/security-dev/2016-December/015254.html
  • https://bugs.openjdk.java.net/browse/JDK-8170813
  • https://issues.apache.org/jira/browse/NET-426

这里描述了可能的解决方案。

从本质上讲,它正在将改变的行为从JDK8u161恢复到以前的工作方式。 您需要设置系统属性

 jdk.tls.useExtendedMasterSecret 

这样做是false

有两种方法:

  • 调用System.setProperty("jdk.tls.useExtendedMasterSecret", "false"); 在启动FTP / S连接之前
  • 使用java -Djdk.tls.useExtendedMasterSecret=false [...]将属性传递给java进程java -Djdk.tls.useExtendedMasterSecret=false [...]

请记住,此解决方案会禁用JVM范围内的安全增强function – 请谨慎操作。