■ 백엔드 ■/PHP2018.06.21 22:13


   php 웹페이지 엑세스 솔루션들






PHP 포함 파일에 직접 액세스하지 못하게합니다.


 Answers

Apache 서버에서 실행되는 PHP 응용 프로그램을 실행하는 가장 쉬운 방법은 디렉토리에 포함을 넣고 .htaccess 파일의 해당 디렉토리에 대한 액세스를 거부하는 것입니다. 인터넷 검색의 문제를 해결하려면 아파치를 사용하는 경우 액세스 할 수 없도록하려는 디렉토리에 ".htaccess"라는 파일에 넣으십시오.

Deny from all

실제로 서버를 완전히 제어 할 수 있다면 (요즘은이 답변을 처음 작성했을 때보 다 작은 응용 프로그램이라도 더 일반적입니다), 가장 좋은 방법은 웹 서버가 제공하는 디렉토리 외부에서 보호하려는 파일을 붙이는 것입니다 . 따라서 앱이 /srv/YourApp/ 에 있으면 /srv/YourApp/app/ 파일을 제공하도록 서버를 설정하고 /srv/YourApp/app/ includes에 포함 시키십시오. 따라서 문자 그대로 액세스 할 수있는 URL이 없습니다. .

 Question

내가 포함으로 독점적으로 사용하는 PHP 파일이 있습니다. 따라서 포함되지 않고 URL을 직접 입력하여 액세스 할 때 실행하는 대신 오류를 던지고 싶습니다.

기본적으로 PHP 파일에서 다음과 같이 확인해야합니다.

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

이 작업을 수행하는 쉬운 방법이 있습니까?




phpMyAdmin 스타일을 사용할 수 있습니다 :

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



포함될 페이지에만 추가하십시오.

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

다음을 포함하는 페이지에 추가하십시오.

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



다음과 같이하십시오.

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



가장 쉬운 방법은 다음과 같이 include를 호출하는 파일에 변수를 설정하는 것입니다.

$including = true;

그런 다음 포함 된 파일에서 변수를 확인하십시오.

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



하나의 진입 점으로 애플리케이션을 구축하는 것이 좋습니다. 즉 모든 파일에 index.php가 있어야합니다.

이것을 index.php에 넣으십시오.

define(A,true);

이 검사는 각 링크 된 파일에서 실행되어야합니다 (require 또는 include를 통해)

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



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

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

그렇지 않으면

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

또는 .htaccess 파일을 include 폴더에 넣고 규칙을 작성하여 직접 액세스하는 것을 방지 할 수 있습니다.




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



파일에 직접 액세스하지 못하게하는 가장 좋은 방법은 웹 서버 문서 루트 (일반적으로 위의 한 수준 위)에 파일을 배치하는 것입니다. 여전히 포함시킬 수는 있지만 http 요청을 통해 다른 사용자가 액세스 할 가능성은 없습니다.

나는 보통 모든 방법을 사용하고 모든 PHP 파일을 부트 스트랩 파일을 제외한 문서 루트 외부에 배치합니다. 전체 웹 사이트 / 응용 프로그램을 라우팅하기 시작하는 문서 루트의 유일한 index.php입니다.




사실 내 충고는 이러한 모든 모범 사례를 수행하는 것입니다.

  • 문서를 웹 루트 외부에 놓거나 웹 서버가 액세스를 거부 한 디렉토리에 놓습니다.
  • 숨겨진 문서에서 확인할 수있는 보이는 문서의 정의를 사용하십시오.
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

이런 식으로 파일이 어떻게 든 잘못 배치되면 (잘못된 FTP 작업) 여전히 보호됩니다.




