ป้องกันการเข้าถึงไฟล์ php ได้โดยตรง


166

ฉันมีไฟล์ php ซึ่งจะใช้เป็นแบบรวม ดังนั้นฉันต้องการโยนข้อผิดพลาดแทนที่จะเรียกใช้งานเมื่อเข้าถึงโดยตรงโดยพิมพ์ URL แทนการรวมไว้

โดยทั่วไปฉันต้องทำการตรวจสอบดังต่อไปนี้ในไฟล์ php:

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

มีวิธีง่ายๆในการทำเช่นนี้หรือไม่?


10
แทนที่จะตาย () คุณควรทดสอบส่วนหัว '("HTTP / 1.1 404 ไม่พบไฟล์", 404); ออกจาก' สิ่งนี้จะ (อย่างน้อยใน Apache) ทำให้เซิร์ฟเวอร์กลับสู่หน้า 404 ปกติ
gnud

ต่อไปนี้เป็นวิธีการง่ายๆสองวิธีที่ฉันได้อธิบายเพื่อปิดใช้งานการเข้าถึงโดยตรงใน PHP ไฟล์ที่รวมอยู่ - codespeedy.com/disable-direct-access-to-the-php-include-file
Faruque Ahamed Mollick

คำตอบ:


174

วิธีที่ง่ายที่สุดสำหรับสถานการณ์ "แอป PHP ทั่วไปที่ทำงานบนเซิร์ฟเวอร์ Apache ที่คุณอาจหรืออาจไม่ได้ควบคุมอย่างเต็มที่" คือการใส่ของคุณไว้ในไดเรกทอรีและปฏิเสธการเข้าถึงไดเรกทอรีนั้นในไฟล์. htaccess ของคุณ หากต้องการบันทึกปัญหาของ Googling ให้คนอื่นถ้าคุณใช้ Apache ให้ใส่ไฟล์นี้ในไฟล์ชื่อ ".htaccess" ในไดเรกทอรีที่คุณไม่ต้องการให้เข้าถึงได้:

Deny from all

หากคุณมีการควบคุมเซิร์ฟเวอร์อย่างเต็มรูปแบบ (พบได้ทั่วไปในวันนี้แม้จะเป็นแอพเล็ก ๆ น้อย ๆ มากกว่าตอนที่ฉันเขียนคำตอบแรก) วิธีที่ดีที่สุดคือติดไฟล์ที่คุณต้องการปกป้องนอกไดเรกทอรีที่เว็บเซิร์ฟเวอร์ของคุณให้บริการ . ดังนั้นหากแอปของคุณ/srv/YourApp/ตั้งค่าให้เซิร์ฟเวอร์ให้บริการไฟล์จาก/srv/YourApp/app/และใส่การรวมไว้/srv/YourApp/includesดังนั้นจึงไม่มี URL ใดที่สามารถเข้าถึงได้


1
ขอบคุณเนื่องจากฉันมีการควบคุมเซิร์ฟเวอร์ที่ฉันใช้งานแอพนี้อย่างเต็มที่นี่คือคำตอบที่ฉันได้ไปด้วย
Alterlife

24
หากคุณมีการควบคุมเต็มรูปแบบของเซิร์ฟเวอร์จะดีกว่าถ้าคุณใส่การกำหนดค่าลงในไดเรกทอรีไดเรกทอรีลงในไฟล์การกำหนดค่าโฮสต์เสมือน Apache อ่านได้เพียงครั้งเดียวในการเริ่มต้น .htaccess ถูกอ่านในทุกการเข้าถึงและการชะลอตัวลงเซิร์ฟเวอร์
Eineki

22
มันคงจะดีถ้ามีตัวอย่างไฟล์. htaccess เป็นส่วนหนึ่งของคำตอบนี้
Graham Lea

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

11
@James: ไม่ใช่ทุกคนที่รู้สึกว่า Stack Overflow ควรเป็นไซต์ "plz send teh codez" หากตอบคำถามอย่างชัดเจนแสดงว่าเป็นคำตอบที่ดี ยกตัวอย่างที่ไม่จำเป็นต้องมีการสนับสนุนเฉพาะการคัดลอกและวางโค้ด
Chuck

188

เพิ่มสิ่งนี้ไปยังหน้าที่คุณต้องการรวมเท่านั้น

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

จากนั้นไปยังหน้าที่เพิ่มเข้าไป

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

