programing

php include 파일에 직접 액세스 금지

bestcode 2022. 9. 16. 00:05
반응형

php include 파일에 직접 액세스 금지

php 파일을 가지고 있는데, 이 파일은 include에만 사용합니다.따라서 URL을 입력해서 직접 접속했을 때 실행하지 않고 오류를 발생시키고 싶습니다.

기본적으로 다음과 같이 php 파일을 확인해야 합니다.

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

쉽게 할 수 있는 방법이 있을까요?

포함시키고 싶은 페이지에 추가합니다.

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

그런 다음 그것을 포함하는 페이지에 추가합니다.

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

일반적인 "PHP 앱이 완전히 제어되거나 완전히 제어되지 않을 수 있습니다" 상황에서 가장 쉬운 방법은 를 디렉토리에 저장하고 .htaccess 파일에서 해당 디렉토리에 대한 액세스를 거부하는 것입니다.Apache를 사용하는 경우 구글링의 문제를 피하기 위해 접근하고 싶지 않은 디렉토리의 ".htaccess"라는 파일에 저장합니다.

Deny from all

실제로 서버를 완전히 제어할 수 있는 경우(이 답변을 처음 작성했을 때보다 작은 애플리케이션이라도 현재 가장 일반적인 방법은 웹 서버가 서비스하는 디렉토리 외부에 보호하는 파일을 고정하는 것입니다.앱이 접속되어 있는 경우/srv/YourApp/, 파일을 처리할 서버를 설정합니다./srv/YourApp/app/인크루드도 넣고/srv/YourApp/includes그 때문에, 문자 그대로 액세스 할 수 있는 URL은 없습니다.

파일이 포함되어 있을 때와 직접 액세스 했을 때의 조작을 달리할 필요가 있다(주로print()return()다음은 변경된 코드입니다.

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

액세스 중인 파일은 항상 포함된 파일이기 때문에 == 1입니다.

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 적절한 응답 생성뿐만 아니라 로깅 및 분석 목적으로도 사용됩니다.

크레딧(크레딧이 있어야 할 경우):휴대성에 대한 기발한 아이디어는 이 답변에서 나왔다.단, 이 방법에는 하나의 단점이 있습니다.다른 폴더에 있는 파일에는, 이 파일의 주소를 지정하기 위해서 다른 주소가 필요하게 됩니다.메인 사이트의 서브폴더내에서 현재의 Web 사이트를 실행하고 있는 경우는, 서버 루트 베이스의 어드레싱이 기능하지 않는 경우가 있습니다.


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를 사용하여 인크루드 파일에 인가 토큰을 전달할 수 있습니다.

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

매우 복잡한 방법이지만 올바른 방법으로 사용한다면 가장 안전하고 다용도적일 수 있습니다.


5: 웹 서버 고유의 설정

대부분의 서버에서는 개별 파일 또는 디렉토리에 대한 권한을 할당할 수 있습니다.모든 포함을 이러한 제한된 디렉토리에 배치하여 서버에서 거부하도록 설정할 수 있습니다.

예를 들어, APACHE의 경우 설정은.htaccess파일입니다. 튜토리얼은 이쪽입니다.

다만, 서버 고유의 설정은, 다른 Web 서버간의 이식성에 악영향을 미치기 때문에, 추천하지 않습니다.거부 알고리즘이 복잡하거나 거부된 디렉토리의 목록이 큰 Content Management Systems와 같은 경우 재구성 세션이 다소 번거로울 수 있습니다.결국 이 일은 암호로 처리하는 것이 최선입니다.


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 서버가 파일에 액세스할 수 있도록 할 수 있습니다.
  • 웹 서버의 파일 시스템 액세스 구성이 제대로 수행되지 않았더라도 이 방법을 사용하면 파일이 실수로 공개되는 것을 방지할 수 있습니다.

제 비정통적인 코딩 관례를 용서해 주세요.어떤 피드백이라도 감사합니다.

파일에 대한 직접 액세스를 방지하는 가장 좋은 방법은 파일을 웹 서버 문서 루트 외부에 배치하는 것입니다(일반적으로 한 단계 위).포함시킬 수는 있지만 누군가가 http 요청을 통해 액세스할 가능성은 없습니다.

저는 보통 모든 PHP 파일을 부트스트랩 파일(문서 루트 내의 lone index.php)을 제외한 문서 루트 외부에 배치하여 웹사이트/애플리케이션 전체를 라우팅하기 시작합니다.

Chuck 솔루션의 대안(또는 보완책)은 다음과 같은 것을 .htaccess 파일에 저장함으로써 특정 패턴과 일치하는 파일에 대한 액세스를 거부하는 것입니다.

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

사실 제 조언은 이 모든 베스트 프랙티스를 실행하라는 것입니다.

  • 문서를 웹 루트 OR 외부에 배치하거나 웹 서버에 의해 접근이 거부된 디렉토리에 저장합니다.
  • 숨겨진 문서가 검사하는 문서의 정의를 사용합니다.
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

이렇게 하면 파일이 잘못 배치되어도(오류 FTP 작업) 보호됩니다.

한 번 이 문제를 해결한 적이 있습니다.

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

그러나 다른 anwser에서 설명한 바와 같이 파일을 웹 서버 문서 루트 외부에 배치하는 것이 이상적입니다.

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

모든 파일은 index.php에서 액세스 할 수 있도록 1개의 입구 포인트로 애플리케이션을 구축하는 것이 좋습니다.

이것을 index.php에 배치합니다.

define(A,true);

이 검사는 각 링크된 파일에서 실행해야 합니다(요구 또는 포함을 통해).

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

제 답변은 접근 방식이 다소 다르지만, 여기에 제시된 답변의 많은 부분이 포함되어 있습니다.다양한 접근방식을 권장합니다.

  1. .htaccess 및 Apache 제한사항
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

,defined or dieapproach에는 여러 가지 장애가 있습니다.첫째, 테스트와 디버깅에 사용하는 가정은 정말 골칫거리입니다.둘째, 마음이 바뀌면 끔찍할 정도로 지루한 리팩터링이 수반됩니다.「찾아 교환해 주세요」라고 말합니다.네, 하지만 그게 모든 곳에 똑같이 쓰여 있다는 걸 어떻게 확신하세요?그걸 수천 개의 파일로 곱하면...O.O.

그리고 .htaccess가 있습니다.관리자가 꼼꼼하지 않은 사이트에 코드가 배포되면 어떻게 됩니까?파일 보안을 .htaccess에만 의존하는 경우 a) 백업, b) 눈물을 닦기 위한 티슈 상자, c) 코드를 사용하는 사람들이 보내는 모든 Hatemail의 불꽃을 끄기 위한 소화기가 필요합니다.

