Ngăn chặn truy cập trực tiếp vào một tập tin php bao gồm


166

Tôi có một tập tin php mà tôi sẽ sử dụng độc quyền như một phần bao gồm. Do đó, tôi muốn đưa ra một lỗi thay vì thực thi nó khi nó được truy cập trực tiếp bằng cách nhập URL thay vì được đưa vào.

Về cơ bản tôi cần thực hiện kiểm tra như sau trong tệp php:

if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");

Có cách nào làm dễ hơn không?


10
thay vì die () bạn nên kiểm tra tiêu đề '("Không tìm thấy tệp HTTP / 1.1 404", 404); lối ra;'. Điều này sẽ (ít nhất là trên apache) làm cho máy chủ trả về trang 404 bình thường.
gnud

Dưới đây là hai phương pháp dễ dàng mà tôi đã giải thích để vô hiệu hóa quyền truy cập trực tiếp vào các tệp được bao gồm trong PHP - mãpeedy.com/disable
Faruque Ahamed Mollick 18/07/17

Câu trả lời:


173

Cách dễ nhất cho tình huống "ứng dụng PHP chung chạy trên máy chủ Apache mà bạn có thể hoặc không thể kiểm soát hoàn toàn" là đưa tài liệu của bạn vào một thư mục và từ chối truy cập vào thư mục đó trong tệp .htaccess của bạn. Để cứu mọi người những rắc rối của Google, nếu bạn đang sử dụng Apache, hãy đặt tệp này vào một tệp có tên ".htaccess" trong thư mục mà bạn không muốn truy cập:

Deny from all

Nếu bạn thực sự có toàn quyền kiểm soát máy chủ (ngày nay phổ biến hơn đối với các ứng dụng nhỏ so với khi tôi mới viết câu trả lời này), cách tiếp cận tốt nhất là dán các tệp bạn muốn bảo vệ bên ngoài thư mục mà máy chủ web của bạn đang phục vụ . Vì vậy, nếu ứng dụng của bạn được /srv/YourApp/cài đặt, hãy đặt máy chủ để phân phát các tệp từ đó /srv/YourApp/app/và đưa bao gồm vào /srv/YourApp/includes, vì vậy theo nghĩa đen không có bất kỳ URL nào có thể truy cập chúng.


1
Cảm ơn, vì tôi có toàn quyền kiểm soát máy chủ nơi tôi chạy ứng dụng này, đây là câu trả lời tôi đã đi cùng.
Alterlife

24
Nếu bạn có toàn quyền kiểm soát máy chủ thì tốt hơn nếu bạn đặt cấu hình vào một thư mục chỉ thị vào tệp cấu hình máy chủ ảo. Apache chỉ đọc nó một lần khi khởi động, .htaccess được đọc trên mọi truy cập và làm chậm máy chủ
Eineki

22
Thật tuyệt khi có một tệp .htaccess như một phần của câu trả lời này.
Graham Lea

7
<Files ~ "\.inc$"> Order Allow,Deny Deny from All </Files>
Dracorat

11
@James: Ngoài ra, không phải ai cũng cảm thấy Stack Overflow phải là trang web "plz send teh codez". Nếu nó trả lời câu hỏi rõ ràng, thì đó là một câu trả lời tốt. Cung cấp một ví dụ không cần thiết chỉ khuyến khích mã hóa sao chép và dán.
Chuck

188

Thêm phần này vào trang mà bạn muốn chỉ được đưa vào

<?php
if(!defined('MyConst')) {
   die('Direct access not permitted');
}
?>

sau đó trên các trang có thêm nó

<?php
define('MyConst', TRUE);
?>

3
Tôi thực sự cần phải học cách gõ nhanh hơn. Đây là cùng một cách tôi muốn đề xuất, vì nó an toàn hơn một phương thức sử dụng một biến để kiểm tra. Vì với một số thiết lập PHP, có thể ghi đè biến.
Mark Davidson

3
Đây là cách một vài ứng dụng 'chính thống' xử lý nó. Tôi biết Joomla làm theo cách này và tôi nghĩ Wiki, Wordpress và những người khác nữa.
UnkwnTech

