ポタージュを垂れ流す。

マイペースこうしん(主に旅行)

「安全ではないデシリアライゼーション」についてpythonのpickleから少しだけ理解する

例によってリレーブログの時間です!前の僕の記事はこれ、前回の方のブログはこちらになります。

amame.hateblo.jp

今回のテーマは「安全ではないデシリアライゼーション」です。

リアライゼーション / デシリアライゼーションとは

リアライゼーションとは、プログラムの実行状態や複雑なデータ構造などを、バイト列やjsonといった直列化された形式で表現することです。今回紹介するpickle形式もその形式の1つです。pythonではdump()とかdumps()関数を呼び出して直列化することが多いと思います。

逆に、デシリアライゼーションとは、シリアライゼーションされたデータを元の状態や形式に復元することです。

pickle

pythonでは、pickleモジュールを利用することでオブジェクトをバイナリ形式でpickleファイルとして保存することができます。利用用途としては、例えば、機械学習などでモデルを学習している途中の状態をpickleファイルで保存したり、学習済モデルのpickleファイルを読み込んで利用する、なんてことに使われています。

pickleめっちゃ便利やん!とはなるのですが、pickleファイルをデシリアライズする際にセキュリティ面の考慮がなされておらず、シェルコードの実行ができてしまいます。悪意のあるpickleファイルであればリモートコード実行とか色々できてしまいます。

pythonのdocumentのpickleの項目にも、

警告 pickle モジュールはエラーや不正に生成されたデータに対して安全ではありません。信頼できない、あるいは認証されていないソースから受け取ったデータを非pickle化してはいけません。

との記述があります。

また、昔はDjangoのセッション管理にpickleが使われていたようで、SECRET_KEYが第三者に漏れると悪意のあるpickleが作れて、悪意のあるcookieが作れてしまうとかそういう脆弱性があったようです。

やってみる

試しに、中身が以下のようになっているExample_bad.pickleを用意しました。

cos
system
(Vecho I\'m gonna pickle you! > message.txt
tR.

これを読み込んでみます。

import pickle

with (open("Example_bad.pickle", "rb")) as f:
    p = pickle.load(f)

これを実行すると、アヤシイExample_bad.pickleを読み込んだだけで、カレントディレクトリに「I'm gonna pickle you!」の記述があるmessage.txtが作成(もしくは、存在していれば置換が)されてしまいます。「お前を漬物にしてやる!」、なんて怖いメッセージでしょうか。

この例はかなり簡単なものでしたが、システムに損害を与えてしまうようなコードが実行できてしまうことを想像するのは難しくないと思います。

まとめ

安全ではないデシリアライゼーションに気をつけよう!

次のブログはこちらです

qwerty11.hatenablog.com