質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

2128閲覧

作成したフォームに脆弱性がないか助言を頂きたい

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2018/12/10 13:51

下記サイトを参考にし、問い合わせフォームを作成したのですが、
脆弱性や気になる点などあれば、助言を頂けると助かります。
https://designsupply-web.com/knowledgeside/1642/

入力 → 確認 → 送信 と画面を遷移してメールを送ります。

入力ページ

php

1 2<form id="mail-form" action="./confirm.php" method="post"> 3 <dl> 4 <dt>会社名<span class="hissu">必須</span></dt> 5 <dd> 6 <input type="text" class="validate required" id="company" name="company" value="" placeholder="株式会社〇〇〇"> 7 <span class="error_required"></span> 8 <span class="error_company"></span> 9 </dd> 10 </dl> 11 <dl> 12 <dt>住所</dt> 13 <dd><input type="text" class="" id="address" name="address" value="" size="50"> 14 <span class="error_required"></span> 15 <span class="error_address"></span> 16 </dd> 17 </dl> 18 <dl> 19 <dt>氏名<span class="hissu">必須</span></dt> 20 <dd><input type="text" class="validate required" id="name" size="50" name="name" value="" placeholder="山田 花子"> 21 <span class="error_required"></span> 22 <span class="error_name"></span> 23 </dd> 24 </dl> 25 <dl> 26 <dt>電話番号<span class="hissu">必須</span></dt> 27 <dd><input type="text" class="validate required tel" id="tel" size="50" name="tel" value="" size="14" maxlength="14" placeholder="091-123-4567"> 28 <span class="error_tel"></span> 29 </dd> 30 </dl> 31 <dl> 32 <dt>メールアドレス<span class="hissu">必須</span></dt> 33 <dd> 34 <input type="text" value="" size="50" name="email" class="email validate required"/> 35 </dd> 36 </dl> 37 <dl> 38 <dt>お問い合わせ内容<span class="hissu">必須</span></dt> 39 <dd><textarea id="message" class="validate required" name="message" value="" rows="5" cols="50"></textarea> 40 <span class="error_required"></span> 41 </dd> 42 </dl> 43 <button type="input-submit-check" id="input-submit-check" value="input-submit-check" name="input-submit-check">同意し、確認画面へ</button> 44 </form> 45

確認ページ

php

1<?php 2 $postData = $_POST; 3 $page_flag = 0; 4 $error = array(); 5 function formValidation($postData) { 6 $error = array(); 7 if(empty($postData['company'])) { 8 $error[] = "会社名を入力してください"; 9 } 10 if(empty($postData['name'])) { 11 $error[] = "お名前を入力してください"; 12 } else if(!preg_match('/^[ぁ-んァ-ヶー一-龠  \r\n\t]+$/',$postData['name'])) { 13 $error[] = "お名前は全角文字で入力してください"; 14 } 15 if(empty($postData['email'])) { 16 $error[] = "メールアドレスを入力してください"; 17 } else if(!preg_match('/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/',$postData['email'])) { 18 $error[] = "メールアドレスを正しく入力してください"; 19 } 20 if(empty($postData['tel'])) { 21 $error[] = "電話番号を入力してください"; 22 } else if(!preg_match('/^0\d{1,4}-\d{1,4}-\d{3,4}$/',$postData['tel'])) { 23 $error[] = "電話番号を正しく入力してください"; 24 } 25 if(empty($postData['message'])) { 26 $error[] = "問い合わせ内容を入力してください"; 27 } else if(!preg_match('/^[ぁ-んァ-ヶー一-龠]+$/',$postData['message'])) { 28 $error[] = "全角文字で入力してください"; 29 } 30 return $error; 31 } 32 $error = formValidation($postData); 33 if(empty($postData['input-submit-check']) || !empty($error)) { 34 $page_flag = 1; 35 } else { 36 $page_flag = 0; 37 } 38?> 39 40<form id="confirm" action="./send.php" method="post"> 41 <input type="hidden" name="company" value="<?php echo $company; ?>"> 42 <input type="hidden" name="address" value="<?php echo $address; ?>"> 43 <input type="hidden" name="name" value="<?php echo $name; ?>"> 44 <input type="hidden" name="email" value="<?php echo $email; ?>"> 45 <input type="hidden" name="tel" value="<?php echo $tel; ?>"> 46 <input type="hidden" name="message" value="<?php echo $message; ?>"> 47 48 <?php if($page_flag == 1): ?> 49<ul class="error"> 50 <?php foreach( $error as $value ): ?> 51 <li><?php echo $value; ?> 52 </li> 53 <?php endforeach; ?> 54</ul> 55<?php endif; ?> 56 <dl> 57 <dt> 58 <label>会社名</label> 59 </dt> 60 <dd><?php echo htmlspecialchars($_POST['company'], ENT_QUOTES, 'UTF-8'); ?></dd> 61 </dl> 62 <dl> 63 <dt> 64 <label>住所</label> 65 </dt> 66 <dd><?php echo htmlspecialchars($_POST['address'], ENT_QUOTES, 'UTF-8'); ?></dd> 67 </dl> 68 <dl> 69 <dt> 70 <label>ご担当者 氏名</label> 71 </dt> 72 <dd><?php echo htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8'); ?></dd> 73 </dl> 74 <dl> 75 <dt> 76 <label>電話番号</label> 77 </dt> 78 <dd><?php echo htmlspecialchars($_POST['tel'], ENT_QUOTES, 'UTF-8'); ?></dd> 79 </dl> 80 <dl> 81 <dt> 82 <label>メールアドレス</label> 83 </dt> 84 <dd><?php echo htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8'); ?></dd> 85 </dl> 86 <dl> 87 <dt> 88 <label>お問い合わせ内容</label> 89 </dt> 90 <dd><?php echo htmlspecialchars($_POST['message'], ENT_QUOTES, 'UTF-8'); ?></dd> 91 </dl> 92 <div class="btnBlock"> 93 <p class="btn02"><a class="button" value="内容を修正する" onclick="history.back(-1)"><span>内容を修正する</span></a></p> 94 95 <?php 96 if($page_flag == 0) { 97 echo '<button type="submit" id="submit" name="submit">送信する</button>'; 98 } 99?> 100 </div> 101 </form>