3
ฉันต้องเรียนรู้วิธีพิมพ์ให้เร็วขึ้น นี่เป็นวิธีเดียวกับที่ฉันแนะนำเพราะมีความปลอดภัยมากกว่าวิธีที่ใช้ตัวแปรเพื่อตรวจสอบ เนื่องจากมีการตั้งค่า PHP บางอย่างอาจเป็นไปได้ที่จะแทนที่ตัวแปร
Mark Davidson

3
นี่คือวิธีที่แอปพลิเคชั่น 'หลัก' จำนวนหนึ่งจัดการได้ ฉันรู้ว่า Joomla ทำอย่างนี้และฉันคิดว่า Wiki, Wordpress และอื่น ๆ ด้วย
UnkwnTech

1
บางทีข้อความอาจมีประโยชน์สำหรับแฮ็กเกอร์ (ไม่มีผู้ใช้จริงจะพบหน้าเหล่านี้) คุณสามารถส่งส่วนหัวของการเปลี่ยนเส้นทางและหยุดการประมวลผล php
bandi

7
เพียงส่งส่วนหัว 404 และออก - หน้าข้อผิดพลาดจะมีลักษณะเหมือนกับหน้า 404 ปกติ (อย่างน้อยใน Apache)
gnud

4
@ Smile.Hunter: นี่เป็นเรื่องเกี่ยวกับการปิดกั้นการเข้าถึงไฟล์สคริปต์รวม / ไลบรารี่ของคุณโดยตรงคำตอบใช้ได้ผล หากพวกเขาสร้างขึ้นsomefile.phpบนเซิร์ฟเวอร์ของคุณและเพิ่มการกำหนดของคุณในนั้นยังคงไม่อนุญาตให้พวกเขาเข้าถึงไฟล์รวมโดยตรง มันจะช่วยให้พวกเขา "รวม" ไฟล์ไลบรารีของคุณ แต่ถ้าพวกเขาไปได้ไกลพอที่จะสร้างไฟล์บนเซิร์ฟเวอร์ของคุณและรู้ว่าสคริปต์ define / include ของคุณคุณมีปัญหาอื่น ๆ ที่อาจคัดค้านการเขียนไฟล์ของพวกเขาเอง .
James

114

ฉันมีไฟล์ที่ฉันต้องทำแตกต่างกันเมื่อรวมกับ vs เมื่อเข้าถึงโดยตรง (ส่วนใหญ่เป็นprint()vs return()) นี่คือรหัสที่แก้ไขบางส่วน:

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

ไฟล์ที่ถูกเข้าถึงจะเป็นไฟล์ที่รวมอยู่เสมอดังนั้น == 1  


12
อันที่จริงแล้วมันเป็นความคิดที่ไม่ดีนักตรวจสอบจำนวนไฟล์ที่รวมอยู่ ฉันสงสัยว่าวิธีไหนดีกว่า: ใช้การกำหนดหรือใช้วิธีนี้ ดูเหมือนว่าจะมีอยู่ในตัวเองมากกว่านี้
Akoi Meexx

ครั้งแรกที่ฉันเคยเห็นใครมาด้วยสิ่งนี้ ฉันไม่ทราบว่าเพราะเหตุใดเพราะดูเหมือนว่าเป็นสิ่งที่มีอยู่ในตัวเองและเป็นสิ่งที่วัดโดยตรงที่คุณต้องการรู้ (ถ้ารวมอยู่หรือไม่) แทนที่จะวัดสิ่งที่คิดว่าเกี่ยวข้อง (เช่นค่าคงที่หรือ บางตำแหน่งถูกแบนโดย. htaccess) สวย.
Jimbo Jonny

อันนี้เจ๋งจริงๆเพราะการใช้. htaccess เพื่อบล็อกไฟล์. php ทั้งหมดอาจไม่สามารถทำได้ตลอดเวลาเนื่องจากอาจมีไฟล์บางไฟล์ในไดเรกทอรีเดียวกันซึ่งจำเป็นต้องเรียกใช้โดยตรงหรือแม้กระทั่งโดย javascripts ขอบคุณสำหรับความคิดที่ยอดเยี่ยม!
Anuj

3
ใช้งานได้ใน PHP5 ขึ้นไปเท่านั้น ก่อน PHP5 คุณต้องการเปรียบเทียบอีกครั้ง 0 แทนที่จะเป็น 1
jmucchiello