그래서 이 질문이 가장 쉬운 것을 요구하는 것은 알지만, 이것이 요구하는 것은 보다 "방어적인 코딩"이라고 생각합니다.

제가 제안하는 것은:

  1. 스크립트를 작성하기 전에require('ifyoulieyougonnadie.php');(없음) include()대체품으로서defined or die)
  2. ifyoulieyougonnadie.php, 다른 상수, 호출 스크립트, 로컬 호스트 테스트 등을 체크하고, 그 후 로직을 구현합니다.die(), throw new Exception, 403,기타.

    main index.php(Joomla 프레임워크)와 ajaxrouter.php(my 프레임워크)의 2가지 가능한 엔트리 포인트로 독자적인 프레임워크를 만들고 있기 때문에 엔트리 포인트에 따라 다른 것을 확인합니다.요청하신 경우ifyoulieyougonnadie.php그 두 파일 중 하나에서 나온 게 아니에요 셰니건이 행해지고 있다는 건 알아요!

    하지만 새로운 진입점을 추가하면 어떻게 될까요?걱정마세요.난 그냥 변했어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();

가장 쉬운 방법은 콜에 포함되는 파일에 다음과 같은 변수를 설정하는 것입니다.

$including = true;

그런 다음 포함된 파일에서 변수를 확인합니다.

if (!$including) exit("direct access not permitted");
debug_backtrace() || die ("Direct access not permitted");

.htaccess 방법 외에도 다양한 프레임워크에서 유용한 패턴을 볼 수 있었습니다.예를 들어, Ruby on Rails 등입니다.이들은 애플리케이션 루트 디렉토리에 별도의 pub/디렉토리를 가지고 있으며 라이브러리 디렉토리는 pub/와 같은 수준의 디렉토리에 존재합니다.다음과 같습니다(이상적이지는 않지만 이해하실 수 있습니다).

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

pub/를 문서 루트로 사용하도록 웹 서버를 설정합니다.이렇게 하면 스크립트가 문서 루트에서 필요한 컴포넌트를 로드하기 위해 접근할 수 있지만 인터넷에서 컴포넌트에 액세스할 수 없습니다.보안 외에도 모든 것이 한 곳에 있다는 것도 장점입니다.

이 셋업은 "access not permitted" 메시지가 공격자에 대한 단서가 되기 때문에 포함된 모든 파일에 체크를 작성하는 것보다 우수합니다.또한 파일 확장자를 잘못 사용하면 lib/, conf/ 등의 디렉토리에 표시되지 않습니다.

Joomla!는 루트 파일에 상수를 정의하고 포함된 파일에 상수가 정의되어 있는지 확인합니다.

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

그렇지 않으면

CodeIgniter와 같은 대부분의 프레임워크가 권장하는 바와 같이 모든 파일을 webroot 디렉토리 외부에 배치함으로써 http 요청의 범위 밖에 유지할 수 있습니다.