完了ページ

php

1<?php 2session_start(); 3if(!$_SESSION){ 4 header('Location: ./input.php'); 5} 6 $company = $_POST["company"]; 7 $address = $_POST["address"]; 8 $name = $_POST["name"]; 9 $email = $_POST["email"]; 10 $tel = $_POST["tel"]; 11 $message = $_POST["message"]; 12$add_header ="From:info@\n"; 13$add_header .= "Reply-to: info@\n"; 14$add_header .= "X-Mailer: PHP/". phpversion(); 15//自動返信メール本文 16$messageuser = sprintf("%s",$name); 17$messageuser .= " 様\n\n"; 18$messageuser .= "この度はお問い合わせいただき誠にありがとうございます。\n\n"; 19$messageuser .= "下記の内容でお問い合わせを承りました。\n\n\n"; 20$messageuser .= "================================\n\n"; 21$messageuser .= sprintf("会社名:%s\n",$company); 22$messageuser .= sprintf("住所:%s\n",$address); 23$messageuser .= sprintf("お名前:%s\n",$name); 24$messageuser .= sprintf("メールアドレス:%s\n",$email); 25$messageuser .= sprintf("電話番号:%s\n",$tel); 26$messageuser .= sprintf("お問い合わせ内容:%s\n",$message); 27$messageuser .= "================================\n\n"; 28//管理者確認用メール本文 29$messageadmin = "フォームより下記の内容でお問い合わせがありました。\n\n\n"; 30$messageadmin .= "================================\n\n"; 31$messageadmin .= sprintf("会社名:%s\n",$company); 32$messageadmin .= sprintf("住所:%s\n",$address); 33$messageadmin .= sprintf("お名前:%s\n",$name); 34$messageadmin .= sprintf("メールアドレス:%s\n",$email); 35$messageadmin .= sprintf("電話番号:%s\n",$tel); 36$messageadmin .= sprintf("お問い合わせ内容:%s\n",$message); 37$messageadmin .= "================================\n\n"; 38//メール設定 39mb_language("ja"); 40mb_internal_encoding("UTF-8"); 41//自動返信メール送信設定 42mb_send_mail($email,"お問い合わせありがとうございます",$messageuser,$add_header); 43//管理者確認用メール送信設定 44mb_send_mail("info@","コンタクトフォームよりお問い合わせがありました",$messageadmin,$add_header); 45session_destroy(); 46?>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/12/10 16:29

デバッグ依頼に近い内容なのでもう少しご自身でも検証してから「質問」してください。
m.ts10806

2018/12/11 05:44