นี่เป็นวิธีที่ชาญฉลาดและช่วยให้คุณควบคุมการเข้าถึงโดยตรงไม่ใช่แค่บล็อกมัน - นั่นคือสิ่งที่ฉันชอบ ฉันมักจะรวมถึงการทดสอบหน่วยในไฟล์ของตัวเองและด้วยวิธีนี้ฉันสามารถห่อการทดสอบหน่วยของฉันในนี้ถ้าคำสั่ง น่าแปลกใจว่ามีประสิทธิภาพมันเป็น ..
whiteatom

34

วิธีที่ดีที่สุดในการป้องกันการเข้าถึงไฟล์โดยตรงคือการวางไว้นอกรูทเอกสารของเว็บเซิร์ฟเวอร์ (โดยปกติแล้วจะอยู่เหนือระดับหนึ่ง) คุณยังสามารถรวมพวกเขาได้ แต่ไม่มีใครเป็นไปได้ที่จะเข้าถึงพวกเขาผ่านทางคำขอ http

ฉันมักจะไปตลอดทางและวางไฟล์ PHP ทั้งหมดของฉันไว้นอกรูทเอกสารนอกเหนือจากไฟล์บู๊ตสแตรป - lone index.php ในรูทเอกสารที่เริ่มต้นกำหนดเส้นทางทั้งเว็บไซต์ / แอปพลิเคชัน


3
นี่เป็นทางออกที่ดีถ้าคุณสามารถทำได้ ฉันเพิ่งจะเริ่มทำงานกับ webhosts ที่ใช้ร่วมกันและค้นพบหนึ่งในหลาย ๆ รำคาญที่จะต้องทุกอย่างจะต้องอยู่ภายใน docroot
Beau Simensen

3
ในผู้ให้บริการโฮสติ้งทุกคนที่ฉันทำงานด้วยฉันมักจะเข้าถึง (แน่นอน) หนึ่งระดับเหนือรากเอกสาร
Eran Galperin

3
ที่โฮสต์บางแห่ง (รวมถึงที่อยู่ปัจจุบันของฉัน) คุณสามารถชี้โดเมนของคุณไปยังโฟลเดอร์ใดก็ได้ที่คุณต้องการ
ไดน่า

