如果文件已添加到 jar 中,为什么 .jar 签名仍然有效?

信息安全 爪哇 代码签名
2021-08-18 04:45:31

我正在阅读JDK 附带的工具的手册页。jarsigner这条线让我很惊讶:

如果生成签名时 JAR 文件中的所有文件从那时起都没有更改,则验证仍然被认为是成功的,如果 .SF 文件的非标题部分中的哈希值等于清单文件中的相应部分。

这对我来说没有意义。攻击者不能在已经签名的 jar 文件中隐藏恶意代码吗?

更新:这是这种情况的一个例子。看起来 jarsigner 会将 jar 标记为包含额外文件,但仍认为它已验证。

=> jar -cf twelfthnight.jar TwelfthNight.html
=> keytool -genkey -alias signFiles -keystore examplestore
=> jarsigner -keystore examplestore twelfthnight.jar signFiles
Enter Passphrase for keystore:
jar signed.

Warning:
The signer certificate will expire within six months.
No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2016-10-16) or after any future revocation date.

=> jarsigner -verify twelfthnight.jar
jar verified.

Warning:
This jar contains entries whose certificate chain is not validated.
This jar contains entries whose signer certificate will expire within six months.
This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2016-10-16) or after any future revocation date.

Re-run with the -verbose and -certs options for more details.

=> jar uf twelfthnight.jar Hamlet.html

=> jarsigner -verify twelfthnight.jar
jar verified.

Warning:
This jar contains unsigned entries which have not been integrity-checked.
This jar contains entries whose certificate chain is not validated.
This jar contains entries whose signer certificate will expire within six months.
This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2016-10-16) or after any future revocation date.

Re-run with the -verbose and -certs options for more details.
3个回答

从我的阅读来看,是的,攻击者可以将恶意代码插入到 jar 中。但是,除非在尝试加载恶意文件的签名部分中有代码,否则恶意文件只是惰性的,无法做任何有意义的事情。

错误和警告

在签名或验证过程中,jarsigner 命令可能会发出各种错误或警告。

如果失败,jarsigner 命令以代码 1 退出。如果没有失败,但有一个或多个严重警告,则 jarsigner 命令在未指定 -strict 选项时以代码 0 退出,或以 OR 退出- 指定 -strict 时警告代码的值。如果只有信息警告或根本没有警告,则该命令始终以代码 0 退出。

...

严重警告

注意:如果您指定 -strict 选项,则会将严重警告报告为错误。

jarsigner 命令发出严重警告的原因包括用于签署 JAR 文件的证书有错误或签署的 JAR 文件有其他问题。

...

hasUnsignedEntry 代码 16。此 jar 包含未经完整性检查的未签名条目。

...

在任何情况下,如果您查看文档中所有其他可能的严重警告,很明显执行 --verify 而不使用 --strict 对脚本使用几乎没有用处。

据我所知,生成的名为 META-INF 的文件夹包含最初在 JAR 文件中的每个类的签名和哈希。添加类不会更改签名的原因是因为 JAR 本身没有整体签名。
一个例子是 Minecraft 改装。在 forge API 之前,它需要删除签名文件夹,因为它修改了其中包含签名的类,但现在他们只需将签名文件替换为由自己的密钥签名的文件,因为这有助于确保 JAR 内容的数据完整性

但是可以在签名之后将文件添加到 jar 中而不会使其无效。

呃,没有 - jar 正在做它说它会做的事情 - 签名的文件都没有改变。但是,是的,你刚刚证明了皇帝没有衣服——这个罐子验证是没有用的。