1
Có thể thông báo này quá hữu ích cho một hacker (không có người dùng thực sự nào tìm thấy các trang này), bạn chỉ cần gửi tiêu đề chuyển hướng và dừng xử lý php.
bandi

7
Chỉ cần gửi tiêu đề 404 và thoát - trang lỗi sẽ trông giống hệt các trang 404 thông thường (ít nhất là trên Apache).
gnud

4
@ Smile.Hunter: đây là về việc chặn truy cập để xem trực tiếp các tệp tập lệnh / thư viện của bạn, câu trả lời hoạt động. Nếu họ đã tạo somefile.phptrên máy chủ của bạn và thêm định nghĩa của bạn vào đó, điều đó vẫn không cho phép họ truy cập trực tiếp vào tệp đính kèm. Nó sẽ cho phép họ "bao gồm" các tệp thư viện của bạn, nhưng nếu họ đủ xa để tạo tệp trên máy chủ của bạn và biết các tập lệnh xác định / bao gồm của bạn, bạn có các vấn đề khác có thể phủ nhận việc ghi tệp của riêng họ với định nghĩa của bạn ở vị trí đầu tiên .
James

114

Tôi có một tệp mà tôi cần phải hành động khác khi nó được bao gồm so với khi nó được truy cập trực tiếp (chủ yếu là một print() so với return()) Đây là một số mã được sửa đổi:

if(count(get_included_files()) ==1) exit("Direct access not permitted.");

Tệp đang được truy cập luôn là một tệp được bao gồm, do đó == 1.  


12
Đó thực sự là một địa ngục của một ý tưởng, kiểm tra số lượng tập tin bao gồm. Tôi tự hỏi cái nào tốt hơn: sử dụng định nghĩa, hoặc sử dụng phương pháp này? Điều này có vẻ khép kín hơn.
Akoi Meexx

Lần đầu tiên tôi từng thấy bất cứ ai nghĩ ra điều này. Mặc dù vậy, tôi không biết tại sao, bởi vì nó dường như khép kín như có thể, và nó trực tiếp đo lường những gì bạn thực sự muốn biết (nếu được bao gồm hay không) thay vì đo lường một cái gì đó được cho là có liên quan (như một hằng số nhất định hoặc một vị trí nhất định bị cấm bởi .htaccess). Xinh đẹp.
Jimbo Jonny

Điều này thực sự thú vị bởi vì sử dụng .htaccess để chặn tất cả các tệp .php có thể không thể thực hiện được vì có thể có một số tệp trong cùng thư mục cần được gọi trực tiếp hoặc thậm chí bằng javascripts. Cảm ơn ý tưởng tuyệt vời này!
Anuj

3
Điều này chỉ hoạt động trong PHP5 trở lên. Pre-PHP5 bạn muốn so sánh lại 0 thay vì 1.
jmucchiello

Đây là một giải pháp thực sự thông minh và cho phép bạn kiểm soát truy cập trực tiếp, không chỉ chặn nó - đó là điều tôi thích. Tôi thường bao gồm kiểm thử đơn vị trong các tệp và theo cách này tôi có thể bao bọc kiểm thử đơn vị của mình trong câu lệnh if này. Tự hỏi nó hiệu quả đến mức nào ..
whiteatom

34

Cách tốt nhất để ngăn chặn truy cập trực tiếp vào các tệp là đặt chúng bên ngoài thư mục gốc của tài liệu máy chủ web (thường là một cấp ở trên). Bạn vẫn có thể bao gồm chúng, nhưng không có khả năng ai đó truy cập chúng thông qua yêu cầu http.

Tôi thường tìm mọi cách và đặt tất cả các tệp PHP của mình bên ngoài gốc tài liệu ngoài tệp bootstrap - một tệp index.php đơn độc trong thư mục gốc bắt đầu định tuyến toàn bộ trang web / ứng dụng.


3
Đây là một giải pháp tuyệt vời nếu bạn có thể làm như vậy. Gần đây tôi chỉ phải bắt đầu làm việc với các webhost được chia sẻ và phát hiện ra một trong nhiều điều khó chịu là mọi thứ phải nằm trong docroot.
Beau Simensen