내가 포함되어있을 때 다르게 행동해야하는 파일이있다. 직접 접근 할 때 (주로 print() vs 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 이전에는 기본 페이지가 include로 간주되지 않습니다.

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가 실행을 중지합니다.

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 : 웹 서버 특정 구성

대부분의 서버에서는 개별 파일이나 디렉토리에 대한 권한을 지정할 수 있습니다. 그러한 제한된 디렉토리에 모든 include를 넣고 서버가이를 거부하도록 구성 할 수 있습니다.

예를 들어, APACHE에서 구성은 .htaccess 파일에 저장됩니다. here 튜토리얼.

그러나 서버 별 구성은 다른 웹 서버 간의 이식성에 좋지 않기 때문에 나에게 권장되지 않습니다. 거부 알고리즘이 복잡하거나 거부 된 디렉토리 목록이 다소 큰 경우에는 재구성 세션을 다소 불편할 수 있습니다. 결국 코드에서 이것을 처리하는 것이 가장 좋습니다.

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 서버는 기본적으로 파일 시스템에 액세스하므로 필요한 특권이있는 정상적인 프로그램과 마찬가지로 컴퓨터의 파일에 액세스 할 수 있습니다.
  • 이 디렉토리에 포함 파일을 배치하면 PHP 서버가 액세스하도록하고, 핫 링크는 사용자에게 거부됩니다.
  • 웹 서버의 파일 시스템 액세스 구성이 제대로 수행되지 않은 경우에도이 방법을 사용하면 실수로 파일이 공개되지 않습니다.

저의 코딩 컨벤션에 대해 불쌍히 생각해주십시오. 저는 숙련 된 PHP 개발자가 아닙니다. 더 나은 방법이있을 수 있습니다. 내 답변에 대한 모든 의견을 보내 주시면 감사하겠습니다.




보다 정확하게 말하면, 다음 조건을 사용해야합니다.

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

get_included_files() 는 포함 된 모든 파일의 이름을 포함하는 색인화 된 배열을 반환합니다 (파일이 실행되고 다음 파일이 포함되었고 이름이 배열에있는 경우). 따라서 파일에 직접 액세스 할 때 파일 이름이 배열의 첫 번째 파일이고 배열의 다른 모든 파일이 포함됩니다.




Javascript를 사용하여 요청이 서버에서만 제공되는지 확인하기 위해 다른 코드 줄을 추가 할 수있는 경우를 제외하고 위조 될 수 있기 때문에 결함이 있지만 다음과 같은 방법을 사용할 수 있습니다. 이 코드는 HTML 코드의 본문 섹션에 배치 할 수 있으므로 오류가 표시됩니다.

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

다른 HTML 코드를 여기에 놓으십시오.

<? } ?>

이렇게 끝내면 오류의 출력이 본문 섹션 내에 표시됩니다. 원하는 경우에는 오류 출력이 항상 표시됩니다.




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



.htaccess 방법 외에도 다양한 프레임 워크에서 유용한 패턴을 보았습니다 (예 : 레일의 루비). 그들은 응용 프로그램 루트 디렉토리에 별도의 pub / 디렉토리가 있고 라이브러리 디렉토리는 pub / 과 동일한 레벨에 있는 디렉토리에 있습니다. 이와 같은 것 (이상적은 아니지만 아이디어를 얻습니다) :

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

pub / document root로 사용하도록 웹 서버를 설정합니다. 이렇게하면 스크립트를보다 잘 보호 할 수 있습니다. 필요한 구성 요소를로드하기 위해 문서 루트에서 손을 뻗지 만 인터넷에서 구성 요소에 액세스하는 것은 불가능합니다. 보안 이외의 또 다른 이점은 모든 것이 한 곳에 있다는 것입니다.

이 설정은 포함 된 모든 파일에서 검사를 만드는 것보다 낫습니다. "액세스가 허용되지 않음"메시지는 공격자에게 단서가되며, 화이트리스트 기반이 아니기 때문에 .htaccess 구성보다 낫습니다. 파일 확장자를 망가뜨린 경우 lib /, conf / etc 디렉토리에는 보이지 않습니다.




앞에서 언급 한 PHP 버전 확인 솔루션이 추가되었습니다.

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



.htaccess로 제안을 찾지 못했습니다. 사용자가 액세스 할 수있게하려는 폴더의 다른 콘텐츠를 차단할 수 있기 때문입니다. 이것이 내 해결책입니다.

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



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

매끄러운 일을 할 것입니다.




내 대답은 접근 방식이 다소 다르지만 여기서 제공된 답변 중 많은 부분을 포함합니다. 나는 다각적 접근법을 추천 할 것이다.

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

그러나 defined or die 접근법 defined or die 접근법에는 여러 가지 장애가 있습니다. 첫째, 테스트 및 디버깅을하는 데는 큰 어려움이 있습니다. 둘째로, 마음이 바뀌면 정신이 마비되는 지루한 리팩터링이 포함됩니다. "찾기 및 바꾸기!" 너는 말한다. 그렇습니다. 그러나 당신이 그것이 정확히 어디서나 똑같이 쓰여졌는지 확신합니까? 이제 수천 개의 파일로 그걸 곱하면 ... oO

