# 4.14 構造化データの読み込みにまつわる問題 安全なウェブアプリケーションの作り方の勉強会資料です。 今回の勉強会では、以下2点を扱います。 * 4.14.2 安全でないデシリアライゼーション * 4.14.3 XML外部実体参照(XXE) ## 4.14.2 安全でないデシリアライゼーション ### 概要 * 転送・保存する目的で、データをバイト列に変換することをシリアライズという。 * シリアライズされたバイト列データをもとの形式に変換することをデシリアライズという * アプリケーションが、シリアライズされた悪意あるデータを受け取るとき、任意のコードが実行されるおそれがある(オブジェクトインジェクション) ![シリアライゼーション](https://i.imgur.com/rGkQgom.png) (引用:[徳丸浩の日記](https://blog.tokumaru.org/2017/09/introduction-to-object-injection.html)) ### 攻撃手法と影響 #### 脆弱なアプリケーションの説明 「好きな色」を`Cookie`に保存する。(シリアライズ) 別ページで`Cookie`を読み取り、表示させる。(デシリアライズ) 1. `/4e/4e-10.php` にリクエスト 2. 「好きな色」(array)をシリアライズ 3. `Cookie`にシリアライズしたデータをセット 4. `/4e/4e-11.php` にリクエスト 5. ログ出力(`/4e/4e-12.php` ) 6. `Cookie`を読み取り、デシリアライズ 7. 画面に「好きな色」を表示 ```sequence Client->Server: 1./4e/4e-10.php Note right of Server: 2.Serialize Server->Client: 3.slialize data を Cookieにセット Note left of Client: Cookie Client->Server: 4./4e/4e-11.php Note left of Server: Cookie Note right of Server: 5.Logging Note right of Server: 6.Deserialize Server->Client: 7.「好きな色」を表示 ``` #### 攻撃手法の説明 Loggerクラスに対して攻撃する。 操作はテキスト`PP354-357`参照。 ### 脆弱性が生まれる原因 P358に下記コードの攻撃シナリオの説明あり。 ハイライトした箇所が攻撃に利用されている。 1. `/var/www/html/xinfo.php`を`$path`としている 2. ログに'<?php phpinfo(); ?>'が書き込まれる 3. http://example.jp/xinfo.php にアクセスされると、実行される <summary>/4a/4e-012.php</summary> ```diff= <?php class Logger { const LOGDIR = '/tmp/'; // ログ出力ディレクトリ private $filename = ''; // ログファイル名 private $log = ''; // ログバッファ public function __construct($filename) { $this->filename = basename($filename); // ファイル名 $this->log = ''; // ログバッファ } // デストラクタではバッファの中身をファイルに書き出し public function __destruct() { + $path = self::LOGDIR . $this->filename; // ファイル名の組み立て // var_dump($path); + $fp = fopen($path, 'a'); if ($fp === false) { die('Logger: ファイルがオープンできません' . htmlspecialchars($path)); } if (! flock($fp, LOCK_EX)) { // 排他ロックする die('Logger: ファイルのロックに失敗しました'); } + fwrite($fp, $this->log); // ログの書き出し fflush($fp); // フラッシュしてからロック解除 flock($fp, LOCK_UN); fclose($fp); } public function add($log) { // ログ出力 $this->log .= $log; // バッファに追加するだけ } } ``` ### 対策 * シリアライズ形式ではなくJSON形式によりデータを受け渡す * クッキーやhiddenパラメータではなく、セッション変数など書き換えできない形でシリアライズ形式のデータを渡す * HMACなどの改ざん検知の仕組みをどうにゅうしてデータが改ざんされていないことを確認する #### シリアライズ形式ではなくJSON形式によりデータを受け渡す --- JSONにすると安全な理由は、下記のブログ参照 https://blog.ohgaki.net/json-escape <summary>/4a/4e-010a.php</summary> ```diff= <?php $colors = array('red', 'green', 'blue'); - setcookie('COLORS', serialize($colors)); + setcookie('COLORS', json_encode($colors)); echo "クッキーをセットしました"; ``` <summary>/4a/4e-011a.php</summary> ```diff= <?php require '4e-012.php'; - $colors = unserialize($_COOKIE['COLORS']); + $colors = json_decode($_COOKIE['COLORS']); //var_dump($colors); echo "好きな色は "; foreach ($colors as $color) { echo htmlspecialchars($color, ENT_COMPAT, 'UTF-8'), ' '; } echo "です"; ``` #### HMACでシリアライズした場合 --- 鍵を設定し、公開キーをCookieに付与する。 デシリアライズの前に、改ざん検知を行う。 ※php書いたことないので、間違えていましたら指摘お願い致します。 [参考](https://hackmd.io/0at41u4kScOrgXy1ChyMiQ?view) 鍵を生成する際に、`salt`という乱数を付与する。 これにより、レインボーテーブルによって割り出されづらくなる。 <summary>シリアライズ</summary> ```diff= <?php + $secret_key = "random_bytes()で生成された強い鍵"; + $salt = "random_bytes()で生成された強いsalt"; $colors = array('red', 'green', 'blue'); + // 送信するデータとその鍵の生成 + $derived_key = bin2hex(hash_hkdf('SHA2-256', $secret_key, 0, serialize($colors), $salt)); setcookie('COLORS', serialize($colors)); + setcookie('DERIVED_KEY', $derived_key); + setcookie('SALT', $salt); echo "クッキーをセットしました"; ``` <summary>デシリアライズ</summary> ```diff= <?php + $secret_key = "random_bytes()で生成された強い鍵"; // 同じ鍵! + // 送信されて来たデータを使い、送信時の鍵導出と同じ手順で鍵を導出 + $sent_key = bin2hex(hash_hkdf('SHA2-256', $secret_key, 0, $_COOKIE['COLORS'], $_COOKIE['SALT'])); + // 再導出した鍵と送られてきた導出鍵を比較 + if (hash_equals($sent_key, $_COOKIE['DERIVED_KEY'] !== true) { + die('攻撃を検出しました。処理を中止します。'); + } require '4e-012.php'; $colors = unserialize($_COOKIE['COLORS']); //var_dump($colors); echo "好きな色は "; foreach ($colors as $color) { echo htmlspecialchars($color, ENT_COMPAT, 'UTF-8'), ' '; } echo "です"; ``` ### 安全でないデシリアライゼーション まとめ | 項目 | 内容 | | -------- | -------- | | 発生箇所 | 外部からの値をデシリアライズ処理しているページ | | 影響を受けるページ | すべてのページが影響を受ける | | 影響の種類 | 情報漏えい、サイト改ざん、他サイトへの攻撃(踏み台)、暗号通貨の採掘(マイニング) | | 影響度合い | 大 | | 利用者の関与度合い | 不要 | | 対策 | [いずれかを実施](https://hackmd.io/d6kI6DZTTRiagZ7fnE854g?view#%E5%AF%BE%E7%AD%96) | ## 4.14.3 XML外部実体参照(XXE) ### 概要 * XMLには、外部ファイルを取り込むことができる機能がある(外部実体参照) * 外部実体参照によってWebサーバ内のファイルを不正に読み取られる可能性がある ### 攻撃手法と影響 テキスト見ながら実演します ### 脆弱性が生まれる原因 XMLの外部実体参照はもともとの機能である。 XXEは上記機能を悪用しているため、コーディング上にバグがあるわけではない。 ### 対策(php) * XMLの代わりにJSONを用いる * libxml2のバージョン2.9以降を用いる * libxml_disable_entity_loader(true)を呼び出す 以上!