또는 include 폴더에 .htaccess 파일을 배치하고 규칙을 작성함으로써 직접 접근을 방지할 수 있습니다.

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

보다 정확하게는, 다음의 조건을 사용할 필요가 있습니다.

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

get_beign_files()는 포함된 모든 파일의 이름을 포함하는 인덱스 배열을 반환합니다(파일이 beign 실행되면 해당 파일이 포함되고 이름이 배열에 포함됨).따라서 파일에 직접 액세스할 때 파일 이름이 배열의 첫 번째가 되고 배열의 다른 모든 파일이 포함되었습니다.

인크루드 파일을 Web 액세스 가능한 디렉토리 밖에 보존하는 것은, 몇번이나 언급되고 있습니다만, 가능한 한 좋은 전략입니다.그러나 아직 언급하지 않은 다른 옵션은 포함 파일에 실행 가능한 코드가 포함되어 있지 않은지 확인하는 것입니다.include 파일에 함수 및 클래스만 정의하고 그 이외의 코드가 없는 경우 직접 액세스할 때 빈 페이지가 생성됩니다.

반드시 브라우저에서 이 파일에 직접 액세스할 수 있도록 허용하십시오. 아무것도 수행되지 않습니다.일부 함수는 정의되지만 호출된 함수는 없으므로 실행되지 않습니다.

<?php

function a() {
    // function body
}

function b() {
    // function body
}

PHP 클래스만 포함하는 파일에도 동일하게 적용됩니다.


가능한 한 파일을 웹 디렉토리 외부에 보관하는 것이 좋습니다.

  • 실수로 PHP가 비활성화될 수 있습니다.이 경우 서버가 PHP를 실행하여 결과를 보내는 대신 브라우저에 PHP 파일의 콘텐츠를 보낼 수 있습니다.이로 인해 코드(데이터베이스 패스워드, API 키 등)가 누출될 수 있습니다.
  • 웹 디렉터리의 파일이 앱에 사용할 수 있는 URL에 스쿼트되어 있습니다.저는 CMS를 사용하여 작업하고 있습니다.CMS는system이는 코드에 사용되는 경로와 충돌하기 때문입니다.난 이게 짜증나.

다음과 같은 작업을 수행합니다.

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

플랫눅스 CMS(http://flatnux.altervista.org)에서는 다음 코드가 사용됩니다.

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

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 모드에서 작동하지 않습니다.

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

다음 방법을 사용할 수 있습니다.단, 조작할 수 있기 때문에 결함이 있습니다.단, Javascript를 사용하여 요청이 서버에서만 전송되도록 하는 다른 코드 행을 추가할 수 있는 경우는 제외합니다.HTML 코드의 [Body]섹션에 이 코드를 배치하면 오류가 표시됩니다.

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

여기에 다른 HTML 코드 배치

<? } ?>

이렇게 끝내면 오류 출력은 항상 본문 섹션에 표시됩니다.

말은 말 .$_SERVER보안상의 이유로
하다, 하다, 하다 등의 할 수 .$root=true;다른 파일을 포함한 첫 번째 파일에 있어요
를 사용합니다.isset($root)을 사용하다

또한 include password는 http 액세스에만 필요하므로 디렉토리를 패스워드로 보호하고 index.php 파일을 제외한 모든 php 스크립트를 유지할 수도 있습니다.또, 그 디렉토리에 액세스 하기 위한 패스워드가 있기 때문에, 필요에 따라서 스크립트에 액세스 할 수 있는 옵션도 제공합니다.디렉토리용 .htaccess 파일과 사용자를 인증하기 위한 .htpasswd 파일을 설정해야 합니다.

또한 cPanel 등을 통해 언제든지 파일에 액세스할 수 있기 때문에 이러한 파일에 정상적으로 액세스할 필요가 없다고 생각되는 경우 위의 솔루션 중 하나를 사용할 수도 있습니다.

도움이 되었으면 좋겠다

가장 쉬운 방법은 include를 웹 디렉토리 외부에 저장하는 것입니다.이렇게 하면 서버는 액세스 할 수 있지만 외부 머신은 액세스 할 수 없습니다.유일한 단점은 서버의 이 부분에 액세스할 수 있어야 한다는 것입니다.장점은 셋업, 구성 또는 추가적인 코드/서버 부하가 필요하지 않다는 것입니다.

.htaccess를 사용하는 권장사항은 사용자가 접근할 수 있도록 허용할 수 있는 폴더의 다른 콘텐츠를 차단할 수 있기 때문에 그다지 좋지 않았습니다.이것이 저의 해결책입니다.

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

PHP 버전 체크가 추가된 앞서 언급한 솔루션:

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

phpMyAdmin Style을 사용할 수 있습니다.

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}

언급URL : https://stackoverflow.com/questions/409496/prevent-direct-access-to-a-php-include-file

반응형