Exercícios para compreender o funcionamento dos módulos PHP e suPHP

Publicado: 18/01/2013 em Linux, Programação, Serviços IP
Tags:,

Os testes foram realizados em uma máquina alvo com:
Linux kernel 2.6.32
SO GNU Linux/Debian 6 (Squeeze)
Servidor de página Apache/2.2.16 (Debian)

Esta máquina servidora fora acessada de uma outra, a máquina do usuário, através de um navegador.

1. Preparar o ambiente para os testes
a) Instalações necessárias na máquina servidora
# apt-get install apache2 apache2-utils apache2-doc php5 libapache2-mod-suphp

b) Criar um usuário web1 e a pasta para realização dos testes na máquina servidora, definindo uma senha e as propriedades da pasta:
# useradd web1
# passwd web1    (será solicitado um password para o usuário web1)
# mkdir /var/www/client1
# chown web1:web1 /var/www/client1/

c) Na máquina do usuário, colocar na tabela de hosts (/etc/hosts) o resolvedor de nome da máquina servidora para facilitar os testes:
192.168.1.5    www.meusitio.com    meusitio.com

d) Preparar a máquina servidora para escutar a porta 8080 nestes testes  (apenas uma conveniência, não é uma exigência).
No arquivo /etc/apache2/ports.conf, trocar as diretivas de portas ficando do seguinte modo:

NameVirtualHost *:8080
Listen 8080
# /etc/init.d/apache2 restart

e) Resultados principais desta etapa de preparação:
– módulos PHP e suPHP do Apache instalados;
– usuário e pasta para execução dos testes criados.

2. Construir um site virtual para auxiliar nos testes
Criar o arquivo de configuração de host virtual /etc/apache2/sites-available/meusitio com o seguinte conteúdo:

<VirtualHost *:8080>
      ServerAdmin webmaster@localhost
      ServerName www.meusitio.com
      ServerAlias meusitio.com
      DocumentRoot /var/www/client1
      <Directory />
           Options FollowSymLinks
           AllowOverride None
      </Directory>
      <Directory /var/www/client1/>
           Options Indexes FollowSymLinks MultiViews
           AllowOverride None
           Order allow,deny
           allow from all
      </Directory>
      ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
      <Directory "/usr/lib/cgi-bin">
           AllowOverride None
           Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
           Order allow,deny
           Allow from all
      </Directory>
      ErrorLog ${APACHE_LOG_DIR}/error.log
      # Possible values include: debug, info, notice, warn, error, crit,
      # alert, emerg.
      LogLevel warn
      CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

O que é importante observar agora neste arquivo:
– existindo arquivos PHP na pasta /var/www/client1/ estes serão executados pelo módulo PHP do Apache, e não pelo módulo suPHP.

3. Teste-1: módulo Apache PHP utilizado
Condição: módulos PHP e suPHP habilitados, mas módulos rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 2 acima.
Crie o arquivo /var/www/client1/index.php  com o seguinte conteúdo:
<?php phpinfo();?>

Fixe as permissões da seguinte forma:
# chmod 777 /var/www/client1/index.php
# chmod 777 /var/www/client1/

Acesse a partir de um navegador da máquina do usuário a URL http://meusitio.com  para obter a página normalmente contendo informações de configuração do ambiente PHP instalado.
Conclusão: módulo Apache PHP sendo utilizado normalmente, e executando o script PHP solicitado.

4. Teste-2: módulo Apache PHP buscado pelo Apache e não encontrado
Condição: módulo suPHP habilitado, mas módulos PHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 2 acima.
Desinstalar o módulo PHP.
# a2dismod php5
# /etc/init.d/apache2 restart

Novamente com o navegador da máquina do usuário acessar o sítio preparado. A resposta será a tradicional mensagem de erro interno:

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Conclusão: módulo PHP5 não encontrado, encaminhando uma mensagem de erro interno.

5. Teste-3: módulo suPHP buscado pelo Apache, mas requisitos de segurança provocam erro de execução e script não é executado.
Condição: módulo suPHP habilitado, e módulos PHP, rewrite e suexec desabilitados. Nova configuração do host virtual do Apache.
Modifique  o arquivo de host virtual /etc/apache2/sites-available/meusitio de forma a possibitar a chamada do módulo suPHP pelo Apache:

