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

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

ただいまの
回答率

90.10%

特定のPHPファイルへの直リンクを禁止する方法

受付中

回答 8

投稿

  • 評価
  • クリップ 3
  • VIEW 9,868

tarotarosu

score 109

前提・実現したいこと

notshow.phpというPHPファイルがあります。このファイルはリンク元がindex.htmlだった場合のみ表示され、かつ直リンクを禁止し、直リンクされた場合は専用のページにリダイレクトする、という処理を以下のコードをnotshow.phpの頭に記述することで実現してみました。

該当のソースコード

//notshow.phpへの直リンク禁止
if (empty($_SERVER["HTTP_REFERER"])) {
  //リダイレクト
  header('Location: リダイレクトさせたいページのURL');
}

挙動としては一応意図したとおりに動きました。しかし、このようにすることで直リンクを禁止したとしても、セキュリティ的に他に問題がないのか心配です。
(例えば、この場合ですとリンク元はどこからでもアクセス可能ですよね?(index.html以外にnotshow.phpへのリンクは載せていないので問題ないとは思っているのですが…))
何か危険な点がございましたらご指摘いただけると非常に助かります_(._.)_

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

+9

リファラーの偽装について補足させてください。偽装の可否は以下のようになります。

閲覧しようとしている当人: リファラーの偽装が可能
閲覧しようとする人は別人: リファラーの偽装は不可能

つまり、悪い人がサイトを作って、notshow.php への直リンクを貼ったとして、そのサイトを閲覧した人が自らリファラーを偽装することは可能ですが、そうするシチュエーションが思いつきません。通常は、サイトを閲覧する人はリファラーの偽装などしないでしょうから、正しいリファラーが送られてくるか、リファラーが送られてこないことは、ある程度想定してもよいでしょう。
一方、サイトを作った人が、直リンクの際に別のリファラーが送信されるようにHTMLを書くことはできません。このために、CSRF対策として、リファラーを使う方法が有効なのです。

「ある程度想定してもよい」と書きましたが、ここに絶対性を求めることはできません。前述のように、アセスする当人は偽装が可能だからです。したがって、直リンク禁止の目的が、「概ね禁止できればよい」なのか、「絶対に直リンクにてアクセスされると困る」かによって判断が変わってきます。たとえばサイトで用いている画像を他サイトから直接<img>タグで使われたくない…が、多少の直アクセスは許容可能という場合は、リファラーによる制御もあり得るということです。

加えて補足が2点あります。

まず、現在提示されている方法ですと、リファラーがない場合をエラーとしていますが、これは不適切です。「直リンク」の場合は、リンク元のURLがリファラーとして設定されるので、リファラーは空ではないからです。したがって、このようなチェックの場合は、リンクしてよいURLやドメイン名を基準とした、いわゆるホワイトリストチェックを書く必要があります。

また、別の方が指摘されているように、ブラウザの設定やプラグイン、セキュリティソフトなどにより、リファラーを常に送信しないように設定している人もいます。リファラーによるチェック処理を置くと、本当は直リンクでない正当なアクセスなのに、このチェックでエラーにされて閲覧できない人が出てきます。

したがって、リファラーによるチェックは、企業内システムなど閲覧する人のブラウザの設定等が想定できる場合のみ用いるとよいでしょう。

結論としては、リファラーによるチェツクはまったく無意味というわけではないものの、完全ではないことと、正当な利用者まで拒否してしまう場合があるので、あまり推奨されない、というのが結論です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+7

//notshow.phpへの直リンク禁止
if (empty($_SERVER["HTTP_REFERER"])) {
 //リダイレクト
 header('Location: リダイレクトさせたいページのURL');
}

このコードだと利用者の不便を生むだけではないでしょうか?直接そのURLにアクセスしたい場合があったときに困りませんか?(これは直リンクとは言わないと思います・・・直リンクは以下のように「他者のサイト内に存在する画像などを直接imgタグのsrc属性などで参照する行為」を指します)

<img src="http://example.com/img.png" alt="他サイトの画像">

既に回答で指摘されている通り,リファラは偽装可能な項目であって,セキュリティ対策的な意味は一切持ちません.無効化だけならrel="noreferrer"属性をつけるだけでできますし,ブラウザの拡張機能をインストールすれば偽装までできます.

【このコードを書いてもできること】
・noreferrer指定されていない他者サイトのaタグをクリックして飛んで来ること

【このコードのせいで出来なくなってしまうこと】
・WebブラウザのアドレスバーにURLを入力して直接アクセスすること

さて,このコードを書いた目的はなんでしょうか?もし「フォーム送信を繰り返して必要事項を順番に埋めていく」タイプのWebページであれば,セッション変数を使って状態を管理すべきです.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+4

直接リンクを禁止 = セキュリティ的に強固
の等式は成り立たないので、セキュリティ問題の有無に関して回答は出来ないですよ。
HTTP_REFERER の偽装も可能ですし。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+4

リファラーはあくまでクライアントが送ってくるものですので、いくらでも偽装できます(リファラーを変更可能なFirefox用の拡張機能すらあります)。「間違えてアクセスするのを防ぐ」程度の意味はあるかもしれませんが、セキュリティとしての効果はほぼ皆無です

逆に、セキュリティソフトウェアを使うことで、「リファラの送信を止める」ような状況もありえます。そうなると、正当なユーザーもアクセスできなくなります

アクセス制御として本格的に考えたいのなら、別な手法を使いましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

PHP: $_SERVER - Manual

'HTTP_REFERER'
現在のページに遷移する前にユーザーエージェントが参照していた ページのアドレス(もしあれば)。これはユーザーエージェントに よってセットされます。全てのユーザーエージェントが これをセットしているわけではなく、また、HTTP_REFERER を変更する機能を持つものもあります。 要するに、信頼するべきものではありません。

あんまり当てになりませんね。

とりあえず、まずはリファラーの内容が当該のサーバアドレスを含むかまでチェックは必要かと思います。
あと本気でやるならトークン発行してとか、結構大変だと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

考えてることをやりたいならリンク元のページでセッションを開始し適当なトークンを埋め込むようにして
notshow.phpにアクセスした時にそのトークンを保持していなかったらエラーページにリダイレクトする
という感じでやればいいんじゃないでしょうか
クロスサイトリクエストフォージェリ対策のような発想ですね
別にセッションでなくてもpostやgetで適切なトークンを投げたときだけリダイレクトしないという対応もできます

セキュリティ的にはリンク元にさえアクセスすればnotshow.phpにアクセスできる状態になりますからリンク元へのアクセスをどう制御してるかに依存します

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

別に直リン自体がなにか悪いことをしているわけじゃないので放置でよいでしょう
むしろセキュリティ的な話であればログインシステムを導入し
セッションでユーザーIDを確認するほうが重要になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

リファラーはブラウザのアドオンなど使用すれば変更可能な情報なので、
リファラーでの判定は完全なセキュリティ対策になりません。

notshow.phpへの遷移を、単純なaタグでの遷移ではなく、POST通信による遷移にしてあげると、
cakeやcodeigniterなどのフレームワークにはPOST通信の認証機能がついてますので、
フレームワークの機能を用いた認証ができます。

フレームワークの機能を用いるため、GET通信でのnotshow.phpへのアクセスも可能なはずなので、
notshow.phpにて、POSTパラメータの有無をチェックし、POSTパラメータが無ければ、
header('Location: リダイレクトさせたいページのURL');
へ遷移させる方法もあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる