Struts1 の ClassLoader 脆弱性問題について

Apache Struts 2の脆弱性が、サポート終了のApache Struts 1にも影響

Struts1なんて星の数ほどのJava開発者がソースコード読んでたはずなのに、よく今まで誰も気づかなかったものだと思う。「目玉の数さえ十分あれば、どんなバグも深刻ではない」という言葉は多くの人が思っていたほど堅牢なものではなかったようだ。

なぜ、わざわざこのようなエントリを書き起こそうかと思ったかというと、同じ問題がJSONICでも起こるのではないかと一瞬冷や汗が出たからである。が、結論から言うと問題はない。

まず、今回の問題だが、 aaa.bbb.ccc といった式言語的な表現を aaa.getBbb().setCcc(value) のような Java プロパティアクセスに展開するような仕組みが用意されていると、すべてのオブジェクトのベースとなる java.lang.Object が持つ getClass().getClassLoader().setXxx(value) にアクセス出来てしまうという点にある。

このような仕組み自体は Servlet系のフレームワークで持たないものなど存在しないと思われるので、本当に問題が起きないのか検証が必須と思われる。すでに SAStruts については問題ないとの報告が出ているが、他のフレームワークも検証した方がよい気がする。

さて、JSONICではなぜ問題が発生していなかったかと言うと、JSONICでは ignore や limit メソッド内で java.lang.Object のプロパティやメソッドを無視するよう書かれていたりするのである。なので、問題はない、とは言ったものの、ignoreやlimitをオーバーライドして無視する処理をスキップしてれば問題は発生する可能性が出てくる。が、それは明示的に書かれた処理なのであるから、開発者の意図した動作と考えるべきだろう。

まぁ、ともかく(私は)ひと安心したということで。

[追記] 前述の通り普通の利用方法をする分には問題はないのではあるが、やはりより安全側に倒した方がよい気がしてきたので以下の対応を入れたいと思う。

  • BeanInfo で以下の条件に当てはまるクラスのメソッドはプロパティ扱いしない(メソッドとしては認識される)
    • java.lang.Object で定義されている(=getClass()はプロパティ扱いされない)
    • java.lang.Class で定義されている
    • java.lang.ClassLoader およびその子クラスで定義されている

[さらに追記] 対応を入れて 1.3.4 としてリリースしてみた。

なお、いろいろ考えた結果「java.lang.ClassLoader およびその子クラスで定義されている部分」については対応を止めることにした。ClassLoaderがダメなら、ThreadやらSecurityManagerやらRuntimeやらいろいろ除外する必要があるし、config系だと必要な場面もあるだろうと考えた末の結論である。外部から値を受け取る Bean にシステム系のオブジェクトを設定した場合、脆弱性が発生するがそれは開発者側で意識すべき問題だろう。