# rm-rf.es | Administración de sistemas

Bitácora personal de un SysAdmin Gnu/Linux, Windows, BSD...

suPHP 0.7.1: SecurityException in Application.cpp:511: Unknown Interpreter: php

Hoy he estado actualizando un equipo. Una de las actualizaciones era la de la versión de suPHP a la 0.7.1. La actualización ha ido bien hasta que he comenzado a probar los sitios web.

Todos recibían un error 500 (Internal Server Error), típico de suPHP, y en los logs se volcaba la siguiente información:

[Sun Oct 17 19:08:03 2010] [error] [client XX.XX.XXX.XX] SecurityException in Application.cpp:511: Unknown Interpreter: php
[Sun Oct 17 19:08:03 2010] [error] [client XX.XX.XXX.XX] Premature end of script headers: index.php

En este momento ya había entrado en modo pánico, pero rebuscando por Internet información sobre esta versión, he visto que había un pequeño cambio o bug (bueno, pequeño…) por el cual, en el fichero de configuración de suPHP (/etc/suphp.conf) los handlers tenían que ir entre comillas:

Antes:

;Handler for php-scripts
x-httpd-php=php:/usr/bin/php-cgi

;Handler for CGI-scripts
x-suphp-cgi=execute:!self

Después:

;Handler for php-scripts
x-httpd-php="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
x-suphp-cgi="execute:!self"

Tras este cambio, y reiniciar apache todo ha vuelto a funcionar a la normalidad.

Instalar php-mcrypt y php-mbstring para PHP 5.2.10 con yum

Hace unos meses vimos como Instalar php 5.2.10 a través de YUM en CentOS. Ahora necesitamos instalar un par de extensiones, php-mcrypt y php-mbstring que no están disponibles en el repositorio para esta versión en concreto. Si instalamos las del repositorio base nos encontraremos con errores e incompatibilidades (son para la rama 5.1.X).

La solución es recurrir al repositorio testing de Centos 5, donde podemos instalar las versiones disponibles para 5.2.9 y 5.2.10 respectivamente que sí que son compatibles.

Instalar php-mcrypt con yum:

# yum --enablerepo=c5-testing install php-mcrypt

Instalar php-mbstring con yum:

# yum --enablerepo=c5-testing install php-mbstring



Ocultar la versión de PHP

Algo importante en la seguridad de servidores web es ofrecer siempre la menor cantidad de información acerca de las versiones del software instalado en el servidor. Hace ya bastante tiempo vimos cómo ocultar o enmascarar la versión de Apachela versión de Bind.

En este caso vamos a ocultar la versión de PHP, es extremadamente sencillo. Únicamente hay que editar el fichero de configuración general php.ini y modificar el siguiente parámetro a Off:

expose_php Off

Ya podemos verificar que al hacer la petición contra el sitio web la información PHP ya no se muestra:

# telnet servidor 80

Connected to xxx.com (xx.xx.xx.xx).
Escape character is '^]'.
HEAD / HTTP/1.0

HTTP/1.1 200 OK
Date: Fri, 13 Aug 2010 14:18:09 GMT
Server: Apache
Last-Modified: Fri, 12 Feb 2010 12:22:56 GMT
ETag: "44967c-6f-53ca4800"
Accept-Ranges: bytes
Content-Length: 111
Connection: close
Content-Type: text/html

Connection closed by foreign host.

Instalar php 5.2.10 a través de YUM en CentOS

Una de las formas más cómodas de instalar servicios y aplicaciones en CentOS es a través del gestor de paquetes YUM. Esto tiene sus desventajas, porque muchas veces las versiones de las aplicaciones no son todo la actuales que necesitamos.

En el caso de php, en CentOS 5.4 sigue instalandose la rama 5.1 con los repositorios por defecto. Podríamos instalar la nueva versión con paquetes RPM precompilados o compilando a mano pero yo soy partidario de unificar todo con un mismo sistema para evitar problemas y simplificar el funcionamiento de el conjunto de aplicaciones. La idea del repositorio testing la encontré en un comentario de este artículo en inglés.

El repositorio que tiene esta versión actualizada de PHP es CentOS-5 Testing así que solamente tendremos que instalarlo. Para ello creamos el fichero correspondiente en la carpeta de repositorios:

# vim /etc/yum.repos.d/centos-test.repo

El contenido:

[c5-testing]
name=CentOS-5 Testing
baseurl=http://dev.centos.org/centos/5/testing/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing

Ahora si hacemos un yum info de php veremos que podemos instalar la versión 5.2.10 (en este caso pone que ya está instalada porque yo ya lo hice):

# yum info php
Loaded plugins: fastestmirror, priorities
Determining fastest mirrors
 * addons: sunsite.rediris.es
 * base: sunsite.rediris.es
 * extras: sunsite.rediris.es
 * updates: sunsite.rediris.es
