5

I was reading the man page for the jarsigner tool that ships with the JDK. This line surprised me:

A verification is still considered successful if none of the files that were in the JAR file when the signature was generated have been changed since then, which is the case if the hashes in the non-header sections of the .SF file equal the hashes of the corresponding sections in the manifest file.

This doesn't make sense to me. Couldn't an attacker hide malicious code in an already-signed jar file?

Update: Here is an example of this scenario. It looks like jarsigner will flag the jar as containing extra files, but still considers it verified.

=> 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.
T.D. Smith
  • 153
  • 1
  • 6
  • "A successful JAR file verification occurs if the signature(s) are valid, and none of the files that were in the JAR file when the signatures were generated have been changed since then." I can see this in the docs page... – pri Jul 18 '16 at 13:49
  • But files can be added to the jar after the signature without invalidating it. – T.D. Smith Jul 18 '16 at 13:51
  • 2
    Have you tried adding files them validating the signature? I wonder if it's just bad doc – Neil Smithline Jul 18 '16 at 13:53
  • @NeilSmithline I updated the question with an example. I was able to add a file and still get a verified jar, though jarsigner did complain about the added file. – T.D. Smith Jul 18 '16 at 14:26
  • 2
    LOL. Well that's a helluva bug/design oversight. It sure seems this should be worth more than a warning to me – Neil Smithline Jul 18 '16 at 22:44

3 Answers3

2

From my reading of this, yes, an attacker could insert malicious code into the jar. However, unless there is a code in the signed part of the that that tries to load the malicious file, the malicious file is just there inert and unable to do anything meaningful.

Errors and Warnings

During the signing or verifying process, the jarsigner command may issue various errors or warnings.

If there is a failure, the jarsigner command exits with code 1. If there is no failure, but there are one or more severe warnings, the jarsigner command exits with code 0 when the -strict option is not specified, or exits with the OR-value of the warning codes when the -strict is specified. If there is only informational warnings or no warning at all, the command always exits with code 0.

...

Severe Warnings

Note: Severe warnings are reported as errors if you specify the -strict option.

Reasons why the jarsigner command issues a severe warning include the certificate used to sign the JAR file has an error or the signed JAR file has other problems.

...

hasUnsignedEntry Code 16. This jar contains unsigned entries which have not been integrity-checked.

...

In any case, if you look at all the other possible severe warnings in the documentation, it becomes quite obvious that doing --verify without --strict is pretty much useless for scripting uses.

Lie Ryan
  • 31,089
  • 6
  • 68
  • 93
0

From what I can tell, the generated folder called META-INF contains signatures and hashes for every class initially inside the JAR file. The reason that adding a class doesn't change the signature is because there is no overall signature for the JAR itself
An example of this is Minecraft modding. Before the forge API, it required deleting the signature folder as it modified classes that had signatures in it, but now they just replace the signature files with one signed by their own key, as it helps ensure the data integrity of the JAR contents

0

But files can be added to the jar after the signature without invalidating it.

erm, no - jar is doing what it said it would do - none of the files which were signed have changed. But yes, you've just shown that the emperor has no clothes - this jar verification is useless.

symcbean
  • 18,278
  • 39
  • 73