3
Trong mọi nhà cung cấp dịch vụ lưu trữ tôi làm việc với tôi luôn có quyền truy cập (chính xác) một cấp trên gốc tài liệu.
Eran Galperin

3
Tại một số máy chủ (bao gồm cả máy chủ hiện tại của tôi), bạn có thể trỏ tên miền của mình vào bất kỳ thư mục nào bạn muốn.
Dinah

1
Đây cũng là một cách thay thế tốt .. sử dụng preg_match -> if (preg_match ("~ continalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {die ('<h3 style = "color: red"> Cảnh báo bảo mật thiết bị - Truy cập trực tiếp không được phép! IP của bạn đã được ghi lại! <H3> '); // Dừng thực thi thêm}
MarcoZen

Url devzone.zend.com/node/view/id/70 đó là 404 ngay bây giờ. Câu trả lời phải bao gồm mã ban đầu được sử dụng từ url không tồn tại đó.
Funk Bốn mươi Niner

31

1: Kiểm tra số lượng tập tin bao gồm

if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
    exit('Restricted Access');
}

Logic: PHP thoát nếu số lượng tối thiểu bao gồm không được đáp ứng. Lưu ý rằng trước PHP5, trang cơ sở không được coi là bao gồm.


2: Xác định và xác minh hằng số toàn cầu

// 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: Nếu hằng số không được xác định, thì việc thực thi đã không bắt đầu từ trang cơ sở và PHP sẽ ngừng thực thi.

Lưu ý rằng vì mục đích di động qua các nâng cấp và thay đổi trong tương lai, làm cho phương thức xác thực này được mô đun hóa sẽ giảm đáng kể chi phí mã hóa vì các thay đổi sẽ không cần phải được mã hóa cứng cho mỗi tệp.

// Put the code in a separate file instead, say 'checkdefined.php':
defined('_DEFVAR') or exit('Restricted Access');

// Replace the same code in the include files with:
require_once('checkdefined.php');

Bằng cách này, mã bổ sung có thể được thêm vào checkdefined.php cho mục đích ghi nhật ký và phân tích, cũng như để tạo phản hồi thích hợp.

Tín dụng khi tín dụng đáo hạn: Ý tưởng tuyệt vời về tính di động xuất phát từ câu trả lời này .


3: Ủy quyền địa chỉ từ xa

// 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');

Hạn chế với phương thức này là thực thi độc lập, trừ khi mã thông báo phiên được cung cấp với yêu cầu nội bộ. Xác minh thông qua địa chỉ vòng lặp ngược trong trường hợp cấu hình máy chủ đơn hoặc danh sách trắng địa chỉ cho cơ sở hạ tầng máy chủ đa máy chủ hoặc cân bằng tải.


4: Ủy quyền mã thông báo

Tương tự như phương pháp trước đó, người ta có thể sử dụng GET hoặc POST để chuyển mã thông báo ủy quyền cho tệp bao gồm:

if($key!="serv97602"){header("Location: ".$dart);exit();}

Một phương pháp rất lộn xộn, nhưng có lẽ cũng an toàn và linh hoạt nhất cùng một lúc, khi được sử dụng đúng cách.


5: Cấu hình máy chủ web cụ thể

Hầu hết các máy chủ cho phép bạn gán quyền cho các tệp hoặc thư mục riêng lẻ. Bạn có thể đặt tất cả bao gồm trong các thư mục bị hạn chế như vậy và để máy chủ được cấu hình để từ chối chúng.

Ví dụ trong APACHE, cấu hình được lưu trữ trong .htaccesstệp. Hướng dẫn tại đây .

Tuy nhiên, xin lưu ý rằng các cấu hình dành riêng cho máy chủ không được tôi khuyên dùng vì chúng không tốt cho tính di động trên các máy chủ web khác nhau. Trong các trường hợp như Hệ thống quản lý nội dung có thuật toán từ chối phức tạp hoặc danh sách các thư mục bị từ chối khá lớn, nó chỉ có thể thực hiện các phiên cấu hình lại khá khủng khiếp. Cuối cùng, tốt nhất là xử lý mã này.


6: Đặt bao gồm trong một thư mục an toàn NGOÀI TRỜI gốc trang web

Ít thích nhất vì giới hạn truy cập trong môi trường máy chủ, nhưng là một phương pháp khá mạnh nếu bạn có quyền truy cập vào hệ thống tệp.

//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");

Hợp lý:

  • Người dùng không thể yêu cầu bất kỳ tập tin bên ngoài htdocs thư mục vì các liên kết sẽ nằm ngoài phạm vi của hệ thống địa chỉ của trang web.
  • Máy chủ php truy cập hệ thống tệp nguyên bản và do đó có thể truy cập các tệp trên máy tính giống như cách một chương trình bình thường với các đặc quyền bắt buộc có thể.
  • Bằng cách đặt các tệp đính kèm trong thư mục này, bạn có thể đảm bảo rằng máy chủ php có thể truy cập chúng, trong khi liên kết nóng bị từ chối cho người dùng.
  • Ngay cả khi cấu hình truy cập hệ thống tệp của máy chủ web không được thực hiện đúng cách, phương pháp này sẽ ngăn các tệp đó vô tình trở thành công khai.

Xin thứ lỗi cho các quy ước mã hóa không chính thống của tôi. Bất kỳ thông tin phản hồi được đánh giá cao.


tôi thích số 2
Baim Sai

26

Một giải pháp thay thế (hoặc bổ sung) cho giải pháp của Chuck sẽ là từ chối quyền truy cập vào các tệp khớp với một mẫu cụ thể bằng cách đặt một cái gì đó như thế này vào tệp .htaccess của bạn

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>

Tôi tin rằng sẽ tốt hơn khi sử dụng .inc.php Tôi tin và đó là một cách phổ biến
Lis

14

Thật ra lời khuyên của tôi là làm tất cả những thực hành tốt nhất này.

  • Đặt các tài liệu bên ngoài webroot HOẶC trong một thư mục bị máy chủ web từ chối truy cập VÀ
  • Sử dụng một định nghĩa trong các tài liệu hiển thị của bạn mà các tài liệu ẩn kiểm tra:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

Bằng cách này, nếu các tệp bị thất lạc bằng cách nào đó (một hoạt động ftp sai lầm) chúng vẫn được bảo vệ.


8

Tôi đã có vấn đề này một lần, giải quyết với:

if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

nhưng giải pháp lý tưởng là đặt tệp bên ngoài gốc tài liệu máy chủ web, như được đề cập trong một anwser khác.


7

Bạn nên xây dựng ứng dụng tốt hơn với một điểm truy cập, tức là tất cả các tệp phải được truy cập từ index.php

Đặt cái này trong index.php

define(A,true);

Kiểm tra này sẽ chạy trong mỗi tệp được liên kết (thông qua yêu cầu hoặc bao gồm)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));

