質問するログイン新規登録

回答編集履歴

1

コメントへの返答を追記しました

2021/06/15 07:30

投稿

ockeghem
ockeghem

スコア11710

answer CHANGED
@@ -9,4 +9,56 @@
9
9
 
10
10
  あと、「ウェブアプリケーションの実行環境や言語に用意されているメール送信用API」でないものは何を指すかということも重要です。そのヒントは、安全なウェブサイトの作り方の後半に出てきます。同書P100(PDFのページではなく冊子としての印刷されたページ番号です)に「3.8 メールヘッダ・インジェクションの例」として、失敗例が紹介されています。ここで使われている方法は、sendmailコマンドを呼び出すというものです。つまり、「メール送信用API」とは、このような手作りのメール送信ではなく、言語等で用意されたものを使えという意味だということが分かります。
11
11
 
12
- ただし、昔はsendmailコマンドを呼び出してメール送信することはわりとありましたが、最近そういうことをする人は少ないと思うので、分かりにくい書き方だなとは思いました。
12
+ ただし、昔はsendmailコマンドを呼び出してメール送信することはわりとありましたが、最近そういうことをする人は少ないと思うので、分かりにくい書き方だなとは思いました。
13
+
14
+ ---
15
+
16
+ 詳しいコメントをありがとうございます。
17
+ 以下の部分ですが、
18
+
19
+ > mail関数のマニュアルに、以下の記述がありました。
20
+ > PHP 5.4.42 および 5.5.27 より前のバージョンでは、additional_headers は、
21
+ メールヘッダインジェクション対策を行っていませんでした。
22
+ したがって、指定したヘッダが安全なものであり、ヘッダ以外のものを含まないようにするのは
23
+ ユーザー側の役目となります。
24
+ > ふーむ。バージョンによっても違うと…
25
+ 公式マニュアルを読み込んで意味を理解しないとダメですね。
26
+
27
+ ここのマニュアルの記載は不正確です。確かにPHP 5.4.42などで「改善」はされた(正確にはPHP 5.4.42、PHP 5.5.26、PHP 5.6.10以降です)のですが、完全にメールヘッダインジェクションが防げるようになったわけではありません。
28
+
29
+ 以下のテストスクリプトは「全てのPHPバージョン」でメールヘッダインジェクション攻撃が可能なサンプルです。Ccヘッダを追加しています。
30
+
31
+ ```PHP
32
+ <?php
33
+ $to = 'alice@example.jp';
34
+ $subj = 'test';
35
+ $body = 'test';
36
+ $ah = "From: bob@example.net\r\nCc: carol@example.com";
37
+ mail($to, $subj, $body, $ah);
38
+ ```
39
+
40
+ 以下は「改善版のPHPでは攻撃できない」サンプルスクリプトです。本文の改ざんを試みています。
41
+
42
+ ```PHP
43
+ <?php
44
+ $to = 'alice@example.jp';
45
+ $subj = 'test';
46
+ $body = 'test';
47
+ $ah = "From: bob@eample.net\r\n\r\nHello!\n";
48
+ mail($to, $subj, $body, $ah);
49
+ ```
50
+
51
+ このように、「改善版」というのは「一部のメールヘッダインジェクション攻撃を防ぐ」というもので、完全に防御できるわけではありません。
52
+
53
+ では、どうすれば安全かというと、安全なウェブサイトの作り方にあるように改行文字をチェックするのも一案ですが、PHP 7.2.0以降で導入されたadditional_headers を配列で指定する方法が安全です。以下のような感じですね。
54
+
55
+ ```PHP
56
+ <?php
57
+ $to = ...
58
+ $subj = ...
59
+ $body = ...
60
+ $ah = ["From" => $from];
61
+ mail($to, $subj, $body, $ah);
62
+ ```
63
+
64
+ これだと、改行を用いたメールヘッダインジェクションはできなくなるので根本的に安全です。