<VirtualHost *:8080>
       ServerAdmin webmaster@localhost
       ServerName www.meusitio.com  
       ServerAlias meusitio.com
       DocumentRoot /var/www/client1
       <Directory />
            Options FollowSymLinks
            AllowOverride None
       </Directory>
       <Directory /var/www/client1/>
             Options Indexes FollowSymLinks MultiViews
             AllowOverride None
             Order allow,deny
             allow from all
             <IfModule mod_suphp.c>
                  <FilesMatch "\.ph(p3?|tml)$">
                  SetHandler application/x-httpd-suphp
                  suPHP_AddHandler application/x-httpd-suphp
                  </FilesMatch>
             </IfModule>
       </Directory>
       ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
       <Directory "/usr/lib/cgi-bin">
             AllowOverride None
             Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
             Order allow,deny
             Allow from all
       </Directory>
       ErrorLog ${APACHE_LOG_DIR}/error.log
       # Possible values include: debug, info, notice, warn, error, crit,
       # alert, emerg.
       LogLevel warn
       CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

É importante observar agora neste arquivo:
caso esteja o módulo suphp habilitado, o script PHP será executado no modo CGI, sob o “wrapper” suphp.

Conclusão: A resposta será a tradicional mensagem de erro interno, conforme teste anterior, mas por outro motivo:  por requisitos de segurança, o suPHP só executa o arquivo de script PHP se as permissões de sua pasta e do próprio arquivo não contrariarem certas regras de segurança definidas em seu arquivo de configuração localizado em /etc/suphp/suphp.conf:
; Security options
allow_file_group_writeable=
allow_file_others_writeable=
allow_directory_group_writeable=
allow_directory_others_writeable=

Se todas estas quatro diretivas de segurança contiverem a indicação “false”, então as permissões da pasta e do arquivo de script PHP  (index.php) não poderão ser superiores a 755 e 644 respectivamente.  Como estavam com 777, motivou o erro.

Pode-se fazer algumas combinações de valores (como as abaixo) e verificar que sempre a resposta na tela do navegador será de indicação de erro:
pasta    –    arquivo
777    –    644
757    –    644
755    –    664
752    –    700
e assim por diante.

Além do resultado mostrado na tela do navegador, estes poderão ser também observados através dos arquivos de log:
/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/suphp/suphp.log

No entanto, se as diretivas de segurança do arquivo de configuração do suPHP forem alteradas, estes valores limitantes de 755 e 644 se deslocarão (sofrerão alterações, portanto).

Vejamos com mais atenção o que significa aquelas diretivas de segurança do suPHP, considerado o octeto “rwx” das permissões de pastas e arquivos:

  • allow_directory_group_writeable: negar a gravação de arquivos ou outros diretórios ao grupo, significa r_x para o octeto da pasta referente ao grupo.
  • allow_directory_others_writeable: idem anterior, referente aos “outros” usuários.

Assim, a permissão máxima para a pasta é 755.
Para os arquivos, o suPHP não permite execução de scripts PHP apenas sua leitura e interpretação.  Assim já se tem rw_.

  • allow_file_group_writeable: negar escrita ao grupo, acumula a permissão r__ ao grupo.
  • allow_file_others_writeable: negar escrita aos outros, acumula a permissão r__ aos outros.

Assim, tem-se o máximo 644 par arquivos. Para os arquivos, 644 significa “owner” com permissão de leitura e gravação, grupo com permissão somente de leitura, outros com permissão somente de leitura.

6. Teste-4:  módulo suPHP ativado pelo Apache, mas requisitos de segurança geram novos erros de execução
Condição: módulo suPHP habilitado, mas módulos PHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 5 acima.

Com o suPHP o proprietário da pasta tem que ser o proprietário do arquivo.  Se isto não acontecer, mesmo que tenhamos 755/644 de permissões, teremos um erro interno de servidor.  Para realização deste teste, modifique o proprietário da pasta e verifique o erro mostrado na tela do navegador:
# chown root:web1 /var/www/client1/