7

Tôi muốn hạn chế quyền truy cập vào tệp PHP trực tiếp, nhưng cũng có thể gọi nó qua jQuery $.ajax (XMLHttpRequest). Đây là những gì làm việc cho tôi.

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;
    }
}

3

Cách dễ nhất là đặt một số biến trong tệp mà các cuộc gọi bao gồm, chẳng hạn như

$including = true;

Sau đó, trong tệp được bao gồm, kiểm tra biến

if (!$including) exit("direct access not permitted");

2
Điều này là nguy hiểm nếu register_globals được bật.
jmucchiello

25
PHP là nguy hiểm nếu register_globals được bật.
David Precious

3

Bên cạnh cách .htaccess, tôi đã thấy một mô hình hữu ích trong các khung khác nhau, ví dụ như trong ruby ​​trên đường ray. Họ có một thư mục pub / thư mục riêng trong thư mục gốc của ứng dụng và các thư mục thư viện đang sống trong các thư mục cùng cấp với pub /. Một cái gì đó như thế này (không lý tưởng, nhưng bạn có ý tưởng):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

Bạn thiết lập máy chủ web của mình để sử dụng pub / làm tài liệu gốc. Điều này cung cấp sự bảo vệ tốt hơn cho các tập lệnh của bạn: trong khi chúng có thể tiếp cận từ gốc tài liệu để tải các thành phần cần thiết thì không thể truy cập các thành phần từ internet. Một lợi ích khác bên cạnh an ninh là mọi thứ đều ở một nơi.

