###皆様から回答を受けて
皆様回答ありがとうございました。
まだ調べている途中ですが、この質問を見た方のために参考にしているサイトと書籍をシェアしたいと思います。
** メールフォーム作成の参考 **
- [書籍]PHP逆引きレシピ 第2版
※第7章の551頁に「メール送信フォームを作成したい」の記述があります。
質問した構成と同じく入力→確認→送信と遷移するメールフォームです。
メールフォームを作成したい方はこの書籍を参考にするとよろしいかと存じます。
** サニタイズやバリデーション関連 **
- [Qiita]$_GET, $_POSTなどを受け取る際の処理
- [Qiita」PHPで各種バリデーション
** ※jQueryを利用して入力等のチェックを行っていても、HTTPリクエストは偽装できるため、PHP側でも入力チェック(バリデーション)を行う必要があります。jQueryでの入力チェックは、ユーザビリティ向上の役割しかありません。 **
入力処理に関しては、上記のサイトもしくは、セキュリティ分野の大家である徳丸氏の著書(体系的に学ぶ 安全なWebアプリケーションの作り方)が参考になるかと思います。
** セキュリティ全般 **
※第10章にセキュリティに関する記述がありますが、初心者の私でも説明が分かりやすいです。
※パーフェクトPHPの書籍の9章にセキュリティ関する記述があります。
書籍のCSRFへの対応方法として「ワンタイムトークンによるチェック」との記述がありますが、
徳丸氏から指摘があります。詳細は下記をご覧ください。
CSRF対策のトークンをワンタイムにしたら意図に反して脆弱になった実装例
** 補足 **
なんと徳丸氏がPHPの書籍に関して、SQLエスケープの解説状況を記載しております。
書籍別にレビューとセキュリティの状況が記載されているので非常にありがたいです。
本件とはあまり関係ありませんが、書籍を選ぶときの参考にもなります。
【注意】質問で記述したコードには脆弱性があります。絶対にコピペしないでください。
--------------- ここからが最初に投稿した質問内容です ---------------
###はじめに
お世話になります。
現在PHPの勉強をしながらセキュアなメールフォームを作成しております。
「入力画面」→「確認画面」→「送信画面」と遷移するメールフォームの作成をしております。
作成したコードを記載しますので、XSSやCSRFなどのセキュリティ面で問題があるか教えてください。
XSS対策のためにhtmlspecialcharsを使用して特殊文字はエスケープしております。
CSRF対策としてopenssl_random_pseudo_bytesでトークンを作成してチェックしております。
###入力画面
lang
1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4<meta charset="utf-8"> 5<title>PHP送信フォームテスト(入力)</title> 6</head> 7<body> 8<form method="post" action="check.php"> 9氏名:<input type="text" name="name"> 10メールアドレス:<input type="text" name="mail"> 11<input type="submit" value="送信確認"> 12</form> 13</body> 14</html>
###確認画面(check.php)
lang
1<?php 2session_start(); 3// HTML特殊文字をエスケープする関数 4function h($str) { 5 return htmlspecialchars($str,ENT_QUOTES,'UTF-8'); 6} 7// CSRFトークンを作成 8$TOKEN_LENGTH = 16; 9$bytes = openssl_random_pseudo_bytes($TOKEN_LENGTH); 10$_SESSION["TOKEN"] = bin2hex($bytes); 11?> 12<!DOCTYPE html> 13<html lang="ja"> 14<head> 15<meta charset="utf-8"> 16<title>PHP送信フォームテスト(確認)</title> 17</head> 18<body> 19<?php 20foreach($_POST as $key => $value){ 21 $$key = $value; 22} 23// 値のチェック 24$errFlg = 0; 25if($name === "") { 26 echo "氏名を入力してください。"; 27 $errFlg = 1; 28} 29if($mail === "") { 30 echo "メールアドレスを入力してください。"; 31 $errFlg = 1; 32} 33if($errFlg === 1) { 34 echo "<input type='button' value='入力画面へ戻る' onClick='history.back()'></body></html>"; 35 exit(); 36} 37?> 38<form method="post" action="fin.php"> 39氏名:<?php echo h($name); ?> 40メールアドレス:<?php echo h($mail); ?> 41<input type="submit" value="送信"> 42<input type="hidden" name="token" value="<?php echo h($_SESSION["TOKEN"]); ?>"> 43<input type="hidden" name="name" value="<?php echo h($name); ?>"> 44<input type="hidden" name="mail" value="<?php echo h($mail); ?>"> 45</form> 46</body> 47</html>
###送信画面(fin.php)
lang
1<?php 2session_start(); 3mb_language("ja"); 4mb_internal_encoding("UTF-8"); 5?> 6<!DOCTYPE html> 7<html lang="ja"> 8<head> 9<meta charset="utf-8"> 10 <title>PHP送信フォームテスト(送信)</title> 11</head> 12<body> 13<?php 14foreach($_POST as $key => $value){ 15 $$key = $value; 16} 17// tokenのチェック 18if($_SESSION["TOKEN"] !== $_POST["token"]) { 19 echo "不正です。</body></html>"; 20 exit(); 21} 22$to = "hoge@hoge.jp"; 23$subject = mb_convert_encoding("メールフォームからの送信","UTF-8"); 24$mailbody = mb_convert_encoding("氏名:$name\nメールアドレス:$mail","UTF-8"); 25 26if($name !== "" && $mail !== "") { 27 if(mb_send_mail($to,$subject,$mailbody,"From:$mail")) { 28 echo "メール送信しました。"; 29 } else { 30 echo "メール送信に失敗しました。"; 31 } 32} else { 33 echo "入力されていません。"; 34} 35?> 36</body> 37</html>
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2014/11/27 01:18
2014/11/27 01:40
退会済みユーザー
2014/11/27 06:12
2014/11/27 08:06
退会済みユーザー
2014/11/27 08:41