Depois disso, pode-se fazer outras combinações (trocando o proprietário do arquivo) e observar novos casos de erros.  Ou seja, com o suPHP o proprietário da pasta tem de ser obrigatoriamente o proprietário do arquivo.

7. Teste-5: módulo PHP ativado e executa normalmente o arquivo independentemente de permissões e de quem seja o proprietário.

Condição: módulo PHP habilitado, e módulos suPHP, rewrite e suexec desabilitados. Arquivo de host virtual do Apache conforme item 5 acima.
Desabilitar o módulo suPHP e habilitar de volta o módulo PHP conforme comandos abaixo:
# a2dismod suphp
# a2enmod php5
# /etc/init.d/apache2 restart

Observar que agora quem será chamado pelo Apache para interpretar o script PHP é o módulo PHP.  Faça algumas combinações entre o proprietário da pasta e do arquivo PHP, deixando-os diferentes entre si. Com o navegador acesse a URL que será executado o script index.php e veja que o mesmo é executado sem problemas independentemente dos proprietários desencontrados entre pasta/arquivo.

Agora altere as permissões da pasta e do arquivo para valores altos (portanto, de maior risco de segurança para o sistema), e veja que o script PHP é novamente sempre executado sem problemas.

Conclusão geral:  a execução de escripts através do módulo suPHP é muito mais segura, oferecendo menores risco para o sistema.

8. Aproveitando para comparar os ambientes PHP
Os contextos PHP são diferentes quando o script PHP é executado através de mod_php e mod_suphp. Isso se torna evidente desde o primeiro momento quando se percebe que os dois módulo utilizam php.ini diferentes:
módulo PHP: utiliza /etc/php5/apache2/php.ini
módulo suPHP: utiliza /etc/php5/cgi/php.ini

Veja o quadro comparativo (a partir do resultado da chamada da função PHP phpinfo()):

Geral
Server API Apache 2.0 Handler CGI/FastCGI
Configuration File (php.ini) Path /etc/php5/apache2 /etc/php5/cgi
Loaded Configuration File /etc/php5/apache2 /etc/php5/cgi
Scan this dir for additional .ini files /etc/php5/apache2/conf.d /etc/php5/cgi/conf.d
Apache Environment
DOCUMENT_ROOT /var/www/client1 /var/www/client1
SCRIPT_FILENAME /var/www/client1/index.php /var/www/client1/index.php
GATEWAY_INTERFACE CGI/1.1 CGI/1.1
SCRIPT_NAME /index.php /index.php
Environment
APACHE_RUN_DIR /var/run/apache2
APACHE_RUN_GROUP www-data
APACHE_RUN_USER www-data
APACHE_LOG_DIR /var/log/apache2
apache2handler
User/Group www-data(33)/33
Loaded Modules core mod_log_config mod_logio prefork http_core mod_so mod_alias mod_auth_basic mod_authn_file mod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_autoindex mod_cgi mod_deflate mod_dir mod_env mod_mime mod_negotiation mod_php5 mod_reqtimeout mod_setenvif mod_status
PHP Variables
_SERVER[“HTTP_ACCEPT”] text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
_SERVER[“HTTP_CONNECTION”] keep-alive keep-alive
_SERVER[“PATH”] /usr/local/bin:/usr/bin:/bin /bin
_SERVER[“SCRIPT_FILENAME”] /var/www/client1/index.php /var/www/client1/index.php
_SERVER[“GATEWAY_INTERFACE”] CGI/1.1 CGI/1.1
_SERVER[“SERVER_PROTOCOL”] HTTP/1.1 HTTP/1.1
cgi-fcgi
cgi.discard_path 0
fastcgi.logging 1
Core
PHP Version 5.3.3-7+squeeze14 5.3.3-7+squeeze14
include_path .:/usr/share/php:/usr/share/pear .:/usr/share/php:/usr/share/pear

9. Um FAQ rápido para ajudar a entender um pouquinho a mais

