インクルードとして排他的に使用するphpファイルがあります。したがって、URLを含める代わりにURLを入力して直接アクセスすると、エラーを実行する代わりにエラーをスローしたいと思います。
基本的には、phpファイルで次のようにチェックする必要があります。
if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");
これを行う簡単な方法はありますか?
一般的な「Apacheサーバーで実行されているPHPアプリを完全に制御できる場合とできない場合」の状況の最も簡単な方法は、インクルードをディレクトリに配置し、.htaccessファイルでそのディレクトリへのアクセスを拒否することです。 Apacheを使用している場合、人々にグーグルの問題を防ぐために、アクセスしたくないディレクトリの「.htaccess」というファイルにこれを配置します。
Deny from all
実際にサーバーを完全に制御できる場合(この答えを最初に書いたときよりも小さなアプリでも最近ではより一般的です)、最善の方法は、保護するファイルをWebサーバーが提供しているディレクトリの外側に固定することです。したがって、アプリが/srv/YourApp/
にある場合は、/srv/YourApp/app/
からファイルを提供するようにサーバーを設定し、/srv/YourApp/includes
にインクルードを配置します。したがって、文字通りそれらにアクセスできるURLはありません。
含めるだけにするページにこれを追加します
<?php
if(!defined('MyConst')) {
die('Direct access not permitted');
}
?>
それを含むページに追加します
<?php
define('MyConst', TRUE);
?>
ファイルが含まれているときと直接アクセスされているとき(主にprint()
対return()
)に異なる動作をする必要があるファイルがあります。変更されたコードを次に示します。
if(count(get_included_files()) ==1) exit("Direct access not permitted.");
アクセスされるファイルは常にインクルードファイルであるため、== 1です。
ファイルへの直接アクセスを防ぐ最善の方法は、ファイルをWebサーバーのドキュメントルートの外側(通常は1レベル上)に配置することです。それらを含めることはできますが、httpリクエストを介してアクセスする可能性はありません。
私は通常、すべてのPHPファイルをドキュメントルートの外に bootstrap file -ルーティングを開始するドキュメントルートの唯一のindex.phpを除いて配置します。ウェブサイト/アプリケーション全体。
Chuckのソリューションの代替(または補完)は、特定のパターンに一致するファイルへのアクセスを.htaccessファイルに入れて拒否することです。
<FilesMatch "\.(inc)$">
Order deny,allow
Deny from all
</FilesMatch>
if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
exit('Restricted Access');
}
Logic:PHPは、最小インクルードカウントが満たされない場合に終了します。 PHP5より前は、ベースページはインクルードと見なされないことに注意してください。
// In the base page (directly accessed):
define('_DEFVAR', 1);
// In the include files (where direct access isn't permitted):
defined('_DEFVAR') or exit('Restricted Access');
Logic:定数が定義されていない場合、実行はベースページから開始されず、PHPは停止します実行中。
// Call the include from the base page(directly accessed):
$includeData = file_get_contents("http://127.0.0.1/component.php?auth=token");
// In the include files (where direct access isn't permitted):
$src = $_SERVER['REMOTE_ADDR']; // Get the source address
$auth = authoriseIP($src); // Authorisation algorithm
if( !$auth ) exit('Restricted Access');
このメソッドの欠点は、内部リクエストでセッショントークンが提供されない限り、実行が分離されることです。単一サーバー構成の場合はループバックアドレス、またはマルチサーバーまたは負荷分散サーバーインフラストラクチャのアドレスホワイトリストを使用して確認します。
前の方法と同様に、GETまたはPOSTを使用して、インクルードファイルに認証トークンを渡すことができます。
if($key!="serv97602"){header("Location: ".$Dart);exit();}
非常に厄介な方法ですが、適切な方法で使用すると、同時に最も安全で汎用性が高くなります。
ほとんどのサーバーでは、個々のファイルまたはディレクトリにアクセス許可を割り当てることができます。すべてのインクルードをこのような制限されたディレクトリに配置し、それらを拒否するようにサーバーを構成できます。
たとえば、Apacheでは、構成は.htaccess
ファイルに保存されます。チュートリアル ここ 。
注ただし、サーバー固有の構成は推奨されませんそれらは異なるWebサーバー間での移植性が悪い。拒否アルゴリズムが複雑な場合、または拒否されたディレクトリのリストがかなり大きい場合、再構成セッションがかなり厄介になるだけです。最後に、コードでこれを処理するのが最善です。
サーバー環境でのアクセス制限のために最も好ましくありませんが、ファイルシステムにアクセスできる場合はかなり強力な方法です。
//Your secure dir path based on server file-system
$secure_dir=dirname($_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR."secure".DIRECTORY_SEPARATOR;
include($secure_dir."securepage.php");
論理:
htdocs
フォルダー外のファイルを要求できません。私の正統でないコーディング規約を許してください。フィードバックは大歓迎です。
実際、私のアドバイスは、これらのベストプラクティスをすべて実行することです。
if (!defined(INCL_FILE_FOO)) {
header('HTTP/1.0 403 Forbidden');
exit;
}
このようにして、ファイルが何らかの方法で誤配置された場合(誤ったftp操作)、ファイルは保護されます。
私は一度この問題を抱えていて、解決しました:
if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...
しかし、理想的な解決策は、別のanwserで述べられているように、Webサーバーのドキュメントルートの外部にファイルを配置することです。
1つの入り口でアプリケーションをビルドする方がよいでしょう。つまり、すべてのファイルはindex.phpから到達する必要があります。
これをindex.phpに配置します
define(A,true);
このチェックは、リンクされた各ファイルで実行する必要があります(requireまたはinclude経由)
defined('A') or die(header('HTTP/1.0 403 Forbidden'));
debug_backtrace() || die ("Direct access not permitted");
PHPファイルへのアクセスを直接制限したかったのですが、jQuery $.ajax (XMLHttpRequest)
経由で呼び出すこともできました。ここに私のために働いたものがあります。
if (empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] != "XMLHttpRequest") {
if (realpath($_SERVER["SCRIPT_FILENAME"]) == __FILE__) { // direct access denied
header("Location: /403");
exit;
}
}
何Joomla!ルートファイルで定数を定義し、インクルードファイルで同じものが定義されているかどうかを確認します。
defined('_JEXEC') or die('Restricted access');
または
codeIgniterのようなほとんどのフレームワークが推奨するように、webrootディレクトリの外部に配置することにより、すべてのファイルをhttpリクエストの範囲外に保つことができます。
または、インクルードフォルダー内に.htaccessファイルを配置してルールを記述することで、直接アクセスを防ぐことができます。
最も簡単な方法は、インクルードを呼び出すファイルに次のような変数を設定することです。
$including = true;
次に、含まれているファイルで、変数を確認します
if (!$including) exit("direct access not permitted");
.htaccess以外にも、さまざまなフレームワーク、たとえばRuby on Railsで有用なパターンを見てきました。アプリケーションのルートディレクトリに個別のpub /ディレクトリがあり、ライブラリディレクトリは次のディレクトリにあります。 同じレベル pub /として。このようなもの(理想的ではありませんが、アイデアは得られます):
app/
|
+--pub/
|
+--lib/
|
+--conf/
|
+--models/
|
+--views/
|
+--controllers/
文書ルートとしてpub /を使用するようにWebサーバーをセットアップします。これにより、スクリプトの保護が強化されます。ドキュメントルートから必要なコンポーネントをロードするためにアクセスすることはできますが、インターネットからコンポーネントにアクセスすることはできません。セキュリティ以外のもう1つの利点は、すべてが1か所にあることです。
「アクセスが許可されていない」というメッセージは攻撃者の手がかりであり、ホワイトリストベースではないため、.htaccess設定よりも優れているため、このセットアップは、含まれるすべてのファイルにチェックを作成するよりも優れています。 lib /、conf /などのディレクトリには表示されません。
より正確な場合、この条件を使用する必要があります。
if (array_search(__FILE__, get_included_files()) === 0) {
echo 'direct access';
}
else {
echo 'included';
}
get_included_files() は、すべてのインクルードファイルの名前を含むインデックス付き配列を返します(ファイルが実行された場合、ファイルはインクルードされ、その名前は配列内にあります)。そのため、ファイルに直接アクセスすると、その名前が配列の最初になり、配列内の他のすべてのファイルが含まれます。
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>
含まれているphpファイルの上部に上記のコードを配置します。
例:
<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
// do something
?>
Flatnux CMSでは次のコードが使用されます( http://flatnux.altervista.org ):
if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
header("Location: ../../index.php");
die("...");
}
私の答えはアプローチが多少異なりますが、ここで提供される答えの多くが含まれています。多面的なアプローチをお勧めします。
defined('_SOMECONSTANT') or die('Hackers! Be gone!');
ただしdefined or die
アプローチには多くの失敗があります。第一に、テストとデバッグの前提が本当に痛いです。第二に、それはあなたがあなたの心を変えた場合、恐ろしく、気が遠くなるほど退屈なリファクタリングを伴います。 「検索して交換!」あなたは言う。はい、しかし、どこでもまったく同じように書かれていると確信していますか?それを何千ものファイルで乗算します... o.O
そして、.htaccessがあります。管理者がそれほど綿密でないサイトにコードを配布するとどうなりますか?ファイルを保護するために.htaccessのみに依存している場合は、a)バックアップ、b)涙を乾かすためのティッシュの箱、c)人々からのすべてのヘイトメールの炎を消すための消火器も必要になりますコードを使用します。
だから私は質問が「最も簡単な」を求めていることを知っていますが、これが求めるのはより「防御的なコーディング」だと思います。
私が提案するのは:
require('ifyoulieyougonnadie.php');
(notinclude()
およびdefined or die
の代わりとして)ifyoulieyougonnadie.php
で、いくつかのロジックを実行します-異なる定数の確認、スクリプトの呼び出し、localhostテストなど-そして、die(), throw new Exception, 403
などを実装します。
メインのindex.php(Joomlaフレームワーク)とajaxrouter.php(私のフレームワーク)の2つの可能なエントリポイントを使用して独自のフレームワークを作成しているため、エントリポイントに応じて、さまざまなことを確認します。 ifyoulieyougonnadie.php
へのリクエストがこれらの2つのファイルのいずれかから来ていない場合、シェナンガンが行われていることがわかります!
しかし、新しいエントリポイントを追加するとどうなりますか?心配ない。 ifyoulieyougonnadie.php
を変更するだけで、並べ替えられますが、「検索と置換」はありません。やった!
同じ定数defined()
を持たない別のフレームワークを実行するためにスクリプトの一部を移動することにした場合はどうなりますか? ...やれやれ! ^ _ ^
この戦略により、開発がより楽しくなり、より少なくなります。
/**
* Hmmm... why is my netbeans debugger only showing a blank white page
* for this script (that is being tested outside the framework)?
* Later... I just don't understand why my code is not working...
* Much later... There are no error messages or anything!
* Why is it not working!?!
* I HATE PHP!!!
*
* Scroll back to the top of my 100s of lines of code...
* U_U
*
* Sorry PHP. I didn't mean what I said. I was just upset.
*/
// defined('_JEXEC') or die();
class perfectlyWorkingCode {}
perfectlyWorkingCode::nowDoingStuffBecauseIRememberedToCommentOutTheDie();
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
仕事をスムーズにします
PhpMyAdminスタイルを使用できます。
/**
* block attempts to directly run this script
*/
if (getcwd() == dirname(__FILE__)) {
die('Attack stopped');
}
<?php
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
if (false !== strpos($url,'.php')) {
die ("Direct access not premitted");
}
?>
これは、GoogleがPHPの例で使用するものです こちらを参照
if (php_sapi_name() != 'cli') {
throw new \Exception('This application must be run on the command line.');
}
インクルードファイルをWebでアクセス可能なディレクトリの外に保存することは何度か言及されており、可能な限り確かに良い戦略です。ただし、まだ言及していない別のオプション:インクルードファイルを確認してください実行可能なコードを含めないでください。インクルードファイルが関数とクラスを定義するだけで、それ以外のコードがない場合は、直接アクセスすると空白ページが生成されます。
ブラウザからこのファイルへの直接アクセスを許可します:it 何もしません。それはいくつかの関数を定義しますが、それらのどれも呼び出されないので、それらのどれも実行されません。
<?php
function a() {
// function body
}
function b() {
// function body
}
同じことがPHPクラスのみを含むファイルにも当てはまり、それ以外は何もありません。
可能な場合は、ファイルをウェブディレクトリ外に保管することをお勧めします。
system
というページを使用できないCMSを使用しています。これは、コードに使用されるパスと競合するためです。これは迷惑です。また、できることは、ディレクトリをパスワードで保護し、そこにすべてのphpスクリプトを保持することです。もちろん、index.phpファイルを除きます。これは、httpアクセスにのみ必要となるため、インクルードパスワードは必要ありません。また、そのディレクトリにアクセスするためのパスワードがあるため、必要に応じてスクリプトにアクセスするオプションも提供します。ディレクトリの.htaccessファイルと、ユーザーを認証するための.htpasswdファイルをセットアップする必要があります。
また、cPanelなどを介していつでもアクセスできるため、通常これらのファイルにアクセスする必要がないと感じた場合は、上記のソリューションを使用することもできます。
お役に立てれば
次のようなことをしてください:
<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
header('HTTP/1.0 403 Forbidden');
exit('Forbidden');
}
?>
ユーザーがアクセスできるようにする可能性のあるフォルダ内の他のコンテンツをブロックする可能性があるため、.htaccessの提案はあまりよくありませんでした。これが私の解決策です。
$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
// direct access to file
}
セキュリティ上の理由から$_SERVER
を使用しないことをお勧めします。
別のファイルを含む最初のファイルで$root=true;
などの変数を使用できます。
そして含まれる2番目のファイルの先頭でisset($root)
を使用します。
以下のメソッドを使用できますが、偽造される可能性があるため、別のコード行を追加して、JavaScriptを使用してサーバーからのみリクエストを送信できるようにする場合を除き、欠陥があります。このコードをHTMLコードのBodyセクションに配置すると、エラーが表示されます。
<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>
他のHTMLコードをここに配置します
<? } ?>
このように終了すると、エラーの出力は常に本体セクション内に表示されます(必要に応じて)。
Httpとcliの両方で動作するこのphpのみで不変のソリューションを見つけました。
関数を定義する:
function forbidDirectAccess($file) {
$self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
(substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}
に直接アクセスしたくないファイルの関数を呼び出します:
forbidDirectAccess(__FILE__);
この質問に対する上記のソリューションのほとんどは、Cliモードでは機能しません。
最も簡単な方法は、インクルードをWebディレクトリの外部に保存することです。そうすれば、サーバーはそれらにアクセスできますが、外部のマシンにはアクセスできません。唯一の欠点は、サーバーのこの部分にアクセスできる必要があることです。利点は、セットアップ、構成、または追加のコード/サーバーストレスを必要としないことです。