@ssnepentheの回答は、あなたが使用しているフックが着信リクエストの中で何か正しいものではないと言っているのは正しいです。
リクエスト情報はPHPですぐに利用できるため、利用可能な最も古いフックを使用してそれらをチェックできます。リクエストAPIのコンテキストでこれを行う場合は、REST APIリクエストの最も早いフックを使用する必要があります。@ssnepenthe'rest_pre_dispatch'
によって提案された問題はありませんが、別のオプションが考えられますrest_authentication_errors
、何か問題が発生した場合にエラーを返すことができるられます。
しかし、ジャック・ヨハンソンは右であると言って、彼らは非常に簡単にクライアントによって変更されるHTTPヘッダー(@ ssnepentheのaswerで使用Refererヘッダなど)は、信頼できるではないこと。つまり、ドアの前に「入場しても安全ですか?」と尋ねる警備員を置くようなものです。行きたい人には:それはうまくいきません。
しかし、Jack Johanssonの回答(ノンス)が提案する解決策も実際の解決策ではありません。ノンスの要点は時間とともに変化することであり、パブリックAPIエンドポイントは時間に基づいて変化するものを持つことができません。さらに、WPナンスは、ログインしているユーザーがいる場合にのみ信頼できます。これは、パブリックAPIの場合とは異なり、ユーザーがログインしている場合、受信ドメインを確認する理由はおそらくありません。ユーザーではなくユーザーを信頼します。ユーザーマシン。
じゃあ何をすればいいの?
まあ、HTTPヘッダーが信頼できない場合でも、利用可能なすべての情報がヘッダーから得られるわけではありません$_SERVER
。
通常、$_SERVER
キーで始まるすべての値HTTP_
はヘッダーから取得され、安全でないユーザー入力として処理する必要があります。
しかし、例えば、$_SERVER['REMOTE_ADDR']
それがどの手段、サーバーへのTCP接続に使用するIPアドレスが含まれている信頼できる1。
つまり、次のいずれかです。
$_SERVER['REMOTE_HOST']
値を生成するようにサーバーを適切に構成する(たとえば、Apache では、HostnameLookups On
内部で必要になりますhttpd.conf
)その値
- に
gethostbyaddr
格納されているIPのドメイン名を解決するために逆DNSルックアップを実行するために使用$_SERVER['REMOTE_ADDR']
ホワイトリストに照らして確認するために使用できるホスト名を確実に取得できます(コードの場合、@ ssnepentheの質問に置き換え$referer = $request->get_header('referer')
て、コードをに置き換えます$referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
)。
しかし、問題があります。
Webサーバーがリバースプロキシの背後にある場合(実際には非常に一般的なソリューション)、WebサーバーへのTCP接続は実際にはプロキシによって行われるため$_SERVER['REMOTE_ADDR']
、最初に要求を送信したクライアントのIPではなく、プロキシのIPになります。
そのような場合の元のリクエストIPは通常として利用できますが$_SERVER['HTTP_X_FORWARDED_FOR']
、それ$_SERVER
で始まる値の1つであるHTTP_
ことは、実際には信頼できません。
したがって、ウェブサーバーがリバースプロキシ2の背後にある場合でも、$_SERVER['REMOTE_ADDR']
そのようなガードには役立ちません。ドメインベースのホワイトリストは、プロキシレベルでのみ実装できます。
つまり、APIエンドポイントのセキュリティ保護のための信頼できるソリューションは、実際の認証メカニズム(oAuthなど)を使用して実装するか、アプリケーションレベルではなくサーバー構成に直接作用して実行する必要があります。
ノート
1まあ、理論的には、誰かがあなたのISPをハッキングしたり、攻撃者があなたのLANの内側から行動したりすると、破壊される可能性があります。どちらの場合も、安全のためにできることはほとんどありません。
2リバースプロキシの背後にあるかどうかわからない場合は、ローカルPCからリクエストを送信$_SERVER['REMOTE_ADDR']
し、サーバー上でローカルPCのIPと$_SERVER['HTTP_X_FORWARDED_FOR']
一致するかどうか、また存在していてローカルPCのIPと一致するかどうかを確認できます。