웹서버 보안을 위한 예방책으로 mod_suphp라는 아파치 웹서버 모듈을 소개하고자 합니다.
해외에서는 suPHP가 이미 널리 사용되고 있는 모양입니다. 그러나 국내엔 구글링 등을 통해 관련 한글문서를 검색해도 거의 자료가 나오지 않더군요. suPHP의 국내 확산을 위해 문서를 한 번 만들어 보았습니다.
▲ 원문출처: http://cafe.naver.com/ArticleRead.nhn?clubid=10576009&articleid=7351
사실 제 경우는 보안 문제를 떠나서 suPHP 도입이 상당히 끌리는 이유가 따로 있었으니 바로 웹호스팅 환경에서 계정별 디스크 quota 설정이 보다 더 용이해진다는 점이었습니다.
아파치 웹서버를 사용하는 경우 웹상에서 첨부파일 형식으로 업로드된 데이터의 경우는 해당 계정 소유권이 아닌 아파치 웹서버 소유권(nobody 또는 apache)으로 올라가기에 해당 계정의 홈디렉토리에서 아파치 소유권으로 올라가 있는 데이터는 nobody 또는 apache 계정의 쿼터 수치로 따로 계산되는 quota 설정의 맹점을 극복하기가 어려워질 수 밖에 없습니다.
그러나 suPHP를 도입하면 웹으로 데이터를 업로드한다 하더라도 아파치 웹서버 소유권이 아닌 해당 계정의 소유권으로만 올라가기에 정확한 쿼터 설정이 가능하게 됩니다.
이렇게 되면 또 하나 반가운 장점이 생기게 되는데 제로보드4, 그누보드, 텍스트큐브, XE 등과 같은 게시판 어플을 사용시 기존 아파치 소유권으로만 데이터가 들어가던 디렉토리와 파일을 FTP나 SSH 상에서 삭제할 수 없던 문제점도 해결된다는 겁니다.
위 2가지 장점만으로도 웹호스팅을 운영하고 있거나 운영을 계획하고 있던 분들께는 반가운 소식이 될 것으로 봅니다.
보안상 얻을 수 있는 장점으로는 shPHP 설정으로 디렉토리는 755, 파일은 644 이상의 퍼미션을 부여하지 않아도 정상적인 웹서비스가 가능해진다는 것입니다. other 퍼미션에 쓰기 권한을 주어야 설치가 가능했던 제로보드4, 그누보드 등을 비롯한 각종 어플리케이션을 설치할 때엔 707이나 777 퍼미션을 줄 필요 없이 그냥 설치를 진행하면 됩니다. 취약한 707, 777 퍼미션을 허용하지 않으니 웹크래킹 예방에 큰 도움이 될 수 있겠죠.
이렇게 보안과 기능상 이점을 두루 얻을 수 있는 suPHP를 CentOS 5.x 32bit에 도입해 보도록 하겠습니다.
APM 구성: Apache 2.0.63, PHP 5.2.10, MySQL 5.0.77, Zend Optimizer 3.3.3
suPHP 설치의 핵심은 php 설치 방식의 변화에 있습니다. 각종 문서에 두루 소개되어 있는 아파치 웹서버에 모듈형으로 연동하는 PHP엔 suPHP를 적용할 수 없습니다. PHP를 CGI 바이너리 형태로 설치해야 합니다.
▼ apache 컴파일 옵션 (prefork가 아닌 worker 방식으로 설치할 경우 suphp 작동 시 아파치 에러 로그에 child process 관련 에러를 내뿜는 경우가 있어 prefork로 설치할 것을 권장합니다)
▼ php 컴파일 옵션
APM 구성이 끝났으면 이제 mod_suphp 최신 소스를 배포 사이트에서 받아 설치합니다.
apr 패키지를 필요로 하므로 apr 관련 패키지를 먼저 설치합니다.
▼ apr 패키지 설치
▼ suPHP 모듈 설치(DSO 방식으로 추가)
▼ 아파치 httpd.conf에 아래 설정 추가
▼ suphp.conf 파일 설정
▼ apache 가상호스트 설정(푸른색으로 추가한 부분)
DocumentRoot /home/aaa/www
ServerName www.aaa.com
ServerAlias aaa.com
suPHP_Engine On
suPHP_UserGroup aaa aaa
AddHandler x-httpd-php .html .htm .php .php3 .php4 .php5 .phtml .cgi .inc
suPHP_AddHandler x-httpd-php .html .htm .php .php3 .php4 .php5 .phtml .cgi .inc
이제 제로보드나 그누보드 등을 설치해 보시기 바랍니다.
707, 777 퍼미션 변경을 어플리케이션에서 요구할 것이나 보안상 suPHP가 이를 막습니다. 퍼미션 변경 없이 그대로 진행 가능합니다.
그리고 게시판 상에서 파일을 첨부한 뒤 해당 파일이 업로드되어 있는 경로를 FTP나 SSH 쉘상에서 확인해 보면 종전까지는 nobody나 apache와 같은 웹서버 소유권으로만 올라가던 것이 이젠 해당 계정의 소유권으로 올라가 있는 것을 확인할 수 있을 것입니다.
이렇게 suPHP의 장점을 강조하며 포스팅을 해 보았으나 실제 테스트를 해 보니 이미 서비스 중인 웹서버에 도입하기에는 쉽지 않은 작업이 될 것으로 보입니다.
일단 제로보드4, 그누보드, XE, 텍스트큐브와 같은 각종 어플리케이션을 초기 설정값 그대로 사용하기에는 조금 어려운 점이 있을 수 있습니다. 설치 단계나 실 운영 중에 디렉토리나 파일 퍼미션을 707이나 777로 강제하는 소스가 있기 때문이죠. 제로보드4의 경우엔 기본 게시판 소스 뿐만 아니라 각종 플러그인, 스킨 게시판 소스 상에서의 적절한 수정 작업이 불가피했습니다.
일단 제로보드4의 경우 아래 소스는 필수적으로 수정해야 하는 것으로 테스트 결과 확인하였습니다.
bbs/lib.php 파일의 아래 부분 수정(994번째 줄 근처, 붉은색 부분처럼 수정)
널리 사용되는 또다른 어플 중 하나인 XE(XpressEngine)의 경우는 게시판 설치 및 초기 운영 단계에서는 소스 수정이 필요 없었습니다.
어쨌든 여타 다른 어플리케이션의 경우 소스 수정이 불가피한 경우가 생긴다면 위에 소개한 제로보드4 소스 수정의 경우과 같이 게시물 작성 및 수정, 첨부파일 업로드 등에 관여하는 소스에서 퍼미션을 707 이상으로 강제하는 부분을 수정해야 하는 때일 것입니다.
그리고 또 하나 난관으로 작용하는 점이 있습니다. 아파치의 버추얼호스트 설정에서 root 소유권의 디렉토리 영역을 DocumentRoot 옵션으로 잡아 운영하고 있는 각종 소스에 대한 문제입니다. 주로 mrtg, webalizer, squirrelmail과 같은 웹브라우저를 통한 제어 및 열람을 지원하는 어플리케이션들이 이에 해당합니다.
suPHP는 보안상 UID/GID 500 이상의 시스템 계정 소유권에 한해서만 755, 644 퍼미션 이하의 디렉토리 및 파일의 웹접근을 허용하고자 하는 취지에서 고안되어 나온 모듈입니다. mrtg, webalizer 등의 문제까지 해결하고자 한다면 root를 비롯한 UID/GID 500 이하의 계정에도 suPHP를 통한 웹접근이 가능토록 suphp.conf 파일의 min_uid=500 , min_gid=500 옵션의 수치를 하향 조정하는 수 밖에 없게 되는데 이렇게 하면 보안으로서의 의미가 퇴색될 수 밖에 없습니다.
이를 극복하려면 cron을 이용하여 root로 생성되어 있는 파일을 주기적으로 특정 계정 소유권으로 강제 변환시키거나 suPHP를 적용하지 않는 Apache + PHP 세트를 하나 더 설치해서 운영하면 됩니다. 그리고 포트는 80번을 피한 다른 포트를 이용해야 하겠죠.
지금까지 suPHP 설치 방법과 장단점을 간략하게나마 열거해 보았습니다. 검색 사이트에서 수집되는 정보들만 확인한 바로는 국내엔 도입 사례가 많지 않은 것으로 보입니다. suPHP 환경에서 정상 작동하는 어플리케이션에 관한 정확한 정보 확산을 위해서는 suPHP 설치에 관한 자료가 먼저 확산되길 바라는 수 밖에 없겠습니다.
끝으로 본 문서를 작성하는데 큰 도움을 주신 스타호스트(http://starhost.co.kr) 운영자님께 깊은 감사의 뜻을 전합니다. 스타호스트님께서 suPHP 지원 어플리케이션 리스트를 계속 업데이트 중이시니 아래 URL 참고하시기 바랍니다.
해외에서는 suPHP가 이미 널리 사용되고 있는 모양입니다. 그러나 국내엔 구글링 등을 통해 관련 한글문서를 검색해도 거의 자료가 나오지 않더군요. suPHP의 국내 확산을 위해 문서를 한 번 만들어 보았습니다.
suPHP란?
suPHP 는 일종의 PHP wrapper 기능과 Apache module (mod_suphp) 를 제공한다고 보면 된다.
각 사용자들의 cgi-bin 디렉토리에 PHP 바이너리를 넣지 않고도 PHP 스크립트를 실행할 수 있도록 하여주며 아파치의 suExec 를 필요로 하지도 않는다.
또한 로깅 기능도 제공하여 주고 있다.
suPHP 는 일종의 PHP wrapper 기능과 Apache module (mod_suphp) 를 제공한다고 보면 된다.
각 사용자들의 cgi-bin 디렉토리에 PHP 바이너리를 넣지 않고도 PHP 스크립트를 실행할 수 있도록 하여주며 아파치의 suExec 를 필요로 하지도 않는다.
또한 로깅 기능도 제공하여 주고 있다.
▲ 원문출처: http://cafe.naver.com/ArticleRead.nhn?clubid=10576009&articleid=7351
사실 제 경우는 보안 문제를 떠나서 suPHP 도입이 상당히 끌리는 이유가 따로 있었으니 바로 웹호스팅 환경에서 계정별 디스크 quota 설정이 보다 더 용이해진다는 점이었습니다.
아파치 웹서버를 사용하는 경우 웹상에서 첨부파일 형식으로 업로드된 데이터의 경우는 해당 계정 소유권이 아닌 아파치 웹서버 소유권(nobody 또는 apache)으로 올라가기에 해당 계정의 홈디렉토리에서 아파치 소유권으로 올라가 있는 데이터는 nobody 또는 apache 계정의 쿼터 수치로 따로 계산되는 quota 설정의 맹점을 극복하기가 어려워질 수 밖에 없습니다.
그러나 suPHP를 도입하면 웹으로 데이터를 업로드한다 하더라도 아파치 웹서버 소유권이 아닌 해당 계정의 소유권으로만 올라가기에 정확한 쿼터 설정이 가능하게 됩니다.
이렇게 되면 또 하나 반가운 장점이 생기게 되는데 제로보드4, 그누보드, 텍스트큐브, XE 등과 같은 게시판 어플을 사용시 기존 아파치 소유권으로만 데이터가 들어가던 디렉토리와 파일을 FTP나 SSH 상에서 삭제할 수 없던 문제점도 해결된다는 겁니다.
위 2가지 장점만으로도 웹호스팅을 운영하고 있거나 운영을 계획하고 있던 분들께는 반가운 소식이 될 것으로 봅니다.
보안상 얻을 수 있는 장점으로는 shPHP 설정으로 디렉토리는 755, 파일은 644 이상의 퍼미션을 부여하지 않아도 정상적인 웹서비스가 가능해진다는 것입니다. other 퍼미션에 쓰기 권한을 주어야 설치가 가능했던 제로보드4, 그누보드 등을 비롯한 각종 어플리케이션을 설치할 때엔 707이나 777 퍼미션을 줄 필요 없이 그냥 설치를 진행하면 됩니다. 취약한 707, 777 퍼미션을 허용하지 않으니 웹크래킹 예방에 큰 도움이 될 수 있겠죠.
이렇게 보안과 기능상 이점을 두루 얻을 수 있는 suPHP를 CentOS 5.x 32bit에 도입해 보도록 하겠습니다.
APM 구성: Apache 2.0.63, PHP 5.2.10, MySQL 5.0.77, Zend Optimizer 3.3.3
suPHP 설치의 핵심은 php 설치 방식의 변화에 있습니다. 각종 문서에 두루 소개되어 있는 아파치 웹서버에 모듈형으로 연동하는 PHP엔 suPHP를 적용할 수 없습니다. PHP를 CGI 바이너리 형태로 설치해야 합니다.
▼ apache 컴파일 옵션 (prefork가 아닌 worker 방식으로 설치할 경우 suphp 작동 시 아파치 에러 로그에 child process 관련 에러를 내뿜는 경우가 있어 prefork로 설치할 것을 권장합니다)
[root@localhost ~]# ./configure --prefix=/usr/local/apache --enable-mods-shared=all --enable-ssl --with-mpm=prefork --enable-suexec --with-suexec --with-suexec-caller=nobody --with-suexec-docroot=/home --with-suexec-logfile=/usr/local/apache/logs/suexec.log --with-suexec-uidmin=500 --with-suexec-gidmin=500 --enable-cgid --enable-cache --enable-disk-cache --enable-mem-cache --enable-deflate
▼ php 컴파일 옵션
[root@localhost ~]# ./configure --prefix=/usr/local/php --enable-mod-charset --enable-safe-mode --enable-sigchild --enable-magic-quotes --with-libxml-dir --with-openssl --with-zlib --with-zlib-dir --with-bz2 --enable-calendar --with-curl --enable-dba --with-gdbm --enable-exif --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --with-ttf --with-freetype-dir --enable-gd-native-ttf --with-gettext --with-imap --with-imap-ssl --with-kerberos --enable-mbstring --with-mhash --with-mcrypt --with-mysql=/usr/local/mysql --enable-sockets --with-regex=php --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --enable-zend-multibyte --enable-force-cgi-redirect --enable-fastcgi
※ 여태 아파치에 DSO 방식으로 php를 연동해서 쓰던 옵션에서 다른 부분은 크게 손 볼 필요 없이 --with-apxs(아파치 2.x.x의 경우 --with-apxs2)만 제거하고 --enable-force-cgi-redirect --enable-fastcgi 옵션만 추가해 주면 무난하게 적용 가능할 것입니다.APM 구성이 끝났으면 이제 mod_suphp 최신 소스를 배포 사이트에서 받아 설치합니다.
apr 패키지를 필요로 하므로 apr 관련 패키지를 먼저 설치합니다.
▼ apr 패키지 설치
[root@localhost ~]# yum -y install apr apr-devel
▼ suPHP 모듈 설치(DSO 방식으로 추가)
[root@localhost ~]# wget http://suphp.org/download/suphp-0.7.1.tar.gz
[root@localhost ~]# tar xvfz suphp-0.7.1.tar.gz
[root@localhost ~]# cd suphp-0.7.1
[root@localhost suphp-0.7.1]# ./configure --sysconfdir=/usr/local/apache/conf --with-apr=/usr/bin/apr-1-config --with-apxs=/usr/local/apache/bin/apxs --with-apache-user=nobody --with-php=/usr/local/php/bin/php-cgi
[root@localhost suphp-0.7.1]# make
[root@localhost suphp-0.7.1]# make install
[root@localhost ~]# tar xvfz suphp-0.7.1.tar.gz
[root@localhost ~]# cd suphp-0.7.1
[root@localhost suphp-0.7.1]# ./configure --sysconfdir=/usr/local/apache/conf --with-apr=/usr/bin/apr-1-config --with-apxs=/usr/local/apache/bin/apxs --with-apache-user=nobody --with-php=/usr/local/php/bin/php-cgi
[root@localhost suphp-0.7.1]# make
[root@localhost suphp-0.7.1]# make install
▼ 아파치 httpd.conf에 아래 설정 추가
LoadModule suphp_module modules/mod_suphp.so
▼ suphp.conf 파일 설정
[root@localhost ~]# cat /usr/local/apache/conf/suphp.conf [global]
;Path to logfile
logfile=/usr/local/apache/logs/suphp.log
;Loglevel
loglevel=info
;User Apache is running as
webserver_user=nobody
;Path all scripts have to be in
docroot=/usr/local/apache/htdocs:${HOME}/www
;Path to chroot() to before executing script
;chroot=/mychroot
; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=false
;PATH environment variable
env_path=/bin:/usr/bin
;Umask to set, specify in octal notation
umask=022
; Minimum UID
min_uid=500
; Minimum GID
min_gid=500
[handlers]
;Handler for php-scripts
x-httpd-php="php:/usr/local/php/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi="execute:!self"
[root@localhost ~]#
;Path to logfile
logfile=/usr/local/apache/logs/suphp.log
;Loglevel
loglevel=info
;User Apache is running as
webserver_user=nobody
;Path all scripts have to be in
docroot=/usr/local/apache/htdocs:${HOME}/www
;Path to chroot() to before executing script
;chroot=/mychroot
; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=false
;PATH environment variable
env_path=/bin:/usr/bin
;Umask to set, specify in octal notation
umask=022
; Minimum UID
min_uid=500
; Minimum GID
min_gid=500
[handlers]
;Handler for php-scripts
x-httpd-php="php:/usr/local/php/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi="execute:!self"
[root@localhost ~]#
▼ apache 가상호스트 설정(푸른색으로 추가한 부분)
DocumentRoot /home/aaa/www
ServerName www.aaa.com
ServerAlias aaa.com
suPHP_Engine On
suPHP_UserGroup aaa aaa
AddHandler x-httpd-php .html .htm .php .php3 .php4 .php5 .phtml .cgi .inc
suPHP_AddHandler x-httpd-php .html .htm .php .php3 .php4 .php5 .phtml .cgi .inc
이제 제로보드나 그누보드 등을 설치해 보시기 바랍니다.
707, 777 퍼미션 변경을 어플리케이션에서 요구할 것이나 보안상 suPHP가 이를 막습니다. 퍼미션 변경 없이 그대로 진행 가능합니다.
그리고 게시판 상에서 파일을 첨부한 뒤 해당 파일이 업로드되어 있는 경로를 FTP나 SSH 쉘상에서 확인해 보면 종전까지는 nobody나 apache와 같은 웹서버 소유권으로만 올라가던 것이 이젠 해당 계정의 소유권으로 올라가 있는 것을 확인할 수 있을 것입니다.
이렇게 suPHP의 장점을 강조하며 포스팅을 해 보았으나 실제 테스트를 해 보니 이미 서비스 중인 웹서버에 도입하기에는 쉽지 않은 작업이 될 것으로 보입니다.
일단 제로보드4, 그누보드, XE, 텍스트큐브와 같은 각종 어플리케이션을 초기 설정값 그대로 사용하기에는 조금 어려운 점이 있을 수 있습니다. 설치 단계나 실 운영 중에 디렉토리나 파일 퍼미션을 707이나 777로 강제하는 소스가 있기 때문이죠. 제로보드4의 경우엔 기본 게시판 소스 뿐만 아니라 각종 플러그인, 스킨 게시판 소스 상에서의 적절한 수정 작업이 불가피했습니다.
일단 제로보드4의 경우 아래 소스는 필수적으로 수정해야 하는 것으로 테스트 결과 확인하였습니다.
bbs/lib.php 파일의 아래 부분 수정(994번째 줄 근처, 붉은색 부분처럼 수정)
// 파일을 삭제하는 함수
function z_unlink($filename) {
@chmod($filename,0755);
$handle = @unlink($filename);
if(@file_exists($filename)) {
@chmod($filename,0755);
$handle=@unlink($filename);
}
return $handle;
}
function z_unlink($filename) {
@chmod($filename,0755);
$handle = @unlink($filename);
if(@file_exists($filename)) {
@chmod($filename,0755);
$handle=@unlink($filename);
}
return $handle;
}
널리 사용되는 또다른 어플 중 하나인 XE(XpressEngine)의 경우는 게시판 설치 및 초기 운영 단계에서는 소스 수정이 필요 없었습니다.
어쨌든 여타 다른 어플리케이션의 경우 소스 수정이 불가피한 경우가 생긴다면 위에 소개한 제로보드4 소스 수정의 경우과 같이 게시물 작성 및 수정, 첨부파일 업로드 등에 관여하는 소스에서 퍼미션을 707 이상으로 강제하는 부분을 수정해야 하는 때일 것입니다.
그리고 또 하나 난관으로 작용하는 점이 있습니다. 아파치의 버추얼호스트 설정에서 root 소유권의 디렉토리 영역을 DocumentRoot 옵션으로 잡아 운영하고 있는 각종 소스에 대한 문제입니다. 주로 mrtg, webalizer, squirrelmail과 같은 웹브라우저를 통한 제어 및 열람을 지원하는 어플리케이션들이 이에 해당합니다.
suPHP는 보안상 UID/GID 500 이상의 시스템 계정 소유권에 한해서만 755, 644 퍼미션 이하의 디렉토리 및 파일의 웹접근을 허용하고자 하는 취지에서 고안되어 나온 모듈입니다. mrtg, webalizer 등의 문제까지 해결하고자 한다면 root를 비롯한 UID/GID 500 이하의 계정에도 suPHP를 통한 웹접근이 가능토록 suphp.conf 파일의 min_uid=500 , min_gid=500 옵션의 수치를 하향 조정하는 수 밖에 없게 되는데 이렇게 하면 보안으로서의 의미가 퇴색될 수 밖에 없습니다.
이를 극복하려면 cron을 이용하여 root로 생성되어 있는 파일을 주기적으로 특정 계정 소유권으로 강제 변환시키거나 suPHP를 적용하지 않는 Apache + PHP 세트를 하나 더 설치해서 운영하면 됩니다. 그리고 포트는 80번을 피한 다른 포트를 이용해야 하겠죠.
지금까지 suPHP 설치 방법과 장단점을 간략하게나마 열거해 보았습니다. 검색 사이트에서 수집되는 정보들만 확인한 바로는 국내엔 도입 사례가 많지 않은 것으로 보입니다. suPHP 환경에서 정상 작동하는 어플리케이션에 관한 정확한 정보 확산을 위해서는 suPHP 설치에 관한 자료가 먼저 확산되길 바라는 수 밖에 없겠습니다.
끝으로 본 문서를 작성하는데 큰 도움을 주신 스타호스트(http://starhost.co.kr) 운영자님께 깊은 감사의 뜻을 전합니다. 스타호스트님께서 suPHP 지원 어플리케이션 리스트를 계속 업데이트 중이시니 아래 URL 참고하시기 바랍니다.