コンタクトフォームを作る際には、脆弱性対策には気をつけませんと。
1. 代表的な攻撃手法
1) XSS(クロスサイトスクリプティング)[ Cross site scripting ]
脆弱性のあるWebサイトを踏み台に、Javascriptなど、悪意のあるプログラム(Attack Code)を
サイトの訪問者に送り込む手法。
2) CSRF(クロスサイトリクエストフォージェリ)[ Cross site request forgeries ]
Webサイトにスクリプトや自動転送(HTTPリダイレクト)を仕込むことによって、閲覧者に意図せず別のWebサイト上で何らかの操作(掲示板への書き込みなど)を行わせる攻撃手法。
3)SQLインジェクション(エスキューエルインジェクション)[ SQL Injection ]
データベースへの問い合わせや操作を行うプログラムにパラメータとしてSQL文の断片を与えることにより、データベースを改ざんしたり不正に情報を入手する攻撃。
4) クリックジャッキング[ Click jacking ]
Webブラウザの操作を乗っ取り、ユーザに意図しない操作を行わせる攻撃手法。
2. 対応
1) XSS(クロスサイトスクリプティング)[ Cross site scripting ]
例)
お問い合わせフォームの「名前」の入力欄に「お名前<script><alert('Warning!! This is UnintendedScript);></script>」というJavascriptのコードを含む文字列を入力し、送信したとすると、。
その際、XSS(クロスサイトスクリプティング)対策が施されていないフォームでは、JavaScriptが作動してしまうのです。
(対策)
「<」と「>」などの特殊文字をHTMLと認識させない方法などがあります。
2) CSRF(クロスサイトリクエストフォージェリ)[ Cross site request forgeries ]
たとえば、お問い合わせフォームを経由して情報を送信する際、HTMLソースを見れば「form」の送信先が分かりますが、その「form」の送信先をコピーして、別のサーバーのWebページに設置してしまえば、そのWebページからもフォームを送信できる場合があります。
そうなれば、外部の無関係なWebページから、大量のデータを本来のフォームへ送り込むことが可能となってしまいます。
たとえば、ボタンひとつで外部のフォームへデータを送信できるようなWebページを作り、そのWebページを不特定多数に向けて公開すれば、何も知らない人たちがボタンを押すたびに、本来のフォームへデータがどんどん送信されてしまうのです・・・。
この攻撃を防ぐためには、お問い合わせフォームなどを作る際に、「入力」「確認」「完了」までの流れにおいて、知らないドメインからの送信ができないような、「秘密の暗号」を設定するなどの対応が必要です。
対策)
トークンの作成
3)SQLインジェクション(エスキューエルインジェクション)[ SQL Injection ]
詳しくはSQLを使うようになったら考えます。
・SQLとして実行されないように特殊文字を一般的な文字列に変換する方法
・バインド処理を行う方法
4) クリックジャッキング[ Click jacking ]
他のサイトでインラインフレーム表示を禁止する(クリックジャッキング対策)
3. Scriptの例
1) mail.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="./js/jQuery.validation.js"></script>
<script type="text/javascript" src="./js/reserve.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#contact-form").validate({
rules : {
name:{required: true}
},
errorClass: "myError"
});
});
</script>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
input.myError {
background-color:#CCFFFF;
}
label.myError {
color:#FF0000;
}
textarea.myError {
background-color:#CCFFFF;
}
</style>
</head>
<body>
<form id="contact-form" action="./check.php" method="post">
<input type="hidden" name="sub_actions" value="confirm">
<table>
<tbody>
<tr>
<th>お名前</th>
<td><input type="text" class="required" name="name" value=""></td>
</tr>
<tr>
<th>メールアドレス</th>
<td><input type="text" class="required email" name="e_mail" value=""></td>
</tr>
<tr>
<th style="vertical-align:top;">お問い合わせ内容</th>
<td><textarea name="comment" rows="4" cols="40"></textarea>
</td>
</tr>
</tbody>
</table>
<div class="bt">
<input type="submit" value="確認画面へ" name="submit">
</div>
</form>
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="./js/jQuery.validation.js"></script>
<script type="text/javascript" src="./js/reserve.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#contact-form").validate({
rules : {
name:{required: true}
},
errorClass: "myError"
});
});
</script>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
input.myError {
background-color:#CCFFFF;
}
label.myError {
color:#FF0000;
}
textarea.myError {
background-color:#CCFFFF;
}
</style>
</head>
<body>
<form id="contact-form" action="./check.php" method="post">
<input type="hidden" name="sub_actions" value="confirm">
<table>
<tbody>
<tr>
<th>お名前</th>
<td><input type="text" class="required" name="name" value=""></td>
</tr>
<tr>
<th>メールアドレス</th>
<td><input type="text" class="required email" name="e_mail" value=""></td>
</tr>
<tr>
<th style="vertical-align:top;">お問い合わせ内容</th>
<td><textarea name="comment" rows="4" cols="40"></textarea>
</td>
</tr>
</tbody>
</table>
<div class="bt">
<input type="submit" value="確認画面へ" name="submit">
</div>
</form>
</body>
</html>
2)check.php
<?php
//mail.phpのPostをSessionに代入する。
//Postは次のページまでしか引き継ぐことが出来ません
//確認ページ、送信ページとページをまたぐ際はこのSessionを使うのが普通です。
//そのため、フォームの確認ページなどで一度Sessionに代入する必要があります。
//いきなり確認画面にアクセスがあれば不正アクセス。
//!$_POSTで $_POSTがSetされているかをチェックし、セットされていなければリダイレクト
if(!$_POST){
header('Location: http://www.example.com/'); // headerlocationはPHPのリダイレクト処理でよく使う。
}
//Sessionを開始するときの決まり文句、これがないとSessionが開始できない
session_start();
$_SESSION = $_POST;
//無事Sessionに保存できているかチェックする(本番では削除)
echo '<pre>'; //HTMLのpreタグを使うと、配列が見やすくなる
print_r($_SESSION); //print_rとは、配列を出力する関数
echo '</pre>';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;v
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
</style>
</head>
<body>
<form id="contact-form" action="./send.php" method="post">
<input type="hidden" name="sub_actions" value="confirm">
<table>
<tbody>
<tr>
<th>お名前</th>
<td><?php echo htmlspecialchars($_POST['name']);?></td>
</tr>
<tr>
<th>メールアドレス</th>
<td><?php echo htmlspecialchars($_POST['e_mail']);?></td>
</tr>
<tr>
<th style="vertical-align:top;">お問い合わせ内容</th>
<td><?php echo htmlspecialchars($_POST['comment']);?>
</td>
</tr>
</tbody>
</table>
<div class="bt">
<p>PCやスマホのメールフォームの修正ボタンなんかhistory.back()で十分!</p>
<input type="button" value="戻る" onclick="history.back();">
<input type="submit" value="送信" name="submit">
</div>
</form>
</body>
</html>
//mail.phpのPostをSessionに代入する。
//Postは次のページまでしか引き継ぐことが出来ません
//確認ページ、送信ページとページをまたぐ際はこのSessionを使うのが普通です。
//そのため、フォームの確認ページなどで一度Sessionに代入する必要があります。
//いきなり確認画面にアクセスがあれば不正アクセス。
//!$_POSTで $_POSTがSetされているかをチェックし、セットされていなければリダイレクト
if(!$_POST){
header('Location: http://www.example.com/'); // headerlocationはPHPのリダイレクト処理でよく使う。
}
//Sessionを開始するときの決まり文句、これがないとSessionが開始できない
session_start();
$_SESSION = $_POST;
//無事Sessionに保存できているかチェックする(本番では削除)
echo '<pre>'; //HTMLのpreタグを使うと、配列が見やすくなる
print_r($_SESSION); //print_rとは、配列を出力する関数
echo '</pre>';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;v
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
</style>
</head>
<body>
<form id="contact-form" action="./send.php" method="post">
<input type="hidden" name="sub_actions" value="confirm">
<table>
<tbody>
<tr>
<th>お名前</th>
<td><?php echo htmlspecialchars($_POST['name']);?></td>
</tr>
<tr>
<th>メールアドレス</th>
<td><?php echo htmlspecialchars($_POST['e_mail']);?></td>
</tr>
<tr>
<th style="vertical-align:top;">お問い合わせ内容</th>
<td><?php echo htmlspecialchars($_POST['comment']);?>
</td>
</tr>
</tbody>
</table>
<div class="bt">
<p>PCやスマホのメールフォームの修正ボタンなんかhistory.back()で十分!</p>
<input type="button" value="戻る" onclick="history.back();">
<input type="submit" value="送信" name="submit">
</div>
</form>
</body>
</html>
3) send.php
<?php
//以下ユーザー確認メール//info@example.comを、あなたのメールアドレスにすることでこのメールフォームをそのまま使えます。
session_start(); //ページ移動したら再びsession_start
$add_header="From:info@example.com\r\n";
$add_header .= "Reply-to: info@example.com\r\n";
$add_header .= "X-Mailer: PHP/". phpversion();
$opt = '-f'.'info@example.com'; //-fって何か意味あったんだけど忘れました -fすると迷惑メールになりにくいとか、そんなことだったと思う。
//以下ヒアドキュメント<<<●● HTMLでも、文字列でも、何いれてもOK●●;
//ヒアドキュメントは、メール送信とかの定型文を書いたりするとき、あとはSQLを書くときも使うかな。
//ヒアドキュメント内ではPHPのプログラムは一切かけない。変数だけ。変数は{}で囲ってあげること
//メールの本文をここでひとまとめに。
$message =<<<HTML
お問い合わせ内容の確認です。
お名前
{$_SESSION['name']}
E_mail
{$_SESSION['e_mail']}
お問い合わせ内容
{$_SESSION['comment']}
内容確認後、担当者より折り返しご連絡をさせて頂きます。
今しばらくお待ちください。//問い合わせ者へのコメント。
HTML;
// カレントの言語を日本語に設定する
mb_language("ja");
// 内部文字エンコードを設定する このエンコード指定は大昔の携帯だとShift-jisにしないとだめだったとか。
// 今はUTF-8にしておけばだいたいOK。
mb_internal_encoding("UTF-8");
mb_send_mail($_SESSION['e_mail'],"【お問い合わせ】確認メール",$message,$add_header,$opt);
//mb_send_mailは5つの設定項目がある
//mb_send_mail(送信先メールアドレス,"メールのタイトル","メール本文","メールのヘッダーFromとかリプライとか","送信エラーを送るメールアドレス");
//5番目の情報は第5引数と呼ばれるものでして、これがないと迷惑メール扱いになることも。
//マスター管理者にも同じメールを送りつける!!
mb_send_mail('info@example.com',"お問い合わせがありました",$message,$add_header,$opt);
session_destroy(); // セッションを破棄
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
</style>
</head>
<body>
<p>送信完了しました</p>
</body>
</html>
//以下ユーザー確認メール//info@example.comを、あなたのメールアドレスにすることでこのメールフォームをそのまま使えます。
session_start(); //ページ移動したら再びsession_start
$add_header="From:info@example.com\r\n";
$add_header .= "Reply-to: info@example.com\r\n";
$add_header .= "X-Mailer: PHP/". phpversion();
$opt = '-f'.'info@example.com'; //-fって何か意味あったんだけど忘れました -fすると迷惑メールになりにくいとか、そんなことだったと思う。
//以下ヒアドキュメント<<<●● HTMLでも、文字列でも、何いれてもOK●●;
//ヒアドキュメントは、メール送信とかの定型文を書いたりするとき、あとはSQLを書くときも使うかな。
//ヒアドキュメント内ではPHPのプログラムは一切かけない。変数だけ。変数は{}で囲ってあげること
//メールの本文をここでひとまとめに。
$message =<<<HTML
お問い合わせ内容の確認です。
お名前
{$_SESSION['name']}
E_mail
{$_SESSION['e_mail']}
お問い合わせ内容
{$_SESSION['comment']}
内容確認後、担当者より折り返しご連絡をさせて頂きます。
今しばらくお待ちください。//問い合わせ者へのコメント。
HTML;
// カレントの言語を日本語に設定する
mb_language("ja");
// 内部文字エンコードを設定する このエンコード指定は大昔の携帯だとShift-jisにしないとだめだったとか。
// 今はUTF-8にしておけばだいたいOK。
mb_internal_encoding("UTF-8");
mb_send_mail($_SESSION['e_mail'],"【お問い合わせ】確認メール",$message,$add_header,$opt);
//mb_send_mailは5つの設定項目がある
//mb_send_mail(送信先メールアドレス,"メールのタイトル","メール本文","メールのヘッダーFromとかリプライとか","送信エラーを送るメールアドレス");
//5番目の情報は第5引数と呼ばれるものでして、これがないと迷惑メール扱いになることも。
//マスター管理者にも同じメールを送りつける!!
mb_send_mail('info@example.com',"お問い合わせがありました",$message,$add_header,$opt);
session_destroy(); // セッションを破棄
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>シンプルなメールフォーム</title>
<style>
#contact-form th{
background-color: #F8F8F8;
border-color: #CCCCCC #CCCCCC #CCCCCC #333333;
border-left: 3px solid #333333;
border-right: 1px dotted #CCCCCC;
border-style: solid dotted solid solid;
border-width: 1px 1px 1px 3px;
padding: 5px 8px;
width: 200px;
}
#contact-form td{
background-color: #FFFFFF;
border-bottom: 1px solid #CCCCCC;
border-right: 1px solid #CCCCCC;
border-top: 1px solid #CCCCCC;
padding: 5px 8px;
}
</style>
</head>
<body>
<p>送信完了しました</p>
</body>
</html>
参考)
1) PHP開発エンジニア必読!最低限必要なセキュリティ対策
(悪意のあるスクリプト例がのっていて分かり易い。)
http://www.hp-stylelink.com/news/2013/09/20130913.php
2) メールフォームへセキュリティ対策の適用
http://webeg.info/php-course/step2-020/
(対策スクリプト例がのっていて分かり易い。)
・変数のホワイトリスト化
・サニタイズ(サニタイジング)
『クロスサイトスクリプティング』『セッションハイジャック』
『クロスサイトリクエストフォージェリ』が該当
htmlentitiesという関数で対応
・入力値バリデート(バリデーション)
・ヌルバイト除去
3)メールフォームにおける迷惑メール、スパムメール対策
https://www.php-factory.net/trivia/09.php
◎ 4)初心者も分かるようPHPメールフォームを解説
http://www.kaasan.info/archives/2151
最低限のコードを分かり易く解説。 JQuearyを利用。
とても分かり易い。 最終版のスクリプト付。
http://www.kaasan.info/archives/2151
0 件のコメント:
コメントを投稿