1
นี่เป็นทางเลือกที่ดีเช่นกันโดยใช้ preg_match -> if (preg_match ("~ globalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {die ('<h3 style = "color: red"> การแจ้งเตือนความปลอดภัยของอุปกรณ์ - การเข้าถึงโดยตรงไม่อนุญาต! IP ของคุณถูกบันทึกแล้ว! <h3> '); // หยุดการประหารอีก}
MarcoZen

url devzone.zend.com/node/view/id/70นั่นคือ 404 ตอนนี้ คำตอบควรมีรหัสที่ แต่เดิมใช้จาก URL ที่ไม่มีอยู่จริง
Funk Forty Niner

31

1: การตรวจสอบจำนวนไฟล์ที่รวม

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

ลอจิก: PHP ออกถ้าไม่นับรวมขั้นต่ำ โปรดทราบว่าก่อนหน้า PHP5 หน้าฐานจะไม่ถือว่าเป็นการรวม


2: การกำหนดและตรวจสอบค่าคงที่ทั่วโลก

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

ลอจิก:หากไม่ได้กำหนดค่าคงที่การดำเนินการจะไม่เริ่มต้นจากหน้าฐานและ PHP จะหยุดการทำงาน

โปรดทราบว่าเพื่อประโยชน์ในการพกพาในการอัปเกรดและการเปลี่ยนแปลงในอนาคตการทำวิธีการรับรองความถูกต้องแบบแยกส่วนนี้จะช่วยลดค่าใช้จ่ายในการเขียนรหัสลงได้อย่างมาก

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

วิธีนี้สามารถเพิ่มรหัสเพิ่มเติมได้ checkdefined.php การเข้าสู่ระบบและการวิเคราะห์เช่นเดียวกับการสร้างการตอบสนองที่เหมาะสม

เครดิตที่เครดิตครบกำหนด:ความคิดที่ยอดเยี่ยมของการพกพามาจากคำตอบนี้


3: การอนุมัติที่อยู่ระยะไกล

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

ข้อเสียของวิธีนี้คือการแยกการดำเนินการเว้นแต่เซสชั่นโทเค็นให้มาพร้อมกับการร้องขอภายใน ตรวจสอบผ่านทางลูปแบ็คในกรณีที่มีการกำหนดค่าเซิร์ฟเวอร์เดียวหรือรายการที่อยู่สีขาวสำหรับโครงสร้างพื้นฐานเซิร์ฟเวอร์แบบหลายเซิร์ฟเวอร์หรือโหลดบาลานซ์


4: การให้สิทธิ์โทเค็น

เช่นเดียวกับวิธีการก่อนหน้านี้หนึ่งสามารถใช้ GET หรือ POST เพื่อส่งโทเค็นการอนุญาตไปยังไฟล์ include:

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

วิธีการที่ยุ่งมาก แต่ก็อาจจะปลอดภัยและหลากหลายที่สุดในเวลาเดียวกันเมื่อใช้อย่างถูกวิธี


5: การกำหนดค่าเฉพาะของเว็บเซิร์ฟเวอร์

เซิร์ฟเวอร์ส่วนใหญ่อนุญาตให้คุณกำหนดสิทธิ์สำหรับแต่ละไฟล์หรือไดเรกทอรี คุณสามารถวางการรวมทั้งหมดของคุณไว้ในไดเรกทอรีที่ถูก จำกัด และมีการกำหนดค่าเซิร์ฟเวอร์ให้ปฏิเสธ

ตัวอย่างเช่นใน APACHE การกำหนดค่าจะถูกเก็บไว้ใน.htaccessไฟล์ กวดวิชาที่นี่

โปรดทราบว่าฉันไม่แนะนำให้ใช้การกำหนดค่าเฉพาะสำหรับเซิร์ฟเวอร์เนื่องจากความสามารถในการพกพาข้ามเว็บเซิร์ฟเวอร์ที่แตกต่างกันนั้นไม่ดี ในกรณีเช่นระบบจัดการเนื้อหาที่ deny-algorithm ซับซ้อนหรือรายการไดเร็กตอรี่ที่ถูกปฏิเสธนั้นค่อนข้างใหญ่, มันอาจทำให้เซสชันการกำหนดค่าใหม่ค่อนข้างน่ากลัวเท่านั้น ในที่สุดก็ควรจัดการในรหัส


6: การวางรวมอยู่ในไดเรกทอรีที่ปลอดภัยนอกรูทไซต์

เป็นที่ต้องการอย่างน้อยเนื่องจากข้อ จำกัด การเข้าถึงในสภาพแวดล้อมเซิร์ฟเวอร์ แต่เป็นวิธีที่ค่อนข้างมีประสิทธิภาพหากคุณมีการเข้าถึงระบบไฟล์

//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โฟลเดอร์เนื่องจากลิงก์จะอยู่นอกขอบเขตของระบบที่อยู่ของเว็บไซต์
  • เซิร์ฟเวอร์ php เข้าถึงระบบไฟล์อย่างเป็นธรรมชาติและด้วยเหตุนี้จึงสามารถเข้าถึงไฟล์บนคอมพิวเตอร์ได้เช่นเดียวกับที่โปรแกรมปกติที่มีสิทธิ์ที่จำเป็นสามารถทำได้
  • ด้วยการวางไฟล์ include ไว้ในไดเรกทอรีนี้คุณสามารถมั่นใจได้ว่าเซิร์ฟเวอร์ php จะเข้าถึงไฟล์เหล่านั้นได้ในขณะที่การเชื่อมโยง hotlink ถูกปฏิเสธไปยังผู้ใช้
  • แม้ว่าการกำหนดค่าการเข้าถึงระบบไฟล์ของเว็บเซิร์ฟเวอร์ไม่ได้ทำอย่างถูกต้องวิธีนี้จะป้องกันไม่ให้ไฟล์เหล่านั้นกลายเป็นสาธารณะโดยไม่ตั้งใจ

โปรดแก้ตัวอนุสัญญาการเข้ารหัสนอกรีตของฉัน ข้อเสนอแนะใด ๆ ที่มีความนิยม


ฉันชอบหมายเลข 2
Baim Wrong

26

อีกทางเลือกหนึ่ง (หรือส่วนเติมเต็ม) ไปยังโซลูชันของ Chuck คือการปฏิเสธการเข้าถึงไฟล์ที่ตรงกับรูปแบบเฉพาะโดยการใส่บางอย่างเช่นนี้ลงในไฟล์. htaccess ของคุณ

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

จะดีกว่าการใช้. inc.php ฉันเชื่อและเป็นเรื่องธรรมดา
Lis

14

จริงๆแล้วคำแนะนำของฉันคือการทำสิ่งที่ดีที่สุดเหล่านี้ทั้งหมด

  • วางเอกสารนอก webroot หรือในไดเรกทอรีที่ปฏิเสธการเข้าถึงโดย webserver AND
  • ใช้การกำหนดในเอกสารที่มองเห็นได้ซึ่งเอกสารที่ซ่อนอยู่ตรวจสอบ:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

วิธีนี้หากไฟล์ถูกวางผิดที่อย่างใดอย่างหนึ่ง (การดำเนินการ ftp ที่ผิดพลาด) พวกเขาจะยังคงได้รับการปกป้อง


8

ฉันมีปัญหานี้ครั้งเดียวแก้ไขด้วย:

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

แต่ทางออกที่ดีที่สุดคือการวางไฟล์ไว้นอกรูทเอกสารของเว็บเซิร์ฟเวอร์ตามที่กล่าวไว้ในอีกอันนึง


7

คุณควรสร้างแอปพลิเคชั่นที่มีทางเข้าหนึ่งจุดนั่นคือเข้าถึงไฟล์ทั้งหมดได้จาก index.php

วางสิ่งนี้ใน index.php

define(A,true);

การตรวจสอบนี้ควรทำงานในแต่ละไฟล์ที่เชื่อมโยง (ผ่านจำเป็นหรือรวม)

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

7

ผมอยากที่จะ จำกัด การเข้าถึง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;
    }
}

