web-dev-qa-db-ja.com

HTML5入力パターンの検証は、クライアント側の検証に十分(または関連性あり)ですか?

HTML5の興味深い機能は<input pattern="" />attribute です。これにより、ブラウザーは開発者が提供する正規表現に対して入力フィールドの値を検証できます。

その後、これはフィールドの ValidityState にバインドされ、UXフィードバックを照会したり、無効な送信を防止したりできます。

サーバーは同じ前提条件検証(およびXSRF)を実装します。

これを前提として、このクライアント側の検証パターンは成熟しており適切です、または何らかの理由でフォーム全体をインターセプトし、送信する前に従来のフィールドごとの検証を行うことが望ましいそれ?

23
msanford

セキュリティの観点から、サーバー上のすべてを再検証する必要があります。 HTML5の機能がどれほど美しく高度になっても、これは常に当てはまります。あなたは単にクライアントを信頼することはできません。 HTML5ルールに従うかどうかはわかりません。それがブラウザかどうかさえわからない。

HTML5機能を使用している場合でも、送信する前に独自のJSクライアント側でフォーム全体を検証する必要がありますか?セキュリティの観点からは重要ではありません。クライアント側の検証はとにかくセキュリティ値がゼロです-上記を参照してください-したがって、セキュリティの観点からは、まったく気にしない方がよいでしょう。

クライアント側の検証は、純粋にユーザーエクスペリエンスに関するものです。独自のJS検証または組み込みのHTML5が最高のUXを生み出すかどうかは興味深い質問ですが、ここでは取り上げません。

110
Anders

コードとスクリーンショット付きの説明

与えられた答えは素晴らしいです。しかし、私はこれをいくつかのコード/スクリーンショットで説明したかった。

肝心な点は、エンドユーザーはクライアント側を操作(無効化/完全に削除/バイパスまたは変更)できるということです。したがって、「クライアント側の検証」は、セキュリティの観点からはまったく役に立ちません。サーバーサイドで常に検証する必要があります。

次のようなHTMLフォームがあるとします。

_<form method="post" action="index.php">
    <input type="email" name="emailAddress" required>
    <button type="submit">Submit form</button>
</form>
_

これは、必須フィールド(required属性)であると言って、電子メールアドレス(_type="email"_)を要求しています。

空のものやメールアドレスではないものを送信しようとすると、エラーになります。

enter image description here

なぜこれがセキュリティの観点から役に立たないのですか?ユーザーがしなければならないのはHTMLを操作することだけです。 Webページのコピーを保存して編集し、再度開くことで、これを行うことができます。または、ブラウザの開発者ツールを使用してマークアップを編集することもできます。 クライアント側のコードであり、管理下にあるため、これを行うことができます.

フォームのマークアップを次のように変更するとします。

_<form method="post" action="index.php">
    <input type="text" name="emailAddress">
    <button type="submit">Submit form</button>
</form>
_

ここで、emailAddressフィールドはtextタイプ(つまり、emailではない)であり、必須フィールドではない(required属性を削除)と言っています。

これをサーバーに送信できます。 「andy」というテキスト文字列は明らかに有効なメールアドレスではありません。しかし、サーバー側の検証がないため(まだ)、サーバーに投稿されます。PHPコードで_$_POST['emailAddress']_を使用すると、 "andy"がデータ。

enter image description here

データなしでフォームを送信することもできます。その場合、アプリケーション(サーバー側の検証なし)では、変数_$_POST['emailAddress']_に空の文字列が含まれます。

これは、エンドユーザーとしてのクライアント側のコードを操作できるためにのみ可能でした。

サーバー側の検証が安全なのはなぜですか?エンドユーザーはサーバー側のコードを操作できません(サーバーが危険にさらされていない限り、これは別の問題です)そして、平均的な人のためにHTMLを操作するほど簡単なものではありません)。

したがって、PHPでは、次のようなチェックを行うことができます。

_if (!filter_var($_POST['emailAddress'], FILTER_VALIDATE_EMAIL)) {
    die('Invalid email address');
}
_

