PHP 매뉴얼
이전 | 15. 장. 보안 | 다음

# CGI 바이너리로 설치

## 가능한 공격

몇가지 이유로 인해 PHP를 서버 소프트웨어(아파치 등)의 모듈로 사용하지 않거나, 다른 종류의 CGI wrappers로 스크립트에 대해 안전한 chroot와 setuid 환경을 제공하기 위해 CGI 바이너리로 PHP를 사용하는 것을 선택할 수 있습니다. 이 설치는 보통 실행 가능한 PHP 바이너리를 웹서버 cgi-bin 디렉토리에 두는 것입니다. CERT 권고 CA-96.11는 어떠한 인터프리터도 cgi-bin에 두지 않을 것을 권장합니다. PHP 바이너리는 독립 인터프리터로 사용할 수 있지만, 이러한 방법의 설치가 가능하도록 하는 몇가지 공격을 방지하도록 설계되어 있습니다.

- 시스템 파일에의 접근: `http://my.host/cgi-bin/php?/etc/passwd`

  URL 후의 물음표(?)에 존재하는 질의 정보는 CGI 인터페이스에 의해 인터프리터에 명령줄 인자로 전해집니다. 보통 인터프리터는 명령줄의 첫 인자에 지정한 파일을 열고 실행합니다.

  CGI 바이너리로 호출할 때, PHP는 명령줄 인자를 해석하는 것을 거절합니다.

- 서버의 어떠한 웹 문서로의 접근: `http://my.host/cgi-bin/php/secret/doc.html`

  PHP 바이너리 이름 뒤의 URL의 경로 정보 부분, `/secret/doc.html`는 일반적으로 CGI 프로그램에 의해 그 이름의 파일을 열고 해석하도록 사용합니다. 보통 몇몇 웹 서버 환경 설정 지시자(아파치: Action)는 PHP 인터프리터에 `http://my.host/secret/script.php` 등의 요청으로 리다이렉트하도록 합니다. 이러한 설치로는, 웹 서버는 우선 디렉토리 `/secret`에 대해 접근 권한을 확인하고, 리다이렉트된 요청 `http://my.host/cgi-bin/php/secret/script.php`을 생성합니다. 불행하게도, 이러한 형식으로 요청이 주어지면, `/secret/script.php`에 대한 접근 확인은 이루어지지 않고, 단순히 `/cgi-bin/php` 파일만을 확인합니다. 이 방법으로 `/cgi-bin/php`에 접근할 수 있는 어떠한 유저라도 웹 서버로 보호된 어떠한 문서라도 접근할 수 있습니다.

  PHP에서는, 서버 문서 트리에 접근 제한을 가진 어떠한 디렉토리가 존재한다면, 컴파일시의 환경설정 옵션 --enable-force-cgi-redirect, 실행시 환경설정 지시자 doc_root와 user_dir를 사용하여 이 공격을 방지할 수 있습니다. 여러가지 조합에 관한 자세한 설명은 아래쪽을 참고하십시오.

## 방법 1: 공개 파일만을 제공

서버가 패스워드나 IP 기반 접근 컨트롤로 제한하는 콘텐츠를 가지고 있지 않다면, 이러한 환경 설정 옵션을 사용할 필요가 없습니다. 웹 서버가 리다이렉트를 허용하지 않거나, 안전하게 리다이렉트된 요청에 대해서 PHP 바이너리와 통신할 방법을 가지고 있지 않다면, 설정 스크립트에 --enable-force-cgi-redirect 옵션을 지정할 수 있습니다. 하지만, 여전히 PHP 스크립트를 호출하는 방법으로 직접 호출 `http://my.host/cgi-bin/php/dir/script.php`이나 리다이렉션 호출 `http://my.host/dir/script.php`에 의존하고 있지 않음을 확인해야 할 것입니다.

아파치에서 리다이렉션은 AddHandler와 Action 지시자를 통해서 설정할 수 있습니다. (아래 참조)

## 방법 2: --enable-force-cgi-redirect 사용

