- ベストアンサー
メールフォームから大量の迷惑メールが届いた!対策方法を教えてください!
- 2年前に作成した商用Webサイトのメールフォームを通じて一気に500通以上の迷惑メールが届きました。対策方法を教えてください。
- 迷惑メールの送信アドレスにはミニバードのドメインを利用しているものもあり、ハッキングの可能性があるのでしょうか?
- 私が作成したメールフォームは必須入力項目を設定しているため、未記入では送信できません。正しく入力しないとエラー表示になるようにも設定しています。なぜ急に大量の迷惑メールが届いたのでしょうか?対策方法をお教えください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
ザクッとしか見ていませんが、おそらく他人へのイヤガラセに利用されているということかも知れません。 誰か悪意の人物Xが居たとして、ターゲットAに嫌がらせをしようとしたとします。 Xは自分のメールアドレスがバレるような方法で、メールボムを送る程のバカではないと仮定します。 ※メールボムをしようと考える時点でバカだという事は置いておく そんなときに、たまたま発見した問い合わせフォームに、ターゲットAのメールアドレスを入力して送信。 ターゲットAの元には、大量の身に覚えのない『【※※※※】お申込みありがとうございます』が到着するという事に。 巻き添えで、質問者様のところにも『【Webサイトからのメール】』が届いているという感じがします。 巻き添えと言えば巻き添えですが、キツイ言い方をすれば自業自得。 むしろ被害者側からすると、不適切なメールフォームを公開してXに加担している迷惑行為者であるとすら言える…。 まあ、勝手にストーリーを創作していると言われればそれまでの、ただの推測・想像・妄想ですが。 なんとなく、送信後Locationで遷移させていないので、F5を押すだけで簡単に大量のいやがらせメールが送信できるために利用されている、という気がしなくもない。 >現実的に考えて、1分のうちに、何十通もメールフォームを通して送信することはできないと思います。 もし、再読み込み(F5)で再送信されるようなプログラムなら、1分のうちに何十通もなんて極めて簡単。 ※Location遷移部分は直接関係ないから省略しただけという可能性も充分にあるけれど… 対策として考えられるのは 1)ログを取り、同一のメールアドレスには、一日5件までなどの上限を設ける。 ※正規の問い合わせで、訂正、追記など、複数件連続する可能性があるので5~10件程度は許容する方が良い 2)同じくログを取って、同一のIPアドレスからの送信は、1日10件までなどの上限を設ける。 ※1)と機能的には重複するが、これを設けることで1000人に対しての一日5件といった、薄く広い嫌がらせなどへの利用を防ぐ ※1)と機能が重複することもあり、なんとなく1)の上限の倍ぐらいの制限の方が良いような気がする(個人的意見) 3)ログを利用して、万一いやがらせがあった場合には、送信者のIPアドレスが判るようにしておく。 ※メール本文にIPアドレスを書いているとさらに有効、送信前に『以下の内容で問い合わせします』と確認画面を加えて、その中にIPアドレスやホスト情報が書かれていればいやがらせの抑止効果が期待できる。 4)IPアドレス(範囲)でブラックリスト、ホワイトリスト機能を作る ※もし海外からの問い合わせは不可とできるなら、IP偽装がいくらか困難になるのだが…それは職種やメールフォームの目的から検討しなければならない。 5)メールアドレスでブラックリスト機能を作る ※万一いやがらせに利用された事が判明した場合に、いやがらせを継続させないための機能 6)再読み込み対策を入れていないなら最優先で実装 7)CAPTCHAを導入する ※簡易的なものでも実用上問題はない。それなりのものを導入すれば「フォームを介さずに送信への対策」あるいは「再読み込み対策」の一助となる。個人的には本格的なものは(ユーザーとして使う場合には)面倒過ぎるので嫌い。 とりあえず、ザクッと思いつくところでこんな感じです。
その他の回答 (5)
- akinomyoga
- ベストアンサー率85% (100/117)
■info_visit_thanks.php の方にも入力情報のチェックを追加する事 以下のような処理の流れになっていますよね: ----- サーバ: info_delivery.html を返す ブラウザ: 客が入力した情報を元に info_delivery.php に対する POST のリクエストを作成し送信する サーバ: info_delivery.php POST で渡された情報をチェックし正しければ [OK] を含んだ html を返す。 ブラウザ: 客が [OK] を押すと、info_delivery.php の返した html に従って info_visit_thanks.php に対する POST のリクエストを作成し送信する。 サーバ: info_visit_thanks.php POST で渡された情報を用いてメールを作成し送信する。 ----- info_visit_thanks.php の方にも渡された情報をチェックする機能をつけないとなりません(つまり、合計で2回チェックするという事)。そうしないと ----- 悪意あるプログラム: info_visit_thanks.php に対する POST のリクエストを自由に作成し送信する。 サーバ: info_visit_thanks.php POST で渡された情報を用いてメールを作成し送信する。 ----- という風にして自由にメールを送れてしまいます。特に mail に、 mail="dummy@mail.address MyHeader1: MyHeaderContent1 MyHeader2: MyHeaderContent2" と言った具合の文字列を設定する事によって自由にヘッダも追加できてしまいます。 ■"From: {$mail}" だとそのメールが、フォームから送信されたのか普通に送信されたのか分からないので、分かるように工夫するという事 例えばですが "From: mail-from-mailform-※※※@sv22.m***bird.netowl.jp" 等として、"※※※" の部分に他人の分からない合い言葉でも設定しておけば、他人は同じメールの送信元を偽装できなくなります。(パケットを拾われて※※※がばれてしまうという可能性も0ではありませんが、その可能性は低いでしょう。) 或いは、顧客毎に From を用いて分類したい、というのであれば、"From: メールフォーム顧客※※※ <$mail>" などとするとか。※※※は例によって適当な合い言葉か何かです。 (※ちなみに当たり前の事ですが念のため: ※※※にはどうでもいい言葉を設定して下さい。メールは平文で(暗号化されずに)ネット上を飛び交いますので、別のサービスのパスワードだとか銀行の暗証番号だとかと同じ物は駄目です。) ■サーバのログが残っていれば、短時間で info_visit_thanks.php に何度もアクセスした履歴が残っているはずです。そのアクセス元に規則があればそれを弾くようにするというのも手です。 ■もっとちゃんとするには info_delivery.php を一回通過した情報である事を info_visit_thank.php 側でチェックする様にするなどできます。例えば、セッションで管理するとか、他の方が書かれている様に生成した乱数を hash を通して Cookie に設定するとか…です。 この様にしても、それを通過する悪意あるプログラムが不可能になるわけではないですが、プログラムを作成するのが一層面倒になりますので抑止力になります。 ■~@sv22.m***bird.netowl.jp > (1)の、@以下は私が利用してるミニバードのドメインとなっているのですが、これは何者かがサーバーにハッキングして嫌がらせを行っているのでしょうか? そんな事はありません。メール欄に好きなメールアドレスを入れれば "From: $mail" を介してそのまま送信元に設定されます。なので、メールフォームのメール欄に ~@sv22.m***bird.netowl.jp と書かれただけです。疑問は、その悪意ある送信者がどうやって個人情報であるはずの sv22.m***bird.netowl.jp というドメイン名を知り得たのかという事です。もし、このドメイン名をパブリックに公開していないのであれば、一連の迷惑メールは、案外そのドメイン名を知っている身内のいたずらかもしれません。
お礼
ありがとうございます。 対策には時間がかかると思いますが、頑張ってみます。
- agunuz
- ベストアンサー率65% (288/438)
(蛇足) >※メールヘッダにある、各項目の意味を調べながら考えているところです。 Receivedヘッダを見れば、スクリプトからの送信かそうでないかくらいは見分けられますよね? メールフォームを運用するなら最低限のメール関連の知識がないとダメです。他人に迷惑をかける可能性だって皆無ではないのですから。メールヘッダの意味がわからないと困ります。さすがにRFCを原語(英語)で全部読めとはいいませんが(汗
お礼
ソースを2回目のご回答の補足とお礼に2つ記載しました。 補足に記載してあるのは、入力から確認までのPHPソースです。 お礼に記載してあるのは、完了のPHPソースです。 少し、省いてるとこや、隠したいとこはアスタリスク(*)に変えました。 長文ですが、何かご指摘お願い致します。
- agunuz
- ベストアンサー率65% (288/438)
>「フォームを介さずPOST先のプログラムへ機械的にデータを >送ってきたのではないでしょうか。」ということでしょうか・・・ チェックはフォーム側(JavaScriptなど)だけでなくphpスクリプトでも行っていますよね?機械的に送り付けるとしても(フォームを介さないとしても)スクリプト側のチェックをかいくぐることは出来ません。 (1)phpスクリプト側のチェックに穴がないか (2)メールアドレスが流出するようなことがなかったか。さすがにフォーム側には書いていないでしょうから、フォームとは無関係なところで。 といったあたりが問題になります。 (1)を調べるにはソースを見ないとどうしようもありません。これは前の回答でも書きましたが、相変わらずソースは転記していただけないのですね(なので何もコメントできません。あしからず)。 (2)の可能性は「このフォームでだけ利用しているメールアドレス」で「phpスクリプトに記述しているだけ」であれば相当に可能性は低くはなります(でも 0 ではない)。当然それ以外の場合には、ある程度どこかに流出してスパムが押し寄せる可能性が常にあります。 #でもGMailならほとんどスパムフォルダに入ってしまいませんか? #ウチも毎日3桁くらいはスパム来ますけど(多くはないですね)。
お礼
<?php if (empty($_POST)) { echo ""; exit; } ?> <?php // フォームデータが空の場合は処理終了 if (empty($_POST)) { echo ""; exit; } // セッションの開始 session_start(); ?> <?php // 入力値の取得・加工 $name = htmlspecialchars($_POST['name'], ENT_QUOTES, "UTF-8"); $tel = htmlspecialchars($_POST['tel'], ENT_QUOTES, "UTF-8"); $mail = htmlspecialchars($_POST['mail'], ENT_QUOTES, "UTF-8"); $pos = htmlspecialchars($_POST['pos'], ENT_QUOTES, "UTF-8"); $ie = htmlspecialchars($_POST['ie'], ENT_QUOTES, "UTF-8"); $ie2 = htmlspecialchars($_POST['ie2'], ENT_QUOTES, "UTF-8"); $tec=$_POST['tec']; $content = htmlspecialchars($_POST['content'], ENT_QUOTES, "UTF-8"); // メール本文の組み立て $to = "※※※※※@gmail.com"; $title = "【申込み】"; $ext_header = "From:{$mail}"; $body = <<<EOM -------------------------------------------------- 【Webサイトからのメール】 {$name} {$tel} {$mail} {$pos} {$ie} {$ie2} {$tec} {$content} -------------------------------------------------- EOM; //文字コードの設定 mb_language("Japanese"); mb_internal_encoding("UTF-8"); // メール送信の実行 $rc = mb_send_mail($to, $title, $body, $ext_header); if (!$rc) { exit; } else { $_SESSION = NULL; } ?> <?php // 入力値の取得・加工 $name = htmlspecialchars($_POST['name'], ENT_QUOTES, "UTF-8"); $tel = htmlspecialchars($_POST['tel'], ENT_QUOTES, "UTF-8"); $mail = htmlspecialchars($_POST['mail'], ENT_QUOTES, "UTF-8"); $pos = htmlspecialchars($_POST['pos'], ENT_QUOTES, "UTF-8"); $ie = htmlspecialchars($_POST['ie'], ENT_QUOTES, "UTF-8"); $ie2 = htmlspecialchars($_POST['ie2'], ENT_QUOTES, "UTF-8"); $tec=$_POST['tec']; $content = htmlspecialchars($_POST['content'], ENT_QUOTES, "UTF-8"); // メール本文の組み立て $to = $mail; $title = "【※※※※】お申込みありがとうございます。"; $ext_header = "From:※※※※@.com"; $body = <<<EOM ======================== 本メールは、システムによる自動配信メールとなっております。 心当たりのない場合、その他ご不明な点がございましたら、 お手数ですが下記よりご連絡いただけますようお願い申し上げます。 ======================== この度は「※※※※」にお申込み頂き誠にありがとうございます。 お申込み内容の確認をお願い致します。 ■お名前 {$name} ■電話番号 {$tel} ■メールアドレス {$mail} ■郵便番号 {$pos} ■住所(番地まで) {$ie} ■住所(建物名・部屋番号) {$ie2} ■商品ジャンル {$tec} ■その他コメント {$content} お申込み頂きました内容につきましては後ほど担当者よりご連絡をいたします。 お返事を差し上げるまでにお時間がかかる場合がございますので、 何卒ご了承いただきますようお願い申し上げます。 /━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━/━ 店名:※※※※ E-mail info@※※※※.com 住所:※※※※ TEL:※※※※ EOM; //文字コードの設定 mb_language("Japanese"); mb_internal_encoding("UTF-8"); // メール送信の実行 $rc = mb_send_mail($to, $title, $body, $ext_header); if (!$rc) { exit; } else { $_SESSION = NULL; } ?>
補足
<?php function myEcho($errorBool, $value) { if($errorBool) { echo'<FONT COLOR="#cc3333">',$value,'</FONT><br/>'; } else { echo $value; } } // 名前のチェック $name = htmlspecialchars($_POST['name'], ENT_QUOTES, "UTF-8"); $nameError = false; if($name=='') { $nameError = true; $name = '※必ず入力してください。'; } // 電話番号のチェック $tel = htmlspecialchars($_POST['tel'], ENT_QUOTES, "UTF-8"); $telError = false; if (!preg_match( '/^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$/', $tel)) { $telError = true; $tel='※正しい電話番号を指定してください。'; } // E-mailのチェック $mail = htmlspecialchars($_POST['mail'], ENT_QUOTES, "UTF-8"); $mailError = false; if (!preg_match( '/^[a-z0-9][a-z0-9_\.\-]*@[a-z0-9][a-z0-9_\.\-]+[a-z]$/i', $mail)) { $mailError = true; $mail='※正しいメールアドレスを指定してください。'; } // 郵便番号 $pos = htmlspecialchars($_POST['pos'], ENT_QUOTES, "UTF-8"); // 住所(番地まで)のチェック $ie = htmlspecialchars($_POST['ie'], ENT_QUOTES, "UTF-8"); $ieError = false; if($ie=='') { $ieError = true; $ie = '※必ず入力してください。'; } // 住所(建物名・部屋番号) $ie2 = htmlspecialchars($_POST['ie2'], ENT_QUOTES, "UTF-8"); // 商品ジャンルのチェック if (empty($_POST["tec"])) { $tec = ""; } else { $tec = implode(" ", $_POST["tec"]); } // その他コメント $content = htmlspecialchars($_POST['content'], ENT_QUOTES, "UTF-8"); ?> <?php // そのままコピペで移動できるように別にしました。(ここがヒントのechoです) if($nameError || $telError || $mailError || $ieError) { echo'<p align="center"><FONT COLOR="#cc3333">入力内容に誤りがあります。※印の項目は必ずご記入ください。</FONT></p>'; } else{ echo'<p class="text4">以下の内容で送信しますか?</p>'; } ?> <table class="table margin01" width="732" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="250px" align="left" bgcolor="#FFF09D">お名前<span class="tabletext1"></span></td> <td> <?php myEcho($nameError,$name);; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">電話番号<span class="tabletext1"></span></td> <td> <?php myEcho($telError,$tel);; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">メールアドレス<span class="tabletext1"></span></td> <td> <?php myEcho($mailError,$mail);; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">郵便番号<span class="tabletext1"></span></td> <td> <?php echo $pos; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">住所(番地まで)<span class="tabletext1"></span></td> <td> <?php myEcho($ieError,$ie);; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">住所(建物名・部屋番号)<span class="tabletext1"></span></td> <td> <?php echo $ie2; ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">商品ジャンル<span class="tabletext1"></span></td> <td> <?php echo $tec ?> </td> </tr> <tr> <td align="left" bgcolor="#FFF09D">その他コメント<span class="tabletext1"></span></td> <td> <?php echo $content; ?> </td> </tr> </table> <?php if($nameError || $telError || $mailError || $ieError) { echo'<form>'; echo'<p align="center" class="margin01"><input type="button" value="戻る" onclick="history.back()" style="width: 150px; height: 30px"/></p>'; echo'</form>'; } else { echo'<form method="post"action="info_visit_thanks.php">'; echo'<input type="hidden" name="name" value="'.htmlspecialchars($_POST['name'], ENT_QUOTES, "UTF-8").'">'; // echo'<input type="hidden" name="tel" value="'.htmlspecialchars($_POST['tel'], ENT_QUOTES, "UTF-8").'">'; echo'<input type="hidden" name="mail" value="'.htmlspecialchars($_POST['mail'], ENT_QUOTES, "UTF-8").'">'; echo'<input type="hidden" name="pos" value="'.htmlspecialchars($_POST['pos'], ENT_QUOTES, "UTF-8").'">'; echo'<input type="hidden" name="ie" value="'.htmlspecialchars($_POST['ie'], ENT_QUOTES, "UTF-8").'">'; echo'<input type="hidden" name="ie2" value="'.htmlspecialchars($_POST['ie2'], ENT_QUOTES, "UTF-8").'">'; echo'<input type="hidden" name="tec" value="'.$tec.'">'; echo'<input type="hidden" name="content" value="'.htmlspecialchars($_POST['content'], ENT_QUOTES, "UTF-8").'">'; echo'<p align="center" class="margin01"><input type="button"onclick="history.back()"value="戻る" style="width: 150px; height: 30px"/>'; echo'<input type="submit"value="OK" style="width: 150px; height: 30px"/></p>'; echo'</form>'; } ?>
- t_ohta
- ベストアンサー率38% (5238/13705)
たぶん、フォームを介さずPOST先のプログラムへ機械的にデータを送ってきたのではないでしょうか。 メールアドレスは、フォームに入力欄があれば何でも入れられるでしょうから何が来てもおかしくはないですよね。 嫌がらせをして楽しむ輩はいますから、インターネットで公開している以上しょうがないですよね。 対策はいくつか考えられます。 一つはフォームを表示する際に、サーバ側で乱数をベースにしたキーを作成しフォームのhiddenに埋め込みます。 同じキーをサーバ側で作成時刻と共に記録しておき、フォームをPOSTしてきた時に照合してキーが正しく且つ作成から一定時間内(10分とか)なら処理し、そうでなければエラー画面を表示するという方法。 もう一つはフォーム入力後確認画面を挟むという方法。 フォームからPOSTされてきたら、入力内容はサーバ側でセッション機能等を使って保存しておき、確認画面で内容を表示します。 確認画面から最終処理プログラムへはOKボタンが押されたことだけをPOSTして、保存しておいた入力内容をメールで送信するようにします。 段階を踏んで、cookieを引き回さないといけないようなページにすると、悪戯する方も手間が増えるので悪さはしにくくなります。 基本的にはフォームのPOST一発で処理が完結しないようにする事ですね。
お礼
ありがとうございます。 私のメールフォームの流れは以下の通りです。 1:各種項目を入力した後に、「メール内容を確認する」のボタンを押す。 2-1(不正の場合):必須項目が未入力だったり、電話番号が全角入力だったり、メールアドレスで日本語が使われていたりすると、確認画面になり「戻る」ボタンだけが押すことができます。 2-2(正しい場合):正しく入力されていれば、「この内容で送信します」または「戻る」のボタンがあります。 3:正しく入力した画面で「この内容で送信します」のボタンを押すと、最後の画面になり、メールを送信しましたを表示しております。 一応、一発で処理はできないようにしております。 サーバー側で乱数をベースにしてキーを作成するというのは、難しそうですが、ググって調べてみます。 とりあえず、頑張って問題解決したいと思います。
- agunuz
- ベストアンサー率65% (288/438)
>メールフォームを通して どの内容で判断していますか?メールヘッダは通常メールフォームから届くものと違いはありませんか?特に「Received:ヘッダ」は要確認です。 その上で「メールフォーム経由で間違いない」ということであれば、メールフォームの入力チェック部分などを転記してみてください(ソースを1行も見ないで憶測で回答は出来ません)。 (蛇足) >迷惑メールをしてきた送信アドレスは複数あり、主に以下の4つです。 まさかメールフォームから送信するメールのFromに入力されたメールアドレスを使っているんですかね。普通はメール本文に「入力されたメールアドレス」として記載はしますが、メール自体のFromにはセットしません。相手にメールを送るにしても(どうせスレッドが繋がらないので)返信じゃなくて新規作成で送ればいいんだし。
お礼
ありがとうございます。メールフォームから送らてきたメールはgmailで受け取っており、いまメールヘッダを確認しました。 ※メールヘッダにある、各項目の意味を調べながら考えているところです。 メールフォームを通してというのは、私の説明に誤りがありました。 現実的に考えて、1分のうちに、何十通もメールフォームを通して送信することはできないと思います。 また、メールフォームで入力する項目には、チェックボックスの項目を設けているため、通常では受け取ったメールではチェック(選択)した名前が表示されます。 しかし、意味不明な文字列が表示されおりました。 よくわかりませんが、他の方の回答にある「フォームを介さずPOST先のプログラムへ機械的にデータを送ってきたのではないでしょうか。」ということでしょうか・・・
お礼
7つの対策方法を教えて頂き、ありがとうございます。 1つずつ実装していきます。 まずは、再読み込み対策を最優先で行います!!