3

วิธีที่ง่ายที่สุดคือการตั้งค่าตัวแปรบางอย่างในไฟล์ที่มีการเรียกเช่น

$including = true;

จากนั้นในไฟล์ที่รวมอยู่ให้ตรวจสอบตัวแปร

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

2
สิ่งนี้เป็นอันตรายหากเปิดใช้งาน register_globals
jmucchiello

25
PHPเป็นสิ่งที่อันตรายหาก register_globals เปิดอยู่
David Precious

3

นอกเหนือจากวิธี. htaccess ฉันได้เห็นรูปแบบที่มีประโยชน์ในกรอบงานต่าง ๆ เช่นในทับทิมบนราง พวกเขามี pub / directory แยกกันในไดเรกทอรี root ของแอปพลิเคชันและไดเรกทอรี Library นั้นอยู่ในไดเรกทอรีในระดับเดียวกับ pub / บางสิ่งเช่นนี้ (ไม่เหมาะ แต่คุณได้รับแนวคิด):

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

คุณตั้งค่าเว็บเซิร์ฟเวอร์เพื่อใช้ pub / as root ของเอกสาร สิ่งนี้มีการป้องกันที่ดีกว่ากับสคริปต์ของคุณ: ในขณะที่สามารถเข้าถึงได้จากรูทเอกสารเพื่อโหลดส่วนประกอบที่จำเป็นมันเป็นไปไม่ได้ที่จะเข้าถึงส่วนประกอบจากอินเทอร์เน็ต ประโยชน์อีกอย่างหนึ่งนอกเหนือจากความปลอดภัยคือทุกอย่างอยู่ในที่เดียว

การตั้งค่านี้ดีกว่าการสร้างการตรวจสอบในทุก ๆ ไฟล์รวมเพราะข้อความ "ไม่อนุญาตการเข้าถึง" เป็นคำใบ้ของผู้โจมตีและดีกว่าการกำหนดค่า. htaccess เนื่องจากไม่ใช่รายการที่อยู่ในรายการ: หากคุณไขไฟล์นามสกุล จะไม่สามารถมองเห็นได้ในไดเร็กทอรี lib /, conf / ฯลฯ


หลังจากนั้นไม่นานฉันต้องการแสดงความคิดเห็นว่าโมเดลที่คุณอธิบายข้างต้นเรียกว่าโมเดล MVC (โมเดล - มุมมอง - คอนโทรลเลอร์) หากคุณโปรดตรวจสอบ google และเพิ่มข้อมูลเพิ่มเติมในคำตอบของคุณ นอกจากนี้ MVC ยังรองรับการใช้งาน Ruby on Rails และ ASP.NET เท่านั้น แต่ยังรองรับ PHP (ดู Lavarel, CakePHP)

