=> ブログ一覧へ

【PHP】正しい連絡フォームの作り方(クライアント側をぜったいに信用するな!!)

公開日:2023-08-04

問題

現在の「モダン」ウェブ開発で、連絡フォームはJavascriptで制御されていますが、これは大きなリスクがあります。

その理由について、直ぐに説明します。

以下のスクショをご覧いただいたら、何が問題は何だと思いますか?

=> /static/fuanform1.png

正解は:送信ボタンは<form>タグの外にある事です。

これでは、Javascriptを無効にした場合、送信ボタンをクリックする事が出来ません。

このフォームを送信する為には、この送信ボタンをフォーム内に移動し、type="button"type="submit"に変更する事で、Javascriptなしでもフォームを送信する事が可能になります。

そんな感じ:

=> /static/fuanform2.png

そうして、入力画面で「required=""」というパラメータがあり、これによりJavascriptが無効であってもフィールドが入力されているかどうかを確認できます。

例:

=> /static/fuanform3.png

しかし、このパラメータを削除すると、どのような事態が起こると思いますか?

正解はこちら:

=> /static/fuanform4.png

また、確認画面ではフォームが<input type="hidden" />タグを沢山含んでいます。

その中の「value=""」部分を変更する事が可能です。

これにより、MySQLインジェクションも可能となります。

解決策

上述の問題を解決する為には、サーバー側でのチェックが必要です。

勿論、クライアント側とサーバー側の両方でチェックを行う事も可能です。

例として、PHPの場合を紹介します(PHPを使用するフォームが多い為):

 true,
  ]);

  if (empty($_SESSION["csrf_token"])) $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
  if (!isset($_SESSION["step"])) $_SESSION["step"] = 1;
  $errmes = [];
  $reqvals = [
    "name" => $_SESSION["name"] ?? "",
    "kana" => $_SESSION["kana"] ?? "",
  ];
  $optvals = [
    "url" => $_SESSION["url"] ?? "",
  ];

  if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (!hash_equals($_SESSION["csrf_token"], $_POST["csrf_token"])) {
      die("不正なCSRFトークン");
    }

    if ($_SESSION["step"] == 1) {
      foreach ($reqvals as $k => $v) {
        $_SESSION[$k] = filter_input(INPUT_POST, $k, FILTER_SANITIZE_STRING);
        if ($_SESSION[$k]) $reqvals[$k] = $_SESSION[$k];
        else $errmes[] = $k."をご入力下さい。";
      }

      foreach ($optvals as $k => $v) {
        $_SESSION[$k] = filter_input(INPUT_POST, $k, FILTER_SANITIZE_STRING);
        $optvals[$k] = $_SESSION[$k];
      }

      if (empty($errmes)) $_SESSION["step"] = 2;
    }
    else if ($_SESSION["step"] == 2) {
      $_SESSION["step"] = 1;
      session_destroy();
      header("Location: /success.html");
      die();
    }
  }
  else {
    $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
    $_SESSION["step"] = 1;
  }
?>



  
    
    連絡フォーム
  
  

    

    
お名前 (必須): " />
お名前 (かな) (必須): " />
御社又は関連サイトのURL: " />
お名前 (必須):
お名前 (かな) (必須):
御社又は関連サイトのURL:

不明なエラー。

結果:

=> /static/anzenform1.png

=> /static/anzenform2.png

=> /static/anzenform3.png

=> /static/anzenform4.png

=> /static/anzenform5.png

=> /static/anzenform6.png

ねぇねぇー!

簡単でしょー!

以上

Proxy Information
Original URL
gemini://technicalsuwako.moe/blog/fix-broken-contact-form.gmi
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
1555.240047 milliseconds
Gemini-to-HTML Time
0.901944 milliseconds

This content has been proxied by September (ba2dc).