LoginSignup
3
6

More than 5 years have passed since last update.

PHP Object Injection とアプリケーションの互換性についての考察

Last updated at Posted at 2017-02-22

PHP Object Injection (POI) とは何か

以下のリンクが参考になります。

PHP の unserialize 関数に、外部からコントロールでき改竄されたことを検証できない値を渡している場合に発生する脆弱性です。

修正方法は、上記のリンクのいずれにも記載がある通り unserialize / serialize 関数を使う代わりに json_decode / json_encode を使うようにすることです。

なお PHP7 から導入された allowed_classesfalse に設定するという方法もありますが、今回は PHP5 系のことを考えて以下では検討しないことにします。
allowed_classesを設定する方法については Practical PHP Object Injection (p. 82) のように本当にバイパスできないものなのか、という意見もあります)

POI 修正前後で失われる互換性について

上記の通り、修正のためにはデータのシリアライズ方式を変更する必要があります。
つまり、アプリケーションの修正前にシリアライズされたデータが、アプリケーション修正後にはデシリアライズできないことになります。
そういった事態が問題になるかどうかはアプリケーションの仕様によるとは思いますが、互換性は失われてしまいます。

もちろん POI により任意の PHP コードが実行できるようになってしまう可能性を考えると、修正により互換性が失われることを許容できる場合もあると思いますが(というよりもそれが大半の場合ではないかと思いますが)、許容できない場合もあると思います。

許容できない、となると前述の方法では修正できないということになってしまいますので、以下ではこの場合について修正方針を考えていきます。

考えられる対応

以下のような状況にあるアプリケーションを考えます。

  • (0): unserialize で外部からコントロール可能な値を処理している (データのシリアライズは serialize で実施)

これを以下のように変更していくとどうでしょうか?

  • (1): データのシリアライズは json_encode で実施するように変更。デシリアライズを、最初に json_decode を試みて失敗したら unserialize するようにする
  • (2): unserialize でデシリアライズする必要のあるデータの割合が、あらかじめ決めておいた閾値より小さくなったタイミングでデシリアライズを json_decode のみに変更する

このように (0) -> (1) -> (2) の順で修正を実施すると、(0) の段階でシリアライズされたデータを (1) の段階でも引き続き処理でき、最終的な (2) に至るまでに互換性が失われるデータを少なくすることができます。

しかし、この修正方法では (1) の修正途中の段階では依然として POI が残ったままであり、この点で問題があるといえます。

そこで、(1) の部分を以下のように変えてみます。

  • (1'): データのシリアライズは json_encode で実施するように変更。デシリアライズを、最初に json_decode を試みて失敗したら unserialize' するようにする。

unserialize' というのは以下のものと考えてください。

  • POI を引き起こす object のデシリアライズはしない
  • それ以外の boolean、integer、string、arrayといったPOIを引き起こさない値のみをデシリアライズする

(0) -> (1') -> (2) の順で修正を実施することで、(0) の段階でシリアライズされたデータを (1') でも引き続き処理しつつ POI は発生させないようになっており、(0) -> (1) -> (2) の順で修正した場合に比べて状況が改善されているといえると思います。

作ったもの

前述した unserialize' に相当するものとして、 restricted-unserialize という composer package を作成しました。

まとめ

  • POI を修正するために unserializejson_encode に置き換える過程で生じる互換性の問題について記述しました
  • 互換性の問題を回避しつつ POI を修正する方法として、 unserialize' を利用する方法を提案しました
  • unserialize' の実装として、 restricted-unserialize というパッケージを作成しました
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6