3

อะไร Joomla! ไม่ได้กำหนดค่าคงที่ในไฟล์รูทและตรวจสอบว่ามีการกำหนดไว้ในไฟล์ที่รวมอยู่หรือไม่

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

หรืออื่น ๆ

หนึ่งสามารถเก็บไฟล์ทั้งหมดนอกการร้องขอ HTTP โดยวางไว้นอกไดเรกทอรี webroot เป็นกรอบงานส่วนใหญ่เช่น CodeIgniter แนะนำ

หรือแม้กระทั่งโดยการวางไฟล์. htaccess ไว้ในโฟลเดอร์ include และกฎการเขียนคุณสามารถป้องกันการเข้าถึงโดยตรง



3

คำตอบของฉันค่อนข้างแตกต่างในแนวทาง แต่รวมถึงคำตอบมากมายที่ให้ไว้ที่นี่ ฉันอยากจะแนะนำวิธีการหลายอย่าง:

  1. .htaccess และ Apache มีข้อ จำกัด อย่างแน่นอน
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

อย่างไรก็ตามdefined or dieวิธีการที่มีจำนวนของความล้มเหลว ประการแรกมันเป็นความเจ็บปวดที่แท้จริงในข้อสันนิษฐานที่จะทดสอบและตรวจแก้จุดบกพร่องด้วย ประการที่สองมันเกี่ยวข้องกับ refactoring น่ากลัวใจทำให้มึนงงน่ากลัวถ้าคุณเปลี่ยนใจ "ค้นหาและแทนที่!" คุณพูด. ใช่ แต่คุณแน่ใจว่ามันถูกเขียนเหมือนกันทุกที่ hmmm? ตอนนี้คูณด้วยไฟล์นับพัน ... oO

แล้วมี. htaccess จะเกิดอะไรขึ้นหากรหัสของคุณถูกแจกจ่ายไปยังเว็บไซต์ที่ผู้ดูแลระบบไม่ได้ระมัดระวัง หากคุณพึ่งพา. htaccess เพื่อรักษาความปลอดภัยไฟล์ของคุณคุณจะต้องสำรองข้อมูลก) กล่องกระดาษทิชชูให้น้ำตาของคุณแห้ง c) เครื่องดับเพลิงเพื่อดับเปลวไฟในหมวกของผู้คน ใช้รหัสของคุณ

ดังนั้นฉันรู้ว่าคำถามถามหา "ง่ายที่สุด" แต่ฉันคิดว่าสิ่งนี้เรียกร้องให้เป็น "การป้องกันการเข้ารหัส" มากกว่า

สิ่งที่ฉันแนะนำคือ:

  1. ก่อนสคริปต์ใด ๆ ของคุณrequire('ifyoulieyougonnadie.php');( ไม่ใช่ include()และแทนdefined or die)
  2. ในifyoulieyougonnadie.phpทำสิ่งตรรกะบางอย่าง - ตรวจสอบค่าคงที่ที่แตกต่างกันเรียกสคริปต์การทดสอบในพื้นที่และอื่น ๆ - จากนั้นใช้ของคุณdie(), throw new Exception, 403ฯลฯ

    ฉันกำลังสร้างเฟรมเวิร์กของตัวเองโดยมีจุดเข้าใช้งานสองจุด - index.php หลัก (Joomla framework) และ ajaxrouter.php (เฟรมเวิร์กของฉัน) - ดังนั้นขึ้นอยู่กับจุดเริ่มต้นฉันจะตรวจสอบสิ่งต่าง ๆ หากคำขอifyoulieyougonnadie.phpไม่มาจากหนึ่งในสองไฟล์เหล่านั้นฉันรู้ว่า shenanigans กำลังถูกดำเนินการ!

    แต่ถ้าฉันเพิ่มจุดเข้าใหม่ ไม่ต้องห่วง. ฉันเพิ่งเปลี่ยน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();

2

หากแม่นยำยิ่งขึ้นคุณควรใช้เงื่อนไขนี้:

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

get_included_files ()ส่งคืนอาร์เรย์ที่จัดทำดัชนีซึ่งมีชื่อของไฟล์ที่รวมทั้งหมด (หากไฟล์ถูกเรียกใช้งาน beign ดังนั้นจะถูกรวมและชื่อจะอยู่ในอาร์เรย์) ดังนั้นเมื่อเข้าถึงไฟล์โดยตรงชื่อของมันคือไฟล์แรกในอาเรย์ไฟล์อื่น ๆ ทั้งหมดในอาเรย์จึงถูกรวมเข้าด้วยกัน


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

