# 4.14 構造化データの読み込みにまつわる問題
安全なウェブアプリケーションの作り方の勉強会資料です。
今回の勉強会では、以下2点を扱います。
* 4.14.2 安全でないデシリアライゼーション
* 4.14.3 XML外部実体参照(XXE)
## 4.14.2 安全でないデシリアライゼーション
### 概要
* 転送・保存する目的で、データをバイト列に変換することをシリアライズという。
* シリアライズされたバイト列データをもとの形式に変換することをデシリアライズという
* アプリケーションが、シリアライズされた悪意あるデータを受け取るとき、任意のコードが実行されるおそれがある(オブジェクトインジェクション)

(引用:[徳丸浩の日記](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)を呼び出す
以上!