AlbertJay
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
前言
在一个宁静的周末,我决定探索一些常见的软件安全问题,以提升自己的技能。作为一名网络安全爱好者,我一直对软件更新机制的安全性特别感兴趣。在这个过程中,我偶然发现了一个广泛使用的多平台 Java 安装程序构建器——install4j——中存在的一个潜在漏洞。这个发现不仅让我兴奋,也让我意识到即使是最常用的软件框架也可能存在安全隐患。
我最初是在研究一款名为 Prosys OPC UA 模拟服务器的软件时,注意到了一个有趣的现象。在安装过程中,当我选择自动更新间隔后,安装向导意外地关闭了。这一现象立即引起了我的注意,因为类似的关闭行为在过去的 XXE 攻击案例中也曾出现过。尽管我没有参加任何安全竞赛的计划,但这个发现激发了我的好奇心,促使我深入研究 install4j 的更新机制。
发现之旅
在安装过程中,我注意到 Prosys OPC UA 模拟服务器使用了 install4j 作为其安装和更新框架。Install4j 是一个广泛使用的多平台 Java 安装程序构建器,可以生成原生安装程序和应用程序启动器。我最初并没有意识到 install4j 的广泛使用,直到后来才发现它被许多知名软件所采用,比如 Burp Suite。
我开始研究 install4j 的更新功能,希望能够找到一些安全漏洞。经过一番努力,我发现了一个潜在的 XXE(XML External Entity)攻击漏洞。这个漏洞存在于 install4j 的最新版本 10.0.4 以及之前的版本中。如果攻击者能够控制更新服务器的响应,就可以利用这个漏洞发起攻击。
漏洞细节
Install4j 的更新功能依赖于从更新服务器获取一个 XML 文件,该文件包含了最新的软件版本信息。当客户端触发更新检查时,会从服务器下载这个 XML 文件并进行解析。然而,install4j 在解析 XML 文件时存在一个严重的安全问题:它没有正确地阻止外部实体的加载。
具体来说,install4j 使用了 com/install4j/runtime/installer/helper/XmlHelper 类中的 parseFile 方法来解析 XML 文件。这个方法的实现如下:
public static Document parseFile(final File file) throws IOException {
return parseFile(file, false, false); // [1]
}
public static Document parseFile(final File file, final boolean validating, final boolean downloadExternalEntities) throws IOException {
return parse(new InputSource(file.toURI().toASCIIString()), validating, downloadExternalEntities); // [2]
}
private static Document parse(final InputSource inputSource, final boolean validating, final boolean downloadExternalEntities) throws IOException {
final DocumentBuilderFactory documentBuilderFactory = createDocumentBuilderFactory(); // [3]
// 方法 [3] 中调用的部分代码
public static DocumentBuilderFactory createDocumentBuilderFactory() {
try {
return DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", null); // [4]
} catch (final Throwable t) {
return DocumentBuilderFactory.newInstance();
}
}
documentBuilderFactory.setValidating(validating);
DocumentBuilder documentBuilder;
try {
documentBuilder = documentBuilderFactory.newDocumentBuilder(); // [5]
} catch (final ParserConfigurationException e) {
throw createIoException(e);
}
if (validating) {
documentBuilder.setErrorHandler(new ErrorHandler() {
@Override
public void error(final SAXParseException exception) throws SAXException {
log(exception);
}
畅读付费文章
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)