그리고 .htaccess가 있습니다. 관리자가 꼼꼼하지 않은 사이트에 코드를 배포하면 어떻게됩니까? 파일을 보호하기 위해 .htaccess에만 의존하는 경우 백업본, b) 눈물을 말리는 조직 상자, c) 사람의 모든 모자 메일에 화염을 내보내는 소화기 귀하의 코드를 사용하십시오.

그래서 나는이 질문이 "가장 쉬운"것을 묻지 만, 나는 이것이 더 방어적인 코딩이라고 생각한다.

내가 제안하는 것은 :

  1. 스크립트가 require('ifyoulieyougonnadie.php'); 하기 전에 require('ifyoulieyougonnadie.php'); ()  include() 하지 않고 defined or die 대신에)
  2. ifyoulieyougonnadie.php 에서 논리 ifyoulieyougonnadie.php 를 수행하십시오 - 스크립트, localhost 테스팅 등을 호출하여 다른 상수를 확인한 다음 die(), throw new Exception, 403 를 구현하고 die(), throw new Exception, 403 등을 die(), throw new Exception, 403 .

    두 가지 가능한 엔트리 포인트 - 메인 index.php (Joomla 프레임 워크)와 ajaxrouter.php (my framework) -를 사용하여 자체 프레임 워크를 생성합니다. 따라서 엔트리 포인트에 따라 여러 가지 사항을 확인합니다. ifyoulieyougonnadie.php 대한 요청 ifyoulieyougonnadie.php 두 파일 중 하나에서 오지 않는다면 나는 헛소리가 착수되고 있음을 알고 있습니다!

    하지만 새로운 진입 점을 추가하면 어떨까요? 걱정 마. 나는 방금 ifyoulieyougonnadie.php 그리고 나는 분류되었고, 더하기 'find and replace'도 없었다. 만세!

    동일한 스크립트 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 (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

이상적인 해결책은 다른 서버에서 언급 한 것처럼 웹 서버 문서 루트 외부에 파일을 배치하는 것입니다.




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



debug_backtrace() || die ("Direct access not permitted");



다음 코드는 Flatnux CMS ( http://flatnux.altervista.org )에서 사용됩니다.

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



Chuck의 해결책에 대한 대안 (또는 보완)은 특정 패턴과 일치하는 파일에 대한 액세스를 .htaccess 파일에 넣는 것입니다.

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



당신이 할 수있는 일은 디렉토리를 암호로 보호하고 index.php 파일을 제외하고 모든 PHP 스크립트를 거기에 보관하는 것입니다. 왜냐하면 include 패스가 필요하기 때문에 http 액세스에만 필요하기 때문입니다. 디렉토리에 액세스하기위한 암호가있는 경우에 대비하여 스크립트에 액세스 할 수있는 옵션도 제공합니다. 디렉토리를위한 .htaccess 파일과 사용자를 인증하는 .htpasswd 파일을 설정해야합니다.

물론 cPanel 등을 통해 항상 액세스 할 수 있기 때문에 정상적으로 파일에 액세스 할 필요가 없다고 생각되는 경우 위에 제공된 솔루션 중 하나를 사용할 수도 있습니다.

희망이 도움이




보안상의 이유로 $_SERVER 를 사용하지 말 것을 제안합니다. 
$root=true; 와 같은 변수를 사용할 수 있습니다 $root=true; 다른 파일을 포함하는 첫 번째 파일에. 
포함 된 두 번째 파일의 시작 부분에서 isset($root) 을 사용하십시오.




가장 쉬운 방법은 포함 항목을 웹 디렉토리 외부에 저장하는 것입니다. 그렇게하면 서버는 외부 시스템없이 액세스 할 수 있습니다. 유일한 단점은 서버의이 부분에 액세스 할 수 있어야한다는 것입니다. 단점은 설정, 구성 또는 추가 코드 / 서버 스트레스가 필요 없다는 것입니다.




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



source : https://code.i-harness.com/ko/q/63f98

Posted by SAP (Study And Programming) by serpiko

댓글을 달아 주세요