エンタープライズギークス (Enterprise Geeks)

企業システムの企画・開発に携わる技術者集団のブログです。開発言語やフレームワークなどアプリケーション開発に関する各種情報を発信しています。ウルシステムズのエンジニア有志が運営しています。

Struts1.1が使っているcommons-beanutils.jarのソースコードを取得する際に遭遇した混乱

Struts1の脆弱性問題(S2-020)に対処するために、commons-beanutils.jarを修正する方法を我々が採用したことは、先日の記事 で述べた通りだ。
この作業を行う中で、jakarta-struts-1.1が使っているcommons-beanutils.jarのソースコードを取得する際に混乱があったことを紹介しておく。

struts-1.1内にPropertyUtilsのソースコードは含まれていない

まず、jakarta-struts-1.1は以下のURLから取得可能だ。

http://archive.apache.org/dist/struts/struts-1.1/

この中に、変更対象のPropertyUtilsクラスのソースコードが含まれていれば話は簡単だったのだが、この中には含まれていない。commons-beanutils.jarは、contributionの扱いであり、jarは同梱されているものの、ソースコードはここには無いのだ。

struts-1.1が依存しているcommons-beanutils.jarのバージョンがおかしい

jakarta-struts-1.1-lib.zipやjakarta-struts-1.1-src.zipに同梱されているcommons-beanutils.jarのMANIFEST.MFには、以下のような記述がある。

Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Extension-Name: org.apache.commons.beanutils
Specification-Title: Jakarta Commons Beanutils
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.6
Implementation-Title: org.apache.commons.beanutils
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.6

Specification-VersionやImplementation-Versionは1.6となっている。そこで、以下のmavenリポジトリーからcommons-beanutils-1.6.jarを取得してみた。

http://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.6/

このcommons-beanutils-1.6.jarと、jakarta-struts-1.1に同梱されているcommons-beanutils.jarを比較してみると、意外なことに中身が異なっていることが分かった。よく調べると、jarファイルのファイルサイズも異なっている。元のcommons-beanutils.jarのファイルサイズは118,726バイト、commons-beanutils-1.6.jarのファイルサイズは118,483バイトだ。

こうなると、周辺のバージョンを探すことになる。探してみると、commons-beanutils-1.6.1.jarであればファイルサイズも合致し、diffを取ってもぴったり一致することが分かった。つまり、jakarta-struts-1.1が使用しているcommons-beanutilsの正確なバージョンは1.6.1だったのだ。ちなみに、commons-beanutils-1.6.1.jarのMANIFEST.MFの記述は以下の通り。

Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Extension-Name: org.apache.commons.beanutils
Specification-Title: Jakarta Commons Beanutils
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.6
Implementation-Title: org.apache.commons.beanutils
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.6

jarがバイナリレベルで合致しているため、当然といえば当然だが、Implementation-Versionなどが1.6.1ではなく1.6となっている。非常に紛らわしい。このjarはバージョン1.6.1であるにもかかわらず、MANIFEST.MFには1.6と記述してあるのだ。

maven上のcommons-beanutils.jarのソースコードがおかしい

commons-beanutilsのバージョンが確定したため、次に以下のmavenリポジトリーからソースコードを取得した。ファイル名はcommons-beanutils-1.6.1-sources.jarである。

http://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.6.1/

しかし、ここでまた問題が発生した。
commons-beanutils-1.6.1-sources.jarには、commons-beanutils-1.6.1.jarには存在するはずのConstructorUtilsなどのクラスのソースコードが含まれていないのだ。何かの間違いかと思い、ConstructorUtilsでソースコード全体をgrepしてみても、そんなキーワードはcommons-beanutils-1.6.1-sources.jarには含まれていなかった。明らかに、commons-beanutils-1.6.1-sources.jarはcommons-beanutils-1.6.1.jarのソースコードでは無いのだ。

正しいソースコードはどこに?

気を取り直し、mavenリポジトリーではなくapache.orgからソースコードを探すことにした。まず、mavenリポジトリーを用いた調査も信用できなくなったため、バイナリーレベルで該当バージョンを探す。以下の場所でcommons-beanutils-1.6.1.zipを取得してみたところ、中に入っていたcommons-beanutils.jarは、Struts1.1に同梱されていたcommons-beanutils.jarとぴったり一致した。やはり、Struts1.1が依存しているのはcommons-beanutils-1.6.1で確定だ。

http://archive.apache.org/dist/commons/beanutils/binaries/

次に、以下の場所からソースコード(commons-beanutils-1.6.1-src.zip)を取得した。この中には、ちゃんとConstructorUtilsなどの必要なクラスが一式揃っており、commons-beanutils-1.6.1のソースコードであると思えた。このソースコード全体を再コンパイルすると、コンパイラーの違いもあるのか、完全にコンパイル結果を一致させることは出来なかったものの、クラスそのものが欠落しているような状態にはならず、確証が得られた。よって、以下の場所にあるcommons-beanutils-1.6.1-src.zipが今回必要なソースコードだったのだ。

http://archive.apache.org/dist/commons/beanutils/source/

まとめ

最後に、struts-1.1が依存している、commons-beanutilsのソースコードを取得する際に遭遇した問題をまとめておく。

Struts 1などの脆弱性問題の対応で、beanutilsの修正版を独自に作る際には、これらに惑わされることのないよう、注意して作業する必要がある。

[近棟 稔]