이 컴파일시의 옵션은 누구라도 `http://my.host/cgi-bin/php/secretdir/script.php`와 같은 URL을 통해서 PHP를 직접 호출할 수 없게 합니다. 대신, 이 모드에서 PHP는 웹서버의 리다이렉트 규칙에 따를 때만 해석을 시도할 것입니다.

아파치에서 리다이렉션의 설정은 다음과 같은 지시자로 설정합니다:

    Action php-script /cgi-bin/php
    AddHandler php-script .php

이 옵션은 아파치 웹 서버에만 테스트되었고, 리다이렉트된 요청에 대해 아파치가 비표준 CGI 환경 변수 `REDIRECT_STATUS`를 설정하게 합니다. 웹 서버가 요청이 직접적인지 리다이렉트된 것인지의 구분을 제공하지 않는다면, 이 옵션을 사용할 수 없고, 이 문서에 제시된 다른 방법의 CGI 실행 방법을 이용해야 합니다.

## 방법 3: doc_root나 user_dir을 설정

스크립트나 실행 파일과 같은 활동적인 콘텐츠를 웹서버 디렉토리에 놓는 것은 때때로 비보안적인 행동으로 생각됩니다. 몇몇 환경 설정의 실수로 스크립트가 실행되지 않고 보통의 HTML 문서로 보여진다면, 지적 재산이나 패스워드와 같은 보안 정보를 노출시키는 결과를 가져올 수 있습니다. 그러므로 많은 시스템 관리자는 파일이 항상 해석이 되고 어떤 방법으로도 표시되어지지 않도록, PHP CGI를 통해서만 접근할 수 있는 스크립트를 위한 또 다른 디렉토리 구조를 만드는 것을 선호합니다.

또한, 앞의 섹션에서 설명한 방법으로 요청을 리다이렉트하지 않게 만드는게 불가능하다면, doc_root를 웹 문서 루트와 다른 장소로 설정할 필요가 있습니다.

PHP 스크립트 문서 루트를 설정 파일에서 지시어 doc_root나, 환경 변수 `PHP_DOCUMENT_ROOT`로 설정할 수 있습니다. 이를 설정하면, PHP의 CGI 버전은 항상 열 파일 이름 및 요청의 경로 정보를 `doc_root`와 결합하여, 이 디렉토리 밖에서는 어떠한 스크립트도 실행하지 못하게 합니다. (아래의 `user_dir`를 제외하고)

Another option usable here is user_dir. When user_dir is unset, only thing controlling the opened file name is `doc_root`. Opening an URL like `http://my.host/~user/doc.php` does not result in opening a file under users home directory, but a file called `~user/doc.php` under doc_root (yes, a directory name starting with a tilde [`~`]).

If user_dir is set to for example `public_php`, a request like `http://my.host/~user/doc.php` will open a file called `doc.php` under the directory named `public_php` under the home directory of the user. If the home of the user is `/home/user`, the file executed is `/home/user/public_php/doc.php`.

`user_dir` expansion happens regardless of the `doc_root` setting, so you can control the document root and user directory access separately.

## 방법 4: 웹 트리 외부의 PHP 파서

매우 안전한 옵션은 PHP 파서 바이너리를 웹트리 밖에 위치시키는 것입니다. 예를 들면, `/usr/local/bin` 안에. 이 방법의 단 한가지 단점은 다음과 같은 줄을 PHP 태그를 포함하는 모든 파일의 첫번째 줄에 넣어야 한다는 점입니다:

    #!/usr/local/bin/php

또한 파일을 실행 가능하게 해 둘 필요가 있습니다. 이것은 정확하게 실행을 위해서 `#!` 쉘 이스케이핑 메카니즘을 사용하는 펄이나 sh, 혹은 다른 일반적인 스크립팅 언어로 쓰여진 CGI 스크립트와 동일하게 취급합니다.

이 방법을 사용할 때, PHP가 `PATH_INFO`와 `PATH_TRANSLATED`를 올바르게 다룰 수 있게 하기 위해서는 PHP 파서를 컴파일 할 때, --enable-discard-path 옵션을 주어야 합니다.

이전 | 처음으로 | 다음
일반적인 고려 사항 | 위로 | Installed as an Apache module