Upgrade to Pro — share decks privately, control downloads, hide ads and more …

デシリアライゼーションを理解する / Inside Deserialization

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

デシリアライゼーションを理解する / Inside Deserialization

PHPカンファレンス小田原2026の資料です

Avatar for HASEGAWA Tomoki

HASEGAWA Tomoki

April 09, 2026

More Decks by HASEGAWA Tomoki

Other Decks in Technology

Transcript

  1. ௕୩઒ஐر ͸͕ͤΘ ͱ΋͖ @tomzoh ٕज़ΧϯϑΝϨϯεӡӦࢀՃ ֤छϓϩάϥϜ։ൃ   $16 ϨτϩήʔϜػ

    ిࢠ޻࡞  Ϗʔϧ αοΧʔ؍ઓ ϨϯλϧΧʔτϨʔε  ΩϟϯϐϯάΧʔ ๅ௩؍ܶʜ ϥΠϑϫʔΫ 𝕏
  2. 長谷川智希 @tomzoh デシリアライゼーションを理解する React2Shell • 2025年12月に発見された超絶インパクトの脆弱性 • React + Next.js

    の React Server Components の脆弱性 • 認証されていない攻撃者がHTTPリクエストを1つ送信するだけで任意コード実行できる • React Server Components • 通常のWebアプリでは /api/update-user みたいなAPIエンドポイントを作ってフロントエ ンドからコールする • Next.jsではプログラマが定義した関数に対応する内部APIエンドポイントが自動で用意され る機能がある • function updateUser(formData){} 的にサーバで定義しておき、 フロントエンドで <form action={updateUser}> 的にする • この処理に脆弱性があった • この脆弱性は安全でないデシリアライゼーションに分類される 5
  3. 長谷川智希 @tomzoh デシリアライゼーションを理解する OWASP Top 10 2017 A1: 2017-Injection A2:

    2017-Broken Authentication A3: 2017-Sensitive Data Exposure A4: 2017-XML External Entities (XXE) A5: 2017-Broken Access Control A6: 2017-Security Miscon fi guration A7: 2017-Cross-Site Scripting (XSS) A8: 2017-Insecure Deserialization A9: 2017-Using Components with Known Vulnerabilities A10: 2017-Insuf fi cient Logging & Monitoring 6 安全でないデシリアライゼーション CSRF SQLインジェクション XSS
  4. 長谷川智希 @tomzoh デシリアライゼーションを理解する PHPまわりで使われているシリアライズ • PHPのSESSION user_id|i:1042;username|s:6:"tanaka";role|s:5:"admin";login_time|i:1744185600; • LaravelでQueueを使う時のjobsテーブルのpayload {"uuid":"d6062a83-cfe3-4f13-b013-701940371442","displayName":"App\\Jobs\

    \FooBarJob","job":"Illuminate\\Queue\ \CallQueuedHandler@call","maxTries":null,"maxExceptions":null,"failOnTimeout":fa lse,"backoff":null,"timeout":14400,"retryUntil":null,"data":{"commandName":"App\ \Jobs\\FooBarJob","command":"O:18:\"App\\Jobs\\FooBar\":1: {s:10:\"\u0000*\u0000queueId\";i:5963;}"}} • WordPressのwp_optionsテーブルのoption_value a:2:{i:0;s:18:"pagespeed-insights";i:1;s:11:"analytics-4";} 9
  5. 長谷川智希 @tomzoh デシリアライゼーションを理解する 脆弱性への道 • unserialize() では新しいクラスやメソッドは作れないが 既存のクラスのインスタンスは作れる • 脆弱性のあるクラスのインスタンスをいい感じのプロパティで作ってやる

    • PHPには特定のタイミングで自動実行されるメソッドがある • __unserialize() / __wakeup() • __destruct() • __toString() • 自動実行されるメソッドで狙った効果を発動させる 10
  6. 長谷川智希 @tomzoh デシリアライゼーションを理解する 安全でないデシリアライゼーション 破壊力絶大の脆弱性 • 一撃で任意コード実行に行き着くことが多く破壊力の大きな脆弱性になりがち • 脆弱なクラス(ガジェット /

    gadget)と組み合わせて攻撃に使われる • デモの場合 LogWriter がガジェット • TodoList をデシリアライズすることを意図した処理に LogWriter をデシリアライズさせていた 21
  7. 長谷川智希 @tomzoh デシリアライゼーションを理解する どうしたら良かった…? • システム外部から来たデータを信じない • 聞き覚えが…? • コンピュータシステムのセキュリティ問題、だいたいこれ

    • XSS, CSRF, SQLインジェクション, … • 本当に serialize() / unserialize() でないといけないか (= オブジェクトとしてシリ アライズする必要があるか) をよく考える • ToDoの配列を json_encode() / json_decode() で良くない? • 我々が書くようなWebアプリの世界では serialize() / unserialize() でないといけな いケースは無いと言って過言では無いのでは • 「こういう時に必要だったんだよね」という体験談ある方ぜひ聞かせて! 22
  8. 長谷川智希 @tomzoh デシリアライゼーションを理解する 余談: unserialize()できなかったオブジェクト • allowed_classes に書かれていないクラスをアンシリアライズするとどうなるか • __PHP_Incomplete_Class

    というクラスのインスタンスができる object(__PHP_Incomplete_Class)#1 (3){ ["__PHP_Incomplete_Class_Name"]=> string(9) "LogWriter" ["path"]=> string(28) "/var/www/html/data/shell.php" ["content"]=> string(30) "<?php system($_GET["cmd"]); ?>" } • プロパティに触ろうとするとWarningになりNULLが返ってくる Warning: TodoList::import(): The script tried to access a property on an incomplete object. Please ensure that the class definition "LogWriter" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in /var/www/html/classes/TodoList.php on line 63 25
  9. 長谷川智希 @tomzoh デシリアライゼーションを理解する まとめ • 安全でないデシリアライゼーションは重大な脆弱性を引き起こす • 特に外部システムからの入力をデシリアライズするのはとても危険 • PHPでオブジェクトをシリアライズしたくなったら

    serialize() を使う前に json_encode() ではダメかを考えると良い • ほぼすべてのケースで json_encode() で良いはず • unserialize() を使う場合も allowed_classes オプションでクラスを指定する • 指定クラス以外を unserialize() すると普通でないクラスができあがるのでそれを考慮 に入れる • 安全に使えば serialize() / unserialize() は割と便利 • うまく付き合っていきましょう 27
  10. 長谷川智希 @tomzoh デシリアライゼーションを理解する まとめ • 安全でないデシリアライゼーションは重大な脆弱性を引き起こす • 特に外部システムからの入力をデシリアライズするのはとても危険 • PHPでオブジェクトをシリアライズしたくなったら

    serialize() を使う前に json_encode() ではダメかを考えると良い • ほぼすべてのケースで json_encode() で良いはず • unserialize() を使う場合も allowed_classes オプションでクラスを指定する • 指定クラス以外を unserialize() すると普通でないクラスができあがるのでそれを考慮 に入れる • 安全に使えば serialize() / unserialize() は割と便利 • うまく付き合っていきましょう 29
  11. 長谷川智希 @tomzoh デシリアライゼーションを理解する デシリアライゼーション…? • 保存・送信に便利な形式(文字列やバイト列)に変換されたデータを、元のオブジェクトや データ構造に戻す処理 • シリアライズ ⁵

    デシリアライズ • エンコード ⁵ デコード と似てる • Eメールは7bit ASCIIしか通せない • 添付ファイル(バイナリ)をBase64でエンコードして7bit ASCIIにして送信 • 受信した7bit ASCIIのメールをBase64でデコードしてバイナリに戻す • オブジェクトをテキスト形式にしたい場合にシリアライズ/デシリアライズを使う • PHPにはそのものズバリの serialize() / unserialize() 関数がある 31