디렉토리나 파일 권한 등도 문제 없고 file_exists()도 true를 반환하는데, 아래와 같이 파일 접근에 실패하는 경우.

$f = '/PATH/TO/FILENAME';
 
// true
var_dump(file_exists($f));
 
// false
var_dump(is_readable($f));
 
// error
require_once $f;
 
Warning:  require_once(/PATH/TO/FILENAME): failed to open stream: Permission denied in /PATH/TO/HOSTFILE on line 10
Fatal error:  require_once(): Failed opening required '/PATH/TO/FILENAME' (include_path='.:/usr/share/pear:/usr/share/php') in /PATH/TO/HOSTFILE on line 10

 

 

SELinux(Security Enhanced Linux)의 문제일 수 있음.
ls -l 했을 때 퍼미션 부분의 뒷쪽에 점(.)이 나오면 SELinux 보안 컨텍스트가 실행되고 있는 것.

[root@hostname]# ls -al
합계 16
drwxr-xr-x.  3 root root 4096  3월 23 15:58 .
drwxr-xr-x. 17 root root 4096  4월  7 10:15 ..
drwxr-xr-x.  3 root root 4096  4월 16 18:02 dir
-rw-r--r--.  1 root root   98  3월 23 15:58 index.php

 

 

SELinux의 보안 컨텍스트는 ls -Z 로 확인가능.

[root@hostname]# ls -Z
drwxr-xr-x. root root unconfined_u:object_r:etc_t:s0 dir
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.php

 

 

unconfined_u:object_r:httpd_sys_content_t:s0 <- 이 부분이 SELinux 보안 컨텍스트인데 자세한 내용은 생략하고,

: 를 기준으로 나눈 3번째 항목인 값인 Type Enforcement 부분이 중요함. 

 

dir은 etc_t 이고 index.php는 httpd_sys_content_t 이다.

 

웹서버 프로세스의 SELinux 값을 출력해보면 아래처럼 나옴.

[root@hostname]# ps -ZC httpd
LABEL                             PID TTY          TIME CMD
system_u:system_r:httpd_t:s0    11872 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11873 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11874 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11875 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11876 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11878 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11881 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11882 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0    11883 ?        00:00:00 httpd

 

 

httpd 프로세스의 Type Enforcement 값이 httpd_t 이므로 관련 권한만 접근이 가능함.

그러므로 httpd_sys_content_t인 index.php는 접근이 가능하지만 etc_t인 dir은 접근이 불가능함.

 

이 문제를 해결하려면 httpd가 접근이 가능하도록 해당 경로의 Type Enforcement를 수정해줘야 함.

// -R 옵션으로 하위 경로까지 전부 변경
[root@hostname]# chcon -R -t httpd_sys_content_t ./dir
 
// 확인
[root@hostname]# ls -Z
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 dir
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.php

 

 

이제 PHP 에서 dir 경로의 파일들에 접근이 가능함.


참고로 httpd_sys_content_t 는 readonly 이며, 쓰기가 필요할 경우엔 httpd_sys_rw_content_t 로 변경해줘야 함.

자세한 타입들은 다음 페이지 참조.

access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-managing_confined_services-the_apache_http_server-types

 

 

 

 

 

 

 

Posted by bloodguy
,