Thiết lập này tốt hơn là chỉ tạo séc trong mỗi tệp được bao gồm vì thông báo "không cho phép truy cập" là đầu mối cho kẻ tấn công và tốt hơn cấu hình .htaccess vì nó không dựa trên danh sách trắng: nếu bạn làm hỏng phần mở rộng tệp nó sẽ không hiển thị trong các thư mục lib /, conf / vv.


Sau một thời gian dài, tôi chỉ muốn nhận xét rằng mô hình mà bạn mô tả ở trên được gọi là mô hình MVC (Model - View - Controller). Nếu bạn vui lòng, hãy kiểm tra google và thêm một số thông tin vào câu trả lời của bạn. Ngoài ra MVC không chỉ hỗ trợ các ứng dụng Ruby on Rails và ASP.NET mà còn cả PHP (xem Lavarel, CakePHP).

3

Những gì Joomla! hiện đang xác định một Hằng trong tệp gốc và kiểm tra xem có được xác định tương tự trong các tệp được bao gồm không.

defined('_JEXEC') or die('Restricted access');

hoặc cái gì đó khác

người ta có thể giữ tất cả các tệp ngoài tầm với của yêu cầu http bằng cách đặt chúng bên ngoài thư mục webroot như hầu hết các khung như CodeIgniter khuyên dùng.

hoặc thậm chí bằng cách đặt tệp .htaccess trong thư mục bao gồm và quy tắc viết, bạn có thể ngăn truy cập trực tiếp.



3

Câu trả lời của tôi hơi khác nhau trong cách tiếp cận nhưng bao gồm nhiều câu trả lời được cung cấp ở đây. Tôi muốn giới thiệu một cách tiếp cận đa dạng:

  1. chắc chắn .htaccess và Apache hạn chế
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

TUY NHIÊN các defined or diephương pháp đều có một số nhược điểm. Thứ nhất, đó là một nỗi đau thực sự trong các giả định để kiểm tra và gỡ lỗi. Thứ hai, nó liên quan đến việc tái cấu trúc một cách khủng khiếp, nhàm chán nếu bạn thay đổi suy nghĩ. "Tìm và thay thế!" bạn nói. Vâng, nhưng làm thế nào chắc chắn rằng bạn được viết giống hệt nhau ở mọi nơi, hmmm? Bây giờ nhân lên với hàng ngàn tệp ... oO

Và sau đó .htaccess. Điều gì xảy ra nếu mã của bạn được phân phối trên các trang web mà quản trị viên không quá cẩn thận? Nếu bạn chỉ dựa vào .htaccess để bảo mật các tệp của mình, bạn cũng sẽ cần a) bản sao lưu, b) hộp khăn giấy để lau khô nước mắt, c) một bình chữa cháy để dập tắt ngọn lửa trong mọi người sử dụng mã của bạn.

Vì vậy, tôi biết câu hỏi yêu cầu "dễ nhất", nhưng tôi nghĩ điều này đòi hỏi nhiều hơn là "mã hóa phòng thủ".

Những gì tôi đề nghị là:

  1. Trước bất kỳ tập lệnh nào của bạn require('ifyoulieyougonnadie.php');( không phải include() và thay thế cho defined or die)
  2. Trong ifyoulieyougonnadie.php, thực hiện một số công cụ logic - kiểm tra các hằng số khác nhau, gọi tập lệnh, kiểm tra localhost và như vậy - và sau đó triển khai die(), throw new Exception, 403, v.v.

    Tôi đang tạo khung riêng của mình với hai điểm nhập có thể - index chính (khung Joomla) và ajaxrouter.php (khung của tôi) - vì vậy tùy thuộc vào điểm nhập, tôi kiểm tra các thứ khác nhau. Nếu yêu cầu ifyoulieyougonnadie.phpkhông đến từ một trong hai tệp đó, tôi biết các shenanigans đang được thực hiện!

    Nhưng nếu tôi thêm một điểm vào mới thì sao? Đừng lo lắng. Tôi chỉ thay đổi ifyoulieyougonnadie.phpvà tôi được sắp xếp, cộng với không 'tìm và thay thế'. Hoan hô!

    Điều gì xảy ra nếu tôi quyết định chuyển một số tập lệnh của mình sang một khung công tác khác không có cùng hằng số defined()? ... Hoan hô! ^ _ ^