ベストアンサーは良いのですが折角ついた回答をどの程度どのように理解したかは伝えてあげてください。でないと「解決したはずなのにまた同じ質問してる」となれば、あなたにアドバイスしてくれる回答者はどんどんいなくなります。そのあたりはm6uさんの回答にあらわれてますので、ぜひ熟読して反応してあげてください。きちんと理解して進まないと困るのはあなた自身ですが、もしかしたら周囲に迷惑をかけてしまうようなアプリケーションを作ってしまう可能性もあります。
guest

回答3

0

私の助言、無視されているようなので、
長文になりますがもう一度書きます。

確認ページでの
$companyや$addressなどの変数は、どこで定義されていますか?
誰も値を詰めていない、未定義の変数を参照しても、カラです。
ちゃんと動作確認、自分でやれてますか?

同じく確認ページで、
echo htmlspecialchars($_POST['company']などと
フォーム受信データを(エスケープ処理したとしても)そのまま表示するのはやめるべきで、
エスケープするから平気っていう話じゃないです。
通常は、
汚染されているかもしれないフォーム受信データから、
不適切な文字列(やバイトデータ)が含まれていないかを
フィルター(最低でもfilter_input())かけて変数に代入し、
$company = filter_input(INPUT_POST, 'company');
さらに不適切な文字列が含まれていないか検証アルゴリズムを敷いて
きれいになったであろうデータを表示したり
次のフォームにhiddenでデータを送ったりします。
このままだと
クロスサイトスクリプティング(XSS)攻撃や
クロスサイトリクエストフォージェリ(CSRF)攻撃の標的になります。
【PHP入門講座】 XSS攻撃への対策 - Qiita
クロスサイト・リクエストフォージェリ(CSRF)と対策 | Webセキュリティの小部屋
最低でも、この記事くらいは読んでほしいし、
ネット上のXSS対策CSRF対策記事を3箇所でも5箇所でも、
とにかくいっぱい読むべき。

あと、一度でも設置されたフォームにアクセスすると
フォームの構造(phpファイル名、フォームのnameなど)がわかってしまうため、
完了ページのphpを直にBOTプログラムなどから叩くことができてしまいます。
自前フォームからの入力のみを許可する仕組みに変えていかないといけないのです。
(全然改良されていないけど、もしも)せっかく確認ページで検証したところで、
完了ページのphpに対して直接POST送信してしまえばザルです。
確認ページにも、完了ページにも、不適切な文字列が含まれていないかどうかを
検証する仕組みを設けなさい。マスト。

一連の質問群を見てきた中で、
大した改良の目が見えないので、
たぶん、理解できていないですよね?
サンプルコードを示されても理解できていない、
質問することもしない、
自分の技術として習得しようとしていないでしょ。
このまま使い続ける、設置しようとするのはやめて、
「webフォーム作成サービス」の類を活用して
自前設置は諦めなさい
スパム送信しまくってうんざりする前に。

免許証持たずに保険に入らずにクルマの運転しているようなものだからね。

投稿2018/12/11 01:15

編集2018/12/11 01:49
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/11 01:21 編集

この質問者の質問、正直言って無視してしまいたいところなのだけど、 こんなザルな仕組みを設置して周囲に迷惑をかけまくることが「あってはならない」と考えて、 あなたのために時間を割いてもう少し丁寧に(内容はキツいけど)書いてみた次第です。 どう考えてどう行動しようとしているのか、 少しはリアクションほしいところです。 状況わかってますか?
m.ts10806

2018/12/11 06:11

コメントで別途書きましたが、この回答をスルーしてしまうようなら無視して良さそうに思います。 m6uさんが浪費するだけになるので(私もついつい浪費やってしまいがちですが・・)
退会済みユーザー

退会済みユーザー

2018/12/12 09:04

ご回答ありがとうございます。外注に依頼し対応して頂きました。
guest

0

ベストアンサー

XSS 可能
CSRF 可能
宛先に複数セット 可能
総合的に見て、スパムの発射台として利用可能

設計がそもそもおかしいです。
基礎から体系的な学習をしてください。

投稿2018/12/10 14:04

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/12/10 14:13

問い合わせフォームは本質的に、「個別ユーザを識別できない状態で連続投稿を防がなければならない」という難問を抱えます。 基礎学習が終わったら、セキュリティ要件を整理してみることをオススメします。
退会済みユーザー

退会済みユーザー

2018/12/11 01:23

伝わるといいな、伝わってほしい。
guest

0

基本的には空メールを送らせて、仮IDを発行しユーザー登録させた後に
登録ユーザーのみにメールでの返信を利用できる仕組みがよいでしょう

投稿2018/12/11 01:22

yambejp

総合スコア114585

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問