5

I would like to enforce a strict Maven dependency policy which goes beyond the basic checksumPolicy=fail approach.

This is an attempt to provide protection against a modified release dependency which still has a valid digest value also known as a "dependency chain attack".

This situation could arise from the following scenarios:

  • the dependency has been updated, but the author has not updated the version number and managed to overwrite the earlier release (or their repo account has been compromised)
  • a man-in-the-middle attack is in place (with on-the-fly rewriting/hashing)
  • the repository itself has been compromised

In discussions with other developers one approach to combat the above is to have a list of known MD5/SHA digests in the pom.xml and have Maven verify that the downloaded dependency has the same digest. This ensures that so long as the source code repository remains secure, any included dependencies that have been compromised will be detected.

Thus my question is twofold:

  1. are there any alternative approaches that would work more efficiently?
  2. are there any existing implementations/plugins that do this job?
Gary
  • 7,167
  • 3
  • 38
  • 57
  • You know that you already have checksums (md5, sha1) in the maven repository? Just change the settings.xml (checksumpolicy?) to fail the build if one of the checksums is not correct. – khmarbaise Jan 08 '13 at 13:59
  • It is not about the checksums being incorrect - it is about them having changed. Please read the question more closely. – Gary Jan 08 '13 at 14:05
  • I have read the question. Are you talking about Maven Central ? – khmarbaise Jan 08 '13 at 14:17
  • Any arbitrary repository. It is likely that Maven Central will have protections in place to avoid overwriting released artifacts, but hacks do happen and it is required that I can detect them. – Gary Jan 08 '13 at 14:29
  • 1
    Useful discussion on [repository protection in Maven Central](http://www.sonatype.com/people/2012/03/the-first-line-of-defense-checksums-and-pgp-signatures-in-repositories/) – Gary Jan 08 '13 at 15:01
  • Related: [Verification of dependency authenticy in Maven POM based automated build systems](http://stackoverflow.com/questions/3307146/verification-of-dependency-authenticy-in-automated-build-systems/34795359#34795359) – Flow Jan 14 '16 at 17:41

2 Answers2

7

If anyone is wrestling with this issue themselves I've created a Maven Enforcer Plugin Rule that deals with it. You can specify a list of artifact URNs that include the expected SHA1 hash value and have the enforcer verify that this is indeed what is being used in the build.

It is available through Maven Central under MIT license, with source code in GitHub here: https://github.com/gary-rowe/BitcoinjEnforcerRules

While the project indicates that it is for the Bitcoinj library, it is actually a general purpose solution which could be included in any security conscious build process. It will also scan your existing project and identify any problem area while it automatically builds the whitelist for you.

Below is an example of the configuration you'd require in your project to use it.

<build>
  <plugins>
    ...
      <!-- Use the Enforcer to verify build integrity -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>1.2</version>
        <executions>
          <execution>
            <id>enforce</id>
            <phase>verify</phase>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <digestRule implementation="uk.co.froot.maven.enforcer.DigestRule">

                  <!-- Create a snapshot to build the list of URNs below -->
                  <buildSnapshot>true</buildSnapshot>

                  <!-- List of required hashes -->
                  <!-- Format is URN of groupId:artifactId:version:type:classifier:scope:hash -->
                  <!-- classifier is "null" if not present -->
                  <urns>

                    <urn>antlr:antlr:2.7.7:jar:null:compile:83cd2cd674a217ade95a4bb83a8a14f351f48bd0</urn>
                    <urn>dom4j:dom4j:1.6.1:jar:null:compile:5d3ccc056b6f056dbf0dddfdf43894b9065a8f94</urn>
                    <urn>org.bouncycastle:bcprov-jdk15:1.46:jar:null:compile:d726ceb2dcc711ef066cc639c12d856128ea1ef1</urn>
                    <urn>org.hibernate.common:hibernate-commons-annotations:4.0.1.Final:jar:null:compile:78bcf608d997d0529be2f4f781fdc89e801c9e88</urn>
                    <urn>org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final:jar:null:compile:3306a165afa81938fc3d8a0948e891de9f6b192b</urn>
                    <urn>org.hibernate:hibernate-core:4.1.8.Final:jar:null:compile:82b420eaf9f34f94ed5295454b068e62a9a58320</urn>
                    <urn>org.hibernate:hibernate-entitymanager:4.1.8.Final:jar:null:compile:70a29cc959862b975647f9a03145274afb15fc3a</urn>
                    <urn>org.javassist:javassist:3.15.0-GA:jar:null:compile:79907309ca4bb4e5e51d4086cc4179b2611358d7</urn>
                    <urn>org.jboss.logging:jboss-logging:3.1.0.GA:jar:null:compile:c71f2856e7b60efe485db39b37a31811e6c84365</urn>
                    <urn>org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final:jar:null:compile:2ab6236535e085d86f37fd97ddfdd35c88c1a419</urn>

                    <!-- A check for the rules themselves -->
                    <urn>uk.co.froot.maven.enforcer:digest-enforcer-rules:0.0.1:jar:null:runtime:16a9e04f3fe4bb143c42782d07d5faf65b32106f</urn>

                  </urns>

                </digestRule>
              </rules>
            </configuration>
          </execution>
        </executions>

        <!-- Ensure we download the enforcer rules -->
        <dependencies>
          <dependency>
            <groupId>uk.co.froot.maven.enforcer</groupId>
            <artifactId>digest-enforcer-rules</artifactId>
            <version>0.0.1</version>
          </dependency>
        </dependencies>

      </plugin>
    ...
  </plugins>
</build>
Gary
  • 7,167
  • 3
  • 38
  • 57
2

Sounds like a good job for the repository itself. Check out this other thread regarding a similar question.

I've no familiarity with the PGP signing scenario in Nexus, but does that sound like a good start?

Community
  • 1
  • 1
Nick Cotter
  • 125
  • 1
  • 9
  • I did take a look at that thread, and it seems that signed JARs are a good way forward. Unfortunately, I can't guarantee that the authors will sign their JARs. Also, I would prefer to use a repo like Maven Central and detect change rather than rely on my own internal repo since this is an open source project. – Gary Jan 08 '13 at 14:56