Tôi thấy chiến lược này làm cho sự phát triển trở nên thú vị hơn và ít hơn rất nhiều:

/**
 * 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();

2

Nếu chính xác hơn, bạn nên sử dụng điều kiện này:

if (array_search(__FILE__, get_included_files()) === 0) {
    echo 'direct access';
}
else {
    echo 'included';
}

get_included_files () trả về mảng được lập chỉ mục chứa tên của tất cả các tệp được bao gồm (nếu tệp được thực thi thì nó được bao gồm và tên của nó nằm trong mảng). Vì vậy, khi tệp được truy cập trực tiếp, tên của nó là đầu tiên trong mảng, tất cả các tệp khác trong mảng được bao gồm.


1
<?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>");
}
?>

đặt mã ở trên vào đầu tập tin php bao gồm của bạn.

Ví dụ:

<?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
?>

if (preg_match ("~ continalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {die ('<h3 style = "color: red"> Cảnh báo bảo mật thiết bị - Truy cập trực tiếp không được phép! IP của bạn đã được ghi lại ! <h3> '); // Dừng thực thi thêm} whre ~ là dấu phân cách
MarcoZen

1

Đoạn mã sau được sử dụng trong CMS Flatnux ( http://flatnux.altervista.org ):

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}

1

Tôi tìm thấy giải pháp chỉ dành cho php và bất biến này hoạt động cả với http và cli:

Xác định hàm:

function forbidDirectAccess($file) {
    $self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
    (substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}

Gọi hàm trong tệp bạn muốn ngăn truy cập trực tiếp vào:

forbidDirectAccess(__FILE__);

Hầu hết các giải pháp được đưa ra ở trên cho câu hỏi này không hoạt động ở chế độ Cli.


nơi nào được cho là nhập URL trong chế độ CLI?
Ý thức chung của bạn

Nó chỉ là để ngăn chặn sự ra mắt của tập lệnh php / inlude trong chế độ cli. Có thể hữu ích trong một dự án với nhiều nhà phát triển.
Ka.

1
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };

1
<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>

1

Lưu trữ các tệp bao gồm của bạn bên ngoài thư mục có thể truy cập web đã được đề cập một vài lần và chắc chắn là một chiến lược tốt nếu có thể. Tuy nhiên, một tùy chọn khác tôi chưa thấy đề cập: đảm bảo rằng các tệp bao gồm của bạn không chứa bất kỳ mã có thể chạy nào . Nếu các tệp bao gồm của bạn chỉ xác định các hàm và các lớp và không có mã nào khác, chúng sẽ chỉ tạo ra một trang trống khi được truy cập trực tiếp.

Bằng mọi cách cho phép truy cập trực tiếp vào tệp này từ trình duyệt: nó sẽ không làm gì cả . Nó định nghĩa một số chức năng, nhưng không ai trong số chúng được gọi, vì vậy không ai trong số chúng chạy.

<?php

function a() {
    // function body
}

function b() {
    // function body
}

Điều tương tự cũng áp dụng cho các tệp chỉ chứa các lớp PHP và không có gì khác.


Vẫn là một ý tưởng tốt để giữ các tệp của bạn bên ngoài thư mục web nếu có thể.

  • Bạn có thể vô tình hủy kích hoạt PHP, trong trường hợp đó, máy chủ của bạn có thể gửi nội dung của các tệp PHP tới trình duyệt, thay vì chạy PHP và gửi kết quả. Điều này có thể dẫn đến mã của bạn (bao gồm mật khẩu cơ sở dữ liệu, khóa API, v.v.) bị rò rỉ.
  • Các tệp trong thư mục web đang ngồi xổm trên các URL bạn có thể muốn sử dụng cho ứng dụng của mình. Tôi làm việc với một CMS không thể có một trang được gọi system, vì điều đó sẽ mâu thuẫn với một đường dẫn được sử dụng cho mã. Tôi thấy điều này gây phiền nhiễu.

0

Làm một cái gì đó như:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>

Điều này sẽ không ngăn nó được tải trong trình duyệt.
UnkwnTech

0

Mặc dù vậy, bạn có thể sử dụng phương pháp sau đây, tuy nhiên, nó có một lỗi, bởi vì nó có thể bị làm giả, ngoại trừ nếu bạn có thể thêm một dòng mã khác để đảm bảo yêu cầu chỉ đến từ máy chủ của bạn bằng cách sử dụng Javascript. Bạn có thể đặt mã này trong phần Thân của mã HTML, do đó lỗi hiển thị ở đó.

<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>

Đặt mã HTML khác của bạn ở đây

<? } ?>

Kết thúc nó như thế này, vì vậy đầu ra của lỗi sẽ luôn hiển thị trong phần thân, nếu đó là cách bạn muốn.


Tôi hiểu rằng tất cả các tiêu đề máy chủ HTTP_ * không đáng tin cậy, vì vậy tốt nhất bạn không nên sử dụng phương pháp này.
andreszs

0

tôi đề nghị không sử dụng $_SERVERvì lý do bảo mật.
Bạn có thể sử dụng một biến như $root=true;trong tệp đầu tiên bao gồm một biến khác.
và sử dụng isset($root)vào đầu tập tin thứ hai được bao gồm.


0

Những gì bạn cũng có thể làm là mật khẩu bảo vệ thư mục và giữ tất cả các tập lệnh php của bạn trong đó, ngoại trừ tệp index.php, vì tại thời điểm bao gồm mật khẩu sẽ không được yêu cầu vì nó sẽ chỉ được yêu cầu cho truy cập http. những gì nó sẽ làm cũng cung cấp cho bạn tùy chọn để truy cập các tập lệnh của bạn trong trường hợp bạn muốn vì bạn sẽ có mật khẩu để truy cập vào thư mục đó. bạn sẽ cần thiết lập tệp .htaccess cho thư mục và tệp .htpasswd để xác thực người dùng.

tốt, bạn cũng có thể sử dụng bất kỳ giải pháp nào được cung cấp ở trên trong trường hợp bạn cảm thấy không cần truy cập các tệp đó một cách bình thường vì bạn luôn có thể truy cập chúng thông qua cPanel, v.v.

Hi vọng điêu nay co ich


0

Cách dễ nhất là lưu trữ bao gồm bên ngoài thư mục web. Bằng cách đó, máy chủ có quyền truy cập vào chúng nhưng không có máy bên ngoài. Mặt trái duy nhất là bạn cần có khả năng truy cập vào phần này của máy chủ. Ưu điểm là nó không yêu cầu thiết lập, cấu hình hoặc căng thẳng mã / máy chủ bổ sung.


0

Tôi không tìm thấy các đề xuất với .htaccess rất tốt vì nó có thể chặn nội dung khác trong thư mục đó mà bạn có thể muốn cho phép người dùng truy cập, đây là giải pháp của tôi:

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}

0
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

sẽ làm công việc trôi chảy


2
Sao chép dán từ CodeIgnitor. Điều đó thật tuyệt nhưng nó thực sự không làm gì cả. Nó BASEPATH const được đặt trong một index.phptập tin nằm ở dưới cùng của cấu trúc cây. CI viết lại các URL để không cần truy cập trực tiếp các tập lệnh.
jimasun

tôi biết không cần nhưng nếu có ai cố gắng làm thế
Varshaan

0

Giải pháp được đề cập trước đó với phiên bản PHP đã được thêm vào:

    $max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
    if (count(get_included_files()) <= $max_includes)
    {
        exit('Direct access is not allowed.');
    }

2
Tôi thực sự không hiểu làm thế nào điều này có thể ngăn chặn truy cập trực tiếp
Adam Lindsay
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.