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.1が依存しているcommons-beanutilsのバージョンは、MANIFEST.MFには1.6と書かれているが、実際には1.6.1である。
- mavenリポジトリーにあるソースコードは、バージョンが異なる。ソースコードはapache.orgから取得すること。
Struts 1などの脆弱性問題の対応で、beanutilsの修正版を独自に作る際には、これらに惑わされることのないよう、注意して作業する必要がある。
[近棟 稔]