addons                                                   |  951 B     00:00
base                                                     | 2.1 kB     00:00
c5-testing                                                                                                                                                     | 1.9 kB     00:00
extras                                                                                                                                                         | 2.1 kB     00:00
updates                                                                                                                                                        | 1.9 kB     00:00
450 packages excluded due to repository priority protections
Installed Packages
Name       : php
Arch       : i386
Version    : 5.2.10
Release    : 1.el5.centos
Size       : 3.1 M
Repo       : installed
Summary    : The PHP HTML-embedded scripting language
URL        : http://www.php.net/
License    : PHP
Description: PHP is an HTML-embedded scripting language. PHP attempts to make it
           : easy for developers to write dynamically generated webpages. PHP also
           : offers built-in database integration for several commercial and
           : non-commercial database management systems, so writing a
           : database-enabled webpage with PHP is fairly simple. The most common
           : use of PHP coding is probably as a replacement for CGI scripts.
           :
           : The php package contains the module which adds support for the PHP
           : language to Apache HTTP Server.

Así que solo queda instalarlo:

# yum install php

Recomiendo una vez hecho esto activar las prioridades de repositorios para evitar que otros paquetes que no sean php se instalen a través de este repositorio. Vamos a dar preferencia al repositorio base de centos.

# yum install yum-priorities

Una vez instalado damos al repositorio de centos base prioridad 10 y al testing 20. Añadimos lo siguiente a cada uno de los apartados entre corchetes del fichero /etc/yum.repos.d/CentOS-Base.repo

 /etc/yum.repos.d/CentOS-Base.repo

Ejemplo:

