OWASPによる最も一般的な10種類の攻撃のリストでは、最初の2つの場所がコードインジェクション攻撃とXSS(クロスサイトスクリプティング)で占められています。 XSSは、他の多くの種類の攻撃と同様に、インジェクション攻撃の成功に依存しているため、これらは密接に関連しています。 この名前では、攻撃のクラス全体が隠されており、その間、攻撃者が望む方法で悪意のあるコードを実行または解釈するように強制するために、データがWebアプリケーションに挿入されます。 このような攻撃には、たとえば、XSS、SQLインジェクション、ヘッダーインジェクション、コードインジェクション、およびフルパスディスクロージャーが含まれます。 そして、これはほんの一部です。
インジェクション攻撃は、すべてのプログラマーにとって恐ろしい話です。 それらは、それらから保護することの多様性、規模、および(場合によっては)複雑さのために、最も一般的で成功しています。 すべてのアプリケーションは、どこかからデータを取得する必要があります。 XSSとUIRedressは特に一般的であるため、私はそれらに別々の章を捧げ、それらを一般的なクラスから分離しました。
OWASPは、インジェクション攻撃の次の定義を提供します。
SQL、OS、LDAPなどのインジェクションの機会は、インタープリターがコマンド要求の一部として信頼できないデータを受信したときに発生します。 悪意のあるデータは、インタプリタをだまして特定のコマンドを実行させたり、許可されていないデータにアクセスさせたりする可能性があります。
SQLインジェクション
SQLインジェクションは、最も一般的で非常に危険な形式のインジェクション攻撃です。 この脅威の重大度を過大評価することは難しいため、攻撃の成功に影響を与えるものと、攻撃から身を守る方法を理解することは非常に重要です。
そのため、データはWebアプリケーションに埋め込まれ、SQLクエリで使用されます。 それらは通常、Webフォームなどの信頼できない入力ソースから取得されます。 ただし、データベース自体など、他の場所からインジェクションを実行することもできます。 プログラマーは、データベースが完全に安全であると信じていることがよくあります。一度は安全だったからといって、将来的に安全になるとは限りません。 データベースからのデータは、他の方法で証明されるまで、つまりテストに合格するまで、信頼できないと見なす必要があります。
攻撃が成功した場合、攻撃者はSQLクエリを操作して、開発者が意図していない操作をデータベースに対して実行することができます。
このリクエストを見てください:
$ db = new mysqli( "localhost"、 "username"、 "password"、 "storedb"); $ result = $ db-> query( "SELECT*FROMトランザクションWHEREuser_id="。$_POST ["user_id"]);
ここにはいくつかのバグがあります。 まず、POSTデータの内容をチェックしてuser_idが正しいかどうかを確認しませんでした。 次に、信頼できないソースに、使用するuser_idを教えてもらいます。攻撃者は有効なuser_idをすり抜けることができます。 おそらく、それは非表示のフォームフィールドに含まれていましたが、編集できないため(攻撃者がデータを入力できることを忘れているため)、安全であると考えました。 第3に、user_idをエスケープせず、バインドされたパラメーターとしてクエリに渡しました。これにより、攻撃者は、最初からチェックできなかったため、SQLクエリを操作する任意の文字列を挿入できます。
これらの3つの省略は、Webアプリケーションでは非常に一般的です。
データベースの信頼に関して、user_nameフィールドを使用してトランザクションを探していたと想像してください。 名前は多岐にわたり、引用符が含まれる場合があります。 攻撃者がユーザー名の1つに埋め込まれた文字列値を保存したとしましょう。 次のいずれかのリクエストでこの値を再度使用すると、データベースが信頼できるソースであると見なされ、侵害されたリクエストを分離および制限しなかったため、クエリ文字列が操作されます。
また、別のSQL実装要素にも注意してください。永続ストレージを常にサーバーに保持する必要はありません。 HTML 5は、SQLとJavaScriptを使用してクエリを送信できるクライアント側データベースの使用をサポートしています。 これには、WebSQLとIndexedDBの2つのAPIがあります。 2010年、W3CはWebSQLの選択を思いとどまらせました。 SQLiteをバックエンドとして使用するWebKitブラウザでサポートされています。 ほとんどの場合、W3C勧告にもかかわらず、下位互換性のためにサポートは継続されます。 その名前が示すように、このAPIはSQLクエリを受け入れます。つまり、インジェクション攻撃の標的になる可能性があります。 IndexedDBは、新しい代替手段であるNoSQLデータベースです(SQLクエリを使用する必要はありません)。
SQLインジェクションの例
SQLクエリの操作には、次の目標があります。
- データ漏洩。
- 保存された情報の開示。
- 保存された情報の操作。
- 承認バイパス。
- クライアント側でのSQLインジェクション。
SQLインジェクション保護
SQLインジェクション保護は、分離の原則に基づいています。 クエリでデータを使用する前に、フォームが正しいことを確認する必要があります。 また、クエリに含める前にデータを分離するか、遷移パラメーターとして含める必要があります。
検査
繰り返しますが、現在のリクエストのPHPソースコードで明示的に作成されていないすべてのデータは信頼できません。 それらを厳密にチェックし、チェックに合格しないものはすべて拒否します。 データを「修正」しようとしないでください。フォーマットに加えることができるのは、表面的な小さな変更のみです。
よくある間違いには、将来の使用(たとえば、表示や計算)のためにデータを検証することや、結果の情報が格納されるデータベースのフィールドを検証しないことが含まれます。
シールド
mysqli拡張機能を使用すると、SQLクエリに含まれるすべてのデータを分離できます。 これは、mysqli_real_escape_string()関数によって実行されます。 PostgresSQLのpgsql拡張機能は、pg_escape_bytea()、pg_escape_identifier()、pg_escape_literal()、およびpg_escape_string()関数を提供します。 mssql拡張機能(Microsoft SQLサーバー)分離関数はなく、addslashes()アプローチは非効率的です-カスタムが必要になります。
あなたの人生をさらに複雑にするために、私はあなたがリクエストに入力されたデータを分離するときに間違いを犯す権利がないと言います。 1回ミスすると、攻撃に対して脆弱になります。
要約します。 シールドはありません 最良の方法保護。 最後の手段として使用する必要があります。 抽象化に使用するデータベースライブラリで、パラメータを強制的にバインドせずに、ベアSQLクエリまたはクエリパーツを構成できる場合に必要になることがあります。 それ以外の場合は、分離を完全に回避することをお勧めします。 このアプローチは複雑でエラーが発生しやすく、データベースの拡張機能によって異なります。
パラメータ化されたクエリ(プレハブ式)
SQLクエリを作成するには、パラメータ化またはパラメータバインディングが推奨される方法です。 すべての 良い図書館 DBはデフォルトでそれを使用します。 PHP用のPDO拡張機能を使用した例を次に示します。
if(ctype_digit($ _ POST ["id"])&& is_int($ _ POST ["id"]))($ validatedId = $ _POST ["id"]; $ pdo = new PDO( "mysql:store.db") ; $ stmt = $ pdo-> prepare( "SELECT*FROMトランザクションWHEREuser_id=:id"); $ stmt-> bindParam( ":id"、$ validatedId、PDO :: PARAM_INT); $ stmt-> execute() ;)else(// id値を拒否し、エラーについてユーザーに通知します)
PDO式で使用可能なbindParam()メソッドを使用すると、準備された式で提供される「プレースホルダー」にパラメーターをバインドできます。 このメソッドは、PDO :: PARAM_INT、PDO :: PARAM_BOOL、PDO :: PARAM_LOB、PDO::PARAM_STRなどの基本的なデータ型のパラメーターを受け入れます。 PDO :: PARAM_STRの場合、特に指定がない限り、これがデフォルトです。他の値も忘れないでください。
手動分離とは異なり、パラメーターバインディング(またはデータベースライブラリで使用される他の方法)は、自動的にバインドされたデータを正しく分離するため、使用する関数を覚えておく必要はありません。 また、一貫性のあるパラメータバインディングは、すべてを手動で分離することを忘れないようにするよりもはるかに信頼性があります。
最小特権の原則の実装
成功したSQLインジェクションを中断することは、それを完全に防ぐことと同じくらい重要です。 攻撃者がSQLクエリを実行する機会を得ると、特定のデータベースユーザーとして実行します。 最小特権の原則により、すべてのユーザーがタスクを実行するために絶対に必要な特権のみを持つことが保証されます。
ユーザーが幅広い権限を持っている場合、攻撃者はテーブルを削除して他のユーザーの権限を変更し、ユーザーに代わって新しいSQLインジェクションを実行する可能性があります。 これを防ぐために、root、管理者、または高い権限を持つ他のユーザーとしてWebアプリケーションからデータベースにアクセスしないでください。
この原則のもう1つの用途は、データベースへのデータの読み取りと書き込みの役割を分離することです。 書き込み専用の権限を持つユーザーと読み取り専用の権限を持つユーザーを選択します。 攻撃が「読み取り中」のユーザーに向けられている場合、攻撃者はテーブル内のデータを操作したり、書き留めたりすることはできません。 アクセスをさらに狭く制限することで、SQLインジェクション攻撃の成功による影響を減らすことができます。
多くのWebアプリケーション、特にオープンソースアプリケーションは、特権レベルがほぼ確実にチェックされないデータベースユーザーを1人だけ持つように設計されています。 したがって、この点を忘れないでください。また、管理者アカウントでアプリケーションを実行しようとしないでください。
コードインジェクション(リモートファイルインクルードと呼ばれる)
コードインジェクションは、攻撃者がソースコードをWebアプリケーションに追加して、解釈および実行できるようにする手法です。 同時に、クライアント側にコードを挿入することについては話していません。たとえば、JavaScriptでは、XSS攻撃がすでにここで使用されています。
信頼できない入力ソースから直接ソースコードを挿入することも、ローカルファイルシステムまたはURLなどの外部リソースからWebアプリケーションにロードさせることもできます。 外部ソースを含めた結果としてコードが挿入される場合、これは通常、リモートファイルインクルード(RFI)と呼ばれますが、RFI自体は常にコード挿入を目的としています。
コードを実装する主な理由:
- 入力検証バイパス、
- 信頼性の低い入力データを、PHPコードと見なされるコンテキストに挿入します。
- ソースコードリポジトリのセキュリティを破る、
- サードパーティライブラリのロードに関する警告を無効にする、
- PHP以外のファイルをPHPインタープリターに渡すようにサーバーを再構成します。
最後の点に特に注意してください。この場合、信頼できないユーザーは任意のファイルをサーバーにアップロードできます。
コードインジェクションの例
の PHPセットコードインジェクションの標的となるため、このタイプの攻撃はプログラマーの監視リストの上位にあります。
ファイルインクルード
コードインジェクションの最も明白なターゲットは、include()、include_once()、require()、およびrequire_once()関数です。 信頼できない入力により、これらの関数に渡されるパスパラメータを決定できる場合は、含めるファイルの選択をリモートで制御できます。 含まれるファイルは実際のPHPファイルである必要はなく、テキストデータを保存できる任意のファイル形式が許可されていることに注意してください(つまり、ほとんど制限はありません)。
パスパラメータは、ディレクトリトラバーサルまたはリモートファイルインクルード攻撃に対しても脆弱である可能性があります。 パスで../または…を使用すると、攻撃者はPHPプロセスがアクセスできるほとんどすべてのファイルに移動できます。 また、デフォルトのPHP構成では、allow_url_includeが無効になっていない限り、上記の関数はURLを受け入れます。
検査
PHP eval()関数は、実行されるPHPコードの文字列を受け取ります。
正規表現の注入
PHPのPCRE(Perl互換正規表現)関数preg_replace()は、e(PREG_REPLACE_EVAL)修飾子を受け入れます。 これは置換文字列を意味し、置換後はPHPコードと見なされます。 また、この行に信頼できない入力がある場合は、実行可能なPHPコードを挿入できます。
欠陥のあるファイル包含ロジック
Webアプリケーションには、定義上、要求を処理するために必要なファイルが含まれています。 ルーティングロジック、依存関係管理、自動読み込み、およびその他のプロセスの欠陥によって悪用された場合、要求パスまたはそのパラメーターを操作すると、サーバーに特定のローカルファイルが含まれるようになります。 Webアプリケーションはそのような操作を処理するように設計されていないため、結果は予測できない可能性があります。 たとえば、アプリケーションは、での使用のみを目的としたルートを無意識のうちに強調表示します コマンドライン。 または、コンストラクターがタスクを実行する他のクラスを公開します( より良いクラスそのように設計しないでください、しかしそれはまだ起こります)。 これらのシナリオはいずれも、アプリケーションのバックエンド操作に干渉する可能性があり、直接アクセスを伴わないリソースを大量に消費する操作に対するデータ操作またはDOS攻撃を可能にします。
コードインジェクションタスク
このタイプの攻撃では、攻撃者が選択した任意のPHPコードを実行できるため、タスクの範囲は非常に広くなります。
コードインジェクションに対する防御
コマンドインジェクション
コマンドインジェクションの例
コマンドインジェクションに対する防御
ログインジェクション(ログファイルインジェクションと呼ばれます)
多くのアプリケーションはログを収集し、許可されたユーザーはHTMLインターフェイスを介してログを表示することがよくあります。 したがって、ログは、他の攻撃を隠し、ログを表示する人をだまし、さらにはログを読み取って分析する監視アプリケーションのユーザーを攻撃したい攻撃者の主な標的の1つです。
ログの脆弱性は、ログの記録を制御するメカニズムと、レコードを表示および分析する際の信頼できないソースとしてのログデータの処理に依存します。
シンプルなロギングシステムでファイルに書き込むことができます テキスト文字列 file_put_contents()を使用します。 たとえば、プログラマーは誤った認証の試行を次の形式の文字列としてログに記録します。
sprintf( "%sによるログイン試行の失敗"、$ username);
攻撃者がフォームで「AdminnSuccessfulloginbyAdminn」という名前を使用した場合はどうなりますか?
この行が信頼できない入力データからログに挿入された場合、攻撃者は失敗したログイン試行を正常にマスクし、管理者パスワードの入力に無邪気に失敗します。 成功した認証試行を追加すると、データの疑わしさはさらに減少します。
ここで重要なのは、攻撃者があらゆる種類のエントリをログに追加できるということです。 XSSベクトルや、コンソールでログエントリを読みにくくする文字を埋め込むこともできます。
ログインジェクションタスク
実装の目標の1つは、ログ形式のインタープリターです。 分析ツールが使用する場合 正規表現ログエントリを解析し、それらを部分に分割してさまざまなフィールドに分散させるには、正規表現が正しいフィールドではなく埋め込みフィールドを選択するように強制する文字列を作成して挿入できます。 たとえば、このエントリはいくつかの問題の原因となる可能性があります。
$ username = "iamnothacker!at Mon Jan 01 00:00:00 +1000 2009"; sprintf( "%sで%sによるログイン試行に失敗しました"、$ username、)
より高度なログインジェクション攻撃は、ディレクトリトラバーサル攻撃に依存してブラウザにログを表示します。 適切な条件下で、PHPコードをログメッセージに挿入し、ブラウザでログファイルを開くと、攻撃者の意志で適切にフォーマットおよび実行されたコードが正常に挿入されます。 また、サーバー上での悪意のあるPHPの実行に関しては、防御の分離の有効性を期待することしかできません。これにより、被害を減らすことができます。
ログインジェクション保護
すべての外部ログメッセージをフィルタリングする最も簡単な方法は、ホワイトリストを使用することです。 文字セットを数字、文字、スペースのみに制限するとします。 不正な文字を含むメッセージは破損していると見なされます。 次に、ログファイルを実装しようとする可能性のあるエントリに関するエントリがログに表示されます。 これは、信頼できない入力を回避できない単純なテキストログに対する簡単な防御です。
保護の2番目の方法は、base64のようなシステムを使用して、信頼できない入力データの一部を変換することです。このシステムは、限られた文字セットをサポートしますが、 テキストフォームさまざまな情報。
パストラバーサル(ディレクトリトラバーサルと呼ばれます)
トラバーサル攻撃は、Webアプリケーションのバックエンドにあるファイルの読み取りまたは書き込み操作に影響を与える試みです。 これは、バックエンド操作に関係するファイルのパスの操作を可能にするパラメーターを挿入することによって行われます。 したがって、このタイプの攻撃は、情報開示とローカル/リモートファイルインジェクションを容易にします。
このような攻撃については個別に検討しますが、パストラバーサルが成功の基盤です。 以下で説明する関数はファイルパスの操作に固有であるため、多くのPHP関数は通常の意味でファイルパスを受け入れないことに注意してください。 代わりに、include()やfile()などの関数はURIを受け入れます。
それは完全に不自然に見えます。 ただし、これは、絶対パスを使用する次の2つの関数呼び出しが同等であることを意味します(たとえば、相対パスの自動ロードに依存しません)。
include('/var/www/vendor/library/Class.php'); include('file:///var/www/vendor/library/Class.php');
実際には、相対パスはサイドで処理されます(php.iniおよび使用可能なオートローダーのinclude_path設定)。 このような場合、PHP関数は、信頼できないデータがファイルパスの先頭に埋め込まれている場合に、攻撃者がHTTPまたはFTP URIを挿入できる、ファイルURIスキーム置換などの多くの形式のパラメーター操作に対して特に脆弱です。 これについては、リモートファイルインクルード攻撃のセクションで詳しく説明しますが、ここでは、ファイルシステムパスのバイパスに焦点を当てます。
この脆弱性には、別のファイルにアクセスするためのパスの変更が含まれます。 これは通常、一連の../シーケンスを引数に挿入することで実現されます。このシーケンスは、関数にアタッチされるか、include()、require()、file_get_contents()などの関数に完全に挿入され、さらに疑わしくない(一部の)関数に挿入されます。 DOMDocument::load()のように。
攻撃者はシーケンス../を使用して、システムを強制的に親ディレクトリに戻します。 したがって、パス/var/www/public/../vendorは実際には/ var / www/vendorにつながります。 シーケンス../after/ publicは、親ディレクトリ、つまり/ var/wwwに戻ります。 したがって、攻撃者はWebサーバーからアクセス可能な/publicディレクトリの外部にあるファイルにアクセスできます。
もちろん、パストラバーサルは単に戻るだけではありません。 .htaccessの制限設定により、ブラウザからアクセスできない子ディレクトリにアクセスするために、新しいパス要素を挿入することができます。 ファイルシステムでのPHPの操作は、Webサーバー上の非公開ファイルおよびディレクトリのアクセス制御構成とは関係ありません。
パストラバーサルの例
パストラバーサルに対する防御
XMLインジェクション
サーバーとクライアント間でデータを渡す軽量の手段としてJSONが導入されたにもかかわらず、XMLは依然として人気のある代替手段であり、WebサービスAPIはJSONと一緒にJSONをサポートすることがよくあります。 XMLは、RSS、Atom、SOAP、RDFなどのXMLスキーマを使用したデータ交換にも使用されます。
XMLはどこにでもあります。これは、Webアプリケーションサーバー、ブラウザー(XMLHttpRequestの要求と応答の推奨形式として)、およびブラウザー拡張機能にあります。 PHPがDOMやSimpleXMLおよびXMLReader拡張機能で使用するlibxml2などの一般的なパーサーによるその遍在性とデフォルトの解析を考えると、XMLはインジェクション攻撃の標的になっています。 ブラウザがXML交換に積極的に参加する場合、許可されたユーザーがXSSを介して、攻撃者によって実際に作成されたXML要求を送信できることを考慮に入れる必要があります。
外部XMLエンティティインジェクション(XXE)
このような攻撃が存在するのは、XML解析ライブラリがカスタムエンティティ参照の使用をサポートしていることが多いためです。 あなたはエンティティの標準的なXML補完に精通するでしょう、それは表現するために使用されます 特殊文字>、<のようなマークアップ および'。 XMLを使用すると、XMLドキュメント自体を介してカスタムエンティティを定義することにより、標準エンティティのセットを拡張できます。 これらは、オプションのDOCTYPEに直接含めることで定義できます。 それらが表す拡張値は、含める必要のある外部リソースを参照できます。 XXE攻撃は、外部リソースのコンテンツが原因で増大する可能性のあるカスタムリンクを格納する通常のXMLの機能のために、まさに人気が高まっています。 通常の状況では、信頼できない入力が予期しない方法でシステムと相互作用することはありません。 そして、ほとんどのXXEプログラマーは、特に懸念されるXXE攻撃をほぼ確実に予期していません。
たとえば、無害な新しいカスタムエンティティを定義しましょう。
]>
この定義を持つXMLドキュメントは、エンティティが許可されている場合はいつでも、エンティティを参照できるようになりました。
]>
PHP DOMのようなXMLパーサーがこのXMLを解釈する場合、ドキュメントが読み込まれるとすぐにこのカスタムエンティティを解析します。 したがって、対応するテキストを要求すると、次のように返されます。
この結果は完全に無害です
明らかに、カスタムエンティティには、繰り返しのテキストとXMLをより短いエンティティ名で表すという利点があります。 XMLは特定の文法に従わなければならないことがよくあり、カスタムエンティティによって編集が容易になります。 ただし、外部入力に対する不信感を考えると、アプリケーションが使用するすべてのXMLに細心の注意を払う必要があります。 たとえば、これは安全なバリエーションではありません。
]>
リクエストされたコンテンツに応じて ローカルファイルデータは、エンティティを拡張するときに使用できます。 次に、リッチコンテンツをXMLパーサーから抽出し、攻撃者が分析できるようにWebアプリケーションの送信データに含めることができます。 たとえば、情報開示のために。 抽出されたファイルはXMLとして解釈されますが、そのような解釈をトリガーする特殊文字はありません。 これにより、ローカルファイルコンテンツの開示範囲が制限されます。 ファイルがXMLとして解釈されているが、有効なXMLが含まれていない場合は、エラーが発生する可能性が高く、コンテンツの開示が妨げられます。 ただし、PHPではスケール制限を回避するための巧妙なトリックを利用できるため、返された応答を攻撃者に返すことができない場合でも、リモートHTTPリクエストはWebアプリケーションに影響を与えます。
PHPでXMLを解析および使用するには、PHP DOM、SimpleXML、およびXMLReaderの3つの一般的な方法があります。 それらはすべてlibxml2拡張機能を使用し、外部エンティティのサポートはデフォルトで有効になっています。 結果として、PHPにはデフォルトのXXE攻撃の脆弱性があり、XMLを使用するWebアプリケーションまたはライブラリのセキュリティを考慮すると非常に見逃しがちです。
また、XHTMLとHTML5は有効なXMLとしてシリアル化できることを忘れないでください。 これは、一部のXHTMLページまたはXMLシリアル化されたHTML 5が、DOMDocument :: loadHTML()の代わりにDOMDocument :: loadXML()を使用してXMLとして解析できることを意味します。 このXMLパーサーの使用は、外部XMLエンティティの挿入に対しても脆弱です。 libxml2はまだHTML5DOCTYPEを認識していないため、XHTMLDOCTYPESとして検証できないことに注意してください。
外部XMLエンティティの埋め込みの例
ファイルの内容と開示
上記では、情報開示の例を見て、カスタムXMLエンティティが外部ファイルを参照できることに注目しました。
]>
この場合、カスタムエンティティはファイルの内容で拡張されます。 このような要求はすべてローカルで行われるため、これにより、アプリケーションが読み取ることができるすべてのファイルの内容を明らかにすることができます。 つまり、拡張エンティティがアプリケーションの送信データに含まれている場合、攻撃者はプライベートアクセスにあるファイルを調べることができます。 確かに、この場合、重大な制限があります。ファイルはXML形式であるか、XMLパーサーエラーを引き起こさない形式である必要があります。 しかし、重要なのは、この制限はPHPでは完全に無視できるということです。
]>
PHPを使用すると、標準のファイルシステム関数であるfile_get_contents()、require()、require_once()、file()、copy()などで受け入れられるプロトコルの1つであるURIとしてラッパーにアクセスできます。 PHPラッパーは、特定のリソースに適用できるいくつかのフィルターをサポートしているため、関数呼び出しによって結果が返されます。 上記の例では、読み取りたいターゲットファイルにconvert.base-64-encodeフィルターを適用します。
これは、攻撃者が利用可能なものを読み取ることができることを意味します PHPファイル、テキスト形式に関係なく。 アプリケーションからのデータをデコードし、それらを免責で分析するだけで十分です。 これはエンドユーザーやアプリケーションのバックエンドに直接害を及ぼすことはありませんが、攻撃者が他の脆弱性を見つけようとしてアプリケーションの構造をよく見ることを可能にします。 さらに、攻撃者が検出されるリスクは最小限に抑えられます。
アクセス制御バイパス
アクセス制御 違う方法。 XXE攻撃はWebアプリケーションのバックエンドで実行されるため、現在のユーザーのセッションを使用することはできません。 ただし、攻撃者はローカルサーバーからの要求を使用して、バックエンドへのアクセス制御をバイパスできます。 この基本的なアクセス制御について考えてみましょう。
if(isset($ _ SERVER ["HTTP_CLIENT_IP"])|| isset($ _ SERVER ["HTTP_X_FORWARDED_FOR"])||!in_array(@ $ _ SERVER ["REMOTE_ADDR"]、array( "127.0.0.1"、 ":: 1 "、)))(header(" HTTP / 1.0 403 Forbidden "); exit("このファイルへのアクセスは許可されていません。 ");)
このPHPは、他の無数のPHPと同様に、ローカルサーバー(ローカルホスト)上の特定のPHPファイルへのアクセスを制限します。 ただし、アプリケーションのフロントエンドに対するXXE攻撃は、攻撃者にこのアクセス制御をバイパスするために必要な正確な資格情報を提供します。これは、XMLパーサーへのすべてのHTTP要求がローカルホストから行われるためです。
]>
ログの閲覧がローカルリクエストに限定されていたとしても、攻撃者はログを取得することができます。 同じことが、この方法でアクセスが制限されている保守または管理インターフェースにも当てはまります。
DOS攻撃
DOS攻撃の場合、サーバーリソースの消費を指示するほとんどすべてのものを使用できます。 攻撃者は、外部XMLエンティティを挿入することにより、適切な条件下でサーバーリソースを消費する任意のHTTP要求を行うことができます。
後で、XMLエンティティの拡張の観点から、他の潜在的なDOSによるXXE攻撃の使用について説明します。
外部XMLエンティティの挿入に対する保護
これらの攻撃は非常に人気があるので、それらに対する防御がいかに簡単であるかに驚くでしょう。 DOM、SimpleXML、およびXMLReaderはすべてlibxml2に依存しているため、実行できるのはlibxml_disable_entity_loader()関数を使用して外部エンティティの使用を無効にすることだけです。 確かに、これはDOCTYPEで事前定義されたカスタムエンティティを無効にしません。これは、HTTPリクエストまたはでの操作を必要とする外部リソースを使用しないためです。 ファイルシステム.
$ oldValue = libxml_disable_entity_loader(true); $ dom = new DOMDocument(); $ dom-> loadXML($ xml); libxml_disable_entity_loader($ oldValue);
これは、文字列、ファイル、またはリモートURIからのXMLのロードを伴うすべての操作に対して実行する必要があります。
アプリケーションが外部エンティティを必要としない場合、およびそのほとんどの要求に対して、通常、よりグローバルなレベルで外部リソースのロードを無効にすることができます。 多くのライブラリにはXXE攻撃に対する固有の脆弱性があるため、ほとんどの場合、これはすべてのXML読み込みの「ポイント」を決定するのに非常に適しています。
libxml_disable_entity_loader(true);
外部リソースの読み込みを一時的に有効にするたびに、TRUEを返すことを忘れないでください。 XSLスタイルの適用が外部エンティティに依存するDocbookXMLからHTMLへの変換などの無害なタスクに必要になる場合があります。
ただし、libxml2を無効にすることは万能薬ではありません。 XMLを解析または処理する他の拡張機能やPHPライブラリを分析して、外部エンティティを使用するための「スイッチ」を見つけます。
これが不可能な場合は、XMLドキュメントでDOCTYPEが宣言されているかどうかをさらに確認してください。 その場合、および外部エンティティも無効になっている場合は、XMLドキュメントを破棄し、潜在的に脆弱なパーサーへの信頼できないXMLアクセスを禁止し、攻撃の可能性としてログに記録します。 他の兆候はないので、これは必要なステップです-エラーも例外もありません。 このチェックを通常の入力検証に組み込みます。 ただし、この方法は完全にはほど遠いため、ルートで外部エンティティの問題に取り組むことを強くお勧めします。
/***迅速な検出を試みます*/$ collapsedXML = preg_replace( "/ [:space:] /"、 ""、$ xml); if(preg_match( "/
また、攻撃の結果である可能性のある疑わしいデータをすぐに削除することもお勧めします。 なぜ危険に見える何かに取り組み続けるのですか? したがって、上記の2つの手段を組み合わせることで、明らかに悪意のあるデータを事前に無視し、データを削除できない場合(たとえば、サードパーティのライブラリの場合)に自分自身を保護することができます。 libxml_disable_entity_loader()はすべてのカスタムエンティティを無効にするのではなく、外部リソースを参照するエンティティのみを無効にするため、データも削除する必要があります。 これにより、XMLエンティティ拡張攻撃の可能性が残ります。
XMLエンティティ拡張
この攻撃は、多くの点でXMLエンティティインジェクション攻撃に似ています。 ただし、この場合、ターゲットアプリケーションのサーバー環境のリソースを使い果たしようとするDOS攻撃に重点が置かれます。 DOCTYPE XMLでは、カスタムエンティティ定義が作成されます。これにより、たとえば、元のエンティティよりもはるかに大きいXML構造をメモリ内に生成できます。 これによりメモリがいっぱいになり、サーバーの効率が低下します。 この攻撃は、HTML 5 XMLシリアル化がlibxml2拡張機能によってHTMLとして認識されない場合、後者にも適用されます。
XMLエンティティ拡張の例
サーバーリソースを枯渇させるためにカスタムXMLエンティティを拡張する方法はいくつかあります。
汎用エンティティ拡張
別名は「四角倍率攻撃」です。 カスタムエンティティは、非常に長い文字列として定義されます。 ドキュメントで繰り返し使用すると、毎回増加します。その結果、XML構造は元のXMLと比較してはるかに多くのRAMを消費します。
]>
カスタムエンティティ文字列のサイズとドキュメントの本文での使用量のバランスが取れている場合は、展開するとサーバーのメモリ消費量を予測するようなXMLファイルまたは文字列を作成できます。 このような繰り返しの質問で埋めると、実際のDOS攻撃が発生します。 このアプローチの欠点:メモリ消費は乗算の単純な効果に依存するため、初期XMLもかなり大きくする必要があります。
エンティティの再帰的拡張
一般的な拡張では、最初は大きなXMLを使用する必要がありますが、再帰的な拡張では、はるかに高い倍率が提供されます。 この方法は、サイズが大幅に増加するような方法で、小さなエンティティの指数分解(解決)セットに基づいています。 非常に論理的には、この方法はXML爆弾およびBillionLaughsAttackと呼ばれることがよくあります。
]>
XML爆弾は大きなXMLを必要としません。これは、アプリケーションによって制限される場合があります。 この攻撃により、メモリは元のエンティティ値のサイズの2^100倍のサイズのテキストでいっぱいになります-。 本物の爆弾!
リモートエンティティ拡張
上記の両方の攻撃は、XMLDTDでローカルに定義されたエンティティを使用します。 ただし、攻撃者は、XMLパーサーが外部HTTP要求を行うことができる場合、エンティティをリモートで判別できます。 XXE(外部XMLエンティティインジェクション)の説明で見たように、この機能は基本的なセキュリティ対策として無効にする必要があります。 したがって、XXEに対して防御することにより、このタイプの攻撃に対しても防御します。
いずれの場合も、この攻撃の場合、XMLパーサーは、関連するエンティティの拡張値を取得するために外部HTTP要求を行う必要があります。 次に、それらは独立して新しい外部エンティティを定義し、パーサーはこれに対して追加のHTTP要求を行う必要があります。 そのため、無害に見えるクエリがすぐに手に負えなくなり、利用可能なサーバーリソースにさらに圧力がかかり、エンティティの再帰的な拡張につながり、事態が悪化する可能性があります。
]>
上記のコードでは、より微妙なDOS攻撃も可能です。外部リクエストは、ローカルアプリケーションまたはサーバーリソースを共有するその他のアプリケーションに適合させる必要があります。 その結果、システムはそれ自体を攻撃します。XMLパーサーを使用して外部エンティティを分解(解決)しようとすると、ローカルアプリケーションに多くの要求を送信し、多くのサーバーリソースを消費します。 この攻撃は、DOS攻撃をさらに実行するために、XXE攻撃の効果を増幅するために使用できます。
XMLエンティティ拡張保護
防御方法は、単一のXXE攻撃の場合と同じです。 カスタムXMLエンティティのローカルファイルおよび関数への展開(解決)を無効にする必要があります。 次の関数を使用して外部HTTPリクエストを無効にします。これは、libxml2の使用に基づいてすべてのPHPXML拡張機能にグローバルに適用されます。
libxml_disable_entity_loader(true);
ただし、PHPは、DOCTYPEを介してXMLDTDを使用してカスタムエンティティの定義を完全に無効にする明確な手段を提供していません。 PHPは定数LIBXML_NOENTを定義し、パブリックプロパティDOMDocument :: $substituteEntitiesもありますが、状況は改善されません。 独自の回避策を使用する必要があるようです。
libxml2は本質的に再帰的なエンティティ分解に耐性がないため、エラーログはクリスマスツリーのように装飾されます。 したがって、再帰エンティティに対する特定の保護を実際に実装する必要はありません。 libxml2が再発した場合に備えて、何かを行う必要がありますが。
したがって、主な新しい脅威は、XML爆弾または一般的なエンティティ拡張を使用したブルートフォースアプローチです。 これらの攻撃は、ローカルまたはリモートのシステムコールを必要とせず、エンティティの再帰も必要としません。 基本的に、唯一の救済策は、XMLにDOCTYPEが含まれている場合、XMLを削除またはサニタイズすることです。 DOCTYPEを使用する必要がなく、信頼できるソースから、つまり検証済みのHTTPS接続を介して取得しなかった場合は、削除する方が安全です。 それ以外の場合、PHPにはDTDを無効にするための有効なオプションがないため、カスタムロジックを作成する必要があります。 libxml_disable_entity_loader(TRUE)を呼び出すことができると仮定すると、次のコードは、拡張に感染したノードの値にアクセスするまでエンティティが拡張されないため、安全です。 そして、このテストの間、これは起こりません。
$dom=新しいDOMDocument; $ dom-> loadXML($ xml); foreach($ dom-> childNodes as $ child)(if($ child-> nodeType === XML_DOCUMENT_TYPE_NODE)(throw new \ InvalidArgumentException( "Invalid XML:Detected use ofillegal DOCTYPE");))
もちろん、安全にプレイし、libxml_disable_entity_loaderをTRUEに設定して、XMLが最初にロードされたときに外部エンティティへの参照が解決されないようにする必要もあります。 これは、XMLパーサーがエンティティ分解を管理するための包括的なオプションのセットを持っていない限り、XMLパーサーがlibxml2に依存しない唯一の可能な防御である可能性があります。
SimpleXMLを使用する場合は、simplexml_import_dom()関数を使用して検証済みのDOMDocumentオブジェクトをインポートできることに注意してください。
7.4Kこの記事では、AJAXフォームの作成と送信について説明します。 その後、animate.cssを使用したアニメーションの実装、JavaScriptを使用したデータ検証を確認できます。
この記事の執筆時点では、Bootstrap3.3.5がフレームワークの現在のバージョンです。 この記事では、デフォルト(12列)のブートストラップビルドを使用しています。 この記事のタスクを完了するときは、で説明されている最新のスニペットとコード構造を使用していることを確認してください。 ブートストラップドキュメント.
ファイルとフォルダの構造
ルートディレクトリを作成し、それに次のファイルとフォルダを追加します。
ブートストラップフォーム:
いくつかのフロントエンドライブラリを含める必要があります。
- ブートストラップ;
- jquery。
これらのライブラリを指定すると、ファイル構造は次のようになります。
ブートストラップフォーム:
フォームの作成
index.htmlファイルを開き、次の基本構造をコピーします AJAXお問い合わせフォーム:
メッセージを送ってください
これは、フォームコンテンツを追加する基本的なHTMLテンプレートです。 必要なCSSファイルとJavaScriptファイルがすべて含まれています。 この特定の例では、bootstrap.jsは必要ないことに注意してください。
Bootstrap内のメディアクエリ用のビューポートメタタグが含まれています。 JavaScriptはファイルの下部に配置されているため、メインコードが最初に処理されます。
bodyタグには、クラスcol-sm-6col-sm-offset-3のdivが含まれています。 これは、smビューポート(小さい)内およびその上に、50%幅の列を表示することを意味します( 列の最大数12)。 col-sm-offset-3クラスは、左マージンを25%に設定します。
これにより、使用可能なスペースの半分を占め、水平方向の中央に配置されるレイアウトが作成されます。 その後、h3を含め、フォームのベースになります。 後でAJAXjQueryフォーム送信イベントをフォームに添付できるように、フォームにIDを指定してください。
苦労なくして勝利はありません
これらはすべて、ユーザーが操作する入力フィールドとボタンです。 行クラスの最初のdivは、col要素の水平方向のグループ化である従来のBootstrap構文です。 Bootstrap内の列は、パディングまたは空白を作成します。 それらを削除することにより、ストリングがコンテナに均等に収まるようにすることができます。
クラスcol-sm-6(50%)で2つの列を作成しました。これを使用して、フォームの上部を区切ります。 最初の列col-sm-6内に、名前と電子メールのラベルとフィールドを作成しました。 それぞれに対応するfor属性を持つラベルが含まれているため、ラベルは対応するフィールドに関連付けられます。
これらの各列には、ラベルを意味的にグループ化するフォームグループが含まれ、下部にわずかなパディングが作成されます。
タイポグラフィ
ブートストラップは、H1-H6のクラスを許可します。 これらは、フィールドを追加したり、スーパーAJAX連絡先フォーム要素のブロックを作成したりすることなく、インライン要素のスタイルを設定するのに役立ちます。 H4のクラスを使用して、ラベルのスタイルを設定し、ラベルを大きくしました。
form-controlクラスは、コンテナの全幅(width 100%)を占めるように、各入力要素に適用されます。 このクラスには、読みやすいフォーム要素を作成できるさまざまなスタイルも追加されています( 大きいサイズ、明確なエッジなど。).
これらの列の後に、メッセージ本文を含めます。 フォームグループにラップし、ラベルやテキストフィールドと同じスタイルを適用します。
アクションの呼び出し
送信ボタンを作成しましょう。 Bootstrapには、さまざまなボタンとその状態のクラスが含まれています。 ボタン「 成功” (btn-成功)、これはデフォルトで緑色です。
また、ボタンの基本設定をリセットするには、btn基本クラスを適用する必要があります( フレーム、パディング、テキストの配置、フォントサイズ)。 大きなボタンを作成するbtn-lgクラスを適用してから、左側のボタンをラップするpull-rightクラスを適用しました。
ボタンの後に、IDが#msgSubmitのdivを含め、次のクラスを適用しました: " h3テキストセンター非表示"。 h3クラスは、より大きな見出しを作成するのに役立ちます。text-centerは、テキストの配置を中央に設定し、非表示のセットは、表示:なしおよび表示:非表示:
データ送信機能の追加
基本的なBootstrapjQueryAJAXフォームを作成しましたが、まだ何もしていません。 次のステップは、ユーザー入力を受け入れ、それを非同期でPHPに送信する関数を作成することです。
scripts.jsファイルを開き、次のコードをコピーします。
$( "#contactForm")。submit(function(event)(//フォーム送信をキャンセルしますevent.preventDefault(); submitForm();));
これ jQueryコードスニペット、#contactFormをリッスンします( 前に述べたように)。 この関数の前に、関数のフォームデータを送信するアクションを保持するイベント変数を処理します。
event.preventDeafult()は、フォームでアクションを選択せずにページが更新されると、フォームデータの送信を停止します。 そして最後に、このコードはsubmitForm()関数を要求します。 :
function submitForm()(//フォームの内容で変数を初期化しますvar name = $( "#name")。val(); var email = $( "#email")。val(); var message = $( " #message ").val(); $ .ajax((type:" POST "、url:" php / form-process.php "、data:" name = "+ name +"&email = "+ email +"&message = "+メッセージ、成功:function(text)(if(text == "success")(formSuccess();))));)function formSuccess()($( "#msgSubmit")。removeClass( "hidden" );)
トリガーされた3つの変数は、フォームの各入力フィールドの値をキャプチャし、後で使用するためにJavaScript変数に渡します。
開始します jquery内のajaxオブジェクト postのパラメータ、PHPファイルのURL、送信するデータ、およびコールバック関数を設定します。 データには、対応するIDを持つ3つの変数すべてが含まれます。 コールバック関数は、AJAXオブジェクトがPHPスクリプトから情報を正常に受信したときに呼び出されます。 関数は返されたテキストを取得し、それが文字列"と等しいかどうかを確認します 成功"。 はいの場合、最後のformSuccess関数が実行されます。
以前に適用した#msgSubmitDIVから非表示のクラスを削除し、テキストを表示します。
PHPメール機能への接続
次に、AJAXフォームからデータを受信し、PHPメール関数を介してコンテンツを送信するスクリプトを作成する必要があります。 process.phpファイルを開き、次のコードを追加します。
使用したい変数を保存する必要があります。 メール関数から3つの入力変数を取得し、PHPで同じ名前を付けることができます。 $ EmailTo変数は、スクリプトで設定できる電子メールアドレスです。 $ Subjectは、電子メールの件名を説明する文字列です。
手紙の本文は、3つの作成された変数を追加して任意に作成されます。 まず、説明テキストを設定します。たとえば、「 名前:"、次に変数、次に改行(/ n)が続きます。 同じ手順を繰り返し、すべてのデータを$body変数にリンクします。
メールを送信するには、メール機能に添付します。 $ success変数に値を割り当てることにより、電子メールの送信先の電子メールアドレス、電子メールの件名、本文、および送信者の電子メールアドレスを設定します。
電子メールの送信プロセスを開始するには、ifステートメントで電子メールを呼び出す必要があります。 このようにして、フォームデータが正常に送信されたかどうかを確認できます。 Mail関数が「 true」、スクリプトは「 成功」、関数がエラーをスローした場合、「 無効”.
この結果はAJAXオブジェクトに返され、クライアント側で処理されます。 AJAXの利点は、すべてクライアント側で非同期に実行されることです。 これにより、ユーザーはAJAXフォームデータを送信しながらサイトとの対話を続けることができます。
輝きましょう
ここでは、有効にできるさまざまな追加機能を通じてユーザーフィードバックを提供することに焦点を当てます。 特に、クライアント側とサーバー側の両方で、エラー処理を使用したフォームフィードバックについて説明します。
また、フォームを検証するためにいくつかのツールを使用します。
- Animate.css:;
- ブートストラップバリデーター。
以前にBootstrapとJQueryで行ったように、それらをプロジェクトに追加します。 これらのツールは、ユーザーがデータを送信した後にフィードバックを提供するのに役立ちます。
プロジェクト構造は次のようになります。
フォームの検証
PHP AJAX連絡フォームデータを入力した後、バリデーターを設定することから始めましょう。 scripts.jsファイルに移動し、フォームデータが送信された後にSubmitForm()関数を呼び出す最初のコードを編集します。
次のように変更する必要があります。
$( "#contactForm")。validator()。on( "submit"、function(event)(if(event.isDefaultPrevented())(//フォームエラーを処理します...)else(//すべて問題ありません!event .preventDefault(); submitForm();)));
この新しいコードスニペットは、Bootstrap Validatorが問題を検出し、コードの実行を停止したかどうかを確認します。 そうでない場合は、標準モードでアクションを続行します。 デフォルトのアクションを除外する必要があります( フォームに入力せずにページをリロードする)フォームデータ送信スクリプトから。
ここで、すべてのフィールドに入力せずにフォームデータの送信ボタンをクリックすると、空のフィールドが赤で強調表示されます。
検証を追加する過程で、ネイティブHTML5検証を無効にしました。 エラーメッセージを含めることで、検証にコンテキストを追加できます。 Bootstrap Validatorには、各フィールドのエラーメッセージを表示できる便利な機能があります。 それらを追加するには、HTMLマークアップを完了する必要があります。
各フォームグループ内のデータ入力フィールドの下に、次のHTMLコードを配置します。
例として、以下は名前と電子メールフィールドに追加された追加のdivです:
これで、AJAX jQueryフォームデータを再送信するときに、フォームフィールドに入力されていない場合、エラーメッセージが表示されます。 このフィールドに入力してください。"。 「」と呼ばれる入力データのデータ属性を追加することによって データエラー」、カスタムエラーメッセージを含めることができます。
例えば:
フィードバックアニメーションの追加
空のフォームフィールドを示す機能を追加しました。 ただし、フォームにアニメーションを追加し、メッセージを追加して、何が起こっているのかをユーザーに知らせるとよいでしょう。 現在、フォームデータを正常に送信すると、「 メッセージが送信されました!「しかし、間違いはどうですか?
既存のコードを使用するために、既存のデータ送信成功メッセージを変更します。 まず、「」というテキストを削除します メッセージが送信されました!'HTMLマークアップから、空のdivを残します:
次に、メッセージのステータスを処理するための新しい関数を作成する必要があります。 次の関数をscripts.jsファイルの最後に追加します。
function submitMSG(valid、msg)(var msgClasses; if(valid)(msgClasses = "h3 text-center tadaアニメーションテキスト-成功";)else(msgClasses = "h3 text-center text-danger";)$( "# msgSubmit ")。removeClass()。addClass(msgClasses).text(msg);)
この関数は2つの引数を取ります。 validはブール変数になります。その値がtrueの場合、データが正常に送信されたことを示すメッセージが表示されます。 falseの場合、エラーメッセージが表示されます。 msgは、divブロックの画面に表示されるメッセージです。
この関数は、成功したデータ送信メッセージまたはエラーメッセージを処理しているかどうかをチェックします。 これは、有効な変数の値をチェックすることによって行われます。 いずれにせよ、適切なCSSクラスで変数を設定します( h3とtext-centerを削除するので、それらを再度有効にする必要があります).
注:成功メッセージクラスには、いくつかのanimate.cssクラスを使用します。 AJAX JQueryお問い合わせフォームデータが正常に送信されると、tadaアニメーションが再生されます。
最後に、この関数は#msgSubmitからすべてのクラスを削除します( クラスの重複を避けるため)次に、優先度クラスを設定し、メッセージテキストをdivに追加します。
このセクションの冒頭にあるバリデーターの初期化の中で、コードを更新して、trueと評価されたときにifステートメント内に次の関数呼び出しを追加します。
submitMSG(false、 "フォームに正しく入力しましたか?");
これで、すべてのフィールドに入力しなかった場合、エラーメッセージが表示されます。 フォームに正しく記入しましたか?»
この新しいsubmitMSG関数の最後のステップは、フォームデータが正常に送信されたときに呼び出すことです。 formSuccess()関数を次のように更新します。
$( "#contactForm")。reset(); submitMSG(true、 "メッセージが送信されました!")
上記のようにsubmitMSG関数を呼び出して成功メッセージを表示するときに、フォームをリセットして値をクリアします。 これで、フォームデータの送信が成功すると、適切なメッセージがアニメーションanimate.css tada:で表示されるはずです。
振ってみよう
フォーム全体にエラーアニメーションを追加しましょう。一般的な「シェイク」アニメーションでうまくいくはずです。
formSuccess()関数の直後に新しい関数を作成し、formError()を呼び出します。
function formError()($( "#contactForm")。removeClass()。addClass( "shakeアニメーション").one( "webkitAnimationEndmozAnimationEnd MSAnimationEnd oanimationend Animationend"、function()($(this).removeClass();)) ;)
この関数は、animate.cssデモページで説明されているアプローチを使用します。これにより、要素にアニメーションを追加して、それを再度呼び出すことができます。
CSSアニメーションには厄介な癖があります。クラスを削除して再度追加しても、再生できません。 この機能は、アニメーションの終了クラスをリセットするのに役立ち、それらを再度追加できるようにします。 ユーザーがすべてのAJAX連絡フォームフィールドに入力せずに[送信]ボタンをクリックすると、シェイクアニメーションが再生されます。 また、彼がすべてのフィールドに再度入力しない場合は、このアニメーションをもう一度再生する必要があります。
このformError()関数は、エラーを報告するために作成したsubmitMSG()関数の上で呼び出すことができます。 たとえば、次のようになります。
formError(); submitMSG(false、 "フォームに正しく入力しましたか?");
これで、ユーザーがすべてのフィールドに入力せずにフォームデータを送信しようとすると、データが揺れて、何かが間違っていることがわかります。
より多くの検証
クライアント側の検証は優れていますが、ブラウザでコードを編集することにより、すべてのユーザーがそれを無効にして、空のフィールドを含むフォームを送信できます。 サーバー側で検証サービスを作成する必要があります。
process.phpファイルを開き、必要な変更を加えて、すべてのフィールドが入力されていることを確認する必要があります。 エラーメッセージをキャッチするために使用する$errorMSG変数を作成し、追加の$_POSTチェックを有効にします。
このPHPコードは、データを適切な変数として設定する前に、空のAJAXフォームフィールドが存在するかどうかをチェックします( $_POSTのコードに設定されている既存の変数を置き換えます)。 フィールドが空の場合、クライアントに送り返す一般的なメッセージを設定します。
元のAJAX呼び出しに応答して、ブラウザーに表示されるエラーメッセージを送信する必要があります。 これを行うには、PHPコードの下部にある前に作成したifステートメントを編集します。
ifステートメントを使用して、$ errorMSG変数が空( "")であるかどうか、および$success変数に使用した組み込みのMail関数のステータスを確認します。 else句には、エラーが$successの失敗の結果であるかどうかを確認するための追加のチェックが含まれています。 はいの場合は、「 何かがうまくいかなかった:「。 それ以外の場合は、空のフィールドをチェックしたときにコンパイルされたメッセージを出力します。
そして最後のステップは、AJAXで新しいメッセージを受け入れ、それをフォームに表示することです。 次のようにscripts.jsファイルのAJAXオブジェクトを更新する必要があります。
$ .ajax((type: "POST"、url: "php / form-process.php"、data: "name =" + name + "&email =" + email + "&message =" + message、success:function( text)(if(text == "success")(formSuccess();)else(formError(); submitMSG(false、text);))));
text==successをチェックするelse条件を更新しました。 それ以外の場合は、シェイクアニメーションを適用するformError()関数を呼び出し、PHPから返されたテキストをsubmitMSG()関数に要求します。
結論
完全なコードを確認するには、Githubをチェックしてください。 今 PHPAJAXフィードバックフォームユーザーが入力しなかったフィールドに関する情報をユーザーに提供します。 ステータスとPHPから返されたメッセージに基づいてコンテキストメッセージを表示します。 また、フロントエンド検証をバイパスしようとしているユーザーのために、サーバー側検証の追加レイヤーを実装しました。
この記事を楽しんでいただけたでしょうか。 コメントに質問やフィードバックを残してください。
この出版物は記事の翻訳です" PHPとAJAXを使用したブートストラップお問い合わせフォームの作成»フレンドリーなプロジェクトチームが作成
これは、インターネットを介して商品やサービスの支払いを行うための手頃で安全な方法です。 このシステムのプロセッサをオンラインストアに追加して、遅滞なく支払いを受け入れます。
更新されたYandex.Money3.0プロトコルでは、さまざまな支払いタイプを使用できます。
- 実際 ヤンデックスマネー;
- 銀行カード;
- ターミナルを介した支払い。
- モバイル決済。
1C-Bitrixプラットフォームのオンラインストアで新しいYandex.Moneyプロトコルを接続するには、新しい支払いシステムを作成し、プロセッサを選択する必要があります
サイトがhttpsプロトコルで応答しているかどうかを確認します。 これは、Yandex.Money3.0プロトコルで支払いを受け入れるための前提条件です。
自己署名SSL証明書、またはすべてがすでに構成されている仮想マシンを使用できます。
次に、 CPPでのストアID, CPPのショーウィンドウ番号、契約締結時にYandexから受け取る必要があります。 ショップパスワード(shopPassword) Yandexのストアプロファイルから。
返済の種類ごとに、独自のハンドラーを作成し、必要な支払いの種類を選択する必要があります。
支払いをテストするには、フィールドに値「Y」を入力する必要があります テストモード。 Yandex.Money 3.0プロトコルに接続するためのアプリケーションを送信すると、特別なリンクが届きます。このリンクを使用して、テスト用のウォレットの残高を1000ルーブルで補充できます。
オンラインストアモジュールの設定で、支払いの成功またはエラーに関するメッセージを含むページへのパスを再定義できます。
すべての。 設定完了です。ご利用ください
以前のバージョンのYandex.Money(1.6)に接続しているお客様は、バージョン3.0にアップグレードする必要はありません。 それらの。 どちらのバージョンも、Yandex.Moneyと1C-Bitrix:SiteManagementの両方でサポートされています。 ただし、バージョン1.6には、Yandex.Money以外の支払いを使用する機能は追加されていません。 この支払いシステムの新しいクライアントは、プロトコル3.0を介して接続されます。
商品配送中 1C-Bitrix:サイト管理 Yandex.Moneyハンドラー(3.0)は、オンラインストア(販売)モジュールのバージョン14.0.0でリリースされます。 このアップデートのリリース前(月末にアルファ版でリリースされると想定しています)、テクニカルサポートを通じてハンドラーをリクエストできます。
基本機能に加えて、次の機能を追加する必要があります。- ユーザーは、メッセージで次のHTMLタグを使用できます。
- タグを閉じるためのチェックが必要です。コードは有効なXHTMLである必要があります
ゲストブック。 JavaScriptとAJAX
基本機能に加えて、次の機能を追加する必要があります。- サーバー側とクライアント側での入力データの検証
- ページをリロードせずにメッセージをプレビューして追加する機能
- HTMLタグの場合、ボタン(、、、、、)でパネルを作成します
- 視覚効果の追加も大歓迎です。
要件
システムは、次の構成のLinuxOSで正しく動作するはずです。
- PHP 5.1+
- MySQL 4.1+
- Apache 2.2+
- PHPZendFrameworkまたはPEAR
- JSjQueryまたはプロトタイプ
P.S.写真はスターリングエンジンを示しています、ウィキペディアはしばしば思考の糧を与えます...
upd:非常に正しいコメントが私のブログに表示されました:
人々、あなたはどうやらこのタスクが誰のために設計されているのか理解していません。 自然に経験のある人は、2つの理由でそれをしません:a)彼は時間を無駄にしたくない、そしてb)彼はそれを与えられないでしょう。しかし現実には、これは一般的に、ジュニアphp開発者のポジションを申請する人の最初の多かれ少なかれ膨大なタスクであることがよくあります。
したがって、80時間は、彼が単にこのタスクを実行するためではなく、php、html、css、js、ajax、mysqlの反対側の履歴書のチェックマークに沿って現実(彼の知識)をもたらすために与えられます。
その結果、スキルと学習能力の両方、およびグーグル能力の特定の不可欠な指標が得られます。
実際にこのタスクに対処します。
そして、何かを見せたいと思っている候補者は、自然にプロジェクトに直接行きます。
タグ:タグを追加
現代のウェブの時代では、ほとんどのサイトはますますインタラクティブになっています。 以前は、更新されたデータを受信するためにページ全体を更新する必要がありましたが、現在では、ページを完全にロードせず、ページの一部のみをロードできるテクノロジーが登場しています。 これにより、ユーザーとサーバー所有者の両方に利便性が提供されます。これは、ページの個別の部分のみが読み込まれるため、ユーザーにとってページの読み込みが高速になり、サーバーが毎回ページを生成して提供する必要がないためです。ユーザーに。 これらの機能は、phpとajaxを使用して簡単に実装できます。
今日は、概念がどのように機能するかをよりよく理解するために、小さな例を分析します。 AJAX。 初心者がphpとajaxがどのように相互作用するかを理解するのが難しい場合があります。多くの人は、ページ全体をリロードせずにフォームをその場で検証する方法の例を探しています。 これがどのように行われるかを簡単に説明し、将来他のツールをすばやく習得して独自のスクリプトを作成できるようにする基本と原則を理解できるようにします。
自分たちで小さなタスクを考えてみましょう。phpとajaxを使用してページをリロードせずに、データベース内の電子メールアドレスの存在を確認します。 このような例は、ブラウザでページをリロードせずにサーバーと対話する方法をよく示しています。また、これはさまざまな種類のユーザーフォームの検証でよく使用されます。 index.php、email.php、validate.jsという名前のルートディレクトリに3つのファイルを作成しましょう。
ページの作成
メールを入力するためのフィールドが1つしかない1つのフォームで簡単なページを作成しましょう。
index.phpファイルの構文
作業する最も簡単な方法 AJAXフレームワークを接続することです jQueryそれはまさに私がしたことです。 jQuery送信するための理解しやすく作業しやすい構文を提供します AJAXリクエスト、これを利用してみませんか?
jsスクリプトの作成
validate.jsファイルの構文
$(document).ready(function()(var email = ""; $( "#email")。keyup(function()(var value = $(this).val(); $ .ajax((type: "POST"、url: "email.php"、data: "email =" + value、success:function(msg)(if(msg == "valid")($( "#message")。html( " このメールをご利用いただけます。このメールはすでに届いています。");)))));)); $("#submit ")。click(function()(if(email ==" ")(alert("データをすべてのメールに入れてください ");)else( $ .ajax((type: "POST"、url: "email.php"、data: "add_email =" + email、success:function(msg)($( "#message")。html(msg);)) );))));));
phpハンドラー
このスクリプトは 役職クライアントからの要求を処理し、結果を返します。 AJAX結果を読み取り、それに基づいて決定を下します。
email.phpファイルの構文
$ connection = mysqli_connect( "localhost"、 "email"、 "email"、 "email"); if(isset($ _ POST ["email"])&& $ _POST ["email"]!= "")($ email = $ _POST ["email"]; $ email = mysqli_real_escape_string($ connection、$ email); if (!filter_var($ email、FILTER_VALIDATE_EMAIL))(echo "invalid";)else($ sql = "SELECT id FROM email WHERE email =" $ email ""; $ result = mysqli_query($ connection、$ sql); if( mysqli_num_rows($ result)== 1)(echo "invalid";)else(echo "valid";)))if(isset($ _ POST ["add_email"])&& $ _POST ["add_email"]!= "" )($ email = mysqli_real_escape_string($ connection、$ _ POST ["add_email"]); $ sql = "INSERT INTO email(email)VALUES(" $ email ")"; if(mysqli_query($ connection、$ sql))(エコー 成功";)else(echo" エラー"; } }
私たちのphpスクリプトでは、POSTリクエストを処理し、ページに特定のテキストを出力する最も一般的なコードです。 結果として AJAXリクエストをphpスクリプトに送信すると、スクリプトはそれを処理して結果を返します。 AJAX結果を読み取り、リアルタイムでページを変更します。
AJAXは、次のコードを使用してPOSTリクエストをスクリプトに渡します。
$ .ajax((type: "POST"、url: "email.php"、data: "email =" + value、success:function(msg)(if(msg == "valid")($( "#message ").html(" このメールをご利用いただけます。"); email = value;)else($("#message ")。html(" このメールはすでに届いています。"); } } });
type-リクエストタイプ、POSTまたはGET。 私たちの場合はPOST;
url-リクエストの送信先のスクリプトのアドレス。
data-リクエストで送信されるデータ。
成功-リクエストが成功した結果として何をすべきか。 この場合、関数が呼び出されます。
スクリプト自体では、データベース内の電子メールの存在のチェックは、電子メールフィールドに文字が入力されるたびに実行されます。 スクリプトでは、セクション$( "#email")。keyup(function()());が入力の処理を担当します。 、id="email"のフィールドでキーが押されているかどうかをチェックします。
ご覧のとおり、コードは非常に単純で、理解するのに特に優れたスキルは必要ありません。すべてがイベントの処理に関連付けられていますkeyup()-キーを押し、クリック()-要素上でマウスをクリックします。 に続く AJAXスクリプトからの要求と応答。 したがって、phpとajaxを使用すると、インタラクティブなページを作成するためのほぼ無制限の可能性を得ることができます。
このコードは高品質のふりをしていませんが、開発する場合は、クライアントおよびサーバーレベルで正しい検証を追加し、cssと入力すると、プロジェクトで使用できます。
ご不明な点がございましたら、お気軽にコメントをお寄せください。
良い一日をお祈りします。またお会いしましょう🙂