วางรหัสด้านบนในด้านบนของไฟล์ 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
?>

if (preg_match ("~ globalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {ตาย ('<h3 style = "color: red"> การแจ้งเตือนความปลอดภัยของอุปกรณ์ - การเข้าถึงโดยตรงไม่ได้รับอนุญาต! <h3> '); // หยุดการประหารชีวิตอีก} whre ~ คือตัวคั่น
MarcoZen


1

ฉันพบโซลูชัน php เท่านั้นและคงที่ซึ่งทำงานได้ทั้งกับ http และ cli:

กำหนดฟังก์ชั่น:

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

เรียกใช้ฟังก์ชันในไฟล์ที่คุณต้องการป้องกันการเข้าถึงโดยตรงไปที่:

forbidDirectAccess(__FILE__);

โซลูชันส่วนใหญ่ที่ให้ไว้กับคำถามนี้ไม่สามารถใช้งานได้ในโหมด Cli


ที่ควรจะพิมพ์ URL ในโหมด CLI
สามัญสำนึกของคุณ

มันเป็นเพียงเพื่อป้องกันการเปิดตัวของสคริปต์ PHP / inlude ในโหมด cli มีประโยชน์ในโครงการที่มีผู้พัฒนาหลายคน
กะ



1

การจัดเก็บไฟล์รวมของคุณนอกไดเรกทอรีที่เข้าถึงได้ในเว็บได้รับการกล่าวถึงสองสามครั้งและเป็นกลยุทธ์ที่ดีหากเป็นไปได้ อย่างไรก็ตามตัวเลือกอื่นที่ฉันยังไม่ได้กล่าวถึง: ตรวจสอบให้แน่ใจว่าไฟล์รวมของคุณไม่มีรหัสที่รันได้ หากไฟล์รวมของคุณเพียงกำหนดฟังก์ชั่นและคลาสและไม่มีรหัสอื่นนอกจากนั้นพวกเขาก็จะสร้างหน้าว่างเมื่อเข้าถึงโดยตรง

โดยทั้งหมดอนุญาตให้เข้าถึงไฟล์นี้โดยตรงจากเบราว์เซอร์: มันจะไม่ทำอะไรเลย มันกำหนดฟังก์ชั่นบางอย่าง แต่ไม่มีใครเรียกพวกเขาดังนั้นจึงไม่มีการเรียกใช้

<?php

function a() {
    // function body
}

function b() {
    // function body
}

เช่นเดียวกับไฟล์ที่มีคลาส PHP เท่านั้นและไม่มีอะไรอื่น


มันยังเป็นความคิดที่ดีที่จะเก็บไฟล์ของคุณไว้นอกสารบบเว็บถ้าเป็นไปได้

  • คุณอาจปิดการใช้งาน PHP โดยไม่ตั้งใจซึ่งในกรณีนี้เซิร์ฟเวอร์ของคุณอาจส่งเนื้อหาของไฟล์ PHP ไปยังเบราว์เซอร์แทนการเรียกใช้ PHP และส่งผลลัพธ์ ซึ่งอาจส่งผลให้รหัสของคุณ (รวมถึงรหัสผ่านฐานข้อมูลคีย์ API และอื่น ๆ ) รั่วไหล
  • ไฟล์ในสารบบเว็บกำลังนั่งยอง ๆ กับ URL ที่คุณอาจต้องการใช้กับแอพของคุณ ฉันทำงานกับ CMS ซึ่งไม่สามารถเรียกเพจได้systemเนื่องจากอาจขัดแย้งกับเส้นทางที่ใช้รหัส ฉันพบว่ามันน่ารำคาญ

0

ทำสิ่งที่ชอบ:

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

สิ่งนี้จะไม่ป้องกันไม่ให้โหลดในเบราว์เซอร์
UnkwnTech

0

คุณสามารถใช้วิธีการต่อไปนี้ด้านล่างแม้ว่าจะมีข้อบกพร่องเพราะสามารถปลอมได้ยกเว้นถ้าคุณสามารถเพิ่มรหัสอีกบรรทัดหนึ่งเพื่อให้แน่ใจว่าคำขอมาจากเซิร์ฟเวอร์ของคุณเท่านั้นโดยใช้ Javascript คุณสามารถวางรหัสนี้ในส่วน Body ของรหัส HTML ของคุณดังนั้นข้อผิดพลาดจะแสดงที่นั่น

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

วางรหัส HTML อื่น ๆ ของคุณที่นี่

<? } ?>

จบแบบนี้ดังนั้นผลลัพธ์ของข้อผิดพลาดจะแสดงอยู่ในส่วนของเนื้อหาเสมอหากเป็นสิ่งที่คุณต้องการ


ฉันเข้าใจว่าส่วนหัวของเซิร์ฟเวอร์ HTTP_ * ทั้งหมดไม่น่าเชื่อถือดังนั้นคุณจึงไม่ควรใช้วิธีนี้
andreszs

0

ฉันขอแนะนำว่าอย่าใช้$_SERVERเพื่อความปลอดภัย
คุณสามารถใช้ตัวแปรเช่นเดียวกับ$root=true;ในไฟล์แรกที่รวมตัวแปรอื่น
และใช้isset($root)ในตอนต้นของไฟล์ที่สองที่รวมอยู่


0

สิ่งที่คุณสามารถทำได้คือป้องกันด้วยรหัสผ่านของไดเรกทอรีและเก็บสคริปต์ php ทั้งหมดของคุณไว้ในนั้นยกเว้นไฟล์ index.php เนื่องจากไม่จำเป็นต้องใช้รหัสผ่านในขณะที่มีการใส่รหัสผ่านเพื่อเข้าถึง http เท่านั้น สิ่งที่จะทำคือให้ตัวเลือกในการเข้าถึงสคริปต์ของคุณในกรณีที่คุณต้องการเพราะคุณจะมีรหัสผ่านเพื่อเข้าถึงไดเรกทอรีนั้น คุณจะต้องตั้งค่าไฟล์. htaccess สำหรับไดเรกทอรีและไฟล์. htpasswd เพื่อตรวจสอบสิทธิ์ผู้ใช้

คุณยังสามารถใช้วิธีแก้ไขปัญหาใด ๆ ที่ให้ไว้ข้างต้นในกรณีที่คุณรู้สึกว่าคุณไม่จำเป็นต้องเข้าถึงไฟล์เหล่านั้นตามปกติเพราะคุณสามารถเข้าถึงได้ผ่าน cPanel เป็นต้น

หวังว่านี่จะช่วยได้


0

วิธีที่ง่ายที่สุดคือเก็บของคุณไว้นอกสารบบเว็บ วิธีนี้ทำให้เซิร์ฟเวอร์เข้าถึงได้ แต่ไม่มีเครื่องภายนอก ข้อเสียเพียงอย่างเดียวคือคุณต้องสามารถเข้าถึงส่วนนี้ของเซิร์ฟเวอร์ของคุณได้ ข้อเสียคือไม่ต้องตั้งค่าการกำหนดค่าหรือความเครียด / รหัสเพิ่มเติมของเซิร์ฟเวอร์


0

ฉันไม่พบข้อเสนอแนะด้วย. htaccess ดีมากเพราะอาจบล็อกเนื้อหาอื่นในโฟลเดอร์นั้นซึ่งคุณอาจต้องการอนุญาตให้ผู้ใช้เข้าถึงนี่เป็นวิธีแก้ปัญหาของฉัน:

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

จะทำงานให้ราบรื่น


2
คัดลอกวางจาก CodeIgnitor มันเจ๋ง แต่จริง ๆ แล้วมันไม่ได้ทำอะไรด้วยตัวเอง การBASEPATH const ตั้งค่าในindex.phpไฟล์ที่วางที่ด้านล่างของโครงสร้างต้นไม้ CI เขียน URL ซ้ำดังนั้นไม่จำเป็นต้องเข้าถึงสคริปต์โดยตรงอีกต่อไป
jimasun

ฉันรู้ว่าไม่มีความจำเป็น แต่ถ้าคนใดคนหนึ่งพยายามที่จะทำเช่นนั้น
Varshaan

0

โซลูชันที่กล่าวถึงก่อนหน้านี้พร้อมการเพิ่มการตรวจสอบรุ่น PHP:

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

2
ฉันไม่เข้าใจจริงๆว่าวิธีนี้สามารถป้องกันการเข้าถึงโดยตรงได้อย่างไร
อดัมลินด์เซย์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.