1- Quais os modos de funcionamento do Apache com o PHP aqui tratados neste post?
Fizemos testes com dois modos de funcionamento:
– utilizando o interpretador PHP como um módulo embutido (“built-in”) do Apache (mod_php);
– utilizando o interpretador PHP como um binário CGI, através da aplicação “wrapper” suphp (módulo suphp).

2- Que módulos próximos ao tema NÃO foram utilizados?
Não foram utilizados os seguintes módulos:
cgi
rewrite
suexec

Estes módulos ficaram desabilitados (a2dismod) ou até mesmo nem sequer carregados do repositório para a máquina.

3- Então posso carregar apenas o módulo PHP ou apenas o módulo suPHP e já poder executar scripts PHP?
Exatamente. Entretanto, executar scripts PHP através do módulo suPHP é mais seguro para o ambiente. No entanto, é mais lento e exigem alguns cuidados quanto a configurações por parte do usuário.

4- Então o que devo usar: PHP ou suPHP?
O suPHP diminui os riscos para o ambiente computacional. Vale a pena sempre buscar utilizar o suPHP para executar scripts PHP, apesar de um performance menor que o funcionamento com mod_php.

5- Como os módulos PHP e suPHP são referenciados no repositório Debian e facilmente localizados pelo Synaptic ?
Para o módulo PHP: procure o pacote php5. Marcando este pacote e fazendo sua instalação, o servidor de páginas Apache já pode responder a solicitações de páginas dinâmicas com scripts PHP simples. Não necessita de mais nada. Para instalar, carregue pacote “PHP”:
# apt-get install php5


Para o módulo suPHP: procure o pacote libapache2-mod-suphp. Marcando este pacote e fazendo sua instalação, o servidor de páginas Apache já pode responder a solicitações de páginas dinâmicas com scripts PHP simples. Não necessita de mais nada. Para instalar, carregue o pacote “libapache2-mod-suphp”:
# apt-get install libapache2-mod-suphp

6- Como habilitar e desabilitar os módulos necessários?
Simples, usando comandos como os exemplificados aqui:
# a2dismod cgi rewrite suexec
# a2enmod php5 suphp
# /etc/init.d/apache2 restart

7- Os módulos exigem configurações específicos depois de carregados?
Alguns sim, outros não. O módulo PHP não exige. Já o módulo suPHP tem seu módulo de configuração em /etc/suphp/suphp.conf.
No entanto é importante perceber que o ambiente PHP pode ser alterado através das variáveis do arquivo php.ini que é lido pelo interpretador PHP tanto no módulo PHP como no módulo suPHP.

8- Onde encontro os arquivos php.ini?
Se estiver utilizando o módulo PHP, o arquivo php.ini se encontra em /etc/php5/apache2/ . Se estiver utilizando o módulo suPHP, ele se encontra em /etc/php5/cgi/

9- Instalando o módulo PHP5 (“PHP5”), o que será carregado do repositório Debian?
Os seguintes pacotes (e alguns outros para resolver as dependências):

  • libapache2-mod-php5 (this package provides the PHP5 module for the Apache 2 webserver, as found in the apache2-mpm-prefork package).
  • php5-common (arquivos comuns para pacotes construídos a partir do código fonte do php5)

10- E instalando o pacote suPHP (“libapache2-mod-suphp”), o que será carregado do repositório Debian?
Três pacotes principais (e outras bibliotecas para resolver as dependências):

  • suphp-common (que gera em /etc/apache2/mods-available/ os arquivos suphp.conf e suphp.load)
  • apache2.2-common
  • php5-cgi (interpretador PHP CGI, construído para uso com Apache2. Será depositado em /usr/lib/cgi-bin/)

pois:
a) O pacote libapache2-mod-suphp depende dos pacotes suphp-common e apache2.2-common
b) O pacote suphp-common depende do pacote php5-cgi
Referências:
1- Módulos do Apache PHP, suPHP, suexec e rewrite no Linux – Debian
2- Documentação do Apache
3- suPHP Homepage

Deixe um comentário, pois isto é muito motivante para continuarmos este trabalho

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s