HOME > Scutumを支える技術 > Scutum技術ブログ

技術者ブログ

クラウド型WAF「Scutum(スキュータム)」の開発者/エンジニアによるブログです。
金床“Kanatoko”をはじめとする株式会社ビットフォレストの技術チームが、“WAFを支える技術”をテーマに幅広く、不定期に更新中!

2021年10月

          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Scutum開発者/エンジニアによる技術ブログ WAF Tech Blog

続・デシリアライズ / jackson-databind編

2017年12月13日
野村 真作(Scutum開発者/株式会社ビットフォレスト シニアマネージャー)

TL;DR

アプリケーション側の問題をライブラリの責任にするのはどうかと思います(;´Д`)

S2-055

先日、Struts 2からまたセキュリティに関する修正としてS2-054及びS2-055がアナウンスされました。
私は、S2-055の概要を知った際に少々慌てました。 なぜなら、S2-052の調査の際に、XMLのハンドラだけでなくJSONのハンドラとしてJacksonLibHandlerを使う場合にも全く同じ事(XMLにおけるXStreamがJSONではJacksonになっているだけ)を行っているのに気付いた為、そちらは大丈夫なのか?と疑問を持って調査しており、その時点ではStruts 2でのJacksonの使い方でなら(少なくともStruts 2プロジェクトから配布されている物に関しては)影響は無い、と判断していたからです。

もしかすると自分の調査不足だったのか?あるいは新たな攻撃手法が見つかったのか?などと考えながらソースコード上の修正点を確認してみたところ、S2-055に関する変更点らしき部分は、バンドルされているライブラリであるJacksonのバージョンアップのみでした。

Jacksonの脆弱性?

では、Jackson側に何か重大な問題が見つかって、Struts 2での使用方法でも影響を受けるのが判明したのか?と、その件に関連するらしいJacksonのissueから始まる一連の流れを追ってみたところ、要するに、Polymorphic Type Handling(PTH)を有効にした状態のObjectMapperに対して信頼できないデータを渡してデシリアライズを行った場合、リモートからの任意のコードの実行(RCE)に繋がるじゃないか、と言う話のようでした。
私個人の意見としては、上掲したS2-052の調査に関する記事でも書いた通り、それはそんな事をやっているアプリケーションの問題だろうと感じます。 例えば、外部入力由来のJSONをJacksonでデシリアライズさせたい場合としてWeb APIをつくる場合などが考えられますが、PTHが必要になる場面はまず無いのではないかと思いますし、仮に必要な場合でも、ObjectMapper.enableDefaultTyping()を使ったり型の指定を実際のクラス名で行ったりするような手抜きをせずに、きちんと論理的な名前を与えるようにすれば解決できるのではないでしょうか。
しかしJacksonとしては結局、RCEに使用できる事が既知であるガジェットをブラックリストに入れて、インスタンス化できなくする事によって対処したようです。

上述のissueでの議論では、正規表現を使ってもっとガチガチのブラックリストにするべきだ、だとか、そもそもブラックリストじゃなくてホワイトリストにできねーの?と言うような意見が出ていますが、開発者の方のスタンスは、ブラックリストがあんまり良くないのはわかった上で、そもそも危険な使い方などしていない大半のユーザには関係の無い話なのだし、デシリアライズ機能のコア部分に過去との互換性を壊してしまうような大幅な制限は行いたくない、と言う感じのようです。
ライブラリの開発者としてはそれなりに妥当な対応だと思いますし、個人的には、それはアプリの責任だろと修正要請自体を突っぱねても良かったのでは...と思わなくもありません。
なお、先日の記事でもご紹介したリサーチペーパーを書かれた方による、PTHを有効にしての信頼できないデータのデシリアライズは本質的に危険であるとの警告を周知するのが良いのでは、と言う提案には、非常に前向きな反応をしていました。

結局どうだったのか

当初の結論通り、やはりStruts 2本体には影響を与えない問題でした。
ここに関しては、同様の調査を行われた方が詳細なレポートを公開しておられるので、気になる方はご一読をお薦めします。

なお私は、S2-055の"Impact of vulnerability"が"Not clear"な辺りから*1、Struts 2の開発側はこれがStruts 2本体に影響を与える問題であるのかどうかの調査も行っておらず、「ようわからんけどライブラリが脆弱性直した言うとるからワイらも脆弱性直した事にするか」のようなノリでS2-055を発行したのではないかと疑っています...。

本題 / Who's bad?

さて、このJacksonの更新を理由に、JBossにCVE-2017-7525及びCVE-2017-15095が発行されているのですが、 良くみるとこれらには、

However the affected code is NOT used at this time: ~略~ However as the vulnerable software ships with the product we have marked them as vulnerable to ensure the issue is tracked.

と書かれています。Struts 2の開発チームとの脆弱性報告への向き合い方の違いを感じますが、それはともかく、要するにこれらもS2-055と同じで、本体には影響しないよ、と言う事のようです。
もちろん脆弱性を持ったライブラリをバンドルして配布する事は避けるべきですし、バンドルしたライブラリの脆弱性は我々のソフトウェアの脆弱性でもあるのだ、との責任感は素晴らしいのですが、この件の場合、その「脆弱性」と言うのは、危険なので避けるべきであるとされている事をユーザアプリケーションが行った場合にのみ発現する問題です。 更に言えば、既知のガジェットによるRCEはとりあえず防げるようにはなるものの、未知のガジェットによるRCEはもちろん、問題の処理を行っているユーザアプリケーションへのオブジェクトインジェクション自体や状態操作の可能性等まで勝手に解決してくれる訳ではありません。
つまり、この修正を適用したところで、危ない事を行っているユーザアプリケーションは結局危ないままなのです。
このような問題に対して、本体は影響を受けない事がわかっているのにセキュリティ修正としてまでリリースする必要が本当にあるのでしょうか。
少なくとも、(殆どの場合)実際には必要の無いアップデートを頻繁に行わされる事になる現場のエンジニアとしては迷惑な話なのではないかと思います。
特に、CVSS3のBase Scoreが8.1ともなると、それなりのスピードでの対応を求められる事になってしまう場合が多いはずです。

そもそも、Java標準のObjectInputStreamなども信頼できないデータを読み込ませてしまうとコード実行されてしまう場合がありますが、同じ理屈で言えばJava自体が使えなくなってしまう(あるいはJacksonと同じようにJava自体の機能を制限しろと言うような話になってしまう)ように思います。

私は、ランタイムやライブラリでfoolproofを突き詰めて、変な制限が増えていく事には違和感を覚えます。 もちろんそれは程度問題でもあり、現実の被害の程度を勘案した上で決めるべき事なのかもしれませんが、信頼できないデータのデシリアライズが本質的に危険である事は、現代においてはOWASP TOP 10にすら入っているような話であり、既にその責任はユーザアプリケーションに移っていると言っても良いのでは、と思っています。

蛇足

上述したJacksonに組み込まれたブラックリストですが、実はミスがありました。
リストに並んでいるのは、インスタンス化させたくない型の名前なのですが、これらのうちSpringのライブラリに含まれている

org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor

は抽象型なので、仮にブラックリストに含まれていなかったとしてもどっちにしろインスタンス化できません。
実際に攻撃に使われるのはこの型を実装した

org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor

org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor

等となるのですが、これらの型は上記ブラックリストに含まれていないので、最新版のJackson(この記事を書いている2017/12/11の時点では2.9.3)でも蹴られずにインスタンス化でき、結果としてRCEが可能なのを確認しています。
一応開発者の方に連絡はしたものの、上述した通り、私はこの件をJacksonの脆弱性だとも考えていないので、その旨と、(PTHを有効にしての)信頼できないデータのデシリアライズはユーザの責任だと言ってしまった方が良いんじゃないかと伝えておきました。笑

この件が理由でまたJacksonやJBossやStruts 2からセキュリティ修正がリリースされる可能性があるのかもしれません。 また、Jackson側での対応がブラックリストでの制限である限り、今後も不毛なモグラ叩きが続く可能性があります。
しかしここまでで述べたように、その修正がJacksonへのブラックリストの追加が由来であるならば、それは基本的には緊急適用する必要は無いものである可能性が高いでしょう。 現場のエンジニアの方はこの事を知っておけば、多少心穏やかに過ごせるかもしれません(もちろん、そのセキュリティ修正の内容をきちんと確認する必要があるのは変わりませんが...)。

Scutumでの対応

この件に関して現実の攻撃パターンになり得て、かつ誤検知がなるべく起こらない範囲で、疑わしい通信を検知できるような仕組みを導入しました。
上述のJacksonのブラックリスト設定ミスへの対応も含めて既に対策済みとなっています。

終わりに

結果的にはやはり明確な脆弱性だと言うほどの物では無かったにせよ、S2-055の調査も無駄ではありませんでした。
我々Scutum開発チームは、WAFの使命には(ランタイムやライブラリとは異なり)「もしお客様のアプリケーションにミスが存在していたとしても、それをなるべくカバーする事」も含まれていると考えています。 むしろ、サーバソフトウェアやフレームワークの脆弱性ではない部分に関しても攻撃を検知/防御できるのはWAFの強みであろうと思うので、その部分を強化できた事は、その分WAFとして成長したと考えても良いのかもな、と思っています。

今後もWAFとしての使命がしっかりと果たせるように開発して行きたいと思います。

  1. *1 本記事の公開時点で、S2-055のアドバイザリのページ内容が変わっていますが、記事を書いていた時点での内容はこちらで確認できます。