これは非友好的なエラー処理方法ですが、ユーザーが有効な電子メールアドレスの代わりに「andy」を送信すると、スクリプトの実行が停止します。したがって、アプリケーションは、電子メールアドレスが存在することを期待していた変数として「andy」を決して使用しません。エンドユーザーは上記のPHPコードを操作できないため、検証をバイパスできる可能性が低くなります。 。これはサーバー側の検証です。エンドユーザーが変更することはできないため、エンドユーザーは(簡単に)変更することはできません。

なぜクライアント側の検証に煩わされるのですか?クライアント側の検証は、「見栄えの良い」ユーザーインターフェイスの機能強化、またはエラーメッセージや無効化フォームなどに役立ちます。田畑。たとえば、ユーザーがメールアドレスを誤って入力した場合に備えて、最初のスクリーンショットにそのメッセージを表示することは、間違いなく優れたUI機能です。フォームは最初の一連の条件では送信されないため、サーバーに送信される不要なデータが削減されます。しかし最終的には、クライアント側で行われたことはエンドユーザーが変更できます。したがって、これは決して安全ではなく、セキュリティの実践に関しては、「クライアント側の検証」を決して考えるべきではありません。クライアント側の検証は、主にユーザーインターフェイスの拡張のみを目的としています。

クライアント側の検証は、クライアント側のアプリケーションにも役立ちます(サーバーに要求/投稿しない場合)。たとえば、上記のフォームがあり、JavaScriptやjqueryで読み取ることにより、ページの_<div>_にemailAddressの内容を表示したとします。ユーザーが<script>alert('hello!');</script>などの何かを入力し、検証がなかった場合、JavaScriptがフィールドの値を_<div>_に書き込もうとしたときにアラートが生成されます。この場合、サーバーには何もポストされません。すべてクライアント側で行われるため、このタイプのシナリオでは、クライアント側の検証が役立ちます。ただし、ユーザーが検証を無効にできるという同じ根拠が適用されます。上記のコードを実行した場合、ローカルマシンでのみ発生し、アプリケーションの他のユーザーには発生しないため、ここでの影響は小さくなります。例えば:

enter image description here

次のコードを使用します(検証なし)。

_<form method="post" action="#">
    <input type="text" name="emailAddress" id="emailAddress" size="100">
    <button type="submit">Submit form</button>
</form>

<div id="test"></div>
_

そして、jqueryはフォームの内容をtestというIDで_<div>_に書き込みます。

_$(document).ready(function() {
    $("button").click(function(e) {
        e.preventDefault();

        $("#test").html($("#emailAddress").val());
    });
});
_
16
Andy

Andersが述べたように、クライアント側の検証はアプリケーションのセキュリティには無関係ですが、UXの観点からは非常に重要です。

クライアント側の検証に重点が置かれているため、フォームへの入力中にユーザーにスムーズで簡単な時間を提供します。私が知っている最も良い例は、jQuery Masksプラグインで、ユーザーに視覚的なフィードバックを提供しながら、入力サイズとパターンを制限するために使用できます。これは、サーバー側で予期されるものとは異なるパターンでユーザーからデータを受信するなど、セキュリティ以外の欠陥に役立つ場合がありますが、攻撃者によって簡単に無視されます。

tl; dr-十分なクライアント側の検証などはありません。単にクライアントを信頼せず、サーバーで受信したすべてのものを処理してから処理します。

6
Bristran

これまでのところ、どの回答も実際には言及していないので、これを追加しましょう。

HTMLのanythingがセキュリティにまったく関係がない理由は、攻撃者が(コンソールにリクエストを入力するか、プラグイン)。実際には、ブラウザー(c/f curlwgetまたは任意のプログラミング言語)を起動することすらありません。

これらに関連する部分は[〜#〜] http [〜#〜]リクエストです。 HTMLペイロードではありません。そして、TLS/SSLレイヤーを除いて、実際の人からのHTTPリクエストの内容を保護するものは何もありませんcreatingリクエスト。

したがって、すべてのセキュリティをサーバー側で行う必要があります。すべてのクライアント側のチェックは、より良いユーザーエクスペリエンス(往復をスキップ)のためにそこにあります。

2
AnoE

HTML検証は、クライアント側からHTMLコードを変更する方法を知らない人にのみ適用されます。これらのHTML検証は、クライアント側から簡単に削除および操作できます。常にデータベースで適切な検証を行ってください。

0
Harshit Singhal