[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
priority=10

Y para el repositorio de Testing:

/etc/yum.repos.d/centos-test.repo
[c5-testing]
name=CentOS-5 Testing
baseurl=http://dev.centos.org/centos/5/testing/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
priority=20

Información sobre PHP desde línea de comandos

A través de la línea de comandos podemos averiguar información relativa a PHP muy interesante, como por ejemplo:

Versión de PHP instalada:

$ php -v

PHP 5.X.X (cli) (built: Jun 18 2009 18:16:19)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with Zend Extension Manager vX.X.X, Copyright (c) 2003-2007, by Zend Technologies
    with Zend Optimizer vX.X.X, Copyright (c) 1998-2007, by Zend Technologies

Módulos de PHP instalados/compilados:

$ php -m
[PHP Modules]
bcmath
calendar
ctype
curl
date
dom
filter
ftp
gd
...
...
...
[Zend Modules]
Zend Extension Manager
Zend Optimizer

Información general PHP:

La salida de este comando es la misma que <? phpinfo() ?> en un script php.

$ php -i
phpinfo()
PHP Version => 5.X.X

System => Linux  #1 SMP Thu May 7 10:39:21 EDT 2009 iX86
Build Date => Jun 18 2009 18:14:47
Configure Command =>  './configure'  '--disable-pdo' '--enable-bcmath' '--enable-calendar' '--enable-ftp' '--enable-gd-native-ttf' '--enable-libxml' '--enable-magic-quotes' '--enable
-mbstring' '--enable-sockets' '--enable-zip' '--prefix=/usr/local' '--with-apxs2=/usr/local/apache/bin/apxs' '--with-curl=/opt/curlssl/' '--with-freetype-dir=/usr' '--with-gd' '--wit
Server API => Command Line Interface
Virtual Directory Support => disabled
....
....
....
This program makes use of the Zend Scripting Language Engine:
Zend Engine vX.X.X, Copyright (c) 1998-2009 Zend Technologies
    with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies
    with Zend Optimizer vX.X.X, Copyright (c) 1998-2007, by Zend Technologies
....
....
....

Mostrar ficheros de configuración cargados y sus rutas:

$ php --ini

Configuration File (php.ini) Path: /xxx/xxx/xx
Loaded Configuration File:         /xxx/xxx/xxx/php.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed:      (none)

Mostrar configuración de un módulo/extensión instalado:

La sintaxis es php –ri módulo

$ php --ri openssl
openssl

OpenSSL support => enabled
OpenSSL Version => OpenSSL X.X.Xe-fips-xxx 01 Jul 2008

Mostrar información de un módulo/extensión instalado:

La sintaxis es php –re módulo

$ php --re openssl
Extension [
 extension #35 openssl version  ] {

  - Constants [36] {
    Constant [ string OPENSSL_VERSION_TEXT ] { OpenSSL X.X.Xe-fips-xxx 01 Jul 2008 }
    Constant [ integer OPENSSL_VERSION_NUMBER ] { 9469999 }
    Constant [ integer X509_PURPOSE_SSL_CLIENT ] { 1 }
    Constant [ integer X509_PURPOSE_SSL_SERVER ] { 2 }
    Constant [ integer X509_PURPOSE_NS_SSL_SERVER ] { 3 }
    Constant [ integer X509_PURPOSE_SMIME_SIGN ] { 4 }
    Constant [ integer X509_PURPOSE_SMIME_ENCRYPT ] { 5 }
    Constant [ integer X509_PURPOSE_CRL_SIGN ] { 6 }
    Constant [ integer X509_PURPOSE_ANY ] { 7 }
    Constant [ integer OPENSSL_ALGO_SHA1 ] { 1 }
    Constant [ integer OPENSSL_ALGO_MD5 ] { 2 }
    Constant [ integer OPENSSL_ALGO_MD4 ] { 3 }
    Constant [ integer OPENSSL_ALGO_MD2 ] { 4 }
    Constant [ integer OPENSSL_ALGO_DSS1 ] { 5 }
...
...
...

Respecto a estos dos últimos puntos, también podemos buscar información acerca de una clase (php –rf clase) y de una función (php –rc función).

Cómo instalar ionCube Loader en Windows

Con la instalación de IonCube loader tendremos la posibilidad de visualizar páginas php con contenido codificado con ionCube. La instalación es sumamente sencilla en Windows (en este caso 2003 Server con php 5.2.X):

En primera instancia descargamos la extensión/módulo desde el sitio web de ioncube:

http://www.ioncube.com/loaders.php

Posteriormente, procedemos a descomprimir el fichero, dentro del cual encontraremos las versiones de los módulos para cada versión de PHP y dos scripts php para testear que la instalación se ha realizado correctamente:

ioncube_loader_win_4.1.dll
ioncube_loader_win_4.2.dll
ioncube_loader_win_4.3.dll
ioncube_loader_win_4.4.dll
ioncube_loader_win_5.0.dll
ioncube_loader_win_5.1.dll
ioncube_loader_win_5.2.dll
ioncube-loader-helper.php
ioncube-encoded-file.php

Bien, llegados a este punto debemos copiar el módulo correspondiente a nuestra versión de php en la carpeta donde guardemos todos los módulos de php, normalmente “ext” dentro de la carpeta PHP.

Posteriormente, llamamos al módulo desde el fichero de configuración php.ini añadiendo la siguiente línea, que hace referencia al módulo comentado antes:

zend_extension_ts = "c:\carpeta_php\ext\ioncube_loader_win_5.2.dll"

Guardamos y testeamos con un navegador si la instalación se ha realizado correctamente, ejecutando el script ioncube-encoded-file.php, tendrá que mostrar lo siguiente:

This file has been successfully decoded. ionCube Loaders are correctly installed.

PHP: Deshabilitar funciones peligrosas

A estas altura todos conocemos la potencia y versatilidad del lenguaje PHP. Existen no obstante ciertas funciones que utilizadas de forma incorrecta, o con fines maliciosos (exploits, crackeos, etc) comprometan seriamente la seguridad del servidor que está ejecutando el php. Estamos hablando de bugs en una versión de php instalada, bugs en la programación, mala securización de un servidor y muchos más puntos a tener en cuenta y que pueden provocar graves problemas de seguridad en una máquina.

Un buen punto sobre el que comenzar a securizar php, es deshabilitar ciertas funciones potencialmente peligrosas, y que si nuestra programación no utiliza, es 100% recomendable desactivar completamente. Para desactivar funciones, debemos listarla en el fichero de configuración de php (php.ini), utilizando la directiva “disable_functions“. El fichero php.ini normalmente se encuentra en /etc/php.ini, no obstante podéis buscarlo con el comando:

whereis php

Un ejemplo sobre el que podemos comenzar de funciones a deshabilitar es el siguiente:

disable_functions ="system,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,pcntl_exec"

En php.net podéis observar las tareas que desempeña cada una y revisar la viabilidad de su desactivación. En otros sitios web van más allá, y amplian mucho más la lista de funciones a desactivar:

disable_functions ="apache_child_terminate, apache_setenv, define_syslog_variables, escapeshellarg, escapeshellcmd, eval, exec, fp, fput, ftp_connect, ftp_exec, ftp_get, ftp_login, ftp_nb_fput, ftp_put, ftp_raw, ftp_rawlist, highlight_file, ini_alter, ini_get_all, ini_restore, inject_code, mysql_pconnect, openlog, passthru, php_uname, phpAds_remoteInfo, phpAds_XmlRpc, phpAds_xmlrpcDecode, phpAds_xmlrpcEncode, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, shell_exec, syslog, system, xmlrpc_entity_decode"

Aquí ya entran las necesidades de cada uno y la adaptación al entorno de trabajo. Os recomiendo investigar las funciones. Securizar este punto os puede librar de muchos disgustos.

PHP: deshabilitar session ID en URL

Si queremos que las URL’s de nuestros sitios PHP no muestren los ID de sesiones:

http://ejemplo.com/?PHPSESSID=4kgj577sgabvnmhjgkdiuy1956if6ska

Puede deshabilitarse a través del fichero .htaccess (servidores apache + cgi como DSO) o en un fichero php.ini personalizado (servidores apache + cgi ó apache + SUPHP), en los dos casos modificando el parámetro session.trans_id.

En .htaccess:

php_flag session.use_trans_sid off

En php.ini:

session.use_trans_sid = off