サイト脆弱性をチェックしよう! -- 第17回:安全でないデシリアライズ
<目次>
目次[非表示]
- 1.デシリアライズとは
- 2.デシリアライズのリスク
- 3.デシリアライズの対策
安全でないデシリアライズはSQLインジェクション、クロスサイト・スクリプティングなどに比べ、あまり広く知られていない脆弱性だ。しかし、ブラウザとの直接通信を行わないバックエンドサーバやスマートフォンアプリケーションで使用されるシリアライズ処理を利用する場合に発見されやすい脆弱性である。
この脆弱性は近年発見されることが多くなってきたため、2017年に公開されたOWASP Top 10でも取り上げられるようになって、ご存じの方も多いと思う。
デシリアライズとは
アプリケーションではプロセス間通信や一時的なプログラム実行の中断、再開を必要とすることがある。これらを実施するためには、実行中のオブジェクトをプロセス間で受け取ることや、ファイルに保存することが必要だ。この時、実行中のオブジェクトを一つのバイト列にしてデータの授受や保存をすることで、容易に処理を行える。
このオブジェクトを一つのバイト列にする処理をシリアライズと呼び、また、シリアライズされたデータを読み込み、元のオブジェクトに復元する処理をデシリアライズと呼ぶ。
シリアライズやデシリアライズ処理を行うことで、アプリケーションは復元されたオブジェクトをコード内で生成されたオブジェクトと同様に操作することが可能となる。
デシリアライズのリスク
シリアライズされた任意のデータを外部から受け取り、そのデータをデシリアライズする際にリスクが生じる。このリスクには2種類あり、1つはオブジェクトの持つフィールドに任意の値が設定可能であること、もう1つはリモートコードの実行だ。
オブジェクトの持つフィールドに任意の値が設定可能である問題
デシリアライズすると、受け取ったバイト列を元にオブジェクトが生成される。しかし、データに対する各フィールドの型の確認、シリアライズできるクラスであることの確認以外は検証されない。このため、外部から直接操作できないフィールドの値を自由に操作することができる。
例えば、UserクラスにisAdminというフィールド(通常このフィールドは自由に設定できない)があり、管理者権限を示すフラグであるとする。このUserクラスをシリアライズしたCookieがあり、このCookieを用いて現在のセッションのユーザのアクセス権限を制御している場合、デシリアライズするオブジェクトのisAdminフィールドをtrueにすることで、管理者権限のないユーザでも、管理者権限を取得することができる。
また、データの検証が実施されないため、フィールドの値を利用している別の場所で、SQLインジェクションなどの脆弱性を引き起こす可能性がある。
リモートコードの実行
デシリアライズを実行する際、明示的に呼び出さなくても呼び出されるメソッドがあり、これを利用して任意のコードが実行できる場合がある。このメソッドはデシリアライズすると同時に実行されるため、生成されたオブジェクトを利用する前に検証するだけでは、任意のコードの実行を防ぐことはできない。
デシリアライズしたオブジェクトのこのメソッドに任意のコードを実行できる脆弱性がない場合、攻撃には利用できない。しかし、デシリアライズするオブジェクトは、シリアライズされたデータによって任意のクラスを指定できる。このため、アプリケーションに存在する脆弱性のあるクラスを利用することで、任意のコードをデシリアライズした時に実行することができる。
デシリアライズの対策
可能ならば、デシリアライズを使用しないデータの受け渡しを推奨する。もし必要ならば、リモートコードの実行を防ぐため、JSON形式等でデータの受け渡しを行ってほしい。加えて、デシリアライズされたオブジェクトが持つフィールドは、全て使用する前にデータの検証等の処理を行って、安全を確保してから使用してほしい。
これらの対策が取れない場合、シリアライズされたデータを署名し、その署名の正当性を検証してからデシリアライズすることで